数组模拟双链表

通过前面的学习我们知道单链表是单个指针指向操作,那么通过类比我们可以把指针设定为两个,并且让它们分别指向前后数据,这就是“双向链表”。使用这种链表,不仅可以从前往后, 还可以从后往前遍历数据,十分方便。

1.使用数组模拟双链表

  1. // e[i] 表示节点i的值
  2. // l[i] 指向当前节点的上一节点(左节点)的指针:即存的是左边一个节点的位置(下标)
  3. // r[i] 指向当前节点的下一节点(右节点)的指针:即存的是右边一个节点的位置(下标)
  4. // idx 存储当前已经用到的节点(当前已经用到哪个节点了)——同单链表
  5. 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

  1. //初始化双链表
  2. void init()
  3. {
  4. r[0] = 1, l[1] = 0;
  5. idx = 2;// 因为初始化就用了两个,因此idx = 2下标是从二开始的
  6. }

3.正下标为k的节点的右边插入x

  1. //在下标为k的节点的右边,插入x
  2. void add(int k ,int x)
  3. {
  4. e[idx] = x;
  5. r[idx] = r[k];
  6. l[idx] = k;
  7. l[r[k]] = idx;
  8. r[k] = idx;
  9. idx ++;
  10. }

那么问题来了如果我们想在下标为k的左边插入x该怎么实现呢?

你可能会说可以向上述在右边插入操作一样实现,那当然是可以的,但是代码就多写了。在下标为k的节点的左边插入x,其实就是在l[k]的右边(l[k]为下标k位置节点的左边节点的下标!)插入x,即我们可以直接调用上述add()函数操作即可,减少了一定的代码量。

  1. // 在下标为k的节点的左边插入x
  2. add(l[k] , x);

4.删除下标为k的节点

  1. // 删除第k个节点
  2. void remove(int k)
  3. {
  4. r[l[k]] = r[k];
  5. l[r[k]] = l[k];
  6. }

5.例题

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

  1. 在最左侧插入一个数;
  2. 在最右侧插入一个数;
  3. 将第 k 个插入的数删除;
  4. 在第 k 个插入的数左侧插入一个数;
  5. 在第 k 个插入的数右侧插入一个数

现在要对该链表进行 MM 次操作,进行完所有操作后,从左到右输出整个链表。

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

输入格式

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

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

  1. L x,表示在链表的最左端插入数 x。
  2. R x,表示在链表的最右端插入数 x。
  3. D k,表示将第 k 个插入的数删除。
  4. IL k x,表示在第 k 个插入的数左侧插入一个数。
  5. 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

【参考代码】

  1. #include<iostream>
  2. using namespace std;
  3. const int N = 100000+10;
  4. int l[N], r[N], e[N], idx;
  5. //初始化双链表
  6. void init()
  7. {
  8. r[0] = 1, l[1] = 0;
  9. idx = 2;// 下标是从二开始的,因此第k个数的下标:k + 1
  10. }
  11. //在下标为k的节点的右边,插入x
  12. void add(int k ,int x)
  13. {
  14. e[idx] = x;
  15. r[idx] = r[k];
  16. l[idx] = k;
  17. l[r[k]] = idx;
  18. r[k] = idx;
  19. idx ++;
  20. }
  21. // 删除第k个节点
  22. void remove(int k)
  23. {
  24. r[l[k]] = r[k];
  25. l[r[k]] = l[k];
  26. }
  27. int main()
  28. {
  29. int m;
  30. cin>>m;
  31. //初始化双链表
  32. init();
  33. while(m --)
  34. {
  35. int k, x;
  36. string opt;
  37. cin>>opt;
  38. //表示在链表的最左端插入数 x(边界节点0的右边)
  39. if(opt == "L")
  40. {
  41. cin>>x;
  42. add(0, x);
  43. }
  44. //表示在链表的最右端插入数 xx(边界节点1的左边边)
  45. else if(opt == "R")
  46. {
  47. cin>>x;
  48. add(l[1],x);
  49. }
  50. //表示将第 k 个插入的数删除
  51. else if(opt == "D")
  52. {
  53. cin>>k;
  54. remove(k + 1);
  55. }
  56. //表示在第 k 个插入的数左侧插入一个数
  57. else if(opt == "IL")
  58. {
  59. cin>>k>>x;
  60. add(l[k + 1], x);
  61. }
  62. else if(opt == "IR")
  63. {
  64. cin>>k>>x;
  65. add(k + 1, x);
  66. }
  67. }
  68. // 遍历双链表
  69. for(int i=r[0]; i!=1; i=r[i]) cout << e[i] << ' ';
  70. return 0;
  71. }

下标是从二开始的,因此第k个数的下标:k + 1

6.总结

双链表的操作与单链表存在着很大的联系,两个指针使得插入操作变得相对来说繁琐了一些,在写代码的过程中一定要手动画图!画图!画图!

