当前位置:   article > 正文

数据结构之链表(C语言)_c 链表

c 链表

链表的概念:

  链表(Linked List)是数据结构中常见的一种基础数据结构,它由一些列节点(Node)组成,每一个节点都包含两部分,一部分是存储数据的数据域(Data),另一部分是记录下一个节点位置的指针域(Next)。链表中的节点在内存中存储的位置是不连续的,而是通过指针来相互连接。

链表有单向链表和双向链表两种形式。接下来我将通过C语言来实现单链表和双链表的一些基本操作,代码统一使用全局变量的头指针的形式来实现。

单链表:

1、建立单链表:

单链表的建立通常使用头插法或者尾插法;

通用代码:

  1. struct Node { //结构体定义
  2. int data;
  3. struct Node* next;
  4. };
  5. int count = 0; //计算节点的数量
  6. struct Node* head = NULL; //头指针
  7. struct Node* new(int x)
  8. {
  9. struct Node* temp = (struct Node*)malloc(sizeof(struct Node)); //给新节点分配内存
  10. temp->data = x; //赋值
  11. temp->next = NULL;
  12. return temp;
  13. }

头插法将新节点插入链表的开头;

代码实现:

  1. void headList(int data)
  2. {
  3. struct Node* A = new(data); //创建新节点
  4. A->next = head; //新节点的指针指向头指针指向的节点
  5. head = A; //头指针指向新节点
  6. count++;
  7. }

尾插法将新节点插入链表的尾巴;

代码实现:

  1. void lastList(int data)
  2. {
  3. struct Node* k = head; //该变量用来替代头指针来进行移动
  4. struct Node* temp = new(data);
  5. if (k == NULL) //链表为空
  6. {
  7. temp->next = head;
  8. head = temp;
  9. return;
  10. }
  11. while (k->next != NULL) Move to the last node
  12. k = k->next;
  13. temp->next = k->next;
  14. k->next = temp;
  15. count++;
  16. }

2、单链表的按位插入

单链表的按位插入是指在指定位置插入一个节点。具体步骤如下:

  1. 定义要插入的节点,并赋值。
  2. 找到要插入位置前一个节点,并定义一个指向该节点的指针p。
  3. 将要插入节点的next指针指向p的next指针所指向的节点。
  4. 将p的next指针指向要插入的节点。

代码实现:

  1. void insert(int x, int data) //x是插入位置 data是新节点的数据
  2. {
  3. struct Node* sert = head; //因为head是全局变量
  4. struct Node* temp = new(data);
  5. if (x<1 || x>count) //插入位置非法
  6. {
  7. printf("error!");
  8. return;
  9. }
  10. for (int i = 1; i < x - 1; i++) //移动到插入的位置
  11. sert = sert->next;
  12. temp->next = sert->next;
  13. sert->next = temp;
  14. }

3、单链表的按位查找和按值查找

步骤基本与按位插入一致;

代码实现:

  1. //按位查找
  2. void finder1(int x)
  3. {
  4. struct Node* find = head;
  5. if (head == NULL) //链表为空
  6. {
  7. printf("empty!\n");
  8. return;
  9. }
  10. if (x<1 || x > count) //查找位置非法
  11. {
  12. printf("error!\n");
  13. return;
  14. }
  15. for (int i = 1; i < x; i++)
  16. {
  17. find = find->next;
  18. }
  19. printf("number is %d \n", find->data); //打印
  20. }
  21. //按值查找
  22. void finder2(int x)
  23. {
  24. struct Node* find = head;
  25. while (find != NULL)
  26. {
  27. if (find->data == x)
  28. {
  29. printf("finding on");
  30. return;
  31. }
  32. find = find->next;
  33. }
  34. printf("false");
  35. }

4、单链表的节点删除

