开启辅助访问      

站内搜索

搜索
热搜: 下载 1.19 1.20

Minecraft(我的世界)苦力怕论坛

[开发教程] 使用二重指针进行单链表操作

发表于 2023-12-13 01:02:17 | 显示全部楼层 |阅读模式 IP:吉林省
本帖最后由 -Shizuku- 于 2023-12-13 01:18 编辑

链表是一种非常基本的数据结构。链表结构十分简单,分为数据域与指针域。数据域存储了表中的数据,指针域则表示链表的连接方式。
单链表仅包含一个指针,即next指针,表示本节点的下一个节点的位置,链表因此也有了易修改的特性,文件系统也充分利用了该特性。
本帖将以Pure C为背景进行说明。

- 指针的本质
指针本身是一个变量,本身储存的值是其指向的对象的地址,可以通过改变指针的值来移动指针,也可以通过改变指针所指的值来间接修改变量。
本次要讲述的是利用上述性质,通过二重指针的操作来实现单链表删除。

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. struct node{
  4.     int data;
  5.     struct node* next;
  6. };

  7. struct node* assign_linked_list(struct node* head);
  8. void print_list(struct node* head);
  9. void del_list(struct node* head,int val);

  10. int main(int argc, const char * argv[]) {
  11.     struct node* head=NULL;
  12.     head=assign_linked_list(head);
  13.    
  14.     int val;
  15.     scanf("%d",&val);
  16.    
  17.     del_list(head,val);
  18.    
  19.     print_list(head);
  20.    
  21.     return 0;
  22. }

  23. struct node* assign_linked_list(struct node* head){
  24.     int n;
  25.     scanf("%d",&n);
  26.     if(n==0){
  27.         return NULL;
  28.     }
  29.     struct node* ptr=(struct node*) calloc(1,sizeof(struct node));
  30.     ptr->data=n;
  31.     ptr->next=assign_linked_list(ptr->next);
  32.     return ptr;
  33. }

  34. void print_list(struct node* head){
  35.     for(struct node* curr=head;curr;){
  36.         printf("%d ",curr->data);
  37.         curr=curr->next;
  38.     }
  39. }

  40. void del_list(struct node* head,int val){
  41.     struct node* prev=NULL;
  42.     for(struct node* curr=head;curr;){
  43.         if(curr->data==val){
  44.             if(prev){
  45.                 prev->next=curr->next;
  46.             }
  47.             else{
  48.                 prev=curr;
  49.             }
  50.             struct node* ptr=curr;
  51.             curr=curr->next;
  52.             free(ptr);
  53.         }
  54.         else{
  55.             prev=curr;
  56.             curr=curr->next;
  57.         }
  58.     }
  59. }
复制代码


以上是一段再正常不过的单链表创建,删除,以及输出的一个程序,可以看到在链表删除的时候利用了prev指针,记录了上一个位点的地址,以方便链表的删除操作,即prev->next=curr->next,移动curr指针后再将现有节点占据的内存释放。这样的写法思想上非常好理解。

  1. void del_list(struct node** head,int val){
  2.     for(struct node** curr=head;*curr;){
  3.         struct node* entry=*curr;
  4.         if(entry->data==val){
  5.             *curr=entry->next;
  6.             free(entry);
  7.         }
  8.         else{
  9.             curr=&entry->next;
  10.         }
  11.     }
  12. }
复制代码


而在本例中,则利用二重指针的特性,基于此prev将不再必要。
在curr移动的过程中,如果需要释放二重指针所指向的当前节点,由于二重指针curr指向的是entry->next这个指针,所以可以直接对二重指针curr解引用获取entry->next的地址,并将其赋值为下一节点的地址,这就是通过指针间接修改值。在此情况下,entry和curr毫无联系,需要移动的也是curr而不是entry,所以可以直接调用free(entry)删除节点。又由于这是单链表,所以也不存在右边与左边连接的问题。
而如果不需要释放当前节点,这时候可以直接修改二重指针的地址,移动二重指针,让它指向entry->next这个指针,即下一节点。

参考:
Linus所述Low-Level Coding问题,信源并不惟一,这里给出一个参考过的文章:https://wordaligned.org/articles/two-star-programming
上述内容的思考是自己的体会,仅作记录。
代码由自己重写。
测试样例中,输入以空格分隔的多个数字,以0结尾作为结束输入标志;
然后再输入一个数字代表需要从链表中删除的值。
苦力怕论坛,感谢有您~
回复

使用道具 举报

发表于 2024-2-4 21:16:36 | 显示全部楼层 IP:天津
链表算比较经典的C(pp)开发实例了,我还记得在链表里倒腾prev、data、next的痛苦时光...
2# 2024-2-4 21:16:36 回复 收起回复
苦力怕论坛,感谢有您~
回复 支持

使用道具 举报

 楼主| 发表于 2024-2-6 15:47:28 | 显示全部楼层 IP:江苏省
lihl 发表于 2024-2-4 21:16
链表算比较经典的C(pp)开发实例了,我还记得在链表里倒腾prev、data、next的痛苦时光... ...

不看建议不回复。
3# 2024-2-6 15:47:28 回复 收起回复
苦力怕论坛,感谢有您~
回复 支持

使用道具 举报

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

本版积分规则

本站
关于我们
联系我们
坛史纲要
官方
哔哩哔哩
技术博客
下载
网易版
安卓版
JAVA
反馈
意见建议
教程中心
更多
捐助本站
QQ群
QQ群

QQ群

访问手机版

访问手机版

手机版|小黑屋|系统状态|klpbbs.com

粤公网安备 44200002445329号 | 由 木韩网络 提供云服务 | GMT+8, 2024-4-29 14:44

声明:本站与Mojang以及微软公司没有从属关系

Powered by Discuz! X3.4 粤ICP备2023071842号