CCE13.【C++ Cont】练习题组13 静态链表专题

news2025/7/15 14:57:36

目录

1.B3630 排队顺序

题目

分析

代码

提交结果

2.B3631 单向链表

题目

分析

前置知识:map数组加快访问速度(简单的哈希表优化)

使用map数组的重要提醒

代码

提交结果

3.★P1160 队列安排

题目

分析

方法1:带头不循环双向链表的设计

方法2:带头循环的双向链表设计

删除元素操作

带头不循环双向链表代码

提交结果

带头循环的双向链表代码

提交结果


1.B3630 排队顺序

题目

https://www.luogu.com.cn/problem/B3630

题目描述

有 n(2≤n≤10^6) 个小朋友,他们的编号分别从 1 到 n。现在他们排成了一个队伍,每个小朋友只知道他后面一位小朋友的编号。现在每个小朋友把他后面是谁告诉你了,同时你还知道排在队首的是哪位小朋友,请你从前到后输出队列中每个小朋友的编号。

输入格式

第一行一个整数 n,表示小朋友的人数。

第二行 n 个整数,其中第 i 个数表示编号为 i 的小朋友后面的人的编号。如果这个数是 0,则说明这个小朋友排在最后一个。

第三行一个整数 h,表示排在第一个的小朋友的编号。

输出格式

一行 n 个整数,表示这个队伍从前到后所有小朋友的编号,用空格隔开。

输入输出样例

输入 #1

6
4 6 0 2 3 5
1

输出 #1

1 4 2 6 5 3

分析

线索:"只知道他后面一位小朋友的编号","后面"体现单向链表

本题较好考察了单链表的概念,本题没有必要创造单链表,而是直接按静态单链表去访问

代码

#include <iostream>
#include <vector>
#define endl "\n"//提高换行的运行速度 
const int N=1e6+10;
using namespace std;
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int n, first, index;
	vector<int> arr(N);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> arr[i];
	}
	cin >> first;
	index = first;
	cout << first << " ";
	while (arr[index] != 0)
	{
		cout<<arr[index]<<" ";
		index = arr[index];
	}
	return 0;
}

其实可以借用 文章的print函数

#include <iostream>
#include <vector>
using namespace std;
const int N=1e3+10;
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int n,head;
	vector<int> next(N);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> next[i];
	}
	cin >> head;
	for (int i=head;i;i=next[i])
	{
		cout<<i<<" ";	
	} 
	return 0;
}

提交结果

2.B3631 单向链表

题目

https://www.luogu.com.cn/problem/B3631

题目描述

实现一个数据结构,维护一张表(最初只有一个元素 1)。需要支持下面的操作,其中 x 和 yy 都是 1 到 10^6 范围内的正整数,且保证任何时间表中所有数字均不相同,操作数量不多于 10^5:

  • 1 x y :将元素 y 插入到 x 后面;
  • 2 x :询问 xx 后面的元素是什么。如果 x 是最后一个元素,则输出 0;
  • 3 x:从表中删除元素 x 后面的那个元素,不改变其他元素的先后顺序。

输入格式

第一行一个整数 q 表示操作次数。

接下来 q 行,每行表示一次操作,操作具体见题目描述。

输出格式

对于每个操作 2,输出一个数字,用换行隔开。

输入输出样例

输入 #1

6
1 1 99
1 99 50
1 99 75
2 99
3 75
2 1

输出 #1

75
99

分析

这道题用单链表或顺序表都能做,但是顺序表的任意位置插入和删除时间复杂度都是O(N),运行速度慢,而借助map数组(题目提示:且保证任何时间表中所有数字均不相同)的单链表时间复杂度为O(1),很快!

前置知识:map数组加快访问速度(简单的哈希表优化)

一般查找链表的某个元素通常使用循环,即遍历链表,时间复杂度为O(N),而如果借助map数组,直接访问其元素map[i],时间复杂度为O(1),即用空间换时间

