当前位置:   article > 正文

“波吉向你发出学习邀请”,数据结构之单双向链表_建立一个非递减有序单链表(不少于5个元素结点),输出该链表中重复的元素以及重复次

建立一个非递减有序单链表(不少于5个元素结点),输出该链表中重复的元素以及重复次

目录

嗨,这里是狐狸​

单链表​

单向链表的节点

 单向链表实验

实验内容:

实验说明 :

源代码 

运行截图:

双向链表​

双向链表的创建

双向链表实验

实验内容:

实验说明:

源代码

 总结​


青春的列车上,如果你要提前下车,请别推醒装睡的我

嗨,这里是狐狸

今天是周末,昨日一夜未眠,不知怎的失眠了,没事就爬起来谢谢博客吧,最近中年的焦虑慢慢蔓延上心头,浑身不舒服,或许坐在电脑屏幕前才能得到一丝宁静吧。今天来给大家分享的是数据结构的知识——单链表以及双向链表。

单链表

         单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) +指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

单向链表的节点

       如下代码所示,双向链表的节点包含两个指向关系和一个数据空间,两个指向分别连接该节点的上一个和下一个节点,数据类型可以是一个结构体类型,也可以是其他类型。

  1. typedef struct node
  2. {
  3. int data;
  4. struct node *pre;
  5. struct node *next;
  6. }Node;

 单向链表实验

实验内容:

1.随机产生或键盘输入一组元素(不少于10个元素),建立一个带头结点的单链表。
2.把单链表中的元素逆置(不允许申请新的结点空间)。
3.删除单链表中所有的偶数元素结点。
4.编写在非递减有序链表中插入一个元素使链表元素仍有序的函数,利用该函数建立一个
       非递减有序单链表。
5.利用算法4建立两个非递减有序单链表,然后合并成一个非递增链表。
6.把算法1建立的链表分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量
       利用已有存储空间)。
7.在主函数中设计一个简单菜单,调用上述算法。

实验说明 :

1.结点类型定义

  1. typedef int ElemType; // 元素类型
  2. typedef struct LNode
  3. {
  4. ElemType data ;
  5. struct LNode * next ;
  6. } LNode, *pLinkList ;

2.为了简单,采用带头结点的单链表。

