单链表相关操作(插入,删除,查找)

通过上一节我们知道顺序表的优点:

可随机存储(O(1)):查找速度快

存储密度高:每个结点只存放数据元素,而单链表除了存放数据元素之外,还需存储指向下一个节点的指针

http://t.csdn.cn/p7OQf

但是顺序表也有明显的缺点,就是需要大片的连续空间,改变容量不方便,所以出现了单链表

目录

一.初始化单链表

二.插入结点

1.带头结点的插入

2.不带头结点的插入:不存在第’0‘个结点,因此i=1时,需要特殊处理

补充:带头结点

指针结点的后插操作

指针的前插操作

三.删除结点

1.带头节点的删除

2.不带头节点的删除

3.删除指定节点

四.单链表的查找

1.按位查找:查找第i个节点的值

2.按值查找:查找链表中是否有元素e

补充:求表的长度


一.初始化单链表

typedef struct LNode{ElemType data;    //每个节点存放一个数据元素struct LNode *next;//指针指向下一个节点
}LNode,*LinkList;
//这里的LinkList==》typedef struct LNode *LinkList,定义一个指向结构体的指针
//在这里
//LNode *L与LinkList L;//都是表示指向单链表第一个节点的指针
//LNode *L强调的是一个节点
//LinkList L强调的是一个单链表/*不带头节点的单链表
bool InitList(LinkList &L)
{L=NULL;//防止空间中存在脏数据return true;}bool Empty(LinkList L)
{return (L=NULL);
}void test()
{LinkList L;InitList(L);}
*///带头结点的单链表
LinkList InitList(LinkList &L)
{L=(LNode *)malloc(sizeof(LNode));//分配一个头结点if(L==NULL)return NULL;L->next=NULL;//声明一个指向单链表的指针return L;}bool Empty(LinkList L)
{if(L->next==NULL){return true;}    elsereturn false;}
//我们可以把头结点看作第0个结点,这样写代码更加方便

二.插入结点

1.带头结点的插入

bool ListInsert(LinkList &L,int i,ElemType e)//i表示插入的位置,e表示插入的元素
{if(i<1){return false;}LNode *p;//指针p指向当前扫描到的结点int j=0;//当前p指向的是第几个结点p=L;    //指向头节点,头节点是第0个节点while(p!=NULL && j<i-1)//循环找到第i-1个结点{p=p->next;j++;}if(p==NULL){return false;}LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return true;}

若先p->next=s,再s->next=p->next,即

 带头结点的插入

最好情况:插在表头O(1)

最坏情况:插在表尾O(n)

平均情况:O(n)

2.不带头结点的插入:不存在第’0‘个结点,因此i=1时,需要特殊处理

bool ListInsert(LinkList &L,int i,ElemType e)
{if(i<1)return false;if(i==1)//插入第1个结点的操作与其他节点操作不同    {LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=L;L=s;//头指针指向新结点return true;}LNoden *p;int j=1;//除了这里j=1和带头结点的指针不同,其他是相同的p=L;while(p!=NULL && j<i-1){p=p->next;j++;}if(p==NULL){return false;}LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return true;
}

删除第一个元素时,需要更改头指针L 

补充:带头结点

指针结点的后插操作

//在p结点之后,插入元素e
bool InsertNextNode(LNode *p,ElemType e)
{if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));if(s=NULL)//如果内存分配失败,如内存不足等return false;s->data=e;s->next=p->next;    p->next=s;return true;}

 指针的前插操作

1.第一种方法:通过前驱节点完成前插操作

需要传入头节点才能找到p的前驱结点,即

bool InsertPriorNode(LinkList L,LNode *p,ElemType e)

bool InsertPriorNode(LinkList L,LNode *p,ElemType e)
{if(p==NULL)return false;LNode *s=(LNode*)malloc(sizeof(LNode));if(s==NULL)return false;LNode *current=L;while(current->next!=p)current=current->next;s->data=e;s->next=current->next;current->next=s;return true;
}

 在这里时间复杂度为O(n),如何减小时间复杂度,可以用第二种方法

2.第二种方法:通过结点的数据交换完成前插操作

bool InsertPriorNode(LNode *p,ElemType e)
{if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));if(s==NULL)return false;s->next=p->next;p->next=s;    //新节点s连到p之后s->data=p->data;//将p中元素复制到s中p->data=e;//p中元素覆盖为ereturn true;}

 关键在于s->data=p->data;p->data=e;这样实现了两节点的数据交换,实现了在p结点前插入e元素,同时这里的时间复杂度是O(1)

所以对于插入节点可以观察到如下两个规律

1.先后再前

s->next=p->next;

p->next=s;

2.先小后大

在第一个节点插入

s->next=L;

L=s        //头指针指向新插入的节点s 

三.删除结点

1.带头节点的删除

bool ListDelete(LinkList &L,int i,ElemType &e)
{if(i<1){return false;}LNode *p=L;int j=0;while(p!=NULL && j<i-1)//这里是寻找要删除结点的前驱结点{p=p->next;j++;}    if(p==NULL)return false;if(p->next==NULL)//如果要删除结点的前驱结点为NULL,那么删除就无意义了return false;LNode *q=p->next;//令q指向被删除结点e=q->data;//用e返回元素的值p->next=q->next;//将*q结点从链表中断开free(q);//释放qreturn true;
}

最好时间复杂度为O(1):删除第一个节点

最坏和平均时间复杂度为O(n)

2.不带头节点的删除

bool ListDelete(LinkList& L, int i, ElemType& e) {if (i < 1)return false;if (i == 1) {    LNode* p = L;L = L->next;free(p);return true;}LNode* p = L;int j = 1;while (p != NULL && j < i - 1) {//寻找删除节点的前驱节点p = p->next;j++;}if (p == NULL || p->next == NULL)return false;LNode* q = p->next;e = q->data;p->next = q->next;free(q);return true;
}

 3.删除指定节点

//删除指定节点p
bool DeleteNode(LNode *p)
{if(p==NULL)return false;LNode *q=p->next;    //    令q指向*p的后继节点q->data=p->next->data;p->next=q->next;//将*q节点从链中断开free(q);//释放后继节点的存储空间return true;}
//如果p的后继节点刚好为NULL,那么p->next->data指向空所以这段代码对此情况不适用
//针对此情况还是要找到其前驱节点,然后进行删除

找前驱节点进行删除

bool DeleteNode(LinkList L, LNode* p, ElemType& e) {if (p == NULL)return false;LNode* q = L;while (q->next != p)q = q->next;q->next = NULL;e = p->data;free(p);return true;
}

四.单链表的查找

1.按位查找:查找第i个节点的值

LNode *GetElem(LinkList L,int i)
{if(i<0)return false;LNode *p=L;int j=0;while(p!=NULL && j<i)//循环找到第i个节点{p=p->next;j++;}return p;}

平均时间复杂度O(n)

2.按值查找:查找链表中是否有元素e

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

平均时间复杂度O(n)

补充:求表的长度

int length(LinkList L)
{int len=0;LNode *p=L;while(p!=NULL){p=p->next;len++;}return len;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/37389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【2023年11月第四版教材】《第4章-信息系统管理(合集篇)》

第4章-信息系统管理之管理方法&#xff08;第四版新增章节&#xff09;&#xff08;第一部分&#xff09; 章节说明1 管理方法1.1 信息系统四个要素1.2 信息系统四大领域1.3 信息系统战略三角1.4 信息系统架构转换1.5 信息系统体系架构1.6 信息系统运行1.7 运行和监控1.8 管理和…

kafka基本概念及操作

kafka介绍 Kafka是最初由Linkedin公司开发&#xff0c;是一个分布式、支持分区的&#xff08;partition&#xff09;、多副本的 &#xff08;replica&#xff09;&#xff0c;基于zookeeper协调的分布式消息系统&#xff0c;它的最大的特性就是可以实时的处理大量数据以满足各…

【LeetCode】242 . 有效的字母异位词

242 . 有效的字母异位词&#xff08;简单&#xff09; 方法&#xff1a;哈希表 思路 首先判断两个字符串长度是否相等&#xff0c;不相等直接返回 false&#xff1b;接下来设置一个长度为26 的哈希表&#xff0c;分别对应26个小写字母&#xff1b;遍历两个字符串&#xff0c;…

Go语言工程实践之测试与Gin项目实践

Go 语言并发编程 及 进阶与依赖管理_软工菜鸡的博客-CSDN博客 03 测试 回归测试一般是QA(质量保证)同学手动通过终端回归一些固定的主流程场景 集成测试是对系统功能维度做测试验证,通过服务暴露的某个接口,进行自动化测试 而单元测试开发阶段&#xff0c;开发者对单独的函数…

KAFKA第二课之生产者(面试重点)

生产者学习 1.1 生产者消息发送流程 在消息发送的过程中&#xff0c;涉及到了两个线程——main线程和Sender线程。在main线程中创建了一个双端队列RecordAccumulator。main线程将消息发送给RecordAccumulator&#xff0c;Sender线程不断从RecordAccumulator中拉取消息发送到K…

03-基础入门-搭建安全拓展

基础入门-搭建安全拓展 1、涉及的知识点2、常见的问题3、web权限的设置4、演示案例-环境搭建&#xff08;1&#xff09;PHPinfo&#xff08;2&#xff09;wordpress&#xff08;3&#xff09;win7虚拟机上使用iis搭建网站&#xff08;4&#xff09;Windows Server 2003配置WEB站…

C#应用处理传入参数 - 开源研究系列文章

今天介绍关于C#的程序传入参数的处理例子。 程序的传入参数应用比较普遍&#xff0c;特别是一个随操作系统启动的程序&#xff0c;需要设置程序启动的时候不显示主窗体&#xff0c;而是在后台运行&#xff0c;于是就有了传入参数问题&#xff0c;比如传入/h或者/min等等。所以此…

YOLO v8目标跟踪详细解读(二)

上一篇&#xff0c;结合代码&#xff0c;我们详细的介绍了YOLOV8目标跟踪的Pipeline。大家应该对跟踪的流程有了大致的了解&#xff0c;下面我们将对跟踪中出现的卡尔曼滤波进行解读。 1.卡尔曼滤波器介绍 卡尔曼滤波&#xff08;kalman Filtering&#xff09;是一种利用线性…

欧拉OS 使用 CentOS 7 yum repo

一、下载CentOS的repo的yum文件 任何基于CentOS的yum的repo 的url是这样的&#xff1a; 但欧拉OS输出这个变量为&#xff1a;openEuler 20.03 (LTS-SP3) 那明显欧拉想要使用这个yum的url找不到这个版本&#xff0c; 所以直接讲这个变量替换为 7, Centos 7的7 然后执行&…

从零实战SLAM-第七课(多视角几何)

在七月算法报的班&#xff0c;老师讲的蛮好。好记性不如烂笔头&#xff0c;关键内容还是记录一下吧&#xff0c;课程入口&#xff0c;感兴趣的同学可以学习一下。 --------------------------------------------------------------------------------------------------------…

设计模式--策略模式

目录 一.场景 1.1场景 2.2 何时使用 2.3个人理解 二. 业务场景练习 2.1业务: 2.2具体实现 2.3思路 三.总结 3.1策略模式的特点&#xff1a; 3.2策略模式优点 3.3策略模式缺点 一.场景 1.1场景 许多相关的类仅仅是行为有异&#xff0c;也就是说业务代码需要根据场景不…

归并排序 与 计数排序

目录 1.归并排序 1.1 递归实现归并排序&#xff1a; 1.2 非递归实现归并排序 1.3 归并排序的特性总结: 1.4 外部排序 2.计数排序 2.1 操作步骤: 2.2 计数排序的特性总结: 3. 7种常见比较排序比较 1.归并排序 基本思想: 归并排序(MERGE-SORT)是建立在归并操作上的一种…

redis分布式集群-redis+keepalived+ haproxy

redis分布式集群架构&#xff08;RedisKeepalivedHaproxy&#xff09;至少需要3台服务器、6个节点&#xff0c;一台服务器2个节点。 redis分布式集群架构中的每台服务器都使用六个端口来实现多路复用&#xff0c;最终实现主从热备、负载均衡、秒级切换的目标。 redis分布式集…

使用Edge和chrom扩展工具(GoFullPage)实现整页面截图或生成PDF文件

插件GoFullPage下载&#xff1a;点击免费下载 如果在浏览网页时&#xff0c;有需要整个页面截图或导出PDF文件的需求&#xff0c;这里分享一个Edge浏览器的扩展插件&#xff1a;GoFullPage。 这个工具可以一键实现页面从上到下滚动并截取。 一、打开“管理扩展”&#xff08;…

网络设备(防火墙、路由器、交换机)日志分析监控

外围网络设备&#xff08;如防火墙、路由器、交换机等&#xff09;是关键组件&#xff0c;因为它们控制进出公司网络的流量。因此&#xff0c;监视这些设备的活动有助于 IT 管理员解决操作问题&#xff0c;并保护网络免受攻击者的攻击。通过收集和分析这些设备的日志来监控这些…

Python 3 使用Hadoop 3之MapReduce总结

MapReduce 运行原理 MapReduce简介 MapReduce是一种分布式计算模型&#xff0c;由Google提出&#xff0c;主要用于搜索领域&#xff0c;解决海量数据的计算问题。 MapReduce分成两个部分&#xff1a;Map&#xff08;映射&#xff09;和Reduce&#xff08;归纳&#xff09;。…

tauri-react:快速开发跨平台软件的架子,支持自定义头部和窗口阴影效果

tauri-react 一个使用 taurireacttsantd 开发跨平台软件的模板&#xff0c;支持窗口头部自定义和窗口阴影&#xff0c;不用再自己做适配了&#xff0c;拿来即用&#xff0c;非常 nice。 开原地址&#xff1a;GitHub - Sjj1024/tauri-react: 一个最基础的使用tauri和react开发…

生成式 AI 在泛娱乐行业的应用场景实践 – 助力风格化视频内容创作

感谢大家阅读《生成式 AI 行业解决方案指南》系列博客&#xff0c;全系列分为 4 篇&#xff0c;将为大家系统地介绍生成式 AI 解决方案指南及其在电商、游戏、泛娱乐行业中的典型场景及应用实践。目录如下&#xff1a; 《生成式 AI 行业解决方案指南与部署指南》《生成式 AI 在…

一个概率论例题引发的思考

浙江大学版《概率论与数理统计》一书&#xff0c;第13章第1节例2&#xff1a; 这个解释和模型比较简单易懂。 接下来&#xff0c;第13章第2节的例2也跟此模型相关&#xff1a; 在我自己的理解中&#xff0c;此题的解法跟上一个题目一样&#xff0c;其概率如下面的二维矩阵&a…

聊聊计算机技术

目录 1.计算机的概念 2.计算机的发展过程 3.计算机的作用 4.计算机给人类带来的福利 1.计算机的概念 计算机是一种用于处理和存储数据的电子设备。它能够执行各种操作&#xff0c;比如计算、逻辑操作、数据存储和检索等。计算机由硬件和软件两部分组成。 计算机的硬件包括中…