数据结构---单链表

2023-09-16 13:52:17

单链表

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) +指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

如图是一个结点

多个结点加上head(头结点)指针(指向了第一个结点的位置)就构成了单链表,最后一个结点的Next指向了空,其中结点的数据存放并不是连续的,像数组那样,但是只要使用Next指针,一样可以达到逻辑上的连续

 

数组模拟

在这里我们用数组模拟单链表

创建一个e[N]数组存储每个结点的数据

创建一个ne[N]数组存储下一个结点的位置,在数组模拟中,也就是对应的数组下标

创建一个idx,表示用到了数组的哪个位置,最开始为0

首先当链表中还没有数据时,头结点应该指向空(NULL),如图

我们把空用数字-1来代替,因为数组中是没有-1下标的,所以最开始头结点指向了-1

void unit() //初始化链表
{
	head = -1;
	idx = 0;
}

好,那现在往链表中添加结点,但是这有两种情况,一种是在头结点后添加. 一种是往已有结点添加

我们先来实现第一种,我们添加的结点就要指向-1,因为他是链表中最后一个结点,那头结点就要存储我们这个结点的数组的下标,也就是这个结点的位置0,如图

void add_head(int x)
{
	e[idx] = x; //存储的值
	eo[idx] = head; //head最开始为-1
	head = idx++; //head指向了 0
}

好,如果是第二种,往第k个结点后添加结点,第一个结点的下标为0,所以第k个结点的下标为k-1

如图 

void add_k(int k, int x)
{
	e[idx] = x; 
	eo[idx] = eo[k]; //这个结点指向了k结点指向的下一个结点的坐标
	eo[k] = idx++; //k结点指向我们新添加的结点

}

将某一个结点删除,一是将头结点后的结点删除,二是将k结点后面的结点删除,不是真正的删除它在数组中的存在,而是链表中访问不到它了

来看第一种

void remove_head()
{
	head = eo[head];
}

第二种

以上的添加和删除节点中的k,在传入参数时为原数据的-1,因为下标是从0开始的,而结点是从一开始

,如果传入时,传入的不是k-1,那么要在函数内对k--

好已经有了初始化链表函数,删除函数,添加结点函数,来道题

题目

实现一个单链表,链表初始为空,支持三种操作:

向链表头插入一个数;
删除第 k 个插入的数后面的数;
在第 k 个插入的数后插入一个数。
现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。

注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。

输入格式
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:

H x,表示向链表头插入一个数 x。
D k,表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)。
I k x,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 0)。
输出格式
共一行,将整个链表从头到尾输出。

数据范围
1≤M≤100000
所有操作保证合法。

输入样例:
 

10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6

输出样例:
 

6 4 6 5

代码

#include <iostream>

using namespace std;


const int N = 10010;

int e[N], eo[N];
int idx,head;

void unit()
{
	head = -1;
	idx = 0;
}
/*
void add_head(int x) //因为题目中插入的k是>0的,所以没有在头结点后插入这步操作
{
	e[idx] = x;
	eo[idx] = head;
	head = idx++;
}
*/
void add_k(int k, int x)
{
	e[idx] = x;
	eo[idx] = eo[k];
	eo[k] = idx++;

}
void remove_head()
{
	head = eo[head];
}
void remove_k(int k)
{
	eo[k] = eo[eo[k]]; 
}
int main(void)
{
	unit();

	int M;
	cin >> M;
	while (M--)
	{
		char op;
		int k=0, x=0;
		cin >> op;
		if (op == 'H')
		{
			cin >> x;
			add_head(x);
		}
		else if (op == 'D')
		{
			cin >> k;
			if (!k)
			{
				remove_head();
			}
			else
			{
				remove_k(k - 1);
			}
		}
		else
		{
			cin >> k >> x;
			if (!k)
			{
				add_head(x);
			}
			else
			{
				add_k(k - 1, x);
			}
		}

	}

    //遍历链表
	for (int i = head; i != -1;i=eo[i])
	{
		cout << e[i] << " ";
	}
}
更多推荐

Linux网络编程

