线性表目录
线性结构定义
线性结构定义
线性结构表示数据元素之间(广义的)有序关系
i.e. 线性表、栈、队列。、串、广义表
特点:
- 存在一个唯一的被称为“第一个”的数据元素
- 存在一个唯一的被称为“最后一个”的数据元素
- 除第一个元素外,每个元素均有唯一一个直接前驱(Immediate Predecessor)
- 除最后一个元素外,每个元素均有唯一一个直接后继(Immediate Successor)
线性表 Linear List
定义
线性表是由n(n≧0)个数据元素(结点)a1,a2,…,an组成的有限序列,且该序列中的所有结点具有相同的数据类型。
线性表中的结点可以是单值元素,也可以是记录型元素。
若线性表中的结点是按值或按关键字值由小到大(或由大到小)排列的,称线性表是有序的
ADT定义
线性表的顺序表示和实现
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。用存储位置的相邻来表示数据元素之间的有序关系。
顺序表(Sequential list):
L
O
C
(
a
i
+
1
)
=
L
O
C
(
a
i
)
+
X
LOC(a_i+1)=LOC(a_i) + X
LOC(ai+1)=LOC(ai)+X
线性表的顺序实现:用动态分配的一维数组
#define LIST_INIT_SIZE 100 //线性表初始大小
#define LISTINCREMENT 10 //线性表增量大小
typedef struct{
ElemType *base; //线性表存储空间的基地址
//ElemType为数据元素的类型,可以用Typedef定义
int length; //线性表当前长度
int listsize; //当前分配的存储容量
//以sizeof(ElemType)为单位
} SqList;
线性表的链式表示和实现
线性表的链式存储是指用一组任意的(连续的或不连续的)存储单元存储线性表中的数据元素。
还必须存储指示其直接后继的地址(或位置),称为指针(pointer)或链(link)
存储方式比较:
链表结构
- 线性链表(linear linked list)/单链表(singly linked list):每一个结点只包含一个指向直接后继的指针域
① 基于C指针实现的单链表
② 基于C数组实现的单链表/静态链表(Static linked list) - 双向链表(doubly linked list):每一个结点包含两个指针域,其一指向直接后继,另一指向直接前驱
- 循环链表(circular linked list):整个链表的指针域链接成一个或多个环
- 双向循环链表:将头结点和尾结点链接起来的双向链表
线性链表/单链表(指针)
typedef struct Lnode {
ElemType data; /*数据域,保存结点的值*/
struct Lnode *next; /*指针域*/
} Lnode, LinkedList; /*结点、链表的类型 */
为操作方便,总是在链表的第一个结点之前附设一个头结点:头结点的数据域可以不存储任何信息(或存储链表长度等信息),头结点的指针域存储指向第一个结点的指针(即第一个结点的存储位置)
- 存在的问题:
链表的表长是隐含的
对输入数据的合法性检查,被推迟
若要在链表的最后一个元素之后插入元素,那么要遍历整个链表
结点的当前位置很重要 - 改进的措施:
增加变量,分别表示:表长、表尾、当前位置
将操作中的参数“位序 i ”改为“当前位置”
// 结点类型
typedef struct LNode {
ElemType data;
struct LNode *next;
} Link, Position;
// 链表类型
typedef struct {
// head, tail分别指向头结点和最后一个结点的指针
Link *head, *tail;
// current指向当前被访问的结点的指针
Link *current; //其初始位置指向头结点
int curpos; //指示当前指针位置,初值为0
int len; //指示链表长度
} LinkedList;
线性链表/单链表(数组→静态链表)
数组的一个分量表示一个结点,用游标代替指针指示结点在数组中的相对位置。
例如:
#define MAXSIZE 1000
typedef struct SLinked{
ElemType data;
int cur;
} SLinkedList[MAXSIZE];
SLinkedList s; //静态链表
PS:在该存储数组中,可以包含一个空闲链表和多个静态链表。用(s,head)表示在s中存储的以head为起始位置的静态链表
例如:下图中空闲链表为0→6→9,一条静态链表的表头为(s, 1),链表为1→2→4→5→7→8→3
双向链表 Doubly Linked List
双向链表:构成链表的每个结点中设立两个指针域,一个指向其直接前趋的指针域prior,一个指向其直接后继的指针域next
typedef struct node {
ElemType data ;
struct node *prior , *next ;
} DoublyLinkedList;
DoublyLinkedList *head;
循环链表 Circular Linked List
单链的循环链表:
每一个结点只包含一个指向直接后继的指针域,但其最后一个结点的指针域指向链表的头结点,整个链表的指针域链接成一个环。
- 判断是否是空链表:head->next==head
- 判断是否是表尾结点:p->next==head
双向循环链表:
具有指向前驱和后继的指针,这样从循环链表的任意一个结点出发都可以找到链表中的其它结点,使得表处理更加方便灵活