代码实现:

  1. void delete(int x)
  2. {
  3. if (x<1 || x>count)
  4. {
  5. printf("error!\n");
  6. return;
  7. }
  8. struct Node* deleter = head;
  9. for (int i = 1; i < x - 1; i++) //移动到删除节点的前一个节点
  10. {
  11. deleter = deleter->next;
  12. }
  13. struct Node* A = deleter->next; //用于释放删除节点空间
  14. deleter->next = deleter->next->next;
  15. free(A);
  16. }

完整代码实现:
 

  1. struct Node {
  2. int data;
  3. struct Node* next;
  4. };
  5. struct Node* head = NULL; //头指针
  6. int count = 0; //计算节点的数量
  7. struct Node* new(int x)
  8. {
  9. struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
  10. temp->data = x;
  11. temp->next = NULL;
  12. return temp;
  13. }
  14. 头插法
  15. void headList(int data)
  16. {
  17. struct Node* A = new(data); //创建新节点
  18. A->next = head;
  19. head = A;
  20. count++;
  21. }
  22. 尾插法
  23. void lastList(int data)
  24. {
  25. struct Node* k = head; //该变量用来替代头指针来进行移动
  26. struct Node* temp = new(data);
  27. if (k == NULL) //链表为空
  28. {
  29. temp->next = head;
  30. head = temp;
  31. count++;
  32. return;
  33. }
  34. while (k->next != NULL) //移动到最后一个节点
  35. k = k->next;
  36. temp->next = k->next;
  37. k->next = temp;
  38. count++;
  39. }
  40. //按位插入
  41. void insert(int x, int data)
  42. {
  43. struct Node* sert = head; //因为head是全局变量
  44. struct Node* temp = new(data);
  45. if (x<1 || x>count) //查找位置非法
  46. {
  47. printf("error!");
  48. return;
  49. }
  50. for (int i = 1; i < x - 1; i++) //移动到插入的位置
  51. sert = sert->next;
  52. temp->next = sert->next;
  53. sert->next = temp;
  54. }
  55. //按位查找
  56. void finder1(int x)
  57. {
  58. struct Node* find = head;
  59. if (head == NULL)
  60. {
  61. printf("empty!\n");
  62. return;
  63. }
  64. if (x<1 || x > count)
  65. {
  66. printf("error!\n");
  67. return;
  68. }
  69. for (int i = 1; i < x; i++)
  70. {
  71. find = find->next;
  72. }
  73. printf("number is %d \n", find->data);
  74. }
  75. //按值查找
  76. void finder2(int x)
  77. {
  78. struct Node* find = head;
  79. while (find != NULL)
  80. {
  81. if (find->data == x)
  82. {
  83. printf("finding on");
  84. return;
  85. }
  86. find = find->next;
  87. }
  88. printf("false");
  89. }
  90. //删除
  91. void delete(int x)
  92. {
  93. if (x<1 || x>count)
  94. {
  95. printf("error!\n");
  96. return;
  97. }
  98. struct Node* deleter = head;
  99. for (int i = 1; i < x - 1; i++)
  100. {
  101. deleter = deleter->next;
  102. }
  103. struct Node* A = deleter->next;
  104. deleter->next = deleter->next->next;
  105. free(A);
  106. }
  107. 打印
  108. void Print()
  109. {
  110. struct Node* h = head;
  111. while (h != NULL)
  112. {
  113. printf("%d ", h->data);
  114. h = h->next;
  115. }
  116. printf("\n");
  117. }
  118. int main()
  119. {
  120. lastList(3);
  121. lastList(1);
  122. lastList(8);
  123. lastList(2);
  124. lastList(31);
  125. lastList(32);
  126. Print();
  127. delete(4);
  128. Print();
  129. insert(4, 9);
  130. Print();
  131. finder1(5);
  132. finder2(2);
  133. return 0;
  134. }

双链表:

1、建立双链表:

通用代码:

  1. struct Node {
  2. int data;
  3. struct Node* per;
  4. struct Node* next;
  5. };
  6. int count = 0;
  7. struct Node* head = NULL;
  8. struct Node* new(int n) //新节点
  9. {
  10. struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
  11. temp->data = n;
  12. temp->next = NULL;
  13. temp->per = NULL;
  14. return temp;
  15. }

