双向循环链表 初始化 插入 删除

╰+攻爆jí腚メ 2021-12-19 15:27 342阅读 0赞
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define OK 1
  4. #define ERROR -1
  5. #define TRUE 1
  6. #define FALSE -1
  7. #define NULL 0
  8. #define OVERFLOW -2
  9. #define ElemType int
  10. #define Status int
  11. typedef int ElemType
  12. typedef int Status
  13. #define LEN sizeof(DuLNode)
  14. #define MLC (LinkList)malloc(sizeof(DuLNode))
  15. /*
  16. //线性表的基本操作列表
  17. InitList(&L) //初始化线性表L
  18. DestroyList(&L) //销毁线性表L
  19. ClearList(&L) //清空线性表L
  20. ListEmpty(L) //判断线性表是否为空
  21. ListLength(L) //求线性表L的长度
  22. GetElem(L,i,&e) //取线性表L的第i个元素
  23. LocateElem(L,e,compare()) //定位检索线性表L中元素e
  24. compare() //比较两个元素的大小,返回Bool
  25. compareArray() //比较两个数组的大小,返回Bool
  26. PriorElem(L,cur_e,&prio_e) //返回线性表L中元素e的直接前驱元素
  27. NextElem(L,cur_e,&next_e) //返回线性表L中元素e的直接后继元素
  28. ListInsert(&L,i,e) //在线性表L的第i个元素之前插入元素e,返回Bool
  29. ListDelete(&L,i,e) //删除线性表L的第i个元素,被删除元素e的值,返回Bool
  30. ListTraverse(L,visit()) //遍历线性表:依次对L的每个元素调用visit()
  31. visit() // visit 一般是指树型链表结构中对某个节点内容进行访问的函数,
  32. // 就是取出节点内容去做某一件事,通常算法中不写出具体函数内容。
  33. // 树型链表结构中自顶开始按照某种顺序顺藤摸瓜至某个节点的过程称为“遍历”
  34. */
  35. //-------双向循环链表--------------
  36. //双向循环链表 初始化 插入 删除
  37. typedef struct DuLNode { //封装 双向链表
  38. ElemType data;
  39. struct DuLNode *prior;//前驱
  40. struct DuLNode *next;//后继
  41. }DuLNode, *DuLinkList;
  42. //初始化 双向循环链表 函数自己产生指针 产生一个头结点
  43. DuLinkList DuLinkListInit_Out_Ptr() {
  44. DuLinkList L = (LinkList)malloc(LEN);
  45. if (L == NULL) //判断是否有足够的内存空间
  46. exit(OVERFLOW);
  47. L->next = L; //next指向自己
  48. L->prior = L; //prior指向自己
  49. return L;
  50. }
  51. Status ListInsert_Dul_Tail_Tan(DuLinkList &L, int i, ElemType e) {
  52. //在带头结点的的双向循环链表中的第i个位置插入元素e
  53. //寻找第i-1个元素p后插法
  54. int j = 0; //计数器
  55. DuLinkList p = L; //p作为工作目标指针
  56. DuLinkList s;//新结点
  57. while (j<i - 1 && p) { //寻找第i-1个元素,插入第i-1个元素后面
  58. p = p->next; //移动指针
  59. j++; //计数器+1
  60. }
  61. if (!p) { //表的长度小于i,空表
  62. return FALSE;
  63. }
  64. s = (DuLinkList)malloc(sizeof(ElemType));//开辟内存
  65. if (!s) { //空间不够,溢出
  66. exit(OVERFLOW);
  67. }
  68. s->data = e;//数据域赋值
  69. //第i-1个元素, p后插入,
  70. s->next = p->next;
  71. s->prior = p;
  72. (p->next)->prior = s;
  73. p->next = s;
  74. }
  75. Status ListInsert_Dul_Head_Tan(DuLinkList &L, int i, ElemType e) {
  76. //在带头结点的的双向循环链表中的第i个位置 插入元素e
  77. //寻找第i个元素p前插法
  78. int j = 0; //计数器
  79. DuLinkList p = L; //p作为工作目标指针
  80. DuLinkList s;//新结点
  81. while (j <= i - 1 && p) { //寻找第i个元素,插入第i个元素前面
  82. p = p->next; //移动指针
  83. j++;//计数器+1
  84. }
  85. if (!p) {
  86. return FALSE;//表的长度小于i
  87. }
  88. s = (DuLinkList)malloc(sizeof(ElemType));
  89. if (!s) {
  90. exit(OVERFLOW);//空间不够,溢出
  91. }
  92. s->data = e; //数据域赋值
  93. //第i个元素, p前插入,
  94. s->next = p;
  95. s->prior = p->prior;
  96. (p->prior)->next = s;
  97. p->prior = s;
  98. }
  99. Status ListDelete_Dul(DuLinkList &L,int i,ElemType e) {
  100. //在带头结点的的双向循环链表中的第i个位置 删除元素e
  101. int j = 0; //计数器
  102. DuLinkList p = L; //p作为工作目标指针
  103. DuLinkList pre;//作用结点pre
  104. DuLinkList nex;//作用结点nex
  105. DuLinkList s;//作用结点cur
  106. while (j <= i - 1 && p) { //寻找第i个元素,插入第i个元素前面
  107. p = p->next; //移动指针
  108. j++;//计数器+1
  109. }
  110. s = p;
  111. pre = p->prior;
  112. nex = p->next;
  113. e = s->data; //数据域赋值
  114. pre->next = nex->prior;
  115. nex->prior = pre->next;
  116. free(s);
  117. return TRUE;
  118. }

转载于:https://www.cnblogs.com/blacop/p/6440609.html

发表评论

表情:
评论列表 (有 0 条评论,342人围观)

还没有评论,来说两句吧...

相关阅读

    相关 循环双向

    一、循环链表 循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。

    相关 双向循环

    一、双向链表 每个结点有两个指针域和若干数据域,其中一个指针域指向它的前趋结点,一个指向它的后继结点。它的优点是访问、插入、删除更方便,速度也快了。但“是以空间换时间”。

    相关 双向循环插入排序

    前两篇博文,我讨论了链表的冒泡排序和选择排序(以Linux内核链表为例),这篇文章,我想说说插入排序。 一、复习数组的插入排序 插入排序在算法思想中属于“减治法”。