单双链表(数组模拟)笔记
如题,我们要使用数组来模拟链表这个数据结构
区别于传统的结构体链表(动态链表):
struct node
{
int value;
struct node* next;//指向下一个节点的指针
}user_define_name;//调用链表的别称
数组模拟链表(静态链表)的速度更快,但是对于空间的优化不如动态链表
单链表的实现:
首先需要两个数组来存储节点的数据值和指向下一个节点的指针值,头节点head
,以及一个计数器来记录总共的节点数
int head value[N],next[N],idx;//N表示链表的最大长度
然后定义init
初始化函数:
void init() {
head = -1;//初始化头节点指向-1
idx = 0;
}
定义add_to_head
添加节点到头节点后的函数:
void add_to_head(int x) {
value[idx] = x;
next[idx] = head;
head = idx;
idx++;
}
定义add
在第k个节点后添加一个节点的函数:
void add(int k, int x) {
value[idx] = x;
next[idx] = next[k];
next[k] = idx;
idx++;
}
定义remove
删除第k个节点后一个节点的函数:
void remove(int k) {
next[k] = next[next[k]];
}
把第k个节点指向的下一个节点的值next[next[k]]
赋给next[k]
即把第k个节点指向的下一个节点定位到下一个节点指向的下一个节点
形如:
a -> b -> c 变为 a -> c
定义inquire
查找第k个节点后一个节点的值的函数:
int inquire(int k) {
if (next[k] != -1) return value[next[k]];//当第k个节点不是尾节点时返回下一个节点的值
else return -1;//是尾节点返回-1
}
缺点:单链表只能定位某个节点后的一个节点,无法做到双端查找,可以引入双链表解决该问题
改进到双链表的实现:
在单链表的基础上增加我们需要额外的一个数组来存储上一个节点的位置:
int value[N],left[N],right[N],idx;
init
初始化函数的改进:
选用0
和1
节点作为头节点和尾节点,初始化时,两者相互引索
void init() {
right[0] = 1;
left[1] = 0;
idx = 2;
}
add
第k个节点后添加一个节点的函数的改进:
void add(int k, int x) {
value[idx] = x;
right[idx] = right[k];
left[idx] = k;
left[right[k]] = idx;
right[k] = idx;
idx++;
}
先把idx
节点左右指针指向k
和right[k]
,即把idx
插在中间
然后先让idx
的右节点的左指针left[right[k]]
指向idx
,再把idx
的左节点的右指针right[k]
指向idx
最后idx++
若是想在第k个节点前添加一个节点,把k
改为传入left[k]
,即可实现
remove
删除第k个节点后一个节点的函数的改进:
void remove(int k) {
right[k] = right[right[k]];
left[right[right[k]]] = k;
}
可以看出这步操作非常的复杂,所以可以重新定义一个 p_remove
删除指定节点的函数:
void p_remove(int k) {
right[left[k]] = right[k];
left[right[k]] = left[k];
}
把指定节点的右节点的左指针指向指定节点的左节点,指定节点的左节点的右指针指向指定节点的右节点
- 使用
inquire
函数查找指定节点的左右节点值,与add
函数操作类似,这里不做赘述