头插法:

代码实现:

  1. void headList(int x)
  2. {
  3. struct Node* temp = new(x);
  4. if (head == NULL)
  5. {
  6. temp->next = head;
  7. head = temp;
  8. temp->per = NULL;
  9. count++;
  10. return;
  11. }
  12. temp->next = head; //新节点指向head指向的节点
  13. head->per = temp; //head指向的节点指向新节点
  14. head = temp; //改变head指向
  15. temp->per = NULL;
  16. count++;
  17. }

尾插法:

代码实现:

  1. void lastList(int x)
  2. {
  3. struct Node* header = head;
  4. struct Node* temp = new(x);
  5. if (head == NULL)
  6. {
  7. temp->next = head;
  8. head = temp;
  9. temp->per = NULL;
  10. count++;
  11. return;
  12. }
  13. while (header->next != NULL) //移动到最后节点
  14. {
  15. header = header->next;
  16. }
  17. temp->next = header->next;
  18. header->next = temp;
  19. temp->per = header;
  20. count++;
  21. }

2、双链表的按位插入

代码实现:

  1. void Insert(int x,int data)
  2. {
  3. if (x<1 || x>count) //判断插入位置是否非法
  4. {
  5. printf("error!\n");
  6. return;
  7. }
  8. struct Node* header = head;
  9. struct Node* temp = new(data);
  10. for (int i = 1; i < x-1; i++)//移动到插入位置前一个位置
  11. {
  12. header = header->next;
  13. }
  14. temp->next = header->next;
  15. temp->per = header;
  16. header->next->per = temp; //插入位置的前节点指向新节点
  17. header->next = temp;
  18. count++;
  19. }

3、双链表的按位删除

双链表的删除操作需要注意边界问题,若删除为首节点时,应及时更新头指针的指向,若删除尾节点时,应做特殊处理。

代码实现:

  1. void delete(int x)
  2. {
  3. struct Node* header = head;
  4. if (x<1 || x>count)
  5. {
  6. printf("error!\n");
  7. return;
  8. }
  9. if (x == 1) //删除首节点
  10. {
  11. struct Node* B = header;
  12. header = B->next;
  13. head = header; //注意要更新头指针
  14. header->per = NULL;
  15. printf("delete a number : %d\n", B->data);
  16. free(B);
  17. count--;
  18. return;
  19. }
  20. for (int i = 1; i < x-1 ; i++) //前一个节点
  21. {
  22. header = header->next;
  23. }
  24. struct Node* A = header->next;
  25. if (A->next == NULL) //若删除节点为最后的节点
  26. {
  27. printf("delete a number : %d\n", A->data);
  28. header->next = A->next; //直接更新前节点的next指针就行
  29. free(A);
  30. count--;
  31. return;
  32. }
  33. header->next = A->next;
  34. A->next->per = header;
  35. printf("delete a number : %d\n", A->data);
  36. free(A);
  37. count--;
  38. }

4、双链表的前后遍历

代码实现:

  1. //链表的遍历
  2. void Print()
  3. {
  4. struct Node* header = head;
  5. while (header != NULL) //从前遍历
  6. {
  7. if (header->next == NULL) //方便从后面遍历
  8. {
  9. printf("%d", header->data);
  10. break;
  11. }
  12. printf("%d ", header->data);
  13. header = header->next;
  14. }
  15. printf("\n");
  16. while (header != NULL)
  17. {
  18. if (header->next == NULL)
  19. break;
  20. header = header->next;
  21. }
  22. while (header != NULL)
  23. {
  24. printf("%d ", header->data);
  25. header = header->per;
  26. }
  27. printf("\n");
  28. }

