链表
单链表
线性表的链式存储称为单链表
-
定义:每个链表节点除了存放自身信息以外,还存放指向后继节点的指针。
// 单链表的结构类型 typedef struct LNode { ElemType data; //数据域 struct LNode *next; //指针域 }LNode, *LinkList
-
带头节点的指针好处:
- 由于开始节点的位置被存放到头结点的指针域中,所以在链表的第一个位置上操作和在表的其他位置上的操作一致,无需特殊处理
- 无论链表是否为空,其头指针都指向头结点的非空指针(空表中头结点的指针域为空),因此空表和非空表的处理也得到了统一
- 思考一下没有Head时对链表的第一元素怎么处理。
-
-
基本操作
-
头插法
// 单链表的结构类型 typedef struct LNode { ElemType data; //数据域 struct LNode *next; //指针域 }LNode, *LinkList LinkList List_HeadInsert(LinkList &L) { //从表尾到表头逆向建立单链表L,每次均在头结点之后插入元素 LNode *s; // 创建一个Lnode的指针,这里是建议先初始化指向NULL int x; //存放键盘输入的值 //初始化头结点 L = new LinkList(sizeof(LNode)); L -> next =NULL; cin>>x; while(x!=999) { s = new LNode*(sizeof(LNode)); s->data =x; // 自己画图理解节点指向的变化 s->next = L->next; L->next = s; cin>>x; } return L; }
-
尾插法
-
```C++
// 单链表的结构类型
typedef struct LNode
{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode, *LinkList
LinkList List_TailInsert(LinkList &L)
{
//从表头到表尾正向建立单链表L,每次均在表尾插入元素
int x; //设存储的数据类型为整型
cin>>x;
L = new LinkList(sizeof(LNode));
L -> next =NULL;
LNode *s, *r=L; //与尾插法不同,这里多创建了一个r指针,为什么?思考一下
while(x!=999)
{
s = new LNode*(sizeof(LNode));
s->data =x;
// 自己画图理解节点指向的变化
r->next = s; // 使得链尾结点指向插入结点
r = s; //r挪动到链尾
cin>>x;
}
r->next = NULL; //链尾指针指向NULL;
return L;
}
```
-
按序号查找结点的值
- 创建一个 L N o d e ∗ p LNode * p LNode∗p将头指针的值给 p p p (这样避免过程中改变头指针的指向)
- 依次进行遍历
- 注意判断序号是否过大或者过小
-
按值查找表节点
- 类似按序号查找结点的值
-
插入节点的操作
- 头插法
- 尾插法
-
删除节点的操作
- 删除元素在链表中间情况,注意被删除元素的前驱和后继直接要连接起来
- 删除元素在链表尾部情况,注意被删除元素的前驱要连接起来(这里其实是:前驱->next = Null)
-
求表长操作
- 设置计数器变量
- 向后移动一下,计数器变量+1;
双链表
定义:在单链表的基础上增加一个指向前驱的prior指针
循环链表
- 循环单链表:在单链表的基础上,表尾结点不指向NULL而是指向头结点
- 循环双链表:在双链表的基础上,表尾节点指向头结点
静态链表
- 定义:借助数组来描述线性表的链式存储结构,结点也有数据域(data)和指针域(next),但是与链表不同的是,这里的指针域是结点的相对位置(数组下标);当然静态链表也是要预先分配一块连续的内存空间。
顺序表与链表
- 顺序表和链表的比较
对比问题 | 顺序表 | 链表 |
---|---|---|
存取方式 | 顺序存储、随机存储 | 顺序存储 |
逻辑结构(物理结构) | 逻辑上相邻的元素物理上也相邻 | 逻辑上相邻的元素物理上不一定相邻 |
查找(按值查找) | O ( n ) O(n) O(n)、对半查找 O ( l o g 2 n ) O(log_{2}n) O(log2n) | O ( n ) O(n) O(n) |
查找(按序号查找) | O ( 1 ) O(1) O(1) | O ( n ) O(n) O(n) |
插入/删除 | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) |
空间分配 | 静态存储 | 动态存储 |
- 顺序表及链表选择
- 存储考虑
- 运算考虑
- 环境考虑