源代码 

  1. #include <iostream>
  2. #include <time.h>
  3. #include <iomanip>
  4. #include <stdlib.h>
  5. using namespace std;
  6. typedef int ElemType;
  7. typedef struct LNode
  8. {
  9. ElemType data;
  10. struct LNode* next;
  11. }LNode, *pLinkList;
  12. pLinkList LinkList_Init() //单链表创建
  13. {
  14. int n;
  15. LNode *phead, *temp, *p;
  16. phead = new LNode;
  17. if (phead == NULL)
  18. {
  19. cout << "链表创建失败!" << endl;
  20. exit(0);
  21. }
  22. cout << "输入需要随机产生的元素的个数(不少于10个):";
  23. cin >> n;
  24. temp = phead;
  25. srand(unsigned(time(NULL)));
  26. for (int i = 0; i < n; i++)
  27. {
  28. p = new LNode;
  29. p->data = rand() % 100;
  30. temp->next = p;
  31. temp = p;
  32. }
  33. temp->next = NULL;
  34. return phead;
  35. }
  36. void LinkList_Display(pLinkList phead) //输出链表
  37. {
  38. phead = phead->next;
  39. while (phead)
  40. {
  41. cout << setw(4) << phead->data;
  42. phead = phead->next;
  43. }
  44. cout << endl;
  45. }
  46. void LinkList_Free(pLinkList phead) //链表释放
  47. {
  48. LNode *p;
  49. while (phead)
  50. {
  51. p = phead;
  52. phead = phead->next;
  53. delete p;
  54. }
  55. }
  56. void LinkList_Convert(pLinkList phead) //单链表中的元素逆置
  57. {
  58. LNode *p1, *p2, *p3; //p3为第一个结点,p2为第二个结点,p1为第三个结点
  59. if (phead->next == NULL)
  60. {
  61. cout << "链表为空!" << endl;
  62. return;
  63. }
  64. p3 = phead->next;
  65. p2 = p3->next;
  66. if (p2 == NULL)
  67. {
  68. return;
  69. }
  70. p1 = p2->next;
  71. p3->next = NULL;
  72. while (p1)
  73. {
  74. p2->next = p3;
  75. p3 = p2;
  76. p2 = p1;
  77. p1 = p1->next;
  78. }
  79. p2->next = p3;
  80. phead->next = p2;
  81. }
  82. void LinkLIst_Del_oushu(pLinkList phead) //删除单链表中所有的偶数元素结点
  83. {
  84. LNode *p1, *p2;
  85. p2 = phead;
  86. phead = phead->next;
  87. while (phead)
  88. {
  89. if (phead->data % 2 == 0)
  90. {
  91. p1 = phead;
  92. phead = phead->next;
  93. delete p1;
  94. p2->next = phead;
  95. continue;
  96. }
  97. p2 = phead;
  98. phead = phead->next;
  99. }
  100. }
  101. void LinkList_Sort(pLinkList phead) //排序
  102. {
  103. ElemType *num, temp;
  104. LNode *p;
  105. int count = 0, i = 0;
  106. if (phead->next == NULL)
  107. {
  108. cout << "链表为空!" << endl;
  109. return;
  110. }
  111. p = phead->next;
  112. while (p)
  113. {
  114. count++;
  115. p = p->next;
  116. }
  117. num = new ElemType[count];
  118. p = phead->next;
  119. while (p)
  120. {
  121. num[i++] = p->data;
  122. p = p->next;
  123. }
  124. for (int j = 0; j < count - 1; j++)
  125. for (int k = 0; k < count - j - 1; k++)
  126. if (num[k] > num[k + 1])
  127. {
  128. temp = num[k];
  129. num[k] = num[k + 1];
  130. num[k + 1] = temp;
  131. }
  132. p = phead->next;
  133. i = 0;
  134. while (p)
  135. {
  136. p->data = num[i++];
  137. p = p->next;
  138. }
  139. delete[] num;
  140. }
  141. void LinkList_Insert(pLinkList phead, ElemType elem) //插入一个元素
  142. {
  143. LNode *p1, *p2, *tmp = NULL;
  144. p1 = phead->next;
  145. p2 = phead;
  146. while (p1)
  147. {
  148. if (elem < p1->data)
  149. break;
  150. p2 = p1;
  151. p1 = p1->next;
  152. }
  153. tmp = new LNode;
  154. tmp->data = elem;
  155. p2->next = tmp;
  156. tmp->next = p1;
  157. }
  158. void LinkList_Divide(pLinkList L1, pLinkList L2) //链表分解成奇数和偶数两个链表
  159. {
  160. LNode *p1, *p2;
  161. p2 = L1;
  162. p1 = L1->next;
  163. while (p1)
  164. {
  165. if ((p1->data) % 2 == 0)
  166. {
  167. L2->next = p1;
  168. L2 = p1;
  169. p1 = p1->next;
  170. p2->next = p1;
  171. }
  172. else
  173. {
  174. p2 = p1; p1 = p1->next;
  175. }
  176. }
  177. L2->next = NULL;
  178. }
  179. void LinkList_Cat(pLinkList L1, pLinkList L2) //链表合并,
  180. {
  181. pLinkList p1, p2;
  182. p2 = L1;
  183. p1 = L1->next;
  184. while (p1)
  185. {
  186. p2 = p1; p1 = p1->next;
  187. }
  188. p2->next = L2->next;
  189. LinkList_Sort(L1);
  190. LinkList_Convert(L1);
  191. }
  192. int main()
  193. {
  194. LNode *L = NULL, *L1 = NULL, *L2 = NULL;
  195. int num;
  196. cout << "1:随机产生或键盘输入一组元素(不少于10个元素),建立一个带头结点的单链表" << endl;
  197. cout << "2:单链表中的元素逆置" << endl;
  198. cout << "3:单链表排序输出" << endl;
  199. cout << "4:删除单链表中所有的偶数元素结点" << endl;
  200. cout << "5:插入一个元素,用该函数建立一个非递减有序单链表(插入)" << endl;
  201. cout << "6:建立两个非递减有序单链表,然后合并成一个非递增链表(合并)" << endl;
  202. cout << "7:链表分解成两个链表,其中一个全部为奇数,另一个全部为偶数" << endl;
  203. cout << "8:退出" << endl;
  204. cout << endl;
  205. while (true)
  206. {
  207. cout << "请输入一个数字选项:";
  208. cin >> num;
  209. switch (num)
  210. {
  211. case 1:
  212. { L = LinkList_Init();
  213. cout << "L链表为:";
  214. LinkList_Display(L);
  215. cout << endl;
  216. }break;
  217. case 2:
  218. { LinkList_Convert(L);
  219. cout << "链表为:";
  220. LinkList_Display(L);
  221. cout << endl;
  222. }break;
  223. case 3:
  224. { LinkList_Sort(L);
  225. cout << "链表为:";
  226. LinkList_Display(L);
  227. cout << endl;
  228. }break;
  229. case 4:
  230. { LinkLIst_Del_oushu(L);
  231. cout << "链表为:";
  232. LinkList_Display(L);
  233. cout << endl;
  234. }break;
  235. case 5:
  236. { ElemType elem;
  237. cout << "输入要插入的元素:";
  238. cin >> elem;
  239. LinkList_Sort(L);
  240. LinkList_Insert(L, elem);
  241. cout << "链表为:";
  242. LinkList_Display(L);
  243. cout << endl;
  244. }break;
  245. case 6:
  246. {
  247. L1 = LinkList_Init();
  248. cout << "L1链表为:";
  249. LinkList_Display(L1);
  250. L2 = LinkList_Init();
  251. cout << "L2链表为:";
  252. LinkList_Display(L2);
  253. LinkList_Cat(L1, L2);
  254. cout << "合并的链表为:";
  255. LinkList_Display(L1);
  256. cout << endl;
  257. }break;
  258. case 7:
  259. {
  260. L2 = new LNode;
  261. LinkList_Divide(L1, L2);
  262. cout << "L1链表为:";
  263. LinkList_Display(L1);
  264. cout << "L2链表为:";
  265. LinkList_Display(L2);
  266. LinkList_Free(L2);
  267. cout << endl;
  268. }break;
  269. case 8:
  270. {
  271. LinkList_Free(L);
  272. delete L1;
  273. cout << endl;
  274. cout << "链表已释放并删除"<<endl;
  275. cout << endl;
  276. }break;
  277. default:
  278. cout << "输入错误!请重新输入!" << endl;
  279. cout << endl;
  280. }
  281. }
  282. return 0;
  283. }

