深入探究:在双链表指定元素的后面进行插入操作的顺序

news2024/10/6 6:24:05

  

归纳编程学习的感悟,
记录奋斗路上的点滴,
希望能帮到一样刻苦的你!
如有不足欢迎指正!
共同学习交流!
🌎欢迎各位→点赞 👍+ 收藏⭐ + 留言​📝

惟有主动付出,才有丰富的果实获得收获!

前言:

        昨天,我们探究了在双链表指定元素的前面进行插入操作的顺序,并总结了方便记忆的规律今天我们继续探究在后面插入的顺序规律,并且将今天的规律与昨天的作对比,综合起来,找到相同之处与不同所在,这会让我们对双链表底层原理理解的更加深入,在考试当中可以快速给出正确优美的答案。         

        注意:本章节讲的是在p指向待插入元素的前面,所以后面讲的结论只适用于往p指向的结点后面插入一个元素,关于p指向待插入元素的后面的规律,请参考上一篇博文!!!

一、代码部分与昨天一样,只改变了宏的定义

#include<stdio.h>
#include<stdlib.h>

// 定义数据类型为整型
#define DataType int
// 定义一个简单的调试宏,用于输出整数
#define debug(a) printf("%d ",a)

// 下面四个宏定义了插入节点时需要执行的操作
#define one s->prior=p       // 设置新节点s的前驱指针指向p
#define two p->next=s        // 将p的后继指针指向新节点s
#define three s->next=p->next // 设置新节点s的后继指针指向p的下一个节点
#define four p->next->prior=s // 如果p后面有节点,则更新该节点的前驱指针为s

// 双向链表结点结构体定义
typedef struct DLNode
{
    DLNode *prior;  // 指向前驱结点
    DLNode *next;   // 指向后继结点
    DataType data;  // 结点存储的数据
}DLNode, *DLinkList;

// 初始化双向链表
void InitDLinkList(DLinkList *head);
// 创建双向链表
void CreatDLinkList(DLinkList head, int a[]);
// 在指定位置i处插入元素e
int InsertElem(DLinkList head, int i, DataType e);
// 顺序打印双向链表中的所有元素
void printElem(DLinkList head);
//逆序打印双向链表中的所有元素
void rprintElem(DLinkList head);

int main()
{	
    // 初始化数组
    int a[10] = {10,20,30,50,60,70,80,90};
    DLinkList L;
    // 初始化链表
    InitDLinkList(&L);
    // 使用数组创建链表
    CreatDLinkList(L, a);
    // 打印链表
    printElem(L);
    // 在第3个位置后面插入40
    InsertElem(L, 3, 40);
	printf("插入元素后,从前往后遍历:\n");
    // 再次打印链表以验证插入操作
    printElem(L);
	printf("插入元素后,从后往前遍历:\n");
    rprintElem(L);
    return 0;
} 

// 初始化链表头结点,并设置其next指针为空
void InitDLinkList(DLinkList *head)
{
    if ((*head = (DLNode*)malloc(sizeof(DLNode))) == NULL)
    {
        exit(-1);  // 如果分配内存失败则退出程序
    };
    (*head)->next = NULL;  // 头结点的next设为NULL
}

// 根据给定数组创建双向链表
void CreatDLinkList(DLinkList head, int a[])
{
    DLNode *p, *s;
    p = head;  // p开始指向头结点
    for (int i = 0; i < 8; i++)
    {
        s = (DLNode*)malloc(sizeof(DLNode));  // 分配新结点
        s->data = a[i];  // 设置新结点的数据
        p->next = s;  // 链接新结点到当前p之后
        s->prior = p;  // 设置新结点的前驱指针
        s->next = NULL;  // 新结点的next设为NULL
        p = s;  // 移动p到新结点
    }
}

// 在指定位置i处插入元素e
int InsertElem(DLinkList head, int i, DataType e)
{
    DLNode *p;
    p = head;
    int j = 0;
    // 查找插入位置
    while (p->next && j < i)
    {
        p = p->next;
        j++;
    }
    if (j < i)
    {
        return 0;  // 如果未找到正确的位置,则返回失败
    }
    DLNode *s;
    s = (DLNode*)malloc(sizeof(DLNode));
    s->data = e;  // 设置新结点的数据
    one;  two;  three;  four;  // 使用宏指令完成新结点的链接
    return 1;  // 返回成功
}

// 顺序打印链表中的所有元素
void printElem(DLinkList head)
{
    DLNode *p;
    p = head->next;  // 跳过头结点,从第一个实际数据结点开始
    while (p)
    {
        printf("%d ", p->data);  // 打印结点数据
        p = p->next;  // 移动到下一个结点
    }
    printf("\n");  // 打印换行符
}
// 逆序打印链表中的所有元素
void rprintElem(DLinkList head)
{
	DLNode *p;
	p=head;
	while(p->next)
	{
		p=p->next;
	}
	while(p!=head)
	{
		printf("%d ",p->data);
		p=p->prior;
	}
	printf("\n");	
}

        代码部分相比昨天只改变了宏的部分,因为只需要把p指向前一个元素,宏定义改成后端插入元素的操作即可,为了第一次看这篇博文的人方便,我还是把代码全部展示上吧。^_^

        重点关注宏定义以及插入的顺序

