链表(数组实现的伟大二踢脚)

一.链表与数组

 链表作为 C 语言中一种基础的数据结构,在平时写程序的时候用的并不多,但在操作系统里面使用的非常多。不管是RTOS还是Linux等使用非常广泛,所以必须要搞懂链表,链表分为单向链表和双向链表,单向链表很少用,使用最多的还是双向链表。单向链表懂了双向链表自然就会了(网上这样说,但我啃了链表三天哭死)。

定义:

      链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构。

特点:

      链表由一系列节点(链表中每一个元素称为节点)组成,节点在运行时动态生成 (malloc),每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针。

 链表最大的作用是通过节点把离散的数据链接在一起,组成一个表(听起来像废话),这大概就是链表 的字面解释了吧。 链表常规的操作就是节点的插入和删除,为了顺利的插入,通常一条链 表我们会人为地规定一个根节点,这个根节点称为生产者。通常根节点还会有一个节点计 数器,用于统计整条链表的节点个数。 双向链表与单向链表的区别就是节点中有两个节点指针,分别指向前后两个节点,其 它完全一样。

下面找到一个数组与链表的对比:

上面我们看的实际上是针对正规链表也就是使用指针来实现的链表,而我们这次使用的二踢脚不对使用的是数组代替指针进行操作, 但本质上是相同的。

二.单向链表 

模板:

// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点
int head, e[N], ne[N], idx;

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

// 在链表头插入一个数a
void insert(int a)
{
    e[idx] = a, ne[idx] = head, head = idx ++ ;
}

// 将头结点删除,需要保证头结点存在
void remove()
{
    head = ne[head];
}

 例题:

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<int,int> e;
int main(){
    int n;
    cin>>n;
    while(n--){
        int a,b,c;
        cin>>a>>b;
        switch(a){
            case 1:
            cin>>c;
            e[c]=e[b];// 插入<y, y的指向>, y的指向为前一个数x的指向
            e[b]=c;// 更新x的指向,使其指向y
            break;
            case 2:
            cout<<e[b]<<endl;
            break;
            case 3:
            int cc=e[b];
            e[b]=e[cc];
            e.erase(cc);
        }
    }
    system("pause");
    return 0;
}

 三.双向链表

模版:

// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,idx表示当前用到了哪个节点
int e[N], l[N], r[N], idx;

// 初始化
void init()
{
    //0是左端点,1是右端点
    r[0] = 1, l[1] = 0;
    idx = 2;
}

// 在节点a的右边插入一个数x
void insert(int a, int x)
{
    e[idx] = x;
    l[idx] = a, r[idx] = r[a];
    l[r[a]] = idx, r[a] = idx ++ ;
}

// 删除节点a
void remove(int a)
{
    l[r[a]] = l[a];
    r[l[a]] = r[a];
}

例题一:

 

 

 

 

 一定要注意模版中针对的是下标k进行插入,不是值,因此我们使用一个桶来存储插入值的下标。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500010;
//r[N]储存该结点后一结点的下标
//l[N]储存该结前一结点的下标
//e[N]储存该点的值
//idx表示插入的次数(即下标)
int e[N];
int l[N];
int r[N];
map<int,int> mp;//存储值的下标
int idx;
void init(){
    //以下标为0的结点为头结点,以下标为1的结点为尾结点
    //初始化
    r[0]=1;
    l[1]=0;
    idx=2;//由于已经进行了两次插入头尾结点的操作,所以idx初始化为2(前面是0,1)
}
//将一结点插入到下标为k的结点的前或后位置处,进行4次指针的变换
//如果要将结点插入至下标为k的结点之前,将add内的实参赋值为(l[k],x)即可
void add(int k,int x){
    e[idx]=x;//将待插值x插入e[idx]
    mp[e[idx]]=idx;
    //将待插结点与前后两结点连接
    l[idx]=k;//将k赋值给插入结点的l[idx]
    r[idx]=r[k];//将下标为k的结点的r[k]赋值给插入结点的r[idx]
    //下面两步操作不能交换顺序
    l[r[k]]=idx;
    r[k]=idx;
    idx++;
}
//将下标为a的数删除,进行两次指针变换即可
void remove(int a){
    //将待删点的下一结点与待删点的前一结点相互连接
    l[r[a]]=l[a];
    r[l[a]]=r[a];
}
int main(){
    int n;
    cin>>n;
    init();
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        add(l[1],x);
    }
    int t;
    cin>>t;
    while(t--){
        int a;
        cin>>a;
        int x;
        cin>>x;
        //int cnt=0;
        /*for(int i=r[0];i!=1;i=r[i]){
            if(e[i]==x){
                cnt=i;
            }
        }*/
        //cout<<cnt<<" ";
        switch(a){
            case 1:
            int y;
            cin>>y;
            add(mp[x],y);
            break;
            case 2:
            remove(mp[x]);
            break;
        }
    }
    for(int i=r[0];i!=1;i=r[i]){
        cout<<e[i]<<" ";
    }
    system("pause");
    return 0;
}

