卡码网15 .链表的基本操作III

链表的基础操作III

时间限制:1.000S  空间限制:128MB

题目描述

请编写一个程序,实现以下链表操作:构建一个单向链表,链表中包含一组整数数据。 

1. 实现在链表的第 n 个位置插入一个元素,输出整个链表的所有元素。
2. 实现删除链表的第 m 个位置的元素,输出整个链表的所有元素。 

要求: 

1. 使用自定义的链表数据结构。
2. 提供一个 linkedList 类来管理链表,包含构建链表、插入元素、删除元素和输出链表元素的方法。
3. 在 main 函数中,创建一个包含一组整数数据的链表,然后根据输入的 n 和 m,调用链表的方法插入和删除元素,并输出整个链表的所有元素。

输入描述

每次输出只有一组测试数据。 

每组的第一行包含一个整数 k,表示需要构建的链表的长度。

第二行包含 k 个整数,表示链表中的元素。 

第三行包含一个整数 S,表示后续会有 S 行输入,每行两个整数,第一个整数为 n,第二个整数为 x ,代表在链表的第 n 个位置插入 x。 

S 行输入... 

在 S 行输入后,后续会输入一个整数 L,表示后续会有 L 行输入,每行一个整数 m,代表删除链表中的第 m 个元素。 

L 行输入...

输出描述

包含多组输出。 

每组第一行输出构建的链表,链表元素中用空格隔开,最后一个元素后没有空格。

然后是 S 行输出,每次插入一个元素之后都将链表输出一次,元素之间用空格隔开,最后一个元素后没有空格;

如果插入位置不合法,则输出“Insertion position is invalid.”。 

然后是 L 行输出,每次删除一个元素之后都将链表输出一次,元素之间用空格隔开,最后一个元素后没有空格; 

如果删除位置不合法,则输出“Deletion position is invalid.”。

输入示例
5
1 2 3 4 5
3
4 3
3 4
9 8
2
1
0
输出示例
1 2 3 3 4 5
1 2 4 3 3 4 5
Insertion position is invalid.
2 4 3 3 4 5
Deletion position is invalid.

 

之前我们也提到过,往数组的中间插入一个元素,后续所有元素都需要往后挪动一位,而链表则不必这么麻烦,那往链表的中间添加或者删除一个节点具体应该怎么做呢?

插入链表的过程

image-20230912120144709

我们可以假设这样一个场景:在传递情报过程中,A的下线是B, 也就是A -> next = B, 现在我们要引入一个C充当A和B之间的中间人,A的下线是C, C的下线是B,我们可以直接将A的next指向C,即A -> next = C, 然后将C的next指向B, 但是B无法直接表示,之前是用A -> next来表示B的,现在A -> next已经指向C了,所以在操作之前,我们需要实现定义一个变量保存B,假设为tmp, 然后将C的next指针指向B即可。

在链表中,具体插入的过程如下:

  • 找到要插入的位置的前一个节点,将之命名为cur, 要插入的位置的下一个节点,将之命名为tmp, 它们之间的关系是cur -> next = tmp
  • 创建一个新的链表newNode, 将curnext指针指向newNode, 即cur -> next = nowNode
  • newNodenext指针指向tmp, 即newNode -> next = tmp

这样就完成了链表节点的插入过程。转换成代码如下:

// 创建了一个新的 ListNode 结构的节点,值为x, 并将其地址赋给指针 newNode
ListNode *newNode = new ListNode(x);
// 创建了一个名为 tmp 的指针,临时存储当前节点 cur 的下一个节点的地址。
ListNode *tmp = cur ->next;
// 将当前节点 cur 的 next 指针更新为指向新节点 newNode,将新节点插入到当前节点后面。
cur->next = newNode;
// 将新节点 newNode 的 next 指针设置为指向之前临时存储的节点 tmp
newNode->next = tmp;

删除链表的过程

image-20230912115756421

删除链表的过程则比较简单,只需要找到删除节点的前一个节点cur, 并将其next 指针设置为指向当前节点的下下个节点,从而跳过了下一个节点,实现了节点的删除操作。

// cur->next 表示当前节点 cur 的下一个节点
// cur->next->next 表示要删除的节点的下一个节点
// 当前节点 cur 的 next 指针不再指向要删除的节点,而是指向了要删除节点的下一个节点
cur->next = cur->next->next;

打印链表

在函数内部,定义了一个名为 cur 的指针,它初始化为指向 head,即链表的头节点。

