当前位置: 首页 > news >正文

线性表中的链表概述

链表

大体的框架

  • 线性表

    逻辑结构

    基本运算/操作

    存储/物理结构

    顺序表(顺序存储)

    定义(如何用代码实现)

    基本操作的实现

    链表(链式存储)

    单链表

    定义(如何用代码实现)

    基本操作的实现

    双链表

    循环链表

    静态链表

单链表的定义和基本操作

定义

  • 什么是单链表
    • 每个节点包括数据和指向下一个元素的指针
    • 优点:无需连续的存储空间

#定义一个单链表(不带头节点)

typedefstructLNode{//定义单链表节点类型ElemType data;//每个节点存放一个数据元素structLNode*next;//指针指向下一个节点}LNode,*LinkList;//LNode强调是一个节点,LinkList强调是一个链表LinkList p=(LNode*)malloc(sizeof(LNode));//增加一个新的节点,并用指针p指向该节点};
初始化(不带头节点)
boolInitList(LinkList&L){L=NULL;returntrue;}
判空(不带头节点)
boolEmpty(LinkList L){if(L==NULL)returntrue;elsereturnfalse;}

#定义一个单链表(带头节点)

typedefstructLNode{Elemtype data;structLNode*next;}LNode,*LinkList;
初始化一个单链表(带头节点)
boolInitList(LinkList&L){L=(LNode*)malloc(sizeof(LNode));if(L==NULL)//内存不足,分配失败returnfalse L->next=NULL;//头节点之后暂时还没有节点returntrue;}
判空(带头节点)
boolEmpty(LinkList L){if(L->next==NULL)returnfalse;elsereturnfalse;}

#按位序插入

带头结点
  • 在第i个位序插入指定元素e
  • 头节点可以看作第0个节点
boolListInsert(LinkList&L,inti,ElemType e){if(i<1)//判断输入位序是否合法returnfalse; LNode*p;intj=0;//位序计数器p=L;//头节点是第0个节点while(p!=NULL&&j<i-1){//循环找到第i-1个节点p=p->next;j++;if(p==NULL)//判断输入位序是否大于链表总长度,是否合法returnfalse;LNode*s=(LNode*)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;//最后修改第i-1个节点returntrue;}
不带头节点
  • 第1个位置插入需要特殊处理,因为没有头节点
boolListInsert(LinkList&L,inti,ElemType e){if(i<1)returnfalse;if(i==1){//插入第一个位序特殊处理LNode*s=(LNode*)malloc(sizeof(LNode));s->data=e;s->next=L;L=s;//头指针指向新节点returntrue;}LNode*p;//扫描节点intj=1;//计数器p=L;//从第一个节点开始扫描while(p!=NULL&&j<i-1){//循环找到第i-1个节点p=p->next;j++;}if(p==NULL)//i值不合法returnfalse;LNode*s=(LNode*)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;returntrue;//插入成功

#指定元素后插操作

bool InsertNextNode(LNode*p,ElemType e){if(p==NULL)//输入不合法returnfalse;LNode*s=(LNode*)malloc(sizeof(LNode));if(s==NULL)//内存分配失败returnfalse;s->data=e;//套路s->next=p->next;p->next=s;returntrue;}
在按位序插入中,找到第i-1个节点后直接调用后插函数即可
  • return InsertNextNode(p,e);

#前插操作

  • 单链表只能往后找wuwuwu
  • 只能遍历链表找到指定节点的前驱节点
  • 时间复杂度O(n)
  • 但其实还有另外一种方法
插入元素
boolInsertPriorNode(LNode*p,ElemType e){if(p==NULL)returnfalse;LNode*s=(LNode*)malloc(sizeof(LNode));if(s==NULL)returnfalse;s->next=p->next;p->next=s;s->data=p->data;p->data=e;returntrue;}
插入节点
boolInsertPriorNode(LNode*p,LNode*s){if(p==NULL||s==NULL)returnfalse;s->next=p->next;p->next=s;Elemtype temp=p->data;p->data=s->data s->data=temp;returntrue;}
  • 也就是先后插,再调换
  • 这种方式的时间复杂度是O(1)
  • 这中偷天换日的操作还是很骚的

#按位序删除

boolListDelete(LinkList&L,inti,ElemType&e){if(i<1)returnfalse;LNode*p;intj=0;p=L;while(p!=NULL&&j<i-1){//循环找到第i-1个节点p=p->next;j++;}if(p==NULL)//i不合法returnfalse;if(p->next==NULL)//i-1之后再无其它节点returnfalse;LNode*q=p->next;//q指向被删除节点e=q->data//e返回删除节点中元素的值p->next=q->next;free(q);returntrue;}

#删除指定节点

  • 孩子们,我们依然找不到前驱节点
  • 难道还要用头指针遍历链表吗???
  • 不,牢大有他的小妙招
boolDeleteNode(LNode*p){if(p==NULL)returnfalse;LNode*q=p->next;//令q指向*p的后继节点p->data=p->next->data;//和后继节点交换数据域p->next=q->next;//p指向q的后继free(q);//终于删除了原本的preturntrue;}
  • 时间复杂度为O(1)
那如果要删除的指定节点是最后一个节点呢?
  • 此时p后面是NULL,那我们只能遍历数组

#按位序查找

//按位查找,返回第 i 个元素(带头结点)LNode*GetElem(LinkList L,inti){if(i<0)returnNULL;LNode*p;//指针p指向当前扫描到的结点intj=0;//当前p指向的是第几个结点p=L;//L指向头结点,头结点是第0个结点(不存数据)while(p!=NULL&&j<i){//循环找到第 i 个结点p=p->next;j++;}returnp;}

#按值查找

//按值查找,找到数据域==e 的结点LNode*LocateElem(LinkList L,ElemType e){LNode*p=L->next;//从第1个结点开始查找数据域为e的结点while(p!=NULL&&p->data!=e)p=p->next;returnp;//找到后返回该结点指针,否则返回NULL}

#求表长

//求表的长度(带头结点)intLength(LinkList L){intlen=0;//统计表长LNode*p=L;while(p->next!=NULL){p=p->next;len++;}returnlen;}

#尾插法建立单链表

LinkList List_TailInsert(LinkList &L){ //正向建立单链表 int x; //设ElemType为整型 L=(LinkList)malloc(sizeof(LNode)); //建立头结点 LNode *s,*r=L; //r为表尾指针 scanf("%d",&x); //输入结点的值 while(x!=9999){ //输入9999表示结束 s=(LNode *)malloc(sizeof(LNode)); s->data=x; r->next=s; r=s; //r指向新的表尾结点 scanf("%d",&x); } r->next=NULL; //尾结点指针置空 return L; }

#头插法建立单链表

  • 可以用于链表的逆置
LinkListList_HeadInsert(LinkList&L){//逆向建立单链表LNode*s;intx;L=(LinkList)malloc(sizeof(LNode));//创建头结点L->next=NULL;//初始为空链表,防止脏数据scanf("%d",&x);//输入结点的值while(x!=9999){//输入9999表示结束s=(LNode*)malloc(sizeof(LNode));//创建新结点s->data=x;s->next=L->next;L->next=s;//将新结点插入表头scanf("%d",&x);}returnL;}
http://www.jsqmd.com/news/1199021/

相关文章:

  • Spring Boot 配置双雄:bootstrap.yml 与 application.yml 的深度解析与实战指南
  • 濮阳人注意!旧金饰别乱卖,这6家正规黄金回收店,覆盖全市不踩雷 - 清奢黄金上门回收
  • 《汉明码(海明码)》:从“分组侦探”到“纠错神探”的实战推演
  • 从零到出活:我用飞算JavaAI一小时搭了套门店抽检整改系统
  • 挺意外的,大模型的底层设施里,还藏着一家国产具身模型公司
  • Unity跨平台摄像头开发全解析:WebCamTexture原理、多平台适配与性能优化
  • 《Java 100 天进阶之路》第4.1篇:Java基础语法易混淆概念对比集(2026版)
  • 刷题APP测评:哪款真正好用?我用半年时间对比了主流公考刷题软件
  • 3步解锁全球同人创作:AO3镜像站完全访问解决方案
  • Android密钥证明测试失败排查:从证书链验证到硬件安全分析
  • 主神空间平台:规则引擎与实时协作系统的架构实践
  • IDEA高效JavaDoc实战:从模板配置到团队规范落地
  • 2026年重卡充电桩厂家怎么选?功率、认证、交付与场景化对比分析
  • 2026从事GEO优化的公司哪个好,实力测评与真实客诉避坑指南 - mypinpai
  • 面向人机交互的动态手势识别:核心数据集与前沿算法综述
  • 我的世界勇者之章3整合包下载及游玩攻略
  • Python实战:Lena图像分块处理与重构的底层逻辑
  • 免费开源工具Bili2text:3步将B站视频转文字稿,提升学习创作效率10倍
  • 本科毕业论文降 AI 软件哪个好?知网 AIGC 一次过 - 我要发一区
  • IDEA执行Springboot项目代码运行按钮是灰色
  • 从车间学徒到电机工程师的成长历程与技术分享
  • 正红色唇膏代工的内幕:从迪奥999同源工艺到车间验货的硬指标
  • 真的有人会用AI做量化么?
  • 如何5分钟实现Unity游戏实时翻译:XUnity.AutoTranslator完全指南
  • Wallpaper Engine创意工坊寻宝指南:为开发者桌面注入灵感与个性
  • 2026年7月最新——盐城防水补漏哪家靠谱?用4项硬标准亲测了3家 - 家居避坑指南
  • 林伽一 · AI科技日报 |GPT-5.6 Sol 首发爆火引发生态变局,苹果起诉 OpenAI 或重塑行业人才规则
  • C++电梯仿真系统:从面向对象设计到调度算法实现
  • JetBrains IDE试用期重置终极方案:30天无限循环的免费体验
  • 分块矩阵从理论到实战:数学公式、工程应用与Python代码全解析