0
点赞
收藏
分享

微信扫一扫

827. 双链表


文章目录

  • ​​Question​​
  • ​​Ideas​​
  • ​​Code​​

Question

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

在最左侧插入一个数;
在最右侧插入一个数;
将第 k 个插入的数删除;
在第 k 个插入的数左侧插入一个数;
在第 k 个插入的数右侧插入一个数
现在要对该链表进行 M 次操作,进行完所有操作后,从左到右输出整个链表。

注意:题目中第 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

Ideas

​双链表关键操作:​

  1. 删除第k个节点右边的节点
  2. 在第k个节点的右边添加值为x的节点(在第k个节点的左边添加值为x的节点可以转换为在第k个节点左侧的右边添加值为x的节点)

需要注意:head为0节点,tail为1节点
从左到右遍历双链表:

for (int i = r[0]; i != 1; i = r[i]) // 1为右边界
cout << e[i] << ' ';

Code

#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int idx,l[N],r[N],e[N];

// 初始化双链表
void init()
{
idx = 2; // head和tail分别占用了0和1
r[0] = 1;
l[1] = 0;
}

// 在k位置右侧插入x
void insert(int k, int x)
{
e[idx] = x;

l[idx] = k; // 新插入节点的左边指向k
r[idx] = r[k]; // 新插入节点的右边指向k的右边

l[r[k]] = idx; // k的右边的左边指向新插入节点
r[k] = idx; // k的右边指向新插入的节点

idx ++;

}

// 删除k位置右边的节点
void remove(int k)
{
r[l[k]] = r[k]; // 让k节点的左边的右指针指向k的右边
l[r[k]] = l[k]; // 让k节点的右边的左指针指向k的左边
}

int main()
{
init();

int m;
cin >> m;
while(m --)
{
string c;
cin >> c;

if (c == "L")
{
int x;
cin >> x;
insert(0, x);
}
else if(c == "R")
{
int x;
cin >> x;
insert(l[1], x);
}
else if(c == "D")
{
int k;
cin >> k;
remove(k + 1); // 0和1被占据
}
else if (c == "IL")
{
int k, x;
cin >> k >> x;
insert(l[k + 1], x); // 在k的左边插入x 等价于 在k的左侧插入x
}
else
{
int k, x;
cin >> k >> x;
insert(k + 1, x);
}

}
for (int i = r[0]; i != 1; i = r[i]) // 1为右边界
cout << e[i] << ' ';

return 0;

}


举报

相关推荐

0 条评论