news 2026/4/18 12:16:01

数据结构——链表自实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据结构——链表自实现


❀保持低旋律节奏->个人主页

专栏链接:《C++学习》、《Linux学习》



文章目录

    • 头文件实现
    • 测试文件实现
    • 易错汇总

头文件实现

#pragmaonce#include<stdio.h>#include<stdlib.h>// 补充bool类型头文件(C语言需手动定义或包含stdbool.h)#include<stdbool.h>// 修正:C语言中结构体指针必须加struct(原代码漏写导致编译报错)structListNode{structListNode*next;intval;};//1.Print函数voidPrint(structListNode*phead){structListNode*cur=phead;if(cur==NULL){printf("NULL\n");}else{while(cur){printf("%d->",cur->val);cur=cur->next;}printf("NULL\n");}}// 创建节点函数structListNode*CreateNode(intx){structListNode*newNode=(structListNode*)malloc(sizeof(structListNode));if(newNode==NULL){perror("malloc error!");exit(1);}newNode->val=x;newNode->next=NULL;returnnewNode;}//1.InsHead头插函数// 二级指针使用原因:要修改原头指针的指向(一级指针传参是值拷贝,无法修改外部指针)structListNode*InsHead(structListNode**pphead,intn){structListNode*newheadNode=CreateNode(n);//先把 头节点拼上去newheadNode->next=*pphead;//然后在把头节点的职位 交给newheadNode*pphead=newheadNode;Print(*pphead);return*pphead;}//2.DelHead头删函数// 二级指针使用原因:删除头节点后需要修改原头指针的指向(比如从h0改为h1),一级指针无法修改外部变量structListNode*DelHead(structListNode**pphead){structListNode*newHead;if(*pphead==NULL){perror("DelHead error!");exit(1);}else{newHead=(*pphead)->next;(*pphead)->next=NULL;free(*pphead);*pphead=NULL;// 释放后置空,避免野指针}Print(newHead);returnnewHead;}//3.InsTail尾插// 注:尾插用一级指针即可(无需修改原头指针指向,仅遍历链表),但空链表时返回新节点更合理structListNode*InsTail(structListNode*phead,intn){structListNode*newNode=CreateNode(n);structListNode*cur=phead;if(phead==NULL){Print(newNode);returnnewNode;}else{while(cur->next!=NULL){cur=cur->next;}cur->next=newNode;}Print(phead);returnphead;}//4.DelTail尾删// 优化:尾删也可封装为二级指针版本(避免返回值覆盖,保持接口一致性),此处保留原逻辑+修复bugstructListNode*DelTail(structListNode*phead){structListNode*head=phead;if(head==NULL){perror("DelTail error: empty list");// 补充错误提示,而非直接exitexit(1);}elseif(head->next==NULL){printf("NULL\n");free(head);// 原代码先置next再free,顺序不影响,但free后head已成野指针,无需置nextreturnNULL;}else{structListNode*tmp=head;while(tmp->next->next!=NULL){tmp=tmp->next;}free(tmp->next);tmp->next=NULL;// 修正:C语言无nullptr,统一用NULL(原代码混用导致编译报错)// tmp->next = nullptr;}Print(head);returnhead;}// 查找函数boolFind(structListNode*phead,intn){structListNode*pcur=phead;if(pcur==NULL){returnfalse;}while(pcur){if(pcur->val==n)returntrue;pcur=pcur->next;}returnfalse;}// 新增:链表销毁函数(避免内存泄漏,必补!)// 二级指针使用原因:销毁后需要将原头指针置空,防止外部使用野指针voidDestroyList(structListNode**pphead){if(pphead==NULL||*pphead==NULL){return;}structListNode*cur=*pphead;while(cur){structListNode*tmp=cur;cur=cur->next;free(tmp);}*pphead=NULL;// 销毁后置空原头指针}

测试文件实现