注:如果文章有任何错误或不足,请各位大佬尽情指出,评论留言留下您宝贵的建议!如果这篇文章对你有些许帮助,希望可爱亲切的您点个赞推荐一手,非常感谢啦

数组模拟双链表,你get到了吗?的更多相关文章

  1. Problem UVA12657-Boxes in a Line(数组模拟双链表)

    Problem UVA12657-Boxes in a Line Accept: 725  Submit: 9255 Time Limit: 1000 mSec Problem Description ...

  2. UVa 12657 Boxes in a Line(数组模拟双链表)

    题目链接 /* 问题 将一排盒子经过一系列的操作后,计算并输出奇数位置上的盒子标号之和 解题思路 由于数据范围很大,直接数组模拟会超时,所以采用数组模拟的链表,left[i]和right[i]分别表示 ...

  3. 【数组模拟的链表or复杂模拟】PAT-L2-002. 链表去重

    L2-002. 链表去重 给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点.即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留.同时,所有被删除的结点必须 ...

  4. 数组模拟单向链表例题(UVa11988)

    指针的链表实现方式是,当前节点的next指向下一个节点,用数组模拟就是 for(int i=next[0];i!=0;i=next[i]) i=next[i]:就是一条链. 例题: 你有一个破损的键盘 ...

  5. python算法双指针问题:使用列表和数组模拟单链表

    这个很多基础算法,python已内部实现了. 所以,要想自己实现链表这些功能时, 反而需要自己来构造链表的数据结构. 当然,这是python灵活之处, 也是python性能表达不如意的来源. valu ...

  6. POJ - 3476 A Game with Colored Balls---优先队列+链表(用数组模拟)

    题目链接: https://cn.vjudge.net/problem/POJ-3476 题目大意: 一串长度为N的彩球,编号为1-N,每个球的颜色为R,G,B,给出它们的颜色,然后进行如下操作: 每 ...

  7. 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  8. 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

    概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...

  9. UVA11988-Broken Keyboard(数组模拟链表)

    Problem UVA11988-Broken Keyboard Accept: 5642  Submit: 34937 Time Limit: 1000 mSec Problem Descripti ...

随机推荐

  1. yapi 事件创建、修改等接口事件监听

    使用的yapi作为接口文档平台.出于业务需求需要对接口创建.修改.删除等事件进行监听. yapi已经实现并预留了这个口子,但是没有找到实现的文档.这里进行简单描述下使用的方式. 一.yapi创建.修改 ...

  2. mybatis if else if 条件判断SQL片段表达式取值和拼接

    前言 最近在开发项目的时候涉及到复杂的动态条件查询,但是mybaits本身不支持if elseif类似的判断但是我们可以间接通过 chose when otherwise 去实现其中choose为一个 ...

  3. SonarQube汉化

    SonarQube安装后默认是英文,如果不习惯看英文,可以进行汉化,官方提供了汉化插件. 登录后,汉化步骤如下: 需要点击了解风险,不然查询到插件后没有install按钮 搜索Chinese,找到插件 ...

  4. 测试验收标准checklist

    需求实现功能清单 功能实现目的 需求改造功能清单 关联功能清单 关联系统 端到端全流程场景 业务联系性场景 业务全流程场景 上下需求关联规则 业务角度在流程中关注项 财报.评级 授信方案 反洗钱 面向 ...

  5. P4717-[模板]快速莫比乌斯/沃尔什变换(FMT/FWT)

    正题 题目链接:https://www.luogu.com.cn/problem/P4717 题目大意 给出两个长度为\(2^n\)的数列\(A,B\)求 \[C_{n}=\sum_{i\ or\ j ...

  6. Fiddler抓HTTPS接口数据,安装证书并不复杂,超详细的图文解说,不信你看!

    @ 目录 前言 安装环境 配置网络 IP 端口 配置网络 浏览器打开下载链接 下载证书 安装证书 证书安装坑 前言 抓包是我测试工作中必须要学会的一个工具,我们都知道,抓取HTTPS接口里需要安装证书 ...

  7. 四、mybatis动态sql

    # 前言前面mysql都是通过静态sql进行查询的,但是如果业务复杂的时候,我们会遇到引号问题,或者多一个空格,这就使得sql代码编写错误了,所以为了解决这个问题,我们有了动态sql. Mybatis ...

  8. PyTorch固定参数

    In situation of finetuning, parameters in backbone network need to be frozen. To achieve this target ...

  9. 踩坑系列《四》a标签的href属性拼接问题

    如上所示,无法直接在 html里面的 a 标签的href属性传递参数时,只需要在 JS 中获取对应 a 标签的id,再通过 attr 方法抓到 href,进行字符串拼接即可

  10. Spring Bean装配笔记

    Spring Bean装配笔记 Spring中的Bean是一个很重要的概念.Spring作为一个Bean容器,它可以管理对象和对象之间的依赖关系,我们不需要自己建立对象,把这部分工作全部转交给容器完成 ...