简单数据结构:list,stack,queue
数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。可透过程序语言所提供的数据类型、引用及其他操作加以实现。一个设计良好的数据结构,应该在尽可能使用较少的时间与空间资源的前提下,支持各种程序运行。透过将数据结构的具体实现封装隐藏于用户界面之后的方法,来让不同的应用程序能够安全地重用这些数据结构。
线性表
线性表(Linear List)简称表,是n(n≥0)个元素的有限序列。
其中:
- 数据元素的个数n定义为表的长度 = list.length() (list.length() = 0,称为空表)
- 将非空的线性表(n>=0)记作:(a[0],a[1],a[2],…,a[n-1])
- 数据元素a[i](0≤i≤n-1)只是个抽象符号,其具体含义在不同情况下可以不同
顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。
链表
链表(Linked list)是不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1),单链表如图:
线性表应当给予以下的基本操作:搜索,删除、插入某个元素。下面,我们以双向链表实现一下。双向链表,顾名思义,就是数据本身具备了左边和右边的俩个指针。假如说双向链表的每个元素都是一个对象,那么每个对象都有一个关键字key,和俩个指针prev,next。
1 | LIST-SEARCH(L, k) //L为链表头,k为所要查找的key |
栈
栈(Stack),由于数据只允许在一端进行操作,因而是一种后进先出(last-in, first-out, LIFO)策略。栈上的INSERT操作被称为压入(PUSH),而无参数的DELETE操作被称为弹出(POP)。如图:
栈应当给予以下的基本操作:判断栈是否为空,入栈,出栈。以下我们会以数组实现基本操作。该数组具有一个属性S.top,指向最新插入的元素。栈中包括的元素S[0..S.top],其中S[0]是栈底元素,S[S.top]是栈顶元素。当S.top=-1时,栈中不包括任何一个元素,即栈空(empty)。
1 | STACK-EMPTY(S) |
队列
队列(Queue),只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。因而是先进先出(FIFO, First-In-First-Out)的线性表。队列的INSERT操作被称为是入队(ENQUEUE),DELETE操作被称为是出队(DEQUEUE)。和栈的POP操作一样,DEQUEUE操作也没有元素参数。如图:
队列应当给予以下的基本操作:入队,出队。以下我们会以数组实现基本操作。该数组具有俩个属性Q.rear、Q.front,Q.rear指向最后一个元素,Q.front指向最新插入的元素。队列中包括的元素为Q[Q.rear..Q.front]。以下实现时,省略了上下溢检查。
1 | QUEUE-ENQUEUE(Q, x) |
exercise :
- 给定一个单链表,如何判断是否为环
- 给定一个单链表,如果存在环,返回环的头指针,否则返回NULL
- 给定俩个单链表,如果有重合,返回重合的头指针,否则返回NULL
- 给定一个单链表,判断是否为回文链表
- 使用俩个栈实现一个队列
- 使用俩个队列实现一个栈