翼度科技»论坛 云主机 LINUX 查看内容

数据结构的练习day1

12

主题

12

帖子

36

积分

新手上路

Rank: 1

积分
36

链表只能一个一个的遍历,不能通过随机访问来获取节点

链表的地址是并要求连续的,是通过内部的指针来进行联系的
  1. /********************************************************************************************************
  2. *
  3. *
  4. *
  5. *
  6. *
  7. *
  8. * Copyright (c)  2023-2024   2556560122@qq.com    All right Reserved
  9. * ******************************************************************************************************/
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdbool.h>
  13. // 指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改
  14. typedef int DataType_t;
  15. // 构造链表的结点,链表中所有结点的数据类型应该是相同的
  16. typedef struct LinkedList
  17. {
  18.   DataType_t data;         // 结点的数据域
  19.   struct LinkedList *next; // 结点的指针域
  20. } LList_t;
  21. // 创建一个空链表,空链表应该有一个头结点,对链表进行初始化
  22. LList_t *LList_Create(void)
  23. {
  24.   // 1.创建一个头结点并对头结点申请内存
  25.   LList_t *Head = (LList_t *)calloc(1, sizeof(LList_t));
  26.   if (NULL == Head)
  27.   {
  28.     perror("Calloc memory for Head is Failed");
  29.     exit(-1);
  30.   }
  31.   // 2.对头结点进行初始化,头结点是不存储有效内容的!!!
  32.   Head->next = NULL;
  33.   // 3.把头结点的地址返回即可
  34.   return Head;
  35. }
  36. // 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
  37. LList_t *LList_NewNode(DataType_t data)
  38. {
  39.   // 1.创建一个新结点并对新结点申请内存
  40.   LList_t *New = (LList_t *)calloc(1, sizeof(LList_t));
  41.   if (NULL == New)
  42.   {
  43.     perror("Calloc memory for NewNode is Failed");
  44.     return NULL;
  45.   }
  46.   // 2.对新结点的数据域和指针域进行初始化
  47.   New->data = data;
  48.   New->next = NULL;
  49.   return New;
  50. }
  51. // 头插
  52. bool LList_HeadInsert(LList_t *Head, DataType_t data)
  53. {
  54.   // 1.创建新的结点,并对新结点进行初始化
  55.   LList_t *New = LList_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 = New;
  70.   return true;
  71. }
  72. // 尾插
  73. bool LList_TailInsert(LList_t *Head, DataType_t data)
  74. {
  75.   if (Head->next == NULL)
  76.   {
  77.     printf("链表尾空!\n");
  78.     return false;
  79.   }
  80.   // 新建一个指针指向Head的next
  81.   LList_t *copy_head = Head->next;
  82.   // 创建一个新的节点
  83.   LList_t *newNode = LList_NewNode(data);
  84.   while (copy_head)
  85.   {
  86.     // 到了尾节点了
  87.     if (copy_head->next == NULL)
  88.     {
  89.       // 尾插
  90.       copy_head->next = newNode;
  91.       // 退出循环
  92.       break;
  93.     }
  94.     copy_head = copy_head->next;
  95.   }
  96.   return true;
  97. }
  98. // 插到目标节点的后面
  99. bool LList_DestInsert(LList_t *Head, DataType_t dest, DataType_t data)
  100. {
  101.   if (Head->next == NULL)
  102.   {
  103.     printf("链表尾空!\n");
  104.     return false;
  105.   }
  106.   // 新建一个指针指向Head的next
  107.   LList_t *copy_head = Head->next;
  108.   // 创建一个新的节点
  109.   LList_t *newNode = LList_NewNode(data);
  110.   while (copy_head)
  111.   {
  112.     // 找到了目标节点
  113.     if (copy_head->data == dest)
  114.     {
  115.       // 指向目标节点的next
  116.       newNode->next = copy_head->next;
  117.       // 目标节点指向新节点
  118.       copy_head->next = newNode;
  119.       // 找到了,退出方法,放回true
  120.       return true;
  121.     }
  122.     // 没找到,指针指向下个节点
  123.     copy_head = copy_head->next;
  124.   }
  125.   // 没找到
  126.   return false;
  127. }
  128. // 寻找链表的最小值
  129. int Select_Min_Node(LList_t *Head)
  130. {
  131.   if (Head->next == NULL)
  132.   {
  133.     printf("链表尾空!\n");
  134.     return -1;
  135.   }
  136.   // 新建一个指针指向Head的next
  137.   LList_t *copy_head = Head->next;
  138.   // 默认最小值是copy_head的data
  139.   int min = copy_head->data;
  140.   while (copy_head->next)
  141.   {
  142.     // 如果min大于下个节点的数值,min就发生交换
  143.     if (min > copy_head->next->data)
  144.     {
  145.       min = copy_head->next->data;
  146.     }
  147.     // 进入下个节点
  148.     copy_head = copy_head->next;
  149.   }
  150.   return min;
  151. }
  152. // 删除最小数据的节点
  153. void DelectMinDataNode(LList_t *Head)
  154. {
  155.   if (Head->next == NULL)
  156.   {
  157.     printf("链表为空!\n");
  158.     return;
  159.   }
  160.   // 新建一个指针指向Head的next
  161.   LList_t *copy_head = Head;
  162.   // 获取链表中的最小数据
  163.   int delVal = Select_Min_Node(Head);
  164.   while (copy_head->next)
  165.   {
  166.     if (copy_head->next->data == delVal)
  167.     {
  168.       // 创建一个指针保存要删除的节点的next
  169.       LList_t *copy_del_next = copy_head->next->next;
  170.       // 释放空间
  171.       free(copy_head->next);
  172.       // 指向要删除的节点的next
  173.       copy_head->next = copy_del_next;
  174.       // 退出循环
  175.       break;
  176.     }
  177.     copy_head = copy_head->next;
  178.   }
  179.   return;
  180. }
  181. // 遍历
  182. void LList_Print(LList_t *Head)
  183. {
  184.   // 对链表的头文件的地址进行备份
  185.   LList_t *Phead = Head;
  186.   // 首结点
  187.   while (Phead->next)
  188.   {
  189.     // 把头的直接后继作为新的头结点
  190.     Phead = Phead->next;
  191.     // 输出头结点的直接后继的数据域
  192.     printf("data = %d\n", Phead->data);
  193.   }
  194. }
  195. int main(int argc, char const *argv[])
  196. {
  197.   // 创建链表头节点
  198.   LList_t *Head = LList_Create();
  199.   // 头插
  200.   LList_HeadInsert(Head, 0);
  201.   LList_HeadInsert(Head, 5);
  202.   LList_HeadInsert(Head, 20);
  203.   LList_HeadInsert(Head, 1);
  204.   // 尾插
  205.   LList_TailInsert(Head, 20);
  206.   // 在目标后面插
  207.   LList_DestInsert(Head, 5, 2);
  208.   // 删除链表中数据最小的节点
  209.   DelectMinDataNode(Head);
  210.   // 遍历链表
  211.   LList_Print(Head);
  212.   return 0;
  213. }