map[i]用来标记i这个元素在链表的什么位置

例如:

map数组将e数组和对应的下标建立联系

上方链表的map数组为

map[i]==-1为链表中删除的元素,其map[i]为无效值

使用map数组的重要提醒

1.存储的数值不能过大; 2.链表中不能有相同的元素;

代码

#include <iostream>
#include <vector>
#define endl "\n"
using namespace std;
const int N=1e6+10;
class List
{
	public:
		int val[N];
		int next[N];
		int map[N];//map数组加快访问速度,map[i]用来标记i这个元素在什么位置
		int head;
		int id;

	List()
	{
		next[0]=1;
		val[1]=1;
		next[1]=-1;
		head=0;
		id=1;
		map[1]=1; 
	}

	void insert(int x,int y)
	{
		int pos=map[x];
		val[++id]=y;
		map[y]=id;
		if (next[pos]==-1)
		{
			//尾插
			next[pos]=id;
			next[id]=-1;
		}
		else
		{
			//头插或者中间插入
			next[id]=next[pos];
			next[pos]=id; 
		}
	}

	void search(int x)
	{
		int pos=map[x];
		if (next[pos]==-1)//为尾部元素 
		{
			cout<<"0"<<endl;
			return;
		}
			
		if (map[x]!=-2)
			cout<<val[next[pos]]<<endl;
	}
	
	void erase(int x)
	{
		int pos=map[x];
		if (next[pos]!=-1)
		{
			map[val[next[pos]]]=-2;
			next[pos]=next[next[pos]];//非尾删
		}
	
	}
};

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	List list;
	int q,op,x,y;
	cin>>q;
	while(q--)
	{
		cin>>op;
		if (op==1)
		{
			cin>>x>>y;
			list.insert(x,y);	
		}	
		else if (op==2)
		{
			cin>>x;
			list.search(x);
		}
		else //op==3
		{
			cin>>x;
			list.erase(x);
		}
	}
	return 0;
}

提醒:const int N=1e6+10;如果N小了会报段错误,如下图

提交结果

3.★P1160 队列安排

题目

https://www.luogu.com.cn/problem/P1160

题目描述

一个学校里老师要将班上 N 个同学排成一列,同学被编号为 1∼N,他采取如下的方法:

  1. 先将 1 号同学安排进队列,这时队列中只有他一个人;

  2. 2∼N 号同学依次入列,编号为 i 的同学入列方式为:老师指定编号为 i 的同学站在编号为 1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;

  3. 从队列中去掉 M 个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式

第一行一个整数 N,表示了有 N 个同学。

第 2∼N 行,第 i 行包含两个整数 k,p,其中 k 为小于 i 的正整数,p 为 0 或者 1。若 p 为 0,则表示将 i 号同学插入到 k 号同学的左边,p 为 1 则表示插入到右边。

第 N+1 行为一个整数 M,表示去掉的同学数目。

接下来 M 行,每行一个正整数 x,表示将 x 号同学从队列中移去,如果 x 号同学已经不在队列中则忽略这一条指令。

输出格式

一行,包含最多 N 个空格隔开的整数,表示了队列从左到右所有同学的编号。

输入输出样例

输入 #1

4
1 0
2 1
1 0
2
3
3

输出 #1

2 4 1

说明/提示

【样例解释】

将同学 2 插入至同学 1 左边,此时队列为:

2 1

将同学 3 插入至同学 2 右边,此时队列为:

2 3 1

将同学 4 插入至同学 1 左边,此时队列为:

2 3 4 1

将同学 3 从队列中移出,此时队列为:

2 4 1

同学 3 已经不在队列中,忽略最后一条指令

最终队列:

2 4 1

【数据范围】

对于 20% 的数据,1≤N≤10。

对于 40% 的数据,1≤N≤1000。

对于 100% 的数据,1<M≤N≤10^5。

分析

不要被题目迷惑,以为同学入队和出队就要使用队列,其实不然,用队列或者顺序表解的时间复杂度都为O(N),没有链表O(1)