#include"list.h"voidInit(){ListNode*h0=(ListNode*)malloc(sizeof(ListNode));ListNode*h1=(ListNode*)malloc(sizeof(ListNode));ListNode*h2=(ListNode*)malloc(sizeof(ListNode));ListNode*h3=(ListNode*)malloc(sizeof(ListNode));h0->val=0;h1->val=1;h2->val=2;h3->val=3;h0->next=h1;h1->next=h2;h2->next=h3;h3->next=NULL;Print(h0);}voidtest1(){ListNode*phead=NULL;phead=InsHead(&phead,1);phead=InsHead(&phead,2);phead=InsHead(&phead,3);phead=InsHead(&phead,4);}voidtest2(){ListNode*phead=NULL;phead=InsHead(&phead,1);phead=InsHead(&phead,2);phead=InsHead(&phead,3);phead=InsHead(&phead,4);phead=DelHead(&phead);phead=DelHead(&phead);phead=DelHead(&phead);phead=DelHead(&phead);}voidtest3(){ListNode*head=NULL;head=InsTail(head,3);head=InsTail(head,2);head=InsTail(head,1);head=InsTail(head,0);}voidtest4(){ListNode*phead=NULL;phead=InsHead(&phead,1);phead=InsHead(&phead,2);phead=InsHead(&phead,3);phead=InsHead(&phead,4);phead=DelTail(phead);phead=DelTail(phead);phead=DelTail(phead);phead=DelTail(phead);}voidtest5(){ListNode*head=NULL;head=InsTail(head,3);head=InsTail(head,2);head=InsTail(head,1);head=InsTail(head,0);if(Find(head,2)==true)printf("找到");else{printf("未找到");}}intmain(){printf("----Init函数----\n");Init();printf("----InsHead----\n");test1();printf("----DelHead----\n");test2();printf("----InsTail----\n");test3();printf("----DelTail----\n");test4();printf("----Find----\n");test5();return0;}

易错汇总

1.解释为什么头插参数为二级指针?并且思考总结什么情况下C语言需要用二级指针?
2.思考C语言中的 malloc检验机制与C++中的检验机制有什么不同? C语言检验机制使用的弊端在哪里?
3.思考在上述代码中为了防止内存泄漏 都做了free野指针、补充销毁函数。请阐述它们的实现方法。
4.思考在上述语法中 C语言和C++的语法上面的不同

1.关于空NULL与nullptr
2.关于结构体 内的成员函数
struct ListNode* 与struct ListNode*

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:45:02

从对抗到共生:解码“厌学拒学”背后的家庭动能阻滞与重建

一、现象透视&#xff1a;被遮蔽的求救信号凌晨两点的深圳湾&#xff0c;写字楼的灯光与住宅楼的台灯形成无声的对峙。孩子上了三个月补习班&#xff0c;数学分数从72分降至68分&#xff0c;理由是“老师讲的我都会&#xff0c;就是不想写”。另一户家庭中&#xff0c;初三女生…

作者头像 李华
网站建设 2026/4/18 8:49:16

C++字符串操作与迭代器解析

代码功能解析该代码演示了C中string类的基本操作&#xff0c;包括字符串修改和迭代器遍历。程序输出结果为&#xff1a;H e l l o w o r l d。关键代码分析string str ("hello world"); 初始化一个字符串str&#xff0c;内容为"hello world"。str[0] H; …

作者头像 李华
网站建设 2026/4/18 11:32:12

GB/T 34399器械冷链温控验证新标准:质量保障的科技防线

新标准扩展了验证范围&#xff0c;新增温控柜、冷藏箱等设备验证要求&#xff0c;细化了温度分布测试布点规则。明确要求验证数据采集间隔不超过2分钟&#xff0c;冷藏设备温度偏差、均匀度、波动度不超过3℃&#xff0c;大幅提升数据精确性。对医疗器械企业而言&#xff0c;标…

作者头像 李华
网站建设 2026/4/18 2:45:57

【完整源码+数据集+部署教程】天线检测与目标识别系统源码分享[一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

一、背景意义 随着无线通信技术的迅猛发展&#xff0c;天线作为无线信号传输和接收的关键组件&#xff0c;其检测与识别的重要性日益凸显。传统的天线检测方法多依赖于人工巡检和经验判断&#xff0c;效率低下且容易受到人为因素的影响&#xff0c;难以满足现代通信网络对高效、…

作者头像 李华
网站建设 2026/4/18 2:45:49

拉普拉斯特征图-目标函数化简推导(手写详细)

学到了很多算法和公式&#xff0c;老师们总是一带而过&#xff0c;这里按照老师课件中推导了一次&#xff0c;并补充了比较困惑的内容&#xff1a;tr&#xff08;迹&#xff09;是怎么被引入公式的这里发现还有两个地方需要补充一下&#xff1a;1.矩阵求导法则/迹求导法则2.广义…

作者头像 李华