概念
- 存储单元物理位置任意(可以是连续的也可以是不连续的)逻辑次序和物理次序不一定相同
- 链表的结点包含数据域和指针域
- n个结点由指针链组成一个链表
- 访问时只能通过头指针进入链表,并依次向后顺序扫描,寻找结点时间不同--顺序存取法
头指针、头结点和首元结点
- 头指针:指向链表中第一个结点的指针
- 头结点:在链表的首元结点之前附设的一个结点
- 首元结点:指链表中存储第一个数据元素a1的结点
- 头指针->头结点->首元结点 头指针->首元结点
设置头结点的好处:
- 便于首元结点的处理
- 便于空表和非空表的统一处理
空表:
- 无头结点:头指针为空
- 有头结点:头结点的指针域为空
单链表(线性链表):
- 由头指针(表头)唯一确定 可以用头指针的名字命名
- 结点只有一个指针域
- 单链表的存储结构
/*-----单链表的存储结构-----*/
typedef struct Lnode { //声明结点的类型和指向结点的指针类型
ElemType data; //结点的数据域
struct Lnode *next; //结点的指针域
}Lnode,*LinkList; //LinkList为指向结构体Lnode的指针类型
- 定义一个这种形式的指针 ①Lnode *p; ②LinkList L;
- 定义指向头结点的头指针(即定义链表L):通常LinkList L;
- 定义指向某一个结点的指针:Lnode *p;
双向链表:
- 结点有两个指针域
- 在单链表的基础上增加一个指向其前驱的指针域prior
- 解决了单链表查找某一结点的前驱结点难的问题
/*---双向链表的结构定义-----*/
typedef struct DulNode {
ElemType data;
struct DulNode *prior,*next;
}DulNode,*DuLinkList;
循环链表:
- 首尾相接(表中最后一个结点的指针域指向头结点) 没有NULL指针
- 由于没有NULL指针 故终止条件为判断p或p->next是否等于头指针
- 优点:从表中任一结点出发均可找到表中其他结点
- ps:表的操作通常在表的首尾位置上进行
- 头指针表示单循环链表:①找a[1]的时间复杂度O(1),找a[n]的时间复杂度O(n) =>不方便
- 尾指针表示单循环链表:①找a[1](R->next->next)的时间复杂度O(1),找a[n](R)的时间复杂度O(1)
双向循环链表
- 头结点的前驱指针指向链表的最后一个结点
- 让最后一个结点的后继指针指向头结点
- 对称性:p->prior->next=p=p->next->prior
- 只涉及一个方向指针的操作与线性链表相同
- 插入删除时需修改两个方向的指针,操作时间复杂度为O(n)
单链表、循环链表和双向链表的时间效率比较