运行截图:

双向链表

         双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

双向链表的创建

        头插法和尾插法只看代码比较难以与理解,建议画出插入节点时的链表变化图则会非常容易理解,另外,个人认为头插法较优,因为其插入逻辑一步到位,不像尾插法还需在后面完成双向链表的环状连接。

1.头插法

  1. Node * creatList()
  2. {
  3. Node * head = (Node*)malloc(sizeof(Node));
  4. Node * cur = NULL;
  5. head->next = head;
  6. head->pre = head;
  7. int data;
  8. scanf("%d",&data);
  9. while(data)
  10. {
  11. cur = (Node*)malloc(sizeof(Node));
  12. cur->data = data;
  13. cur->next = head->next;
  14. cur->pre = head;
  15. head->next = cur;
  16. cur->next->pre = cur;
  17. scanf("%d",&data);
  18. }
  19. return head;
  20. }

2.尾插法

  1. Node * creatList()
  2. {
  3. Node * head = (Node*)malloc(sizeof(Node));
  4. Node * phead = head;
  5. Node * cur = NULL;
  6. phead->next = NULL;
  7. phead->pre = NULL;
  8. int data;
  9. scanf("%d",&data);
  10. while(data)
  11. {
  12. cur = (Node*)malloc(sizeof(Node));
  13. cur->data = data;
  14. phead->next = cur;
  15. cur->pre = phead;
  16. phead = cur;
  17. scanf("%d",&data);
  18. }
  19. //完成回环
  20. cur->next = head;
  21. head->pre = cur;
  22. return head;
  23. }

双向链表实验

实验内容:

1.利用尾插法建立一个双向链表。
2.遍历双向链表。
3.实现双向链表中删除一个指定元素。
4.在非递减有序双向链表中实现插入元素e仍有序的算法。
5.判断双向链表中元素是否对称,若对称返回 1,否则返回 0。
6.设元素为正整型,实现算法把所有奇数排列在偶数之前。
7.在主函数中设计一个简单菜单,调用上述算法。

实验说明:

双向链表的类型定义

  1. typedef int ElemType; // 元素类型
  2. typedef struct DuLNode
  3. {
  4. ElemType data;
  5. DuLNode *prior, *next;
  6. } DuLNode, *pDuLinkList;