例题二

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

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

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

输入格式

第一行包含整数 M,表示操作次数。

接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:

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

共一行,将整个链表从头到尾输出。

数据范围

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 M = 1e5 + 10;
int e[M],l[M],r[M],idx;
int m;
void init(){
	r[0] = 1;
	l[1] = 0;
	idx = 2; // idx从2开始,所以删除第k个插入的数是remove(k+1) 
}

void add(int k,int x){
	e[idx] = x;
	r[idx] = r[k];
	l[idx] = k;
	l[r[k]] = idx;
	r[k] = idx;
	idx ++;
}

void remove(int k){
	r[l[k]] = r[k];
	l[r[k]] = l[k];
}
int main(){
	cin>>m;
	init();
	while(m--){
		string op;
		cin>>op;
		if(op == "R"){
			int x;
			cin>>x;
			add(l[1],x);
		}
		else if( op == "L"){
			int x;
			cin>>x;
			add(0,x);
		}
		else if( op == "D"){
			int k;
			cin>>k;
			remove(k+1); // idx从2开始,所以删除第k个插入的数是remove(k+1) 
		}
		else if (op == "IL"){
			int k,x;
			cin>>k>>x;
			add(l[k+1],x);
		}
		else{
			int k,x;
			cin>>k>>x;
			add(k+1,x);
		}
	}
	for(int i=r[0];i!=1;i = r[i]) cout<<e[i]<<" ";
	
	
}

 终于在我三天不懈之努力才弄出来这篇可以弄懂的数组方式实现的链表,虽然五一假期,但代码人永不退缩(真累啊我哭死)!!!

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

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

相关文章

2024.5.1【项目测试报告】模拟微信实现网页聊天室

目录 项目介绍 核心功能 额外拓展 核心技术 项目页面设计 注册页面 登录页面 找回密码页面 网页聊天室页面 个人中心页面 测试计划 功能测试 注册页面 登录页面 找回密码页面 个人中心页面 网页聊天室页面 自动化测试 单例驱动 获取屏幕截图 注册页面自动化测…

GPG的使用

这里写自定义目录标题 安装加密程序生成加密密钥怎么备份自己的密钥就可以使用公钥加密邮件信息了 安装加密程序 下载gpg4win&#xff1a; https://www.gpg4win.org/index.html 免费的&#xff0c;如果使用的是苹果电脑&#xff0c;使用https://gpgtools.org/。 如果是linux&a…

【精选文献】JAG|基于时序Sentinel-1 SAR影像小农耕作区烟草空间分布制图

目录 文章简介 01 文章摘要 02 研究背景、目标及创新点 03 研究区域与数据集 04 研究方法 05 研究结果 06 研究讨论 07 研究结论 08 文章引用 文章简介 论文名称&#xff1a;Mapping tobacco planting areas in smallholder farmlands using Phenological-Spatial-Te…

golang判断通道chan是否关闭的2种方式

chan通道在go语言的办法编程中使用频繁&#xff0c;我们可以通过以下2种方式来判断channel通道是否已经关闭&#xff0c;1是使用 for range循环&#xff0c;另外是通过 for循环中if 简短语句的 逗号 ok 模式来判断。 示例代码如下&#xff1a; //方式1 通过for range形式判断…

LNMP部署wordpress

1.环境准备 总体架构介绍 序号类型名称外网地址内网地址软件02负载均衡服务器lb0110.0.0.5192.168.88.5nginx keepalived03负载均衡服务器lb0210.0.0.6192.168.88.6nginx keepalived04web服务器web0110.0.0.7192.168.88.7nginx05web服务器web0210.0.0.8192.168.88.8nginx06we…

Nodejs -- 流程控制库