宏定义: 

#define one s->prior=p       // 设置新节点s的前驱指针指向p
#define two p->next=s        // 将p的后继指针指向新节点s
#define three s->next=p->next // 设置新节点s的后继指针指向p的下一个节点
#define four p->next->prior=s // 如果p后面有节点,则更新该节点的前驱指针为s

上述案例的插入顺序:

这里给出图像便于理解:

 我们还用昨天的顺序,方便记忆,像在空中画一个躺下来的数字8

下面我们看该顺序1234的运行结果:

        什么!!!竟然没有将40正确的插入30的后面,输出是一个死循环,为什么昨天1234的顺序可以正确的插入50的前面呢???我这里只让p指向了待插入元素的前面

        我们改变一下顺序,变成1324顺序,再运行一下,观察结果如何,只调换2和3的位置。

我们看运行结果: 

上面的两个例子表明1234和1324都不可行。

我们再把2放在最后面成1342,观察结果:

结果表明1342可以正确插入。 

二、分析为什么1234和1324不可以,而1342可行呢?

        这个问题与昨天极其相似,我们直接顺着昨天的思路,观察先2后3还有先2后4为什么不行?

我们给出先2后3的代码部分:

p->next=s;

s->next=p->next;

这两步合起来不就是s->next=s吗,和昨天的错误一样,都是s自己指向了自己,但是昨天并不影响输出原链表,因为只是找不到正确的前驱了,但是这个会影响输出原来的链表,因为这个找不到正确的后继了,从前往后遍历会因为s形成了环而找不到双链表的尾结点,造成一直输出s里面保存的数据。

我们在给出先2后4的代码:

p->next=s;

p->next->prior=s

合并一下就是s->prior=s,错误很明显了

        只要充分理解昨天《标题二》的内容,这里我相信会很容易的。 

三、下面我们给出正确的8种情况的顺序,以及16种错误顺序

四、总结规律 

有了昨天的经验,我们直接看2关于3和4的位置

发现

2只要在3和4的后面就是正确的,

2只要在3前面或者4前面就是错误的

五、我们来一道考研真题练练手

4-4.设双向循环链表中结点的结构有数据域 data,指针域 pre和next,链表不带头结点。若在指针 p所指结点之后插入结点 s,则应执行下列( )操作。【南京理工大学 2005 一、3(1分)】【北京交通大学 2006 一、1(2 分)】
A.p->next=s; s->pre=p;p->next->pre=s; s->next=p->next;
B.p->next=s; p->next->pre=s; s->pre=p; s->next=p->next;
C.s->pre=p; s->next=p->next; p->next=s; p->next->pre=s;
D.s->pre=p; s->next =p->next; p->next->pre=s; p->next=s;

有了结论可以快速标序号找到答案,就是D

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

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

相关文章

Redis篇(缓存机制 - 分布式缓存)(持续更新迭代)

目录 一、单点 Redis 的问题 1. 数据丢失问题 2. 并发能力问题 3. 故障恢复问题 4. 存储能力问题 5. 四种问题的解决方案 二、Redis持久化&#xff08;两种方案&#xff09; 1. RDB持久化 1.1. 简介 1.2. 执行时机 save命令 bgsave命令 停机时 触发RDB条件 1.3. …

SpringMVC项目的创建和使用

1.新建module&#xff0c;名称叫02_springmvc &#xfeff; &#xfeff; 2.新建文件夹web &#xfeff; &#xfeff; 3.点击确定&#xff0c;就会看到如下图&#xff0c;idea自动给我们创建了web.xml &#xfeff; &#xfeff; 这时候web文件夹多一个小点点的标识 &am…

OS_过程调用与系统调用

2024.06.25&#xff1a;操作系统过程调用与系统调用学习笔记 第5节 过程调用与系统调用 5.1 过程调用/函数调用/子程序调用5.2 系统调用5.2.1 系统调用汇编层 5.3 过程调用与系统调用的对比 5.1 过程调用/函数调用/子程序调用 &#xff08;过程调用&#xff09;也称为&#xf…

SpringBoot框架下校园资料库的构建与优化

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…

【Conda】修复 Anaconda 安装并保留虚拟环境的详细指南

目录 流程图示1. 下载 Anaconda 安装程序2. 重命名现有的 Anaconda 安装目录Windows 操作系统Linux 操作系统 3. 运行新的 Anaconda 安装程序Windows 操作系统Linux 操作系统 4. 同步原环境使用 robocopy 命令&#xff08;Windows&#xff09;使用 rsync 命令&#xff08;Linux…

CUDA与TensorRT学习四:模型部署基础知识、模型部署的几大误区、模型量化、模型剪枝、层融合

文章目录 一、模型部署基础知识1&#xff09;FLOPS和TOPS定义介绍、计算公式&#xff08;1&#xff09;基础定义&#xff08;2&#xff09;计算公式&#xff08;3&#xff09;FLOPS在GPU试怎么运算&#xff1f;&#xff08;4&#xff09;Ampere SM的电子元件结构 2&#xff09;…