其次本题要求"若 p 为 0,则表示将 i 号同学插入到 k 号同学的左边,p 为 1 则表示插入到右边",有左有右一定用双向链表(循环或不循环)

方法1:带头不循环双向链表的设计

由于学生入队的顺序是固定的,而且从2~N,显然不用专门开数组val[]来存储学生的编号,更不需要遍历指针id,从而简化代码,只需要next[]和prev[]数组和头指针head

 一开始链表只存储哨兵位和编号为1的学生

逻辑结构

(-1代表无效下标)

物理结构

上面这个表有两种看法

看法1:竖着看,相当于逻辑结构的每个节点(下标充当val数组,即节点的数据域)

看法2:横着看,为物理存储方式

方法2:带头循环的双向链表设计

删除元素操作

注意:删除某个元素x时需要用一个状态数组is_erase来看

is_erase[x]==0说明没有删除过,可以删除;删除过x后is_erase[x]==1,确保下次不再删除x

带头不循环双向链表代码

#include <iostream>
#include <vector>
using namespace std;
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int n,k,p,m,x;
	cin>>n;
	vector<int> next(n+1,-1);
	vector<int> prev(n+1,-1);
	vector<int> is_erase(n+1,0);
	//处理头结点和编号为1的学生 
	next[0]=1;
	prev[1]=0;
	prev[0]=-1;
	next[1]=-1; 

	for (int i=2;i<=n;i++)//i既为下标又为学生的编号 
	{
		cin>>k>>p;
		if (p==0)//i放在k的左边 
		{
			next[i]=k;
			prev[i]=prev[k];
			next[prev[k]]=i;
			prev[k]=i;	//因为一开始要访问到prev[k],所以最后修改prev[k] 
		}	
		else //p==1
		{
			if (next[k]==-1)
			{
				next[k]=i;//尾插单独写
				prev[i]=k;
			}
			else
			{
				next[i]=next[k];
				prev[i]=k;
				prev[next[k]]=i;
				next[k]=i;//因为一开始要访问到next[k],所以最后修改next[k] 
			}
			
		}
	}
	cin>>m;
	while(m--)
	{
		cin>>x;
		//is_erase数组用于检查x是否被删过一次了 
		if (!is_erase[x])
		{
			if (next[x]==-1)
			{
				//尾删单独写 
				next[prev[x]]=-1;
			}
			else
			{
				next[prev[x]]=next[x];
				prev[next[x]]=prev[x];
				is_erase[x]=1;
			} 
		}
	}
	for (int i=next[0];i!=-1;i=next[i])
	{
		cout<<i<<" ";
	}
	return 0;
}

提交结果

带头循环的双向链表代码

#include <iostream>
#include <vector>
using namespace std;
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int n, k, p, m, x;
	cin >> n;
	vector<int> next(n + 1, -1);
	vector<int> prev(n + 1, -1);
	vector<int> is_erase(n + 1, 0);

	next[0] = 1;
	prev[1] = 0;
	prev[0] = 1;
	next[1] = 0;

	for (int i = 2; i <= n; i++)//i既为下标又为学生的编号 
	{
		cin >> k >> p;
		if (p == 0)//i放在k的左边 
		{
			next[i] = k;
			prev[i] = prev[k];
			next[prev[k]] = i;
			prev[k] = i;	//因为一开始要访问到prev[k],所以最后修改prev[k] 
		}
		else //p==1
		{
			prev[i] = k;
			next[i] = next[k];
			prev[next[k]] = i; //因为一开始要访问到next[k],所以最后修改next[k] 
			next[k] = i; 
		}
	}
	cin >> m;
	while (m--)
	{
		cin >> x;
		//is_erase数组用于检查x是否被删过一次了 
		if (!is_erase[x])
		{
			//中间删
			next[prev[x]] = next[x];
			prev[next[x]] = prev[x];
			is_erase[x] = 1;
		}
	}
	for (int i = next[0]; i != 0; i = next[i])
	{
		cout << i << " ";
	}
	return 0;
}