源代码

  1. #include <iostream>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #include <iomanip>
  5. using namespace std;
  6. typedef int ElemType;
  7. typedef struct DuLNode
  8. {
  9. ElemType data;
  10. struct DuLNode *prior, *next;
  11. } DuLNode, *pDuLinkList;
  12. pDuLinkList DuLinkLinst_Init() //建立双向链表
  13. {
  14. int n;
  15. DuLNode *phead, *tmp, *p;
  16. srand(unsigned(time(NULL)));
  17. cout << "输入建立链表的元素个数:";
  18. cin >> n;
  19. phead = new DuLNode;
  20. phead->next = phead;
  21. phead->prior = phead;
  22. p = phead;
  23. for (int i = 0; i < n; i++)
  24. {
  25. tmp = new DuLNode;
  26. tmp->data = rand() % 100;
  27. tmp->prior = p;
  28. p->next = tmp;
  29. p = tmp;
  30. }
  31. p->next = phead;
  32. phead->prior = p;
  33. return phead;
  34. }
  35. void DuLinkList_Display(pDuLinkList phead) //输出双向链表
  36. {
  37. DuLNode *p;
  38. p = phead->next;
  39. while (p != phead)
  40. {
  41. cout << setw(4) << p->data;
  42. p = p->next;
  43. }
  44. cout << endl;
  45. }
  46. void DuLinkList_Free(pDuLinkList phead) //释放双链表
  47. {
  48. DuLNode *p, *t;
  49. p = phead->next;
  50. while (p != phead)
  51. {
  52. t = p;
  53. p = p->next;
  54. delete t;
  55. }
  56. delete p;
  57. }
  58. void DuLinkList_Del(pDuLinkList phead, ElemType x) //删除指定元素
  59. {
  60. DuLNode *p1, *p2;
  61. p1 = phead->next;
  62. p2 = phead;
  63. while (p1)
  64. {
  65. if (x == p1->data)
  66. {
  67. p2->next = p1->next;
  68. p1->next->prior = p2;
  69. delete p1;
  70. return;
  71. }
  72. p2 = p1;
  73. p1 = p1->next;
  74. }
  75. cout << "指定元素未找到!" << endl;
  76. }
  77. void DuLinkList_Sort(pDuLinkList phead) //排序
  78. {
  79. DuLNode *p;
  80. int count = 0, i = 0;
  81. ElemType *num, tmp;
  82. p = phead->next;
  83. if (p == phead)
  84. {
  85. cout << "双向链表为空!" << endl;
  86. return;
  87. }
  88. while (p != phead)
  89. {
  90. count++;
  91. p = p->next;
  92. }
  93. num = new ElemType[count];
  94. p = phead->next;
  95. while (p != phead)
  96. {
  97. num[i++] = p->data;
  98. p = p->next;
  99. }
  100. for (int k = 0; k < count - 1; k++)
  101. for (int j = 0; j < count - k - 1; j++)
  102. if (num[j] > num[j + 1])
  103. {
  104. tmp = num[j];
  105. num[j] = num[j + 1];
  106. num[j + 1] = tmp;
  107. }
  108. p = phead->next;
  109. i = 0;
  110. while (p != phead)
  111. {
  112. p->data = num[i++];
  113. p = p->next;
  114. }
  115. delete[] num;
  116. }
  117. void DuLinkList_Insert(pDuLinkList phead, ElemType elem) //插入一个元素
  118. {
  119. DuLNode *p, *tmp;
  120. p = phead->next;
  121. while (p != phead)
  122. {
  123. if (elem <= p->data)
  124. break;
  125. p = p->next;
  126. }
  127. tmp = new DuLNode;
  128. tmp->data = elem;
  129. tmp->next = p;
  130. tmp->prior = p->prior;
  131. p->prior->next = tmp;
  132. p->prior = tmp;
  133. }
  134. int DuLinkList_symmetry(pDuLinkList phead) //链表中元素是否对称
  135. {
  136. DuLNode *p1, *p2;
  137. p1 = phead->prior;
  138. p2 = phead->next;
  139. while (p1 != p2)
  140. {
  141. if (p1->data != p2->data)
  142. {
  143. return 0;
  144. }
  145. p1 = p1->prior;
  146. p2 = p2->next;
  147. }
  148. return 1;
  149. }
  150. void DuLinkList_jiousort(pDuLinkList phead) //奇数在偶数前面
  151. {
  152. DuLNode *p1, *p2;
  153. p1 = phead->next;
  154. p2 = p1->next;
  155. if (p1 == phead)
  156. {
  157. cout << "双向链表为空!" << endl;
  158. return;
  159. }
  160. if (p2 == phead)
  161. {
  162. return;
  163. }
  164. while (p1 != phead)
  165. {
  166. if ((p1->data) % 2 != 0)
  167. {
  168. p2 = p1;
  169. p1 = p1->next;
  170. p1->prior = p2->prior;
  171. p2->prior->next = p1;
  172. p2->next = phead->next;
  173. phead->next->prior = p2;
  174. phead->next = p2;
  175. p2->prior = phead;
  176. }
  177. else
  178. p1 = p1->next;
  179. }
  180. }
  181. int main()
  182. {
  183. DuLNode *L = NULL;
  184. ElemType t;
  185. int num;
  186. cout << "1:利用尾插法建立一个双向链表" << endl;
  187. cout << "2:遍历双向链表" << endl;
  188. cout << "3:双向链表中删除一个指定元素" << endl;
  189. cout << "4:在非递减有序双向链表中实现插入元素e仍有序的算法。" << endl;
  190. cout << "5:判断双向链表中元素是否对称,若对称返回 1,否则返回 0" << endl;
  191. cout << "6:设元素为正整型,实现算法把所有奇数排列在偶数之前" << endl;
  192. cout << "7:退出" << endl;
  193. while (true)
  194. {
  195. cout << "请输入一个数字选项:";
  196. cin >> num;
  197. switch (num)
  198. {
  199. case 1:
  200. {
  201. L = DuLinkLinst_Init();
  202. cout << "L双向链表为:";
  203. DuLinkList_Display(L);
  204. cout << endl;
  205. }break;
  206. case 2:
  207. {
  208. cout << "双向链表为:";
  209. DuLinkList_Display(L);
  210. cout << endl;
  211. }break;
  212. case 3:
  213. {
  214. cout << "输入需要删除的元素:";
  215. cin >> t;
  216. DuLinkList_Del(L, t);
  217. cout << "双向链表为:";
  218. DuLinkList_Display(L);
  219. cout << endl;
  220. }break;
  221. case 4:
  222. {
  223. cout << "输入要插入的元素:";
  224. cin >> t;
  225. DuLinkList_Sort(L);
  226. DuLinkList_Insert(L, t);
  227. cout << "双向链表为:";
  228. DuLinkList_Display(L);
  229. cout << endl;
  230. }break;
  231. case 5:
  232. {
  233. if(DuLinkList_symmetry(L)==1)
  234. cout << "双向链表中元素对称" << endl;
  235. else
  236. cout << "双向链表中元素不对称" << endl;
  237. cout << endl;
  238. }break;
  239. case 6:
  240. {
  241. DuLinkList_jiousort(L);
  242. cout << "双向链表为:";
  243. DuLinkList_Display(L);
  244. cout << endl;
  245. }break;
  246. case 7:
  247. {
  248. DuLinkList_Free(L);
  249. cout << endl;
  250. return 0;
  251. }break;
  252. default:
  253. cout << "输入错误!请重新输入!" << endl;
  254. cout << endl;
  255. }
  256. }
  257. return 0;
  258. }

