喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑💻
此外,《程序员必备技能》专栏和《程序员必备工具》专栏(该专栏暂未开设)日后会逐步更新,感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏
什么是静态链表
- 单链表:各个结点在内存中星罗棋布、散落天涯;每个结点存放一个数据元素,和一个指向下一个结点指针
- 静态链表:分配一整片连续的内存空间,各个结点集中安置;每个结点包含一个数据元素和下一个结点的数组下标(游标)
在静态链表中,0号结点充当了头结点的角色,也就是说这个结点中是不存放数据元素的,而头结点的下一个结点,存放在数组下标为2
的这个位置。
索引 | 数据元素(data) | 指针(next) |
---|---|---|
0 | 头 | 2 |
1 | e 2 e_2 e2 | 4 |
2 | e 1 e_1 e1 | 1 |
3 | e 4 e_4 e4 | 6 |
4 | e 3 e_3 e3 | -1 |
5 | ||
6 | e 5 e_5 e5 | 0 |
在这个静态链表中
头结点的指针是2
,指向索引为2
的结点,也就是
e
1
e_1
e1
e
1
e_1
e1的指针是1
,指向索引为1
的结点,也就是
e
2
e_2
e2
e
2
e_2
e2的指针是4
,指向
e
3
e_3
e3
e
3
e_3
e3的指针是-1
,表示静态链表的结束
如何定义一个静态链表
用代码定义一个静态链表:
#define MaxSize 10 //静态链表的最大长度
struct Node{ //静态链表结构类型的定义
ElemType data; //存储数据元素
int next; //下一个元素的数组下标
};
void testSLinkList(){
struct Node a[MaxSize]; //数组a作为静态链表
//......
}
课本上还给了一种定义的方式:
#define MaxSize 10
typedef struct{
ElemType data;
int next;
}SLinkList[MaxSize];
其实这种方式和下面的方式等价:
#define MaxSize 10
struct Node{
ElemType data;
int next;
};
typedef struct Node SLinkList[MaxSize];
//定义方法 1
void testSLinkList(){
SLinkList a;
//......
}
//定义方法 2
void testSLinkList(){
struct Node a[MaxSize];
//......
}
/*
* 定义方法1 和 定义方法2 是等价的
* 那么为什么课本要使用上面那种方法定义静态链表呢?
* 因为下面这种定义方式
* 会让我们看起来像是定义了一个Node型的数组而不是链表
* 而用SLinkList,一看就知道是静态链表
*/
简述基本操作的实现
初始化静态链表:
1. 把a[0]
的next
设为-1
2. 把其他结点的next
设为一个特殊值用来表示结点空闲,如-2
查找:
从头结点出发挨个往后遍历结点
直到找到想要的数据元素
时间复杂度:
O
(
n
)
O(n)
O(n)
插入位序为i
的结点:
1. 找到空的结点,存入数据元素
2. 从头结点出发,找到位序为i-1
的结点
3. 修改新结点的next
4. 修改i-1
号结点的next
删除结点:
1. 从头结点出发找到前驱结点
2. 修改前驱结点的游标
3. 被删除结点的next
设为-2
静态链表这一部分考试中很少考察,代码实现更是如此
总结:
静态链表就是用数组的方式来实现的链表
在逻辑上相邻的元素,也可以在物理上不相邻
各个元素之间的关系是通过游标来表示的
优点:增、删操作不需要大量移动元素
缺点:不能随机存取,只能从头结点开始依次往后查找;容量固定不可变
适用场景:
- 不支持指针的低级语言
- 数据元素数量固定不变的场景(如操作系统的文件分配表FAT)