p==0和p==1都可以等价为中间插入,头插和尾插不用区分

提交结果

可以看到两种方法明显方法2代码量较少,特殊情况不用单独判断

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

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

相关文章

内联函数(c++)

预处理&#xff1a;优点&#xff1a;内嵌到目标代码&#xff0c;减少函数的调用。 缺点&#xff1a;在预处理阶段完成替换&#xff0c;避免了语义上的差错。 egg&#xff1a; #define SQR(X) ((X)*(X)) 函数&#xff1a;优点&#xff1a;完成了某一类操作的抽象&#xff0c;…

R7周:糖尿病预测模型优化探索

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 一、数据预处理 1.设置GPU import torch.nn.functional as F import torch.nn as nn import torch, torchvisiondevice torch.device("cuda"…

线程怎么创建?Java 四种方式一网打尽

&#x1f680; Java 中线程的 4 种创建方式详解 创建方式实现方式是否推荐场景说明1. 继承 Thread 类class MyThread extends Thread❌ 不推荐简单学习、单线程场景2. 实现 Runnable 接口class MyRunnable implements Runnable✅ 推荐更适合多线程共享资源3. 实现 Callable 接…

STM32之DHT11温湿度传感器---附代码

DHT11简介 DHT11的供电电压为 3&#xff0d;5.5V。 传感器上电后&#xff0c;要等待 1s 以越过不稳定状态在此期间无需发送任何指令。 电源引脚&#xff08;VDD&#xff0c;GND&#xff09;之间可增加一个100nF 的电容&#xff0c;用以去耦滤波。 DATA 用于微处理器与DHT11之间…

工业相机——镜头篇【机器视觉,图像采集系统,成像原理,光学系统,成像光路,镜头光圈,镜头景深,远心镜头,分辨率,MTF曲线,焦距计算 ,子午弧矢】

文章目录 1 机器视觉&#xff0c;图像采集系统2 相机镜头&#xff0c;属于一种光学系统3 常规镜头 成像光路4 镜头光圈5 镜头的景深6 远心镜头 及 成像原理7 远心镜头种类 及 应用场景8 镜头分辨率10 镜头的对比度11 镜头的MTF曲线12 镜头的焦距 计算13 子午弧矢 图解 反差 工业…

openwrt查询网关的命令

方法一&#xff1a;route -n 方法二&#xff1a;ip route show

华为OD机试真题——查找接口成功率最优时间段(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C、GO六种语言的最佳实现方式&#xff1b; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析&#xff1b; 本文收录于专栏&#xff1a;《2025华为OD真题目录…

【“星睿O6”AI PC开发套件评测】开箱+刷机+基础环境配置

开箱 很荣幸可以参与“星睿O6”AI PC开发套件评测&#xff0c;话不多说先看开箱美图&#xff0c;板子的包装还是蛮惊艳的。 基础开发环境配置 刷机 刷机参考这里的文档快速上手即可&#xff0c;笔者同时验证过使用USB和使用NVMe硬盘盒直接在硬盘上刷机&#xff0c;操作下来建…

力扣面试150题--环形链表和两数相加

Day 32 题目描述 思路 采取快慢指针 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public boolean hasCycle(ListNod…

STM32 TIM输入捕获

一、输入捕获简介 IC&#xff08;Input Capture&#xff09;输入捕获输入捕获模式下&#xff0c;当通道输入引脚出现指定电平跳变时&#xff0c;当前CNT的值将被锁存到CCR中&#xff0c;可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数每个高级定时器和通用定…

python项目实战-后端个人博客系统

本文分享一个基于 Flask 框架开发的个人博客系统后端项目&#xff0c;涵盖用户注册登录、文章发布、分类管理、评论功能等核心模块。适合初学者学习和中小型博客系统开发。 一、项目结构 blog │ app.py │ forms.py │ models.py │ ├───instance │ blog.d…

白鲸开源与亚马逊云科技携手推动AI-Ready数据架构创新

在昨日举办的2025亚马逊云科技合作伙伴峰会圆桌论坛上&#xff0c;白鲸开源创始人兼CEO郭炜作为嘉宾&#xff0c;与亚马逊云科技及其他行业领袖共同探讨了“AI-Ready的数据架构&#xff1a;ISV如何构建面向生成式AI的强大数据基座”这一重要话题。此次论坛由亚马逊云科技大中华…

探秘LLM推理模型:hidden states中藏着的self verification的“钥匙”

推理模型在数学和逻辑推理等任务中表现出色&#xff0c;但常出现过度推理的情况。本文研究发现&#xff0c;推理模型的隐藏状态编码了答案正确性信息&#xff0c;利用这一信息可提升推理效率。想知道具体如何实现吗&#xff1f;快来一起来了解吧&#xff01; 论文标题 Reasoni…

大数据开发环境的安装,配置(Hadoop)

1. 三台linux服务器的安装 1. 安装VMware VMware虚拟机软件是一个“虚拟PC”软件&#xff0c;它使你可以在一台机器上同时运行二个或更多Windows、DOS、LINUX系统。与“多启动”系统相比&#xff0c;VMWare采用了完全不同的概念。 我们可以通过VMware来安装我们的linux虚拟机…

驱动开发硬核特训 · Day 16:字符设备驱动模型与实战注册流程

&#x1f3a5; 视频教程请关注 B 站&#xff1a;“嵌入式 Jerry” 一、为什么要学习字符设备驱动&#xff1f; 在 Linux 驱动开发中&#xff0c;字符设备&#xff08;Character Device&#xff09;驱动 是最基础也是最常见的一类驱动类型。很多设备&#xff08;如 LED、按键、…

Virtuoso ADE采用Spectre仿真中出现MOS管最小长宽比满足要求依然报错的情况解决方法

在ADE仿真中错误问题如下&#xff1a; ERROR (CMI-2440): "xxx.scs" 46338: I2.M1: The length, width, or area of the instance does not fit the given lmax-lmin, wmax-wmin, or areamax-areamin range for any model in the I2.M3.nch_hvt group. The channel w…

大模型应用开发之LLM入门

一、大模型概述 1、大模型概念 LLM是指用有大量参数的大型预训练语言模型&#xff0c;在解决各种自然语言处理任务方面表现出强大的能力&#xff0c;甚至可以展现出一些小规模语言模型所不具备的特殊能力 2、语言模型language model 语言建模旨在对词序列的生成概率进行建模…

武汉昊衡科技OLI光纤微裂纹检测仪:高密度光器件的精准守护者

随着AI技术应用越来越广&#xff0c;算力需求激增&#xff0c;光通信系统正加速向小型化、高密度、多通道方向演进。硅光芯片、高速光模块等核心器件内部的光纤通道数量成倍增加&#xff0c;波导结构愈发精细&#xff0c;传统检测手段因分辨率不足、效率低下&#xff0c;难以精…

SQL 函数进行左边自动补位fnPadLeft和FORMAT

目录 1.问题 2.解决 方式1 方式2 3.结果 1.问题 例如在SQL存储过程中&#xff0c;将1 或10 或 100 长度不足的时候&#xff0c;自动补足长度。 例如 1 → 001 10→ 010 100→100 2.解决 方式1 SELECT FORMAT (1, 000) AS FormattedNum; SELECT FORMAT(12, 000) AS Form…

Tailwind CSS实战:快速构建定制化UI的新思路

引言 在当今快节奏的前端开发环境中&#xff0c;开发者不断寻找能够提高效率并保持灵活性的工具。Tailwind CSS作为一个功能型优先的CSS框架&#xff0c;正在改变开发者构建用户界面的方式。与Bootstrap和Material UI等传统组件库不同&#xff0c;Tailwind不提供预设组件&…