【数据结构】单链表按位序插入元素e【前插】(带头结点的和不带头结点的)这篇很重要,文字说明比起其他篇是正确的

声明单链表的结构体成员

struct LNode {int data;struct LNode *next;
};typedef struct LNode LNode;// 或者: 两者是等价的
typedef struct LNode {int data;struct LNode *next;
}LNode;

按位序插入元素e:就是在第i个位置插入新结点,数据域为e

以下带头结点的:

思路:在第i个位置插入,就要找到第i-1个位置,然后在它的后面分配存储空间,创建新结点,再改变新结点以及其左右结点的指针指向,完成插入

  1. 由于单链表不具有随机存取的特点,不能想找i就找i,只能从头开始依次遍历,也就是从头指针L开始,即第0个结点,因为一开始的时候L是指向第一个(i=1)结点的,
  2. 就要用到循环,由于有条件判断,就用了while循环
  3. 单链表具有指针域,声明的L头指针是指向链表的第一个实际元素的,但是L的指向不能动,它必须指向链表的第一个元素,所以就要再声明一个新的指针变量p,让它初始化指向单链表的第一个结点,即让p=L,以此实现从头开始遍历
  4. 遍历到第i-1个位置,就可以停止,在其后面创建结点,分配存储空间
  5. 怎么能用代码表示,新结点一定是在i-1结点的后面呢:让新结点的指针域指向i-1的指向,再让i-1的指针域指向新结点,通过指针完成,再给新结点的数据域赋值e,新结点就插入完成了
  6. 注意:为了代码的健壮性,在执行上述代码时,我觉得有几个要注意的地方:
  • 首先,要确保查找的位序是合法的,不然就不要执行了,会报错的,位序i从1开始,最多只能在第1 个位置插入新结点,<1肯定不合法
  • 其次,如果查找的位序根本就不存在当前的单链表中,那么while循环走到最后,p指针应该是指向NULL,指向NULL的时候就不要再继续循环了,因为后面以及没有结点了
  • 最后,由于是动态声明的单链表,可以动态分配存储空间,就不存在空间满了不能插入的情况,可以不做这个兼容

代码:

bool ListInsert(LinkList &L, int i, int e) {LNode *p;int j=0;p=L;if(i<1) {return false;		// 位序不合法,返回false停止指向插入操作}while(p!=NULL && j<i-1) {p=p->next;		// p结点的指针域存储的下一结点的地址赋值给p结点,表示p结点此时就走到了原p的下一节点,此时的P的指针域存的就是原p下一结点的指针域存的结点地址// 不能写成p->next=p,因为p->next=p表示p指针域指向的元素是p结点,就是自己指向自己了j++;}// 如果循环完整个单链表都没有找到要找的位序,最后p应该是指向null,如果p指向null,就不应该再指向插入操作了if(p==NULL) {// 我感觉,p最后会走向NULL,说明要找的位序都超过单链表的长度了,其实也可以在i<1的时候加个条件判断i>L.length也可以吧return false;}// 找到i-1,跳出循环,此时p指针指向i-1// 假设原顺序是p-q-r,现在想在p和q之间插入s,值为eLNode *s = (LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;		// p->next:p结点的指针域,存储下一结点的地址,即q结点的地址// s->next:s结点的指针域,存储下一结点的地址	// 将p结点的下一结点地址即q结点的地址,赋值给s结点的指针域存储,也就是说此时s指向的下一结点是qp-next=s;		// s表示新结点,p->next表示p的指针域,存储下一结点的地址// s赋值给p->next,就是说p指向的下一节点是s,即形成了p-s-q-rreturn true;
}

分析一下时间复杂度:

  1. 最好时间复杂度,i=1时,循环0次,O(1)
  2. 最坏时间复杂度,插在表尾,i=n,循环n-1次,O(n)
  3. 平均时间复杂度,插在除表头和表尾之外的任意位置,他们的概率都是一样的p=1/(n-1)
    平均循环次数=总次数*概率=(1+2+3+…+n-1)*1/(n-1)=n(n-1)/2 * 1/(n-1) = n/2,O(n)

以下是不带头结点的:

请注意,头指针L和头结点是两个东西,一个单链表,它可以没有头结点,但它一定有头指针,头指针指向链表的第一个结点,如果链表带头结点,头指针L就指向头结点,头结点不存储数据,如果链表不带头结点,头指针L就指向链表的第一个实际结点

思路:在第i个位置插入结点,就要找到第i-1个结点,在它的后面创建新结点,给新结点分配存储空间,然后通过改变指针指向来实现,与带头结点的步骤一致。

  • 只是有一点,此时考虑的是不带头结点的单链表,所以L指向第一个实际结点,在位序i=1的位置插入结点时,找i-1的位置,就找不到,因为原先是把头结点当作位序为0的位置做插入的。所以此时就要单独考虑i=1时的情况。
  1. i=1时,第一个结点前面是头指针L,应该让头指针L指向新插入的i=1的结点,让新插入的i=1的结点的指针域存储原i=1的结点的地址,也就是原先头指针L存储的地址
  2. 原先带头结点的单链表查找i是从0开始遍历的,因为头结点可看作位序为0的结点,在第1个位置插入就是在头结点后面插,所以要从i-0=0开始遍历。现在没有头结点,i=1的位置单独写逻辑了,只要考虑从第二个位置开始之后的,也就是从i-1=1开始遍历
bool inserList_Nohead(LinkList &L, int i, int e) {if(i<1) {return false;}if(i==1) {LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=L;L=s;}int j=1;LNode *p;p=L;// 以下这段和上面带头结点的插入其实是一样的,可以用一个函数调用,就不要写那么多代码了while(p!=NULL && j<i-1) {p=p->next;		// p->next:p结点的指针域,存储下一结点的地址,赋值给p结点就表示此时p结点变成了下一节点,// 如果写成p->next=p,就表示:p结点的指针域存储的结点是p结点,就是自己指向自己,这个链表就断了j++;}if(p==NULL) {return false;}LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return true;
}

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

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

相关文章

2023-10-10 mysql-{mysql_rm_db}-失败后回滚-记录

摘要: 2023-10-10 mysql-{mysql_rm_db}-失败后回滚-记录 mysql_rm_db 完整函数代码: /**Drop all tables, routines and events in a database and the database itself.@param thd Thread handle@param db Database name in the case given by userIts alr…

找单身狗2

一个数组中只有两个数字是出现一次&#xff0c;其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。 例如&#xff1a;有数组的元素是&#xff1a;1,2,3,4,5,1,2,3,4,6&#xff0c;只有5和6只出现1次&#xff0c;要找出5和6。 这里我们不妨回忆一下之前找单身…

实现SHELL中的列表和字典效果

很多情况下我们需要有种类型来存储数据&#xff0c;在python中有列表和字典&#xff0c;golang中有切片slice和map&#xff0c;那么在shell中&#xff0c;我们能否实现列表和字典呢&#xff0c;答案是肯定的&#xff0c;下面跟着博哥的示例来一步步掌握在shell中实现列表和字典…

centos7下安装elasticsearch7.8.1并配置远程连接

1、下载安装包 sudo wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.8.1-linux-x86_64.tar.gz 2、解压 sudo tar -zxvf elasticsearch-7.8.1-linux-x86_64.tar.gz 3、添加用户并设置密码 sudo useradd es sudo passwd es # 设置密码 Lida15…

嵌入式系统开发【深入浅出】 EXTI 与 NVIC

目录 CPU 感知外部事件变化的三种方式 中断分三个级别 中断控制器 STM32 的中断和异常 NVIC 中断控制器 NVIC 结构体成员 抢占优先级和响应优先级 简单配置NVIC中断控制器 EXTI 外部中断【中断源级】​ STM32系列微控制器实际上最多有23根外部中断线&#xff08;EXT…

“桥接模式”和“NAT模式”以及“host-only模式(仅主机模式)”

使用虚拟机的时候&#xff0c;我们常看到网络链接配置中&#xff0c;有【桥接】、【NAT】、【仅主机】的选项&#xff0c;今天就来介绍一下这三种网络链接模式。 关于虚拟机中配置网络的内容可以看这篇博客&#xff1a; 深入浅出的介绍一下虚拟机VMware Workstation——part2…

千兆以太网传输层 UDP 协议原理与 FPGA 实现(UDP回环)

文章目录 前言心得体会一、UDP GMII 回环测试工程介绍二、UDP GMII 回环测试工程顶层设计三、UDP GMII 回环测试工程仿真设计四、UDP GMII 回环测试工程仿真波形五、UDP GMII 回环测试工程上板演示前言 经过前面章节的理论讲解和模块设计,相信大家已经对以太网传输以及如何实…

自己一天在家没事就爱折腾

来吃馍馍了&#xff0c;看我自己动手做的花卷&#xff0c;味道一定美极了&#xff0c;哈哈&#xff0c;有没有想吃的呀&#xff01;快来我家&#xff0c;我和你一起分享。

三维地下管线建模软件MagicPipe3D V3.1.3发布

经纬管网建模系统MagicPipe3D V3.1.3持续更新&#xff0c;内容如下&#xff1a; &#xff08;1&#xff09;新增管线流向配置&#xff0c;建模生成带流向箭头管道模型&#xff1b; &#xff08;2&#xff09;新增建模完成后可以直接载入3DTiles或obj模型功能&#xff1b; &a…

5.(vue3.x+vite)v-if与v-show区别

前端技术社区总目录(订阅之前请先查看该博客) 1:效果预览 2:v-if与v-show区别 1、v-if会增删DOM元素。 2、v-show比v-if性能更高,因为v-show只能动态的改变样式(display),不需要增删DOM元素。 3、v-if切换时候回实时的销毁和重建内部的事件、钩子函数等,v-show只会…

基于大规模分布式系统的云原生运维实践

在云计算、大数据、人工智能等新兴技术的推动下,众多行业都在经历一场轰轰烈烈的数字化转型大潮。随着容器技术和编排系统的发展、基础设施不断云化、分布式微服务架构不断演进和敏捷、DevOps等开发理念的带动&#xff0c;应用云化已经是不可逆转的趋势&#xff0c;云原生也成为…

Docker 网络访问原理解密

How Container Networking Works: Practical Explanation 这篇文章讲得非常棒&#xff0c;把docker network讲得非常清晰。 分为三个部分&#xff1a; 1&#xff09;docker 内部容器互联。 2&#xff09;docker 容器 访问 外部root 网络空间。 3&#xff09;外部网络空间…

k8s集群安装v1.20.9后-2-改造部署自己的服务k8sApp,增加istio

1.环境准备: K8s集群,已经实现了k8s-app小例子,可以正常访问。(已包含docker) 在此基础上对项目进行改进,实现istio流量切换。 2.安装部署istio 2.1 安装go 官网下载go和istio的安装包,上传到k8s集群虚拟机上(三个机器都安装) [root@node1 ~]# cd /root/Public/i…

Cisdem Video Player for mac(高清视频播放器) v5.6.0中文版

Cisdem Video Player mac是一款功能强大的视频播放器&#xff0c;适用于 macOS 平台。它可用于播放不同格式的视频文件&#xff0c;并具有一些实用的特性和功能。 Cisdem Video Player mac 中文版软件特点 多格式支持&#xff1a;Cisdem Video Player 支持几乎所有常见的视频格…

Git: tag管理

查看 git tag//会查看到仓库内所有的tag,与分支无关添加 附注标签会包含完整的标签信息&#xff0c;可以进行校验&#xff0c;轻量标签是某个特定提交的引用&#xff0c;包含信息较少。一般正式发版时要使用附注标签 git tag -a V1.0.0 -m "My Version V1.0.0"//在…

Kubernetes新增节点

1. K8S节点Hosts及防火墙设置 node3节点进行如下配置&#xff1a; #添加hosts解析&#xff1b; cat >/etc/hosts<<EOF 127.0.0.1 localhost localhost.localdomain 192.168.1.146 master1 192.168.1.147 node3 EOF #临时关闭selinux和防火墙&#xff1b; sed -i /SE…

破解mariadb密码

破解mariadb密码 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.先停止mariadb systemctl stop mariadb.service 2.进单用户模式 mysqld_safe --skip-grant-tables & 3.登录mariadb mysql -uroot #&#xff08;不用密码也能登录&#xff09; 4.切换到mysql …

基于FPGA的视频接口之千兆网口(二链路)

简介 相信网络上对于FPGA驱动网口的开发板、博客、论坛数不胜数,为何博主需要重新手敲一遍呢,而不是做一个文抄君呢!因为目前博主感觉网络上描述的多为应用层上的开发,非从底层开始说明,本博主的思虑还是按照老规矩,按照硬件、底层、应用等关系,使用三~四篇文章,来详细…

SQLite:TIMESTAMP类型使用

SQLite&#xff1a;CURRENT_TIMESTAMP是以GMT时区为准&#xff0c;而不是本地机器的时区 在本文中&#xff0c;我们将介绍SQLite数据库中的一个特性&#xff1a;CURRENT_TIMESTAMP。在SQLite中&#xff0c;我们可以使用CURRENT_TIMESTAMP函数来获取当前时间戳。然而&#xff0…

php函数

1. strstr() 返回a在b中的第一个位置 2.substr() 截取字符串 3.PHP字符串函数parse_str(将字符串解析成多个变量)-CSDN博客 4.explode() 字符串分割为数组 5.trim&#xff08;&#xff09; 1.去除字符串两边的 空白字符 2.去除指定字符 6.extract()函数从数组里…