什么时候链表迭代到最后一个节点呢?检查当前节点 cur 的下一个节点是否存在(不为 NULL), 当前节点的下一个节点为NULL时说明下一个节点为空节点,即链表的末尾。

while(cur -> next != NULL) {
  
}

在循环体内,打印当前节点 cur 的下一个节点(cur->next)的值(val)。接下来,将 cur 更新为指向链表中的下一个节点,以便在下一次循环中打印下一个节点的值。

while (cur->next != NULL) {
    cout << cur->next->val << " ";
    cur = cur -> next;
}

循环体结束时,表示已经遍历完了整个链表。最后打印一个换行符,用于分隔不同的输出行。

// 打印链表
void printLinklist(ListNode* head) {
    ListNode* cur = head;
    while (cur->next != NULL) {
        cout << cur->next->val << " ";
        cur = cur -> next;
    }
    cout << endl;
}

代码编写

我们照例,先把代码的基础结构以及定义链表的结构体写出来。

#include <iostream>
using namespace std;
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};
int main() {
  
}

首先,需要接收整数k, 表示需要构建链表的长度

int main() {
  int k, val; // k表示链表长度,val表示构建链表时输入的值
  cin >> k;
}

然后我们需要构建一个长度为k的链表,在构建链表之前,可以先创建一个虚拟头节点以及初始化一个指针cur指向虚拟头节点,方便后续节点的接入。

ListNode* dummyHead = new ListNode(0); // 创建了一个虚拟头结点
ListNode* cur = dummyHead; // 定义一个指向当前节点的指针 cur,初始指向虚拟头结点
for (int i = 0; i < k; i++) { // 或者使用while(n--)
    cin >> val;
    ListNode *newNode = new ListNode(val); // 构造一个新的节点
    cur -> next = newNode; // 将新节点接入链表
    cur = cur -> next;      // cur 指向下一个节点
}

之后,需要接收一个整数s表示s行输入,每行两个整数,第一个整数为 n,第二个整数为 x ,代表在链表的第 n 个位置插入 x。

int s, n, x; // s表示s行输入,n代表插入位置,x代表插入元素的值
cin >> s; // 输入s
while (s--) {
    cin >> n >> x; // 输入n和x

}

题目中要求,插入位置不合法时,输出"Insertion position is invalid."

什么时候才会插入位置不合法呢,当插入的位置n是一个小于等于0的数或者n大于链表的长度时,插入位置不合法。

⚠️ 需要注意,插入后链表的长度会变化,所以我们可以提前定义一个变量listLen指代链表的长度

int listLen = k; // 定义链表的长度
if (n <= 0 || n > listLen) { // 当要插入的位置非法时
    cout << "Insertion position is invalid." << endl; // 输出错误提示
    continue;
}

如果不满足上面的if语句,说明插入的位置合法,后续执行的操作是完成插入以及打印链表。

插入链表节点的过程在前面已经描述过,只需找到需要插入位置的前一个节点即可, 也就是第n-1个节点,从虚拟头节点开始遍历,需要走n-1

// 指针重新指向虚拟头结点,准备用cur遍历链表
cur = dummyHead;
// 寻找添加节点的位置,i从1开始,
for (int i = 1; i < n; i++) {
   cur = cur->next;
}

插入节点的代码直接拿来使用即可,不要忘记将链表长度加1

// 插入节点
ListNode *newNode = new ListNode(x); // 构造一个新的节点
ListNode *tmp = cur ->next;
cur->next = newNode;
newNode->next = tmp;

// 链表长度加1
listLen++;

接着完成打印链表即可

// 打印链表
printLinklist(dummyHead);

链表节点删除的前置步骤类型,需要接收一个整数 L,表示后续会有 L 行输入,每行一个整数 m,代表删除链表中的第 m 个元素。

int l,m;
cin >> l;
while (l--) {
    cin >> m;
}

判断是否是非法输入

if (m <= 0 || m > listLen) {
    cout << "Deletion position is invalid." << endl;
    continue;
}

找到要删除节点的前一个节点

// 指针重新指向虚拟头结点,准备用cur遍历链表
cur = dummyHead;

//开始寻找删除节点的位置,i从1开始,因为节点计数从1开始
for (int i = 1; i < m; i++) cur = cur->next;
// 删除节点
cur->next = cur->next->next;
listLen--; // 链表长度减一
// 如果删除节点后链表为空则不打印
if (listLen != 0) printLinklist(dummyHead);

 c++代码实现:

#include<iostream>
using namespace std;
typedef struct ListNode{
    int data;
    ListNode *next;
    ListNode(int x):data(x),next(nullptr){}
}*L;
void printLinkList(ListNode *dummyHead){
    ListNode *cur=dummyHead;
    while(cur->next!=NULL){
        cout<<cur->next->data<<" ";
        cur=cur->next;
    }
    cout<<endl;
}
int main(){
    int k;
    L dummyHead=new  ListNode(0);//创建一个虚拟头节点
    cin>>k;
    int listlen=k;//记录链表的长度
    L cur=dummyHead;//定义一个指向当前节点的指针cur,初始指向虚拟头节点
    int val;
    for(int i=0;i<k;i++){
        cin>>val;
        L newNode=new ListNode(val);
        cur->next=newNode;
        cur=cur->next;
    }
    int s,n,x;
    cin>>s;
    while(s--){
        cin>>n>>x;
        if(n<=0||n>listlen){
            cout << "Insertion position is invalid." << endl;
            continue;
        }
        //指针重新指向虚拟头节点。准备用cur遍历链表
        cur=dummyHead;
        //
        for(int i=1;i<n;i++)
            cur=cur->next;
            L newNode=new ListNode(x);
            L tmp=cur->next;
            cur->next=newNode;
            newNode->next=tmp;
            listlen++;
            printLinkList(dummyHead);
        
    }
    int l,m;
    cin>>l;
    while(l--){
        cin>>m;
        if(m<=0||m>listlen){
              cout << "Deletion position is invalid." << endl;
            continue;
        }
        cur=dummyHead;
        for(int i=1;i<m;i++) 
        cur=cur->next;
        cur->next=cur->next->next;
        listlen--;
        if(listlen!=0){
            printLinkList(dummyHead);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机基础知识62

模型层回顾&#xff1a;基本使用 # 模型层有orm框架&#xff1a;对象关系映射 数据库中&#xff1a;一个个表 &#xff1a;user表&#xff0c;book表&#xff0c;一条条的记录 程序中&#xff1a;一个个类&#xff0c;一个个对象 数据库中一张表---->程序中一个…

【JavaSE】:String类(一):基本使用方法

String类 一.String类的基本构成二.字符串比较1.比较相等2.比较大小 三.字符串查找四.字符串转换五.字符串替换六.字符串的拆分七.字符串的截取八.其他操作方法 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以…

【软件推荐】卸载360软件geek;护眼软件flux;

卸载360软件geek f.lux: software to make your life better (justgetflux.com) 卸载完扫描残留 护眼软件 hf.lux: software to make your life better (justgetflux.com)https://justgetflux.com/https://justgetflux.com/

INFINI Labs 产品更新 | 修复 Easysearch 跨集群复制索引同步问题,Gateway 内存异常增长等问题

INFINI Labs 产品又更新啦~&#xff0c;本次更新主要对 Easysearch、Gateway、Console、Agent 等产品功能进行优化和相关 Bug 修复&#xff0c;解决了内存异常增长等问题&#xff0c;以下是详细说明。 INFINI Easysearch v1.6.2 INFINI Easysearch 是一个分布式的近实时搜索与…

YOLOv8改进 | 2023 | AKConv轻量级架构下的高效检测(可变核卷积)

一、本文介绍 本文给大家带来的改进内容是AKConv&#xff08;可变核卷积&#xff09;是一种创新的卷积神经网络操作&#xff0c;它旨在解决标准卷积操作中的固有缺陷&#xff08;采样形状是固定的&#xff09;&#xff0c;AKConv的核心思想在于它为卷积核提供了任意数量的参数…

最小化安装 Neokylin7.0 用于搭建 Hadoop 集群

文章目录 环境搭建背景虚拟机创建和环境配置安装过程注意事项虚拟机设置软件选择KOUMP系统分区网络和主机名打开以太网&#xff0c;并记录信息配置 IPv4修改主机名 创建用户 hadoop完全分布式搭建-CSDN博客 环境搭建背景 为什么不从hadoop100或者hadoop101开始&#xff0c;而是…

【Python表白系列】这个情人节送她一个漂浮的爱心吧(完整代码)

文章目录 漂浮的爱心环境需求完整代码详细分析系列文章 漂浮的爱心 环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0&#xff08;可选&#xff0c;这个库用于打包&#xff0c;使程序没有python环境也可以运行&#xff0c;如果想发给好朋友的话需要这…

外包搞了6年,技术退步明显......

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

对 Vision Transformers 及其基于 CNN-Transformer 的变体的综述

A survey of the Vision Transformers and its CNN-Transformer based Variants 摘要1、介绍2、vit的基本概念2.1 patch嵌入2.2 位置嵌入2.2.1 绝对位置嵌入(APE)2.2.2 相对位置嵌入(RPE)2.2.3卷积位置嵌入(CPE) 2.3 注意力机制2.3.1多头自我注意(MSA) 2.4 Transformer层2.4.1 …

【精选】VulnHub Shuriken-1 (超详细过程思路)

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

spring @Autowired 和 @Qualifier 配合使用实现按名称属性赋值源码

一、调用过程 1、QualifierAnnotationAutowireCandidateResolver.java用于解析注解候选类&#xff0c;在构造器中往qualifierTypes集合中添加注解类。 2、执行逻辑 &#xff08;1&#xff09;、接着上篇博客【Spring之Autowired 属性多实现和单实现源码解析 】AutowiredAnnot…

【话题】程序员养生指南(AI生成)

目录 程序猿可能出现的职业病有哪些&#xff1f; 如何预防和对付这些职业病&#xff1f; 一、颈椎病的预防 二、神经衰弱的调适 三、肩周炎的防护 四、视力下降的保护 五、饮食与运动的重要性 六、消化系统职业病的预防 程序员养生心得&#xff1a;呵护健康&#xff0c…

每天五分钟计算机视觉:经典的卷积神经网络之VGG-16模型

VGG-16 Vgg16是牛津大学VGG组提出来的,相比于AlexNet来说,AlexNet的一个改进是采用连续的几个4*3的卷积核来代替AlexNet中的较大的卷积核(11*11,5*5)。前面我们也说过了使用小卷积核是优于大的卷积核的,因为多层非线性层可以增加网络深度来保证学习到更加复杂的模式,而且代…

Vlan配置

需求 1 PC1和PC3所在接口为Access接口 PC2/4/5/6处于同一网段&#xff0c;其中pc2可以访问pc4/5/6 PC4可以访问pc5&#xff0c;但不能访问pc6 PC5不能访问PC6 2 PC1/3与PC2/4/5/6不再同一网段 3 所有PC通过DHCP获取IP地址&#xff0c;且PC1/3可以正常访问PC2/4/5/6 R1 [V200R00…

(下)11.24_苍穹外卖后端二刷day11day12笔记

其实后面已经没有什么好写的了&#xff0c;就随便写写 day11-5 . StringUtils.join 的用处是将datalist里面的元素一个个取出来&#xff0c;然后用“&#xff0c;” 拼接起来&#xff0c;形成一个字符串类型。 day11-6 LocalDateTime.of 的用处是获取date&#xff08;因为…

算法通关村第六关—二叉树的层次遍历经典问题(白银)

二叉树的层次遍历经典问题 一、层次遍历简介 广度优先遍历又称层次遍历&#xff0c;过程如下&#xff1a;  层次遍历就是从根节点开始&#xff0c;先访问根节点下面一层全部元素&#xff0c;再访问之后的层次&#xff0c;图里就是从左到右一层一层的去遍历二叉树&#xff0c…

LangChain的函数,工具和代理(三):LangChain中轻松实现OpenAI函数调用

在我之前写的两篇博客中:OpenAI的函数调用,LangChain的表达式语言(LCEL)中介绍了如何利用openai的api来实现函数调用功能&#xff0c;以及在langchain中如何实现openai的函数调用功能&#xff0c;在这两篇博客中&#xff0c;我们都需要手动去创建一个结构比较复杂的函数描述变量…

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

我的往期文章&#xff1a; leetCode 647.回文子串 动态规划 优化空间 / 中心扩展法 双指针-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133883091?spm1001.2014.3001.5501leetCode 131.分割回文串 回溯算法 图解 笔记-CSDN博客https://blog.csdn.n…

杏色主题卧室书房一体装修,温馨舒适的不二之选!福州中宅装饰,福州装修

分享一间暖杏色系卧室装修案例&#xff0c;希望可以给你们一些启发&#xff01; 01.配色&#xff1a;杏色&#xff1b;浅杏色&#xff1b;浅咖色&#xff1b;咖色&#xff1b;茶色 你是否想要一个宁静而优雅的居室&#xff0c;融合了卧室与书房的功能&#xff0c;提供既实用又…

java基础语法总结

导言&#xff1a; Java语言是一种面向对象的编程语言&#xff0c;具有简单、可移植、安全、高性能等特点。本篇文章主要对java的基础的语法进行一个简单的总结和概述。 目录 导言&#xff1a; 正文&#xff1a; 1. 数据类型与变量 2. 运算符与逻辑控制 3. 方法 4. 数组…