复制代码
  1. /********************************************************************************************************
  2. *
  3. *查找链表的倒数第k个节点的数据
  4. *思想: 可以根据链表的节点数-k来获取需要head的next的次数来获取节点
  5. *
  6. *
  7. *
  8. * Copyright (c)  2023-2024   2556560122@qq.com   All right Reserved
  9. * ******************************************************************************************************/
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdbool.h>
  13. // 指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改
  14. typedef int DataType_t;
  15. // 构造链表的结点,链表中所有结点的数据类型应该是相同的
  16. typedef struct LinkedList
  17. {
  18.   DataType_t data;         // 结点的数据域
  19.   struct LinkedList *next; // 结点的指针域
  20. } LList_t;
  21. // 创建一个空链表,空链表应该有一个头结点,对链表进行初始化
  22. LList_t *LList_Create(void)
  23. {
  24.   // 1.创建一个头结点并对头结点申请内存
  25.   LList_t *Head = (LList_t *)calloc(1, sizeof(LList_t));
  26.   if (NULL == Head)
  27.   {
  28.     perror("Calloc memory for Head is Failed");
  29.     exit(-1);
  30.   }
  31.   // 2.对头结点进行初始化,头结点是不存储有效内容的!!!
  32.   Head->next = NULL;
  33.   // 3.把头结点的地址返回即可
  34.   return Head;
  35. }
  36. // 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
  37. LList_t *LList_NewNode(DataType_t data)
  38. {
  39.   // 1.创建一个新结点并对新结点申请内存
  40.   LList_t *New = (LList_t *)calloc(1, sizeof(LList_t));
  41.   if (NULL == New)
  42.   {
  43.     perror("Calloc memory for NewNode is Failed");
  44.     return NULL;
  45.   }
  46.   // 2.对新结点的数据域和指针域进行初始化
  47.   New->data = data;
  48.   New->next = NULL;
  49.   return New;
  50. }
  51. // 头插
  52. bool LList_HeadInsert(LList_t *Head, DataType_t data)
  53. {
  54.   // 1.创建新的结点,并对新结点进行初始化
  55.   LList_t *New = LList_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 = New;
  70.   return true;
  71. }
  72. // 遍历
  73. void LList_Print(LList_t *Head)
  74. {
  75.   // 对链表的头文件的地址进行备份
  76.   LList_t *Phead = Head;
  77.   // 首结点
  78.   while (Phead->next)
  79.   {
  80.     // 把头的直接后继作为新的头结点
  81.     Phead = Phead->next;
  82.     // 输出头结点的直接后继的数据域
  83.     printf("data = %d\n", Phead->data);
  84.   }
  85. }
  86. /********************************************************************************************************
  87. *
  88. * 查找链表中倒数第k个位置上的节点
  89. * ①先遍历链表记录链表的节点数
  90. * ②然后通过for循环链表来获取到链表中倒数第k个位置上的节点,并且返回其data
  91. * ③找到返回1,没找到返回0
  92. *
  93. *
  94. *
  95. * ******************************************************************************************************/
  96. int SelectRecNode(LList_t *Head, DataType_t k)
  97. {
  98.   if (Head->next == NULL)
  99.   {
  100.     printf("链表为空!\n");
  101.     return 0;
  102.   }
  103.   // 新建一个指针指向Head的next
  104.   LList_t *copy_head = Head->next;
  105.   // 记录其节点数
  106.   int count = 0;
  107.   // 通过while循环记录链表的节点数
  108.   while (copy_head)
  109.   {
  110.     count++;
  111.     copy_head = copy_head->next;
  112.   }
  113.   // 把copy_head重新指向Head的next
  114.   copy_head = Head->next;
  115.   // 通过节点数-k就是其节点在链表中的位置
  116.   for (int i = 0; i < count - k; i++)
  117.   {
  118.     copy_head = copy_head->next;
  119.   }
  120.   printf("链表中倒数第%d个节点的数值是%d\n", k, copy_head->data);
  121.   return 1;
  122. }
  123. int main()
  124. {
  125.   // 创建链表头节点
  126.   LList_t *Head = LList_Create();
  127.   // 头插
  128.   LList_HeadInsert(Head, 1);
  129.   LList_HeadInsert(Head, 2);
  130.   LList_HeadInsert(Head, 3);
  131.   LList_HeadInsert(Head, 4);
  132.   LList_HeadInsert(Head, 5);
  133.   LList_HeadInsert(Head, 6);
  134.   LList_Print(Head);
  135.   SelectRecNode(Head, 3);
  136. }
复制代码
来源:https://www.cnblogs.com/DengJian111222/p/18151538
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

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

x

上一篇: shell脚本正则表达式

下一篇: 实验

举报 回复 使用道具