完整代码:
 

  1. struct Node {
  2. int data;
  3. struct Node* per;
  4. struct Node* next;
  5. };
  6. int count = 0;
  7. struct Node* new(int n) //新节点
  8. {
  9. struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
  10. temp->data = n;
  11. temp->next = NULL;
  12. temp->per = NULL;
  13. return temp;
  14. }
  15. struct Node* head = NULL;
  16. //头插法
  17. void headList(int x)
  18. {
  19. struct Node* temp = new(x);
  20. if (head == NULL)
  21. {
  22. temp->next = head;
  23. head = temp;
  24. temp->per = NULL;
  25. count++;
  26. return;
  27. }
  28. temp->next = head;
  29. head->per = temp;
  30. head = temp;
  31. temp->per = NULL;
  32. count++;
  33. }
  34. //
  35. //尾插法
  36. void lastList(int x)
  37. {
  38. struct Node* header = head;
  39. struct Node* temp = new(x);
  40. if (head == NULL)
  41. {
  42. temp->next = head;
  43. head = temp;
  44. temp->per = NULL;
  45. count++;
  46. return;
  47. }
  48. while (header->next != NULL) //移动到最后节点
  49. {
  50. header = header->next;
  51. }
  52. temp->next = header->next;
  53. header->next = temp;
  54. temp->per = header;
  55. count++;
  56. }
  57. //按位插入
  58. void Insert(int x,int data)
  59. {
  60. if (x<1 || x>count)
  61. {
  62. printf("error!\n");
  63. return;
  64. }
  65. struct Node* header = head;
  66. struct Node* temp = new(data);
  67. for (int i = 1; i < x-1; i++)//移动到插入位置前一个位置
  68. {
  69. header = header->next;
  70. }
  71. temp->next = header->next;
  72. temp->per = header;
  73. header->next->per = temp; //插入位置的前节点指向新节点
  74. header->next = temp;
  75. count++;
  76. }
  77. //删除
  78. void delete(int x)
  79. {
  80. struct Node* header = head;
  81. if (x<1 || x>count)
  82. {
  83. printf("error!\n");
  84. return;
  85. }
  86. if (x == 1) //删除首节点
  87. {
  88. struct Node* B = header;
  89. header = B->next;
  90. head = header; //注意要更新头指针
  91. header->per = NULL;
  92. printf("delete a number : %d\n", B->data);
  93. free(B);
  94. count--;
  95. return;
  96. }
  97. for (int i = 1; i < x-1 ; i++) //前一个节点
  98. {
  99. header = header->next;
  100. }
  101. struct Node* A = header->next;
  102. if (A->next == NULL) //若删除节点为最后的节点
  103. {
  104. printf("delete a number : %d\n", A->data);
  105. header->next = A->next;
  106. free(A);
  107. count--;
  108. return;
  109. }
  110. header->next = A->next;
  111. A->next->per = header;
  112. printf("delete a number : %d\n", A->data);
  113. free(A);
  114. count--;
  115. }
  116. //链表的遍历
  117. void Print()
  118. {
  119. struct Node* header = head;
  120. while (header != NULL) //从前遍历
  121. {
  122. if (header->next == NULL) //方便从后面遍历
  123. {
  124. printf("%d", header->data);
  125. break;
  126. }
  127. printf("%d ", header->data);
  128. header = header->next;
  129. }
  130. printf("\n");
  131. while (header != NULL)
  132. {
  133. if (header->next == NULL)
  134. break;
  135. header = header->next;
  136. }
  137. while (header != NULL)
  138. {
  139. printf("%d ", header->data);
  140. header = header->per;
  141. }
  142. printf("\n");
  143. }
  144. int main()
  145. {
  146. lastList(3);
  147. lastList(1);
  148. lastList(8);
  149. lastList(2);
  150. lastList(31);
  151. lastList(32);
  152. Print();
  153. Insert(3, 5);
  154. Print();
  155. delete(1);
  156. Print();
  157. return 0;
  158. }

其他的链表操作基本上都是大同小异,例如双链表查找最小值、按值查找、暗值删除等一些扩展的操作,可根据基础代码进行编写,加深对链表操作的理解和熟练度。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/645976
推荐阅读
相关标签
  

闽ICP备14008679号