链表算法总结
知识概览
链表包括单链表和双链表,这里讨论算法题中的链表。为了考虑算法题中对于时间效率的要求,链表通常是用数组模拟成静态链表的形式,速度快。
单链表可以用来写邻接表(包括n个链表),邻接表可以存储树和图,最短路问题、最小生成树问题、最大流问题都可以用邻接表来存储。
双链表用来优化某些问题。
单链表
题目链接
https://www.acwing.com/problem/content/828/
代码
#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) { e[idx] = x, ne[idx] = head, head = idx++; } // 将x插到下标是k的点后面 void add(int k, int x) { e[idx] = x, ne[idx] = ne[k], ne[k] = idx++; } // 将下标是k的点后面的点删掉 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 if (op == 'I') { cin >> k >> x; add(k - 1, x); } } for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' '; cout << endl; return 0; }
双链表
题目链接
https://www.acwing.com/problem/content/829/
代码
#include <iostream> using namespace std; const int N = 100010; int e[N], l[N], r[N], idx; // 初始化 void init() { // 0表示左端点head,1表示右端点tail r[0] = 1, l[1] = 0; idx = 2; } // 在下标是k的点的右边,插入x void add(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() { int m; cin >> m; init(); while (m--) { string op; int k, x; cin >> op; if (op == "L") { cin >> x; add(0, x); } else if (op == "R") { cin >> x; add(l[1], x); } else if (op == "D") { cin >> k; remove(k + 1); } else if (op == "IL") { cin >> k >> x; add(l[k + 1], x); } else { cin >> k >> x; add(k + 1, x); } } for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' '; cout << endl; return 0; }