链表-删除倒数第k个节点

打印 上一主题 下一主题

主题 992|帖子 992|积分 2976

链表功能的实现-删除倒数第k个节点


(1)基本设计头脑:
使用双指针法。初始化两个指针p和q,均指向头结点的下一个结点。首先让q指针先移动k-1次,若在此过程中q变为空,则说明链表长度不足k,返回0。否则,同时移动p和q,直到q为空。此时p指向的结点即为倒数第k个结点。
(2)详细实现步骤

  • 初始化first和second指向第一个数据结点。
  • 移动first指针k-1次,若中途first为空则返回0。
  • 同时移动first和second直到first下一个节点为空,此时p指向目标结点。
  • 输出结点数据并返回1。
(3)算法实现
  1. /*****************************************************
  2. *   file name:sequencelist.c
  3. *   author   :zzlyx1239@126.com
  4. *   date     :2025.3.10
  5. *   brief    :单链表顺序存储
  6. *   note     :none
  7. *
  8. *   Copyright (c) 2025 zzlyx1239@126.com All Right Reserved
  9. *
  10. *******************************************************/
  11. #include <stdio.h>
  12. #include <stdbool.h>
  13. #include <stdlib.h>
  14. //将int类型重命名为DataType
  15. typedef int DataType_t;
  16. //定义一个链式存储的顺序表,声明顺序表中的数据类型、指针
  17. typedef struct LinkList
  18. {
  19.     DataType_t      data;//定义链式存储中的数据部分
  20.     struct LinkList *next;//定义指向后继元素的指针
  21. }LList_t;
  22. //创建一个链表,并初始化
  23. LList_t *LinkList_Creat(void)
  24. {
  25.     //1.为头节点申请堆内存空间
  26.     LList_t *Head=(LList_t *)calloc(1,sizeof(LList_t));
  27.     if(Head==NULL)
  28.     {
  29.         perror("calloc for Head is Failed!!!");
  30.         exit(-1);//异常退出
  31.     }
  32.    
  33.     //2.申请成功,进行初始化
  34.     Head->next=NULL;
  35.     return Head;
  36. }
  37. //创建新节点并初始化
  38. LList_t *LList_NewNode(DataType_t data)
  39. {
  40.     //为新节点申请内存空间
  41.     LList_t *New=(LList_t*)calloc(1,sizeof(LList_t));
  42.     if(New==NULL)
  43.     {
  44.         perror("calloc for newnode memory is failed!!!");
  45.         return NULL;
  46.     }
  47.     //对新节点进行初始化
  48.     New->data=data;
  49.     New->next=NULL;
  50.     return New;
  51. }
  52. //向链表中插入新的元素,头插法
  53. bool LList_HeadAdd(LList_t *Head,DataType_t e)
  54. {
  55.     //调用创建新节点的函数来创建新节点
  56.     LList_t *New=LList_NewNode(e);
  57.     if(NULL==New)
  58.     {
  59.         perror("cannot add new node!!!");
  60.         return false;
  61.     }
  62.     //如果头节点后面没有节点
  63.     if(Head->next==NULL)
  64.     {
  65.         Head->next=New;
  66.         return true;
  67.     }
  68.     New->next=Head->next;
  69.     Head->next=New;
  70.     return true;
  71. }
  72. //尾插法
  73. bool LList_TailInsert(LList_t *Head,DataType_t e)
  74. {
  75.     //调用创建新节点的函数来创建新节点
  76.     LList_t* New=LList_NewNode(e);
  77.     if(NULL==New)
  78.     {
  79.         perror("cannot add new node!!!");
  80.         return false;
  81.     }
  82.     //如果头节点后面没有节点,直接插入即可
  83.     if(Head->next==NULL)
  84.     {
  85.         Head->next=New;
  86.         return true;
  87.     }
  88.     //遍历到最后一个节点
  89.     LList_t *Phead = Head;
  90.     while(Phead->next)
  91.     {
  92.         Phead=Phead->next;
  93.     }
  94.     Phead->next=New;
  95.     return true;
  96. }
  97. //头删
  98. bool LList_HeadDel(LList_t *Head)
  99. {
  100.     //备份首节点
  101.     LList_t* Phead=Head->next;
  102.     //判断链表是否为空,如果为空则删除失败
  103.     if(Head->next==NULL)
  104.     {
  105.         printf("Linklist is Empty!!!");
  106.         return false;
  107.     }
  108.     //链表非空,删除首届点
  109.     Head->next=Phead->next;
  110.     Phead->next=NULL;
  111.     //释放首节点
  112.     free(Phead);
  113.     return true;
  114. }
  115. //设计一个算法,删除单链表中最小值节点
  116. bool LList_DelMin(LList_t *Head)
  117. {
  118.     LList_t *Min_Prev;
  119.     LList_t *Min=Head->next;//假设最小值节点为首节点
  120.     LList_t *Phead=Head->next;//记录首节点地址
  121.     //遍历链表找到最小值节点
  122.     while(Phead->next)
  123.     {
  124.         if(Min->data>Phead->next->data)
  125.         {
  126.             Min_Prev=Phead;//将最小节点前驱给Min_Prev
  127.             Min=Phead->next;//将最小节点给Min
  128.         }
  129.         Phead=Phead->next;
  130.     }
  131.     //删除最小值节点
  132.     Min_Prev->next=Phead->next;
  133.     Min->next=NULL;
  134.     free(Min);
  135.     return true;
  136. }
  137. //删除链表中倒数第k个节点,成功返回1并输出节点data值,失败返回0
  138. DataType_t LList_DelKNode(LList_t *Head,unsigned int k)
  139. {
  140.     //1.定义两个节点记录指针移动
  141.     LList_t *LList_First=Head->next;//first节点:首节点
  142.     LList_t *LList_Second=Head->next;//second节点:首节点
  143.     LList_t *Second_prev=Head;//记录second节点的前驱节点
  144.     //2.检查列表是否为空
  145.     if(Head->next==NULL)
  146.     {
  147.         printf("LinkList is empty!!!");
  148.         return 0;
  149.     }
  150.     //3.先让first节点向后移动k-1,并且first节点不能是NULL
  151.     for(int i=1;i<=k-1;i++)
  152.     {
  153.         LList_First=LList_First->next;
  154.         if(LList_First==NULL)
  155.         {
  156.             return false;
  157.         }
  158.     }
  159.     //3.让Second节点与First节点一起移动,直到First—>next=NULL
  160.     while(LList_First->next)
  161.     {
  162.         LList_First=LList_First->next;
  163.         LList_Second=LList_Second->next;
  164.         Second_prev=Second_prev->next;
  165.     }
  166.     //此时Second节点即是倒数第k个节点,删除Second节点
  167.     printf("倒数第%d个节点的值为:%d\n",k,LList_Second->data);
  168.     Second_prev->next=LList_Second->next;
  169.     LList_Second->next==NULL;
  170.     free(LList_Second);//释放删除节点的空间
  171.     return 0;
  172. }
  173. //遍历
  174. void LList_Print(LList_t *Head)
  175. {
  176.         //对链表的头文件的地址进行备份
  177.         LList_t *Phead = Head;
  178.        
  179.         //首结点
  180.         while(Phead->next)
  181.         {
  182.                 //把头的直接后继作为新的头结点
  183.                 Phead = Phead->next;
  184.                 //输出头结点的直接后继的数据域
  185.                 printf("data = %d\n",Phead->data);
  186.         }
  187. }
  188. int main()
  189. {
  190.     //创建链表
  191.     LList_t *Head=LinkList_Creat();
  192.     //向链表中插入新节点
  193.     LList_HeadAdd(Head,1);
  194.     LList_HeadAdd(Head,2);
  195.     LList_HeadAdd(Head,5);
  196.     LList_HeadAdd(Head,6);
  197.     LList_HeadAdd(Head,8);
  198.     LList_HeadAdd(Head,4);
  199.     LList_HeadAdd(Head,16);
  200.     LList_HeadAdd(Head,39);
  201.     LList_HeadAdd(Head,46);
  202.     //遍历输出
  203.     LList_Print(Head);
  204.     printf("\n");
  205.     //删除 头删
  206.     LList_HeadDel(Head);
  207.     LList_Print(Head);
  208.     printf("\n");
  209.     //删除最小值节点
  210.     LList_DelMin(Head);
  211.     LList_Print(Head);
  212.     printf("\n");
  213.     //删除倒数第k个节点
  214.     LList_DelKNode(Head,3);
  215.     LList_Print(Head);
  216.     return 0;
  217. }
复制代码
运行结果



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

杀鸡焉用牛刀

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