运行截图: 

 

 总结

         如果把编程语言比作一个句子,那数据结构就好比是一篇文章。写好句子要意思清晰明确,写文章的话,更看重的是其传达的思想。马克吐温有句话是这样说的,当你手拿着锤子的时候,看见很多东西都是钉子。这句话原来的意思我不大想深究,毕竟这不是技术问题。而在读过了著名黑客雷蒙德的一篇经典文章《何成 为一名黑客》,我对这个说法有一个新的感悟。他在文中写道:“做一名黑客会有很多乐趣,但却  是要费很多气力方能得到的乐趣。 这些努力需要动力。成功的运动员从锻炼身体、超越自我极限的愉悦中得到动力。 同样,做黑客,你得能从解决问题,磨练技术及锻炼智力中得到基本的乐趣。”锤子是工具,钉子是问题,当工具被用来解决你的问题的时候,享受那种满足的感觉,   是很难用言语来形容的。学习 C 语言不是光为了学习 C 语言,你是要用它来解决问题的。很遗憾在现实中,很多同学在大一大二学完了C 语言这门课程,甚至也考了一个不错的分数之后, 就把这门工具丢到一旁了,再也没理了。他们没有享受到这种乐趣,这是很可惜的。你是一个手拿锤子的人吗?握紧!

        好叭。今天就到这里了,我也该去睡觉了,后续我还会发布更多的项目源或者学习资料,希望大家可以持续关注,有什么问题可以回帖留言。想要提前掌握的可以加群领取C/C++学习资料以及其他项目的源码的可以加群【1083227756】了解。想要对程序员的未来发展有兴趣的可以关注微信公众号:【狐狸的编码时光】,希望和大家一起学习进步!

念七可爱卡通情侣头像 可做表情包的卡通情侣头像

 

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

闽ICP备14008679号