单、双 链 表
数组模拟链表
①单链表:邻接表{储存图和树}
②双链表:优化某些问题
单链表
// head 表示头结点的下标
// e[i] 表示节点i的值
// ne[i] 表示节点i的next指针是多少
// idx 存储当前已经用到了哪个点
e[i]和ne[i]用下标关联起来:
思路:
1.插入操作(将x插到头结点)
①将你要插入的x的指针指向head的下一个位置
ne[idx] = head;
②head指向x的指针
head = idx;储存x的值
e[idx] = x;idx已经被使用过了,因此idx走向下一个位置
idx ++ ;
2.插入操作(将x插入在第k个数后面)
同理:
e[idx] = x;
ne[idx] =ne[k];
ne[k] = idx;
idx ++ ;
3.删除操作
箭头跳过2,指向3
ne[k] = ne[ne[k]];
#include <iostream> using namespace std; const int N = 100010; // head 表示头结点的下标 // e[i] 表示节点i的值 // ne[i] 表示节点i的next指针是多少 // idx 存储当前已经用到了哪个点 int head, e[N], ne[N], idx; // 初始化 void init() { head = -1; idx = 0; } // 将x插到头结点 void add_to_head(int x) { //1.将你要插入的x的指针指向head的下一个位置 ne[idx] = head; //2.head指向x的指针 head = idx; //储存x的值 e[idx] = x; //idx已经被使用过了,因此idx走向下一个位置 idx ++ ; } // 将x插到下标是k的点后面 void add(int k, int x) { e[idx] = x; ne[idx] =ne[k]; ne[k] = idx; idx ++ ; } // 将下标是k的点后面的点删掉:k-1 void remove(int k) { ne[k] = ne[ne[k]]; } int main() { int m; cin >> m; init(); while (m -- ) { int k, x; char op; cin >> op; if (op == 'H') { cin >> x; add_to_head(x); } else if (op == 'D') { cin >> k; if (!k) head = ne[head];//删除头结点 else remove(k - 1); } else//op=='l' { cin >> k >> x; add(k - 1, x); } } for (int i = head; i != -1; i = ne[i])//i = ne[i]表示:i往后走一步; i != -1表示i不是空节点 cout << e[i] << ' '; cout << endl; return 0; }
双链表
//l[N]每个点左边的点的值
//r[N]每个点右边的点的值
//让下标是0的点是head(左端点),下标是1的点是tail尾结点(右端点)
// e[N] 表示节点i的值
// idx 存储当前已经用到了哪个点
思路:
1.初始化
0是左端点,1是右端点
r[0] = 1, l[1] = 0;0的右端点是1,1的左端点是0
2.插入操作(插入点的右边)
e[idx] = x;//赋值
r[idx] = r[k];
l[idx] = k;
绿箭头:
//注意不能写反:
l[r[k]] = idx;
r[k]=idx;idx ++ ;
3.插入操作(插入点的左边)
直接调用插入右边的函数,k的左边就是l[k]
4.删除操作
让点的右边的左边=点的左边
l[r[k]] = l[k];
让点的左边的右边=点的右边
r[l[k]] = r[k];
#include <iostream> using namespace std; const int N = 100010; int m; //l[N]每个点左边的点的值 //r[N]每个点右边的点的值 //让下标是0的点是head(左端点),下标是1的点是tail尾结点(右端点) // e[N] 表示节点i的值 // idx 存储当前已经用到了哪个点 int e[N], l[N], r[N], idx; // 在节点k的右边插入一个数x void insert(int k, int x) { e[idx] = x;//赋值 r[idx] = r[k]; l[idx] = k; //注意不能写反: l[r[k]] = idx; r[k]=idx; idx ++ ; } // 删除节点k void remove(int k) { r[l[k]] = r[k]; l[r[k]] = l[k]; } int main() { cin >> m; //初始化: // 0是左端点,1是右端点 r[0] = 1, l[1] = 0;//0的右端点是1,1的左端点是0 idx = 2; while (m -- ) { string op; cin >> op; int k, x; if (op == "L") { cin >> x; insert(0, x); } else if (op == "R") { cin >> x; insert(l[1], x); } else if (op == "D") { cin >> k; remove(k + 1); } else if (op == "IL") { cin >> k >> x; insert(l[k + 1], x); } else { cin >> k >> x; insert(k + 1, x); } } for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' '; cout << endl; return 0; }