https://zhuanlan.zhihu.com/p/29627391

======知识点======

单链表

image.png

单链表删除结点

image.png

单链表添加结点

image.png

双向链表

image.png

双向链表删除结点

image.png

双向链表添加结点

image.png

循环链表

https://zhuanlan.zhihu.com/p/360567636
一个结点
image.png

循环链表头插法

image.png

循环链表在指定位置插入结点

image.png

循环链表删除结点

image.png

======代码实现=======

单链表 邻接表

https://www.acwing.com/problem/content/828/
image.png
image.png

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 10;
  4. int m;
  5. int hh, e[N], ne[N], idx;
  6. void add_to_head(int x){
  7. e[idx] = x, ne[idx] = hh, hh = idx++;
  8. }
  9. void add_to_node(int k, int x){
  10. e[idx] = x, ne[idx] = ne[k], ne[k] = idx++;
  11. }
  12. void remove(int k){
  13. ne[k] = ne[ne[k]];
  14. }
  15. int main(){
  16. hh = -1;
  17. cin >> m;
  18. while (m--){
  19. string op;
  20. cin >> op;
  21. if (op[0] == 'H'){
  22. int x;
  23. cin >> x;
  24. add_to_head(x);
  25. }
  26. else if (op[0] == 'D'){
  27. int k;
  28. cin >> k;
  29. if (k == 0) hh = ne[hh]; //如何删除的是头结点
  30. else remove(k - 1);
  31. }
  32. else{
  33. int k, x;
  34. cin >> k >> x;
  35. add_to_node(k - 1, x);
  36. }
  37. }
  38. for (int i = hh; i != -1; i = ne[i]) printf("%d ", e[i]);
  39. puts("");
  40. return 0;
  41. }

image.png

头插法演示
8202b6c10561485792a9dd9a9f975e2a.gif

单链表 结构体 TLE

  1. // new Node(); 非常慢,链表大小1e4 1e5就会超时
  2. // 这部分代码,希望大家能看懂C语言的指针,不推荐这种写法
  3. #include <bits/stdc++.h>
  4. #include <stddef.h>
  5. // How to fix C error ‘NULL undeclared’
  6. // https://techoverflow.net/2019/06/20/how-to-fix-c-error-null-undeclared/
  7. using namespace std;
  8. const int N = 1e5 + 10;
  9. struct Node{
  10. int data, id;
  11. Node *next;
  12. };
  13. int m, idx;
  14. Node *head;
  15. void add_to_head(int x){
  16. Node *t = new Node();
  17. t->data = x;
  18. t->next = head;
  19. t->id = idx++;
  20. head = t;
  21. }
  22. void add_to_node(int k, int x){
  23. Node *t = head;
  24. while (t->next != NULL){
  25. if (t->id == k) break;
  26. t = t->next;
  27. }
  28. Node *nw = new Node();
  29. nw->data = x;
  30. nw->id = idx++;
  31. nw->next = t->next;
  32. t->next = nw;
  33. }
  34. void remove(int k){
  35. Node *t = head;
  36. while (t->next != NULL){
  37. if (t->id == k) break;
  38. t = t->next;
  39. }
  40. Node *p = t->next;
  41. t->next = p->next;
  42. delete p;
  43. }
  44. int main(){
  45. head = new Node;
  46. head->next = NULL;
  47. cin >> m;
  48. while (m--){
  49. string op;
  50. cin >> op;
  51. if (op[0] == 'H'){
  52. int x;
  53. cin >> x;
  54. add_to_head(x);
  55. }
  56. else if (op[0] == 'D'){
  57. int k;
  58. cin >> k;
  59. if (k == 0) head = head->next; //如何删除的是头结点
  60. else remove(k - 1);
  61. }
  62. else{
  63. int k, x;
  64. cin >> k >> x;
  65. add_to_node(k - 1, x);
  66. }
  67. }
  68. while (head->next != NULL){
  69. printf("%d ", head->data);
  70. head = head->next;
  71. }
  72. puts("");
  73. return 0;
  74. }

双链表 邻接表

https://www.acwing.com/problem/content/829/

image.png
image.png

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 10;
  4. int m;
  5. int e[N], L[N], R[N], idx;
  6. // k -> idx -> R[k]
  7. void insert(int k, int x){
  8. e[idx] = x;
  9. R[idx] = R[k]; // 先把idx挂好
  10. L[idx] = k;
  11. L[R[k]] = idx; // 然后弄原来的结点
  12. R[k] = idx++;
  13. }
  14. void remove(int k){
  15. L[R[k]] = L[k];
  16. R[L[k]] = R[k];
  17. }
  18. int main(){
  19. // r[0] 指向第一个点,0 1两个点作为两端,r[0] = 1, l[1] = 0 模拟成环
  20. // 用0, 1表示左端点、右端点,第一个数从idx = 2开始
  21. R[0] = 1, L[1] = 0, idx = 2;
  22. cin >> m;
  23. while (m--){
  24. string op;
  25. cin >> op;
  26. if (op == "L"){
  27. int x;
  28. cin >> x;
  29. insert(0, x);
  30. }
  31. if (op == "R"){
  32. int x;
  33. cin >> x;
  34. insert(L[1], x);
  35. }
  36. if (op == "D"){
  37. int k;
  38. cin >> k;
  39. remove(k+1);
  40. }
  41. if (op == "IL"){
  42. int k, x;
  43. cin >> k >> x;
  44. insert(L[k+1], x); // 2-index
  45. }
  46. if (op == "IR"){
  47. int k, x;
  48. cin >> k >> x;
  49. insert(k+1, x);
  50. }
  51. }
  52. for (int i = R[0]; i != 1; i = R[i]) printf("%d ", e[i]);
  53. puts("");
  54. return 0;
  55. }

循环链表 结构体

  1. // 约瑟夫环问题
  2. // 1~n个人,从第1个人开始报数,数到m的人出列
  3. // 如此循环,直到最后一个人出列为止
  4. // 输出出列的顺序
  5. #include <bits/stdc++.h>
  6. using namespace std;
  7. struct node{
  8. int id;
  9. node *next;
  10. };
  11. node *head, *r;
  12. int n, m;
  13. int main(){
  14. cin >> n >> m;
  15. head = new node();
  16. head->id = 1;
  17. head->next = NULL;
  18. r = head;
  19. for (int i = 2; i <= n; i++){
  20. node *p = new node();
  21. p->id = i;
  22. p->next = NULL;
  23. r->next = p;
  24. r = p;
  25. }
  26. r->next = head;
  27. r = head;
  28. for (int i = 1; i <= n; i++){
  29. for (int j = 1; j <= m - 2; j++) r = r->next; //r走到了m-1的位置上
  30. cout << r->next->id << ' '; //m-1的下一个是m
  31. r->next = r->next->next; //删除结点
  32. r = r->next; //挪到下一个从1开始数
  33. }
  34. puts("");
  35. return 0;
  36. }