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

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

可随机存储(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.hqwc.cn/news/67283.html

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

相关文章

基于ssm+vue的新能源汽车在线租赁管理系统源码和论文PPT

基于ssmvue的新能源汽车在线租赁管理系统源码和论文PPT010 开发环境&#xff1a; 开发工具&#xff1a;idea 数据库mysql5.7(mysql5.7最佳) 数据库链接工具&#xff1a;navcat,小海豚等 开发技术&#xff1a;java ssm tomcat8.5 摘 要 随着科学技术的飞速发展&#xff0…

完整版:TCP、UDP报文格式

目录 TCP报文格式 报文格式 报文示例 UDP报文格式 报文格式 报文示例 TCP报文格式 报文格式 图1 TCP首部格式 字段长度含义Source Port16比特源端口&#xff0c;标识哪个应用程序发送。Destination Port16比特目的端口&#xff0c;标识哪个应用程序接收。Sequence Numb…

如何在iPhone手机上修改手机定位和模拟导航?

如何在iPhone手机上修改手机定位和模拟导航&#xff1f; English 首先&#xff0c;你需要在Mac电脑上下载安装 Location Simulator/定位模拟工具 和 Runner 这两款应用程序。 完成安装后&#xff0c;打开软件&#xff0c;并用USB连接手机设备 修改iPhone手机定位和模拟导航 …

第二部分:AOP

一、AOP简介 AOP(Aspect Oriented Programming)面向切面编程&#xff0c;一种编程范式&#xff0c;指导开发者如何组织程序结构。 AOP是OOP&#xff08;面向对象编程&#xff09;的进阶版。 作用&#xff1a;在不改变原始设计的基础上为其进行功能增强。 spring理念&#x…

嵌入式Linux驱动开发系列五:Linux系统和HelloWorld

三个问题 了解Hello World程序的执行过程有什么用? 编译和执行&#xff1a;Hello World程序的执行分为两个主要步骤&#xff1a;编译和执行。编译器将源代码转换为可执行文件&#xff0c;然后计算机执行该文件并输出相应的结果。了解这个过程可以帮助我们理解如何将代码转化…

TIOBE2023年8月榜单发布,Python超越老将C/C++蝉联冠军

TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标&#xff0c;评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎&#xff0c;TIOBE 官网近日公布了 2023 年 8 月的编程语言排行榜。 此次的榜单中&#xff0c;Python依旧稳居第一&#xff0c;占比达到了13.33%。…

【BASH】回顾与知识点梳理(二十三)

【BASH】回顾与知识点梳理 二十三 二十三. Linux 账号管理&#xff08;二&#xff09;23.1 账号管理新增与移除使用者&#xff1a; useradd, 相关配置文件, passwd, usermod, userdelusermoduserdel 23.2 用户功能&#xff08;普通用户可使用&#xff09;idfingerchfnchsh 23.3…

【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 管理和…

Tomcat日志中文乱码

修改安装目录下的日志配置 D:\ProgramFiles\apache-tomcat-9.0.78\conf\logging.properties java.util.logging.ConsoleHandler.encoding GBK

【Windows 11】安装 Android子系统 和 Linux子系统

本文使用电脑系统&#xff1a; 文章目录 一、安卓子系统1.1 安装 WSA1.2 使用 二、Linux子系统2.1 安装 WSL 以及WSL 相关概念2.2 安装一个Linux发行版2.21 从Microsoft Store 安装2.22 用命令安装 2.23 拓展 三、拓展3.1 存储位置3.2 虚拟化技术3.3 Windows 虚拟内存3.3 wsl …

02:STM32--EXTI外部中断

目录 一:中断 1:简历 2:AFIO 3:EXTI ​编辑 4:NVIC基本结构 5:使用步骤 二:中断的应用 A:对外式红外传感计数器 1:连接图​编辑 2:函数介绍 3:硬件介绍 4:计数代码 B;旋转编码计数器 1:连接图 2:硬件介绍 3:旋转编码器代码: 一:中断 1:简历 中断&#xff1a;在主程…

三、性能测试场景设计

性能测试场景设计 一、引言&#xff1a;如果公司要求你去做性能测试&#xff0c;遇到这些场景&#xff0c;我们要如何设计&#xff1f;二、6种常见设计方法1、普通性能场景设计2、负载测试性能场景 一、引言&#xff1a;如果公司要求你去做性能测试&#xff0c;遇到这些场景&am…