当前位置:   article > 正文

数据结构—带头结点的单循环链表

带头结点的单循环链表

1.基本操作

  • 循环链表的特点是最后一个元素的指针域指向头结点。

  • 因此对于循环链表的初始化(设表的头结点是L, 不再是L->next=NULL,而是L->next=L。循环链表为空时,头结点的下一个结点依然是头结点本身。因此但虚幻链表的初始化如下:
  1. //初始化
  2. int InitList(LinkList &L)
  3. {
  4. L=new LNode;
  5. L->next=L; //非循环链表的初始化是头指针的指针域置空 L->next=NULL
  6. return 1;
  7. }
  • 从循环链表中的任何一个结点的位置都可以找到其他所有结点,而单链表做不到;
  • 循环链表中没有明显的尾端,如何避免死循环?
  • 循环条件:
    • p!=NULL  -—>  p!=L                    
    • p->next!=NULL ——>  p->next!=L
  • 所以根据循环链表的特点,判断循环链表是否为空时,只需判断头结点的下一个结点是否是头结点即可:
  1. //判断链表是否为空
  2. int ListEmpty(LinkList L)
  3. {
  4. if(L->next==L)
  5. {
  6. return 1;//空
  7. }
  8. else
  9. {
  10. return 0;//非空
  11. }
  12. }
  • 从头检查每一个结点,若当前结点不是头结点,则链表长度加1,由此可计算链表的长度:
  1. //获取链表长度
  2. int ListLength(LinkList L)
  3. {
  4. int length=0;
  5. LNode *p;
  6. p=L->next;
  7. while(p!=L)
  8. { //当p不是头结点时,链表长度加1
  9. p=p->next;
  10. length++;
  11. }
  12. return length;
  13. }
  • 遍历链表
  1. //遍历链表
  2. void TraveList(LinkList L)
  3. {
  4. LNode *p;
  5. p=L->next;
  6. printf("遍历链表:\n");
  7. while(p!=L)
  8. { //当p不是头结点时,输出元素值
  9. printf("%d ",p->data);
  10. p=p->next;
  11. }
  12. printf("\n");
  13. }
  • 使用头插法和尾插法创建单循环链表的方法和创建一般单链表的操作一样,区别在于建立空链表的语句不同。一般单链表是L->next=NULL,而单循环链表是L->next=L。
  • 头插法
  1. //头插法创建单循环链表
  2. void CreateList1(LinkList &L,int n)
  3. {
  4. //创建长度为n的单循环链表
  5. L=new LNode;
  6. L->next=L;
  7. printf("请输入链表元素值:\n");
  8. for(int i=n;i>0;--i)
  9. {
  10. printf("请输入第%d个元素的值:",i);
  11. LNode *p;
  12. p=new LNode;//生成新结点
  13. scanf("%d",&p->data);
  14. p->next=L->next;;
  15. L->next=p;
  16. }
  17. }
  • 尾插法
  1. //尾插法创建单循环链表
  2. void CreateList2(LinkList &L,int n)
  3. {
  4. L=new LNode;
  5. L->next=L;
  6. struct LNode *r;
  7. r=L;
  8. for(int i=0;i<n;i++)
  9. {
  10. printf("请输入第%d个元素的值:",i+1);
  11. LNode *p;
  12. p=new LNode;
  13. scanf("%d",&p->data);
  14. p->next=L;
  15. r->next=p;
  16. r=p;
  17. }
  18. }
  • 单循环链表的删除操作和一般单链表的操作时一样的。要注意的是单循环链表的插入操作:
  1. //单循环链表的插入操作
  2. int ListInsert(LinkList &L,int location,int &e)
  3. {
  4.     //在L的location位置插入元素e
  5.      LNode *p;
  6.      p=L;
  7.      int j=0;
  8.      while(p->next!=L&&j<location-1)
  9. {
  10.    //注意:由于p初始时指向头结点,所以循环的条件是 p->next!=L,而不是 p!=L 
  11.          p=p->next;                      
  12.          j++;
  13.      }
  14.      if(p==L||j>location-1)
  15. {
  16.          return 0;
  17.      }
  18.      LNode *s;
  19.      s=new LNode;
  20.      s->data=e;
  21.      s->next=p->next;
  22.      p->next=s;
  23.      return 1;
  • 删除操作
  1. //单循环链表的删除操作
  2. int ListDelete(LinkList &L,int location,int &e)
  3. {
  4. //删除L中location位置的元素,并用e返回其值
  5. LNode *p;
  6. p=L;
  7. int j=0;
  8. while(p->next!=L&&j<location-1)
  9. {
  10. p=p->next;
  11. j++;
  12. }
  13. if(p==L||j>location-1)
  14. {
  15. return 0;
  16. }
  17. LNode *q;
  18. q=new LNode;
  19. q=p->next;
  20. p->next=q->next;
  21. e=q->data;
  22. delete q;
  23. return 1;
  24. }

2.代码实现

  • man.cpp
  1. #include<iostream>
  2. using namespace std;
  3. //存储结构
  4. typedef struct LNode
  5. {
  6. int data;
  7. struct LNode *next;
  8. }LNode, *LinkList;
  9. //初始化
  10. int InitList(LinkList &L)
  11. {
  12. L = new LNode;
  13. L->next = L; //非循环链表的初始化是头指针的指针域置空 L->next=NULL
  14. return 1;
  15. }
  16. // 判断链表是否为空
  17. int ListEmpty(LinkList L)
  18. {
  19. if (L->next == L)
  20. {
  21. return 1; // 空
  22. }
  23. else
  24. {
  25. return 0; // 非空
  26. }
  27. }
  28. // 获取链表长度
  29. int ListLength(LinkList L)
  30. {
  31. int length = 0;
  32. LNode *p;
  33. p = L->next;
  34. while (p != L)
  35. { //当p不是头结点时,链表长度加1
  36. p = p->next;
  37. length++;
  38. }
  39. return length;
  40. }
  41. // 遍历链表
  42. void TraveList(LinkList L)
  43. {
  44. LNode *p;
  45. p = L->next;
  46. printf("遍历链表:\n");
  47. while (p != L)
  48. { //当p不是头结点时,输出元素值
  49. printf("%d ", p->data);
  50. p = p->next;
  51. }
  52. printf("\n");
  53. }
  54. // 头插法创建单循环链表
  55. void CreateList1(LinkList &L, int n)
  56. {
  57. //创建长度为n的单循环链表
  58. L = new LNode;
  59. L->next = L;
  60. printf("请输入链表元素值:\n");
  61. for (int i = n; i > 0; --i)
  62. {
  63. printf("请输入第%d个元素的值:", i);
  64. struct LNode *p;
  65. p = new LNode;//生成新结点
  66. scanf("%d", &p->data);
  67. p->next = L->next;;
  68. L->next = p;
  69. }
  70. }
  71. // 尾插法创建单循环链表
  72. void CreateList2(LinkList &L, int n)
  73. {
  74. L = new LNode;
  75. L->next = L;
  76. struct LNode *r;
  77. r = L;
  78. printf("请输入链表元素值:\n");
  79. for (int i = 0; i < n; i++)
  80. {
  81. printf("请输入第%d个元素的值:", i + 1);
  82. LNode *p;
  83. p = new LNode;
  84. scanf("%d", &p->data);
  85. p->next = L;
  86. r->next = p;
  87. r = p;
  88. }
  89. }
  90. //单循环链表的插入操作
  91. int ListInsert(LinkList &L, int location, int &e)
  92. {
  93. //在L的location位置插入元素e
  94. LNode *p;
  95. p = L;
  96. int j = 0;
  97. while (p->next != L && j < location - 1)
  98. {
  99. //注意:由于p初始时指向头结点,所以训话的条件是 p->next!=L
  100. //而不是 p!=L
  101. p = p->next;
  102. j++;
  103. }
  104. if (p == L || j > location - 1)
  105. {
  106. return 0;
  107. }
  108. LNode *s;
  109. s = new LNode;
  110. s->data = e;
  111. s->next = p->next;
  112. p->next = s;
  113. return 1;
  114. }
  115. //单循环链表的删除操作
  116. int ListDelete(LinkList &L, int location, int &e)
  117. {
  118. //删除L中location位置的元素,并用e返回其值
  119. LNode *p;
  120. p = L;
  121. int j = 0;
  122. while (p->next != L && j < location - 1)
  123. {
  124. p = p->next;
  125. j++;
  126. }
  127. if (p == L || j > location - 1)
  128. {
  129. return 0;
  130. }
  131. LNode *q;
  132. //q = new LNode;
  133. q = p->next;
  134. p->next = q->next;
  135. e = q->data;
  136. delete q;
  137. return 1;
  138. }
  139. int main()
  140. {
  141. LinkList L;
  142. if (InitList(L))
  143. {
  144. printf("初始化成功!\n");
  145. }
  146. else
  147. {
  148. printf("初始化失败!\n");
  149. }
  150. if (ListEmpty(L))
  151. {
  152. printf("当前链表为空.\n");
  153. }
  154. else
  155. {
  156. printf("链表非空.\n");
  157. }
  158. printf("请输入链表长度:");
  159. int n;
  160. scanf("%d", &n);
  161. CreateList2(L, n);
  162. if (ListEmpty(L))
  163. {
  164. printf("当前链表为空.\n");
  165. }
  166. else
  167. {
  168. printf("链表非空.\n");
  169. }
  170. printf("当前链表长度是:%d\n", ListLength(L));
  171. TraveList(L);
  172. printf("请输入插入位置和值:\n");
  173. int location, e;
  174. scanf("%d,%d", &location, &e);
  175. if (ListInsert(L, location, e))
  176. {
  177. printf("插入成功\n");
  178. }
  179. else
  180. {
  181. printf("插入失败\n");
  182. }
  183. TraveList(L);
  184. printf("请输入删除元素的位置:\n");
  185. int e1, location1;
  186. scanf("%d", &location1);
  187. if (ListDelete(L, location1, e1))
  188. {
  189. printf("删除成功\n");
  190. printf("删除的元素值为:%d\n", e1);
  191. }
  192. else
  193. {
  194. printf("删除失败\n");
  195. }
  196. TraveList(L);
  197. system("pause");
  198. return 0;
  199. }
  • 运行结果

 

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

闽ICP备14008679号