一.协议1.1什么是协议从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。假设,A、B双方欲传输文件。规定:第一次,传输文件名,接收方接收到文件名,应答OK给传输方;第二次,发送文件的尺寸,接收方接牧到该数据再次应答一个OK;第三次.传输文件内容。同样.接收方接收数据完成后应答OK表示文件内容接收成

PostgreSQL 数据库实现公网远程连接

文章目录前言1.安装postgreSQL2.本地连接postgreSQL3.Windows安装cpolar4.配置postgreSQL公网地址5.公网postgreSQL访问6.固定连接公网地址7.postgreSQL固定地址连接测试前言PostgreSQL是一个功能非常强大的关系型数据库管理系统(RDBMS),下面简

在pandas中使matplotlib动态画子图的两种方法【推荐gridspec】

先上对比图,第一种方法,这里仅展示1个大区,多个的话需要加一层循环就可以了,主要是看子图的画法当大区下面的国家为1个或2个时,会进行报错#获取非洲国家列表african_countries=df[df['大区']=='南亚大区']['进口国'].unique()#动态计算子图的行列数量num_countries=len

datax同步数据翻倍,.hive-staging 导致的问题分析

一、背景有同事反馈Datax从Hive表同步数据到Mysql数据翻倍了。通过查看Datax任务日志发现,翻倍的原因是多读取了.hive-staging_xx开头的文件。接下里就是有关.hive-staging的分析。二、环境Hive版本2.1.1三、分析3.1.hive-staging_hive产生的原因通过Spark

【Java】泛型 之 编写泛型

写泛型类比普通类要复杂。通常来说,泛型类一般用在集合类中,例如ArrayList<T>,我们很少需要编写泛型类。如果我们确实需要编写一个泛型类,那么,应该如何编写它?可以按照以下步骤来编写一个泛型类。首先,按照某种类型,例如:String,来编写类:publicclassPair{privateStringfirst;

Spring面试题1:Spring框架的核心功能是什么?Spring框架的好处是什么?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点Spring框架的核心功能是什么Spring框架的核心功能包括:控制反转(IoC):Spring通过IoC容器管理对象的生命周期和依赖关系。它将对象的创建、组装和管理交给Spring容器,使得应用程序更加松耦合

CSS 模糊效果 CSS 黑白效果 CSS调整亮度 对比度 饱和度 模糊效果 黑白效果反转颜色

CSS模糊效果CSS黑白效果CSS调整亮度饱和度模糊效果黑白效果实现调整亮度饱和度模糊效果黑白效果使用filter1、模糊2、亮度3、对比度4、饱和度5、黑白效果6、反转颜色7、组合使用8、filer完整参数实现调整亮度饱和度模糊效果黑白效果使用filter1、模糊blur()用于模糊元素,可以设置模糊的程度,例如fi

【Redis】Redis 的学习教程(十)之使用 Redis 实现消息队列

消息队列需要满足的要求:顺序一致:要保证消息发送的顺序和消费的顺序是一致的,不一致的话可能会导致业务上的错误消息确认机制:对于一个已经被消费的消息(已经收到ACK)不能再次被消费消息持久化:要具有持久化的能力,避免消息丢失,这样当消费者异常宕机导致再次重启后需要重新消费消息时可以再次获取Redis提供了三种不同的方式来

python 异步任务框架 Celery 入门,速看!

01、简介Celery是使用python编写的分布式任务调度框架。它有几个主要的概念:celery应用用户编写的代码脚本,用来定义要执行的任务,然后通过broker将任务发送到消息队列中broker代理,通过消息队列在客户端和worker之间进行协调。celery本身并不包含消息队列,它支持一下消息队列RabbitMQ

在MySQL中使用VARCHAR字段进行日期筛选

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

Mysql---第七篇

系列文章目录文章目录系列文章目录一、简述MyISAM和InnoDB的区别二、简述mysql中索引类型及对数据库的性能的影响一、简述MyISAM和InnoDB的区别MyISAM:不支持事务,但是每次查询都是原子的;支持表级锁,即每次操作是对整个表加锁;存储表的总行数;一个MYISAM表有三个文件:索引文件、表结构文件、数

热文推荐