【小沐学GIS】blender导入OpenTopography地形数据(BlenderGIS、OSM、Python)

文章目录 1、简介1.1 blender1.2 OpenStreetMap地图 2、BlenderGIS2.1 下载BlenderGIS2.2 安装BlenderGIS2.3 申请opentopography的key2.4 抓取卫星地图2.5 生成高度图2.6 获取OSM数据 结语 1、简介 1.1 blender https://www.blender.org/ Blender 是一款免费的开源 3D 创作套…

[uni-app]小兔鲜-07订单+支付

订单模块 基本信息渲染 import type { OrderState } from /services/constants import type { AddressItem } from ./address import type { PageParams } from /types/global/** 获取预付订单 返回信息 */ export type OrderPreResult {/** 商品集合 [ 商品信息 ] */goods: …

微信小程序地理定位与逆地址解析详解

地理定位 1 原理与思路 在微信小程序中&#xff0c;地理定位功能可以通过调用微信提供的API接口来实现。这些接口允许我们获取用户的当前位置或者让用户通过地图选择位置。获取到位置信息后&#xff0c;我们可以使用逆地址解析来获取详细的地址信息&#xff0c;如省、市、区、…

CUDA安装教程

文章目录 一、CUDA的下载和安装1.1 查看NVIDIA适配CUDA版本1.2 下载CUDA Toolkit1.3 安装CUDA 二、环境配置三、查看是否安装成功 一、CUDA的下载和安装 CUDA在深度学习中允许开发者充分利用NVIDIA GPU的强大计算能力来加速深度学习模型的训练和推理过程。 1.1 查看NVIDIA适配…

15分钟学 Python 第39天:Python 爬虫入门(五)

Day 39&#xff1a;Python 爬虫入门数据存储概述 在进行网页爬虫时&#xff0c;抓取到的数据需要存储以供后续分析和使用。常见的存储方式包括但不限于&#xff1a; 文件存储&#xff08;如文本文件、CSV、JSON&#xff09;数据库存储&#xff08;如SQLite、MySQL、MongoDB&a…

多模态理论基础——什么是多模态?

文章目录 多模态理论1.什么是多模态&#xff08;multimodal&#xff09;2.深度学习中的多模态 多模态理论 1.什么是多模态&#xff08;multimodal&#xff09; 模态指的是数据或者信息的表现形式&#xff0c;如文本、图像、音频、视频等 多模态指的是数据或者信息的多种表现…

算法笔记(十)——队列+宽搜

文章目录 N 叉数的层序遍历二叉树的锯齿形层序遍历二叉树最大宽度在每个树行中找最大值 BFS是图上最基础、最重要的搜索算法之一&#xff1b; 每次都尝试访问同一层的节点如果同一层都访问完了&#xff0c;再访问下一层 BFS基本框架 void bfs(起始点) {将起始点放入队列中;标记…

一款基于.NET开发的简易高效的文件转换器

前言 今天大姚给大家分享一款基于.NET开发的免费&#xff08;GPL-3.0 license&#xff09;、简易、高效的文件转换器&#xff0c;允许用户通过Windows资源管理器的上下文菜单来转换和压缩一个或多个文件&#xff1a;FileConverter。 使用技术栈 ffmpeg&#xff1a;作为文件转换…

vite学习教程03、vite+vue2打包配置

文章目录 前言一、修改vite.config.js二、配置文件资源/路径提示三、测试打包参考文章资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝3W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容&…

Python | Leetcode Python题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; class Solution:def circularArrayLoop(self, nums: List[int]) -> bool:n len(nums)def next(cur: int) -> int:return (cur nums[cur]) % n # 保证返回值在 [0,n) 中for i, num in enumerate(nums):if num 0:continueslow, fas…

Qt中使用QPainter绘制阴影

困扰了很久的问题&#xff0c;今天终于明白了如何绘制QGraphicDropShadowEffect同样效果的阴影&#xff0c;故写下这篇文章分享给大家。其方法是复制Qt源代码中QGraphicDropShadowEffect绘制实现的核心代码然后稍作修改实现&#xff0c;先看效果和封装过后的源代码&#xff1a;…

在 Ubuntu 安装 Python3.7(没有弯路)

注&#xff1a;当前Ubuntu版本为18.04 下载Python源码包 wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz安装前准备 安装依赖组件 apt-get updateapt-get install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libs…

c++----多态(初识)

大家好&#xff0c;今天我们来讲讲我们c中的一个关键知识&#xff0c;叫做多态。但是我们学习多态之前必须将我们前面学习过的继承学习过后才能学习。当然大家可能会先想什么叫多态&#xff0c;我们从名字上上看的话就是多种姿态嘛。毕竟看起来这么容易理解&#xff0c;但其实也…

服务器conda环境安装rpy2

参考博客 https://stackoverflow.com/questions/68936589/how-to-select-r-installation-when-using-rpy2-on-conda 现在我遇到这样一个问题&#xff0c;服务器系统环境没有R(没有权限安装&#xff09;&#xff0c;我只能在minconda的conda环境中使用R, 使用方法如下 我现在…