数组模拟双链表,你get到了吗?
数组模拟双链表
通过前面的学习我们知道单链表是单个指针指向操作,那么通过类比我们可以把指针设定为两个,并且让它们分别指向前后数据,这就是“双向链表”。使用这种链表,不仅可以从前往后, 还可以从后往前遍历数据,十分方便。
1.使用数组模拟双链表
// e[i] 表示节点i的值
// l[i] 指向当前节点的上一节点(左节点)的指针:即存的是左边一个节点的位置(下标)
// r[i] 指向当前节点的下一节点(右节点)的指针:即存的是右边一个节点的位置(下标)
// idx 存储当前已经用到的节点(当前已经用到哪个节点了)——同单链表
int e[N], l[N], r[N], idx;
2.初始化双链表
我们默认初始化:0表示左端点(首),1表示右端点(尾),这两个是边界点。
初始化两个哨兵节点(0、1分别是首和尾),R[0]=1,L[1]=0,分别表示将首节点0向右连接到尾节点1、将尾节点1向左连接到首节点0。R[0]表示0的右,L[1]表示1的左
因为初始化就用了两个,因此idx = 2
//初始化双链表
void init()
{
r[0] = 1, l[1] = 0;
idx = 2;// 因为初始化就用了两个,因此idx = 2下标是从二开始的
}

3.正下标为k的节点的右边插入x
//在下标为k的节点的右边,插入x
void add(int k ,int x)
{
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx;
idx ++;
}

那么问题来了如果我们想在下标为k的左边插入x该怎么实现呢?
你可能会说可以向上述在右边插入操作一样实现,那当然是可以的,但是代码就多写了。在下标为k的节点的左边插入x,其实就是在l[k]的右边(l[k]为下标k位置节点的左边节点的下标!)插入x,即我们可以直接调用上述add()函数操作即可,减少了一定的代码量。
// 在下标为k的节点的左边插入x
add(l[k] , x);
4.删除下标为k的节点
// 删除第k个节点
void remove(int k)
{
r[l[k]] = r[k];
l[r[k]] = l[k];
}

5.例题
实现一个双链表,双链表初始为空,支持 5 种操作:
- 在最左侧插入一个数;
- 在最右侧插入一个数;
- 将第 k 个插入的数删除;
- 在第 k 个插入的数左侧插入一个数;
- 在第 k 个插入的数右侧插入一个数
现在要对该链表进行 MM 次操作,进行完所有操作后,从左到右输出整个链表。
注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。
输入格式
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
L x,表示在链表的最左端插入数 x。R x,表示在链表的最右端插入数 x。D k,表示将第 k 个插入的数删除。IL k x,表示在第 k 个插入的数左侧插入一个数。IR k x,表示在第 k 个插入的数右侧插入一个数。输出格式
共一行,将整个链表从左到右输出。
数据范围
1≤M≤100000
所有操作保证合法。输入样例:
10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2输出样例:
8 7 7 3 2 9
【参考代码】
#include<iostream>
using namespace std;
const int N = 100000+10;
int l[N], r[N], e[N], idx;
//初始化双链表
void init()
{
r[0] = 1, l[1] = 0;
idx = 2;// 下标是从二开始的,因此第k个数的下标:k + 1
}
//在下标为k的节点的右边,插入x
void add(int k ,int x)
{
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx;
idx ++;
}
// 删除第k个节点
void remove(int k)
{
r[l[k]] = r[k];
l[r[k]] = l[k];
}
int main()
{
int m;
cin>>m;
//初始化双链表
init();
while(m --)
{
int k, x;
string opt;
cin>>opt;
//表示在链表的最左端插入数 x(边界节点0的右边)
if(opt == "L")
{
cin>>x;
add(0, x);
}
//表示在链表的最右端插入数 xx(边界节点1的左边边)
else if(opt == "R")
{
cin>>x;
add(l[1],x);
}
//表示将第 k 个插入的数删除
else if(opt == "D")
{
cin>>k;
remove(k + 1);
}
//表示在第 k 个插入的数左侧插入一个数
else if(opt == "IL")
{
cin>>k>>x;
add(l[k + 1], x);
}
else if(opt == "IR")
{
cin>>k>>x;
add(k + 1, x);
}
}
// 遍历双链表
for(int i=r[0]; i!=1; i=r[i]) cout << e[i] << ' ';
return 0;
}
下标是从二开始的,因此第k个数的下标:k + 1
6.总结
双链表的操作与单链表存在着很大的联系,两个指针使得插入操作变得相对来说繁琐了一些,在写代码的过程中一定要手动画图!画图!画图!
注:如果文章有任何错误或不足,请各位大佬尽情指出,评论留言留下您宝贵的建议!如果这篇文章对你有些许帮助,希望可爱亲切的您点个赞推荐一手,非常感谢啦

