C语言单向循环链表的增删操纵

火影  金牌会员 | 2024-5-18 04:33:24 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 869|帖子 869|积分 2607

  1. /********************************************************************************************************
  2. *
  3. *
  4. * 设计双向链表的接口
  5. *
  6. *
  7. *
  8. * Copyright (c)  2023-2024   a1583839363@163.com   All right Reserved
  9. * ******************************************************************************************************/
  10. //指的是双向链表中的结点有效数据类型,用户可以根据需要进行修改
  11. typedef int DataType_t;
  12. //构造双向链表的结点,链表中所有结点的数据类型应该是相同的
  13. typedef struct DoubleLinkedList
  14. {
  15.     DataType_t               data; //结点的数据域
  16.     struct DoubleLinkedList *prev; //直接前驱的指针域
  17.     struct DoubleLinkedList *next; //直接后继的指针域
  18. }DoubleLList_t;
  19. //创建一个空双向链表,空链表应该有一个头结点,对链表进行初始化
  20. DoubleLList_t * DoubleLList_Create(void)
  21. {
  22.     //1.创建一个头结点并对头结点申请内存
  23.     DoubleLList_t *Head = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
  24.     if (NULL == Head)
  25.     {
  26.         perror("Calloc memory for Head is Failed");
  27.         exit(-1);
  28.     }
  29.     //2.对头结点进行初始化,头结点是不存储数据域,指针域指向NULL
  30.     Head->prev = NULL;
  31.     Head->next = NULL;
  32.     //3.把头结点的地址返回即可
  33.     return Head;
  34. }
  35. //创建新的结点,并对新结点进行初始化(数据域 + 指针域)
  36. DoubleLList_t * DoubleLList_NewNode(DataType_t data)
  37. {
  38.     //1.创建一个新结点并对新结点申请内存
  39.     DoubleLList_t *New = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
  40.     if (NULL == New)
  41.     {
  42.         perror("Calloc memory for NewNode is Failed");
  43.         return NULL;
  44.     }
  45.     //2.对新结点的数据域和指针域(2个)进行初始化
  46.     New->data = data;
  47.     New->prev = NULL;
  48.     New->next = NULL;
  49.     return New;
  50. }
  51. //头插
  52. bool DoubleLList_HeadInsert(DoubleLList_t *Head,DataType_t data)
  53. {
  54.     // 1.创建新的结点,并对新结点进行初始化
  55.     DoubleLList_t *New = DoubleLList_NewNode(data);
  56.     if (NULL == New)
  57.     {
  58.         printf("can not insert new node\n");
  59.         return false;
  60.     }
  61.     // 2.判断双向链表是否为空,如果为空,则直接插入即可
  62.     if (NULL == Head->next)
  63.     {
  64.         Head->next = New;
  65.         return true;
  66.     }
  67.     // 3.如果双向链表为非空,把新结点插入到链表的头部\
  68.     New->next = Head->next;
  69.     Head->next->prev = New;
  70.     Head->next = New;
  71.     return true;
  72. }
  73. //尾插
  74. bool DoubleLList_TailInsert(DoubleLList_t *Head,DataType_t data)
  75. {
  76.     // 1.创建新的结点,并对新结点进行初始化
  77.     DoubleLList_t *New = DoubleLList_NewNode(data);
  78.     if (NULL == New)
  79.     {
  80.         printf("can not insert new node\n");
  81.         return false;
  82.     }
  83.     // 2.判断双向链表是否为空,如果为空,则直接插入即可
  84.     if (NULL == Head->next)
  85.     {
  86.         Head->next = New;
  87.         return true;
  88.     }
  89.     // 3.如果双向链表为非空,遍历链表,找到尾结点
  90.     DoubleLList_t *Tail = Head;
  91.     while(Tail->next != NULL)
  92.     {
  93.         Tail = Tail->next;
  94.     }
  95.     // 4.把新结点插入到链表的尾部
  96.     Tail->next = New;
  97.     New->prev = Tail;
  98.     return true;
  99. }
  100. //指定插
  101. bool DoubleLList_DestInsert(DoubleLList_t *Head,DataType_t destval,DataType_t data)
  102. {
  103.     // 1.创建新的结点,并对新结点进行初始化
  104.     DoubleLList_t *New = DoubleLList_NewNode(data);
  105.     if (NULL == New)
  106.     {
  107.         printf("can not insert new node\n");
  108.         return false;
  109.     }
  110.     // 2.判断双向链表是否为空,如果为空,则直接插入即可
  111.     if (NULL == Head->next)
  112.     {
  113.         Head->next = New;
  114.         return true;
  115.     }
  116.     // 3.如果双向链表为非空,遍历链表,找到插入位置
  117.     DoubleLList_t *Dest = Head->next;
  118.     while (Dest->data != destval && Dest != NULL)
  119.     {
  120.         Dest = Dest->next;
  121.     }
  122.     if (NULL == Dest)
  123.     {
  124.         return false;
  125.     }
  126.     // 4.说明找到目标结点,则把新结点插入到目标结点的后面
  127.     New->next = Dest->next;
  128.     Dest->next->prev = New;
  129.     New->prev = Dest;
  130.     Dest->next = New;
  131.     return true;
  132. }
  133. //头删
  134. bool DoubleLList_HeadDel(DoubleLList_t *Head)
  135. {
  136.     // 1.判断链表是否为空,如果为空,则直接退出
  137.     if (NULL == Head->next)
  138.     {
  139.         return false;
  140.     }
  141.     // 2.对链表的首结点的地址进行备份
  142.     DoubleLList_t *Temp = Head->next;
  143.     // 3.链表是非空的,则直接删除首结点
  144.     Head->next = Temp->next;
  145.     Temp->next = NULL;
  146.     Temp->next->prev = NULL;
  147.     free(Temp);
  148.     return true;
  149. }
  150. // 尾删
  151. bool DoubleLList_TailDel(DoubleLList_t *Head)
  152. {
  153.     // 1.判断链表是否为空,如果为空,则直接退出
  154.     if (NULL == Head->next)
  155.     {
  156.         return false;
  157.     }
  158.     // 2.遍历链表,找到尾结点
  159.     DoubleLList_t *Tail = Head;
  160.     while (Tail->next != NULL)
  161.     {
  162.         Tail = Tail->next;
  163.     }
  164.     // 3.删除尾结点
  165.     Tail->prev->next = NULL;
  166.     Tail->prev = NULL;
  167.     free(Tail);
  168.     return true;
  169. }
  170. // 指定删
  171. bool DoubleLList_DestDel(DoubleLList_t *Head, DataType_t destval, DataType_t data)
  172. {
  173.     // 1.判断链表是否为空,如果为空,则直接退出
  174.     if (NULL == Head->next)
  175.     {
  176.         return false;
  177.     }
  178.     // 2.链表是非空的,遍历链表,找到待删除结点
  179.     DoubleLList_t *Dest = Head;
  180.     while (Dest->data != destval && Dest != NULL)
  181.     {
  182.         Dest = Dest->next;
  183.     }
  184.     if (NULL == Dest)
  185.     {
  186.         return false;
  187.     }
  188.     // 3.删除指定结点
  189.     Dest->prev->next = Dest->next;
  190.     Dest->next->prev = Dest->prev;
  191.     Dest->prev = NULL;
  192.     Dest->next = NULL;
  193.     free(Dest);
  194.     return true;
  195. }
  196. //遍历链表
  197. bool DoubleLList_Print(DoubleLList_t *Head)
  198. {
  199.     //对双向链表的头结点的地址进行备份
  200.     DoubleLList_t *Phead = Head;
  201.     //判断当前链表是否为空,为空则直接退出
  202.     if (Head->next == Head)
  203.     {
  204.         printf("current linkeflist is empty!\n");
  205.         return false;
  206.     }
  207.     //从首结点开始遍历
  208.     while(Phead->next)
  209.     {
  210.         //把头结点的直接后继作为新的头结点
  211.         Phead = Phead->next;
  212.         //输出头结点的直接后继的数据域
  213.         printf("data = %d\n",Phead->data);
  214.         //判断是否到达尾结点,尾结点的next指针是指向首结点的地址
  215.         if (Phead->next == Head->next)
  216.         {
  217.             break;
  218.         }
  219.     }
  220.     return true;
  221. }
  222. int main(int argc, char const *argv[])
  223. {
  224.     return 0;
  225. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表