为什么要用静态单双链表?
之所以要静态单链表与静态双链表,
是因为,相对而言用链表创建速度慢,
而且,用链表书写也麻烦。
静态单链表
一般有四个变量,分别为head, e[N], ne[N], idx
一般有五个操作,分别为初始化,头插,任意插,头删,任意删。
第零步-变量解释
head 表示头指针,指向头节点,存储头结点的下标,初始化为-1.
e[i] 表示第 i 个结点存储的值 。用时再初始化。
ne[i] 表示第 i 个结点指向的下一个结点,存储下一个结点的下标 。用时再初始化
idx 表示下一个可以用的结点下标。初始化为0.
第一步-初始化
//初始化
void init()//*****
{
head = -1;//-1表示空结点的下标。
idx = 0;//当前可用的下标从0开始。也可放在main函数外,作全局变量,自动初始化。
}
第二步-头插
//将值为x的结点插到头节点,成为头节点
void add_to_head(int x)
{
e[idx] = x, ne[idx] = head, head = idx ++ ;//idx 已用, 加1 存储下一个可以用的结点下标
}
第三步-任意插
//将值为x的结点插入下标为k的结点后面
void add(int k, int x)
{
e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ;
}
第四步-头删
void remove_head()
{
head = ne[head];
}
第五步-任意删
//将下标是k的结点的后面一个结点删掉
void remove(int k)
{
ne[k] = ne[ne[k]];
}
静态双链表
一般有四个变量,分别为e[i], l[i], r[i], idx
。
一般有三个操作,分别为初始化,任意插,任意删
第零步-变量解释
e[i] 表示第i个结点存储的值。用时再初始化。
l[i] 表示第i个结点左边的结点的下标。初始化l[1] = 0.
r[i] 表示第i个结点右边的结点的下标。初始化r[0] = 1.
idx 表示当前可以使用的下标.初始化为2.因为0代表头节点,1代表尾结点
第一步-初始化
//静态双链表的初始化, 0 是 头节点的下标, 1是尾结点的下标
void init()
{
r[0] = 1;
l[1] = 0;
idx = 2; // 0, 1已经用来, 只能从2开始
}
第二步-任意插
//在下标为k的结点的右边插入一个值为x的新结点
void add(int k, int x)
{
e[idx] = x;
l[idx] = k;
r[idx] = r[k];
l[r[k]] = idx; // l[r[idx]] = idx;
r[k] = idx; // r[l[idx]] = idx;
idx ++ ;
}
第三步-任意删
//删除下标为k的结点
void remove(int k)
{
l[r[k]] = l[k];//右边的左边等于左边
r[l[k]] = r[k];//左边的右边等于右边
}
总结
静态单双链表速度快,书写顺滑。
单有四个变量head, e[N], ne[N], idx
,五个操作初始化,头插,任意插,头删,任意删
双有四个变量e[i], l[i], r[i], idx
,三个操作初始化,任意插,任意删
ps: 初始化往往会不记得!