数组模拟双链表,你get到了吗?的更多相关文章
- Problem UVA12657-Boxes in a Line(数组模拟双链表)
Problem UVA12657-Boxes in a Line Accept: 725 Submit: 9255 Time Limit: 1000 mSec Problem Description ...
- UVa 12657 Boxes in a Line(数组模拟双链表)
题目链接 /* 问题 将一排盒子经过一系列的操作后,计算并输出奇数位置上的盒子标号之和 解题思路 由于数据范围很大,直接数组模拟会超时,所以采用数组模拟的链表,left[i]和right[i]分别表示 ...
- 【数组模拟的链表or复杂模拟】PAT-L2-002. 链表去重
L2-002. 链表去重 给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点.即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留.同时,所有被删除的结点必须 ...
- 数组模拟单向链表例题(UVa11988)
指针的链表实现方式是,当前节点的next指向下一个节点,用数组模拟就是 for(int i=next[0];i!=0;i=next[i]) i=next[i]:就是一条链. 例题: 你有一个破损的键盘 ...
- python算法双指针问题:使用列表和数组模拟单链表
这个很多基础算法,python已内部实现了. 所以,要想自己实现链表这些功能时, 反而需要自己来构造链表的数据结构. 当然,这是python灵活之处, 也是python性能表达不如意的来源. valu ...
- POJ - 3476 A Game with Colored Balls---优先队列+链表(用数组模拟)
题目链接: https://cn.vjudge.net/problem/POJ-3476 题目大意: 一串长度为N的彩球,编号为1-N,每个球的颜色为R,G,B,给出它们的颜色,然后进行如下操作: 每 ...
- 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现
概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...
- UVA11988-Broken Keyboard(数组模拟链表)
Problem UVA11988-Broken Keyboard Accept: 5642 Submit: 34937 Time Limit: 1000 mSec Problem Descripti ...
随机推荐
- scrum项目冲刺_day09总结
摘要:今日完成任务. 1.短信服务完成(由于使用免费的接口,导致部分手机会收到垃圾短信) 2.注册登录完成 3.导航还在进行 总任务: 一.appUI页面(已完成) 二.首页功能: 1.图像识别功能( ...
- (超简单)VScode配置C/C++环境图文教程(Windows系统下)
(超简单)VScode配置C/C++环境图文教程(Windows系统下) 本文参考文章 Visual Studio Code (vscode) 配置 C / C++ 环境 下载VScode.下载Min ...
- Mongodb的基本使用及对接多数据源
mongodb介绍 MongoDB(来自于英文单词"Humongous",中文含义为"庞大")是可以应用于各种规模的企业.各个行业以及各类应用程序的开源数据库. ...
- 什么是云效 Projex,云效Projex企业级高效研发项目管理平台
云效项目协作Projects是一款企业级高效研发项目管理平台, 提供了快速实践的敏捷研发项目管理机制,提供对需求.迭代.缺陷各个维度的协同管理以及相关的统计报告,让研发团队高效协作.践行敏捷并持续交付 ...
- sonar扫面代码总体流程
- find_elements与find_element的区别
find_element不能使用len,find_elements可以使用len获取元素数量,判断页面有无某个元素,这个方法可以用来断言. 如添加用户后,判断是否添加成功. 删除用户后,判断是否删除成 ...
- FormData上传文件 带进度条
* jQuery ajax FormData 上传文件 template $.ajax({ url: url, type: 'POST', data: new FormData(form), dat ...
- bzoj4589-Hard Nim【FWT】
正题 题目链接:https://darkbzoj.tk/problem/4589 题目大意 求有多少个长度为\(n\)的数列满足它们都是不大于\(m\)的质数且异或和为\(0\). 解题思路 两个初始 ...
- spring-data-redis 上百万的 QPS 压力太大连接失败,我 TM 人傻了
大家好,我们最近业务量暴涨,导致我最近一直 TM 人傻了.前几天晚上,发现由于业务压力激增,某个核心微服务新扩容起来的几个实例,在不同程度上,出现了 Redis 连接失败的异常: org.spring ...
- Java - 你的 Java 代码有这些坏味道吗?
列举一些 Java 开发中常见的"不良实践",来源于代码扫描(https://github.com/pmd/pmd),和诸君一起学习参考: 1 - 关闭资源 CloseResour ...