流程控制库 尾触发和next 尾触发最多的应用是在Connect的中间件 var app connect() app.use(connect.staticCache()) app.use(connect.static(__dirname /public)) app.use(conect.cokkieParser()) app.use(connect.session()) app.use(connect.query()) app.use(connect.…

跨平台终端软件——quardCRT

作为一个技术栈比较复杂的程序&#xff0c;工作常常会在windows/linux/macos等不同的平台切换开发&#xff0c;开发过程中最常用的就是终端工具了&#xff0c;一个趁手的终端可以成倍的提高工作效率&#xff0c;因此我一直希望能找个一个跨平台体验一致无缝切换的终端软件&…

Unity Audio Filter 入门

概述&#xff1a; 如果你在你项目中需要一些特殊的声音效果&#xff0c;那这部分声音过滤器的部分一定不要错过喔&#xff0c;让我们来学习这部分的内容吧&#xff01; 这部分理论性比较强&#xff0c;认真看我的注解哈&#xff0c;我尽量解释的易懂一点。 Audio Chorus Filter…

街道征迁项目档案管理系统

街道征迁项目档案管理系统是一个用于管理街道征迁项目档案的软件系统。该系统的主要功能包括档案录入、档案存储、档案检索、档案共享等。 系统的用户可以通过该系统录入征迁项目相关的档案信息&#xff0c;包括项目名称、征迁范围、土地面积、征迁补偿费用等。同时&#xff0c…

vue本地调试devtools

一、谷歌浏览器加载扩展程序 二、把解压的压缩包添加即可&#xff0c;重启浏览器 三、启动前端本地项目&#xff0c;即可看到Vue小图标

AD | Altium Designer(原理图设计、电路仿真、PCB绘图)汉化版

Altium Designer(原理图设计、电路仿真、PCB绘图) 通知公告 Altium Designer(AD)是一种功能强大的电子设计自动化(EDA)软件。它主要用于设计和开发电子产品,如电路板(PCB)、集成电路(IC)和嵌入式系统。AD提供了完整的设计工具套件,包括原理图设计、PCB布局、仿真、设…

ICode国际青少年编程竞赛- Python-1级训练场-识别循环规律1

ICode国际青少年编程竞赛- Python-1级训练场-识别循环规律1 1、 for i in range(4):Dev.step(6)Dev.turnLeft()2、 for i in range(3):Dev.turnLeft()Dev.step(2)Dev.turnRight()Dev.step(2)3、 for i in range(3):Spaceship.step(5)Spaceship.turnLeft()Spaceship.step(…

互联网轻量级框架整合之MyBatis底层运转逻辑

MyBatis运转过程中主要步骤有两个&#xff0c;其一读取配置文件缓存到Configuration对象&#xff0c;用于构建SqlSessionFactory&#xff1b;其二是SqlSession的执行过程&#xff0c;这其中SqlSessionFactory的构建过程相对很好理解&#xff0c;而SqlSession的执行过程就相对复…

LT6911GX HDMI2.1 至四端口 MIPI/LVDS,带音频 龙迅方案

1. 描述LT6911GX 是一款面向 VR / 显示应用的高性能 HDMI2.1 至 MIPI 或 LVDS 芯片。HDCP RX作为HDCP中继器的上游&#xff0c;可以与其他芯片的HDCP TX配合使用&#xff0c;实现中继器功能。对于 HDMI2.1 输入&#xff0c;LT6911GX 可配置为 3/4 通道。自适应均衡功能使其适合…

vue3+vite+js 实现移动端,PC端响应式布局

目前使用的是vue3vite&#xff0c;没有使用ts 纯移动端|PC端 这种适用于只适用一个端的情况 方法&#xff1a;amfe-flexible postcss-pxtorem相结合 ① 执行以下两个命令 npm i -S amfe-flexible npm install postcss-pxtorem --save-dev② main.js文件引用 import amfe-f…

FreeRTOS信号量

信号量简介 def 1&#xff1a; 信号量是一种解决问题的机制&#xff0c;可以实现共享资源的访问 信号量浅显理解例子&#xff1a; 空车位&#xff1a; 信号量资源&#xff08;计数值&#xff09; 让出占用车位&#xff1a; 释放信号量&#xff08;计数值&#xff09; 占用车…

LT6911UXB HDMI2.0 至四端口 MIPI DSI/CSI,带音频 龙迅方案

1. 描述LT6911UXB 是一款高性能 HDMI2.0 至 MIPI DSI/CSI 转换器&#xff0c;适用于 VR、智能手机和显示应用。HDMI2.0 输入支持高达 6Gbps 的数据速率&#xff0c;可为4k60Hz视频提供足够的带宽。此外&#xff0c;数据解密还支持 HDCP2.2。对于 MIPI DSI / CSI 输出&#xff0…

jvm 马士兵 01

01.JVM是什么 JVM是一个跨平台的标准 JVM只识别class文件&#xff0c;符合JVM规范的class文件都可以被识别

知乎广告开户流程,知乎广告的优势是什么?

社交媒体平台不仅是用户获取知识、分享见解的场所&#xff0c;更是品牌展示、产品推广的重要舞台。知乎作为国内知名的知识分享社区&#xff0c;以其高质量的内容生态和庞大的用户基础&#xff0c;成为了众多企业进行广告投放的优选之地。云衔科技通过其专业服务&#xff0c;助…

数字身份管理:Facebook如何利用区块链技术?

随着数字化进程的加速&#xff0c;个人身份管理已成为一个关键议题。在这方面&#xff0c;区块链技术正在逐渐展现其巨大潜力。作为全球最大的社交媒体平台&#xff0c;Facebook也在积极探索和应用区块链技术来改进其数字身份管理系统。本文将深入探讨Facebook如何利用区块链技…