You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

##AcWing 827. 双链表

一、题目描述

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

  • 在最左侧插入一个数;
  • 在最右侧插入一个数;
  • 将第 k 个插入的数删除;
  • 在第 k 个插入的数左侧插入一个数;
  • 在第 k 个插入的数右侧插入一个数

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

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

输入格式 第一行包含整数 M,表示操作次数。

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

L x,表示在链表的最左端插入数 xR x,表示在链表的最右端插入数 xD 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

二、理解与感悟

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

  1. 初始化 0这个位置标识,留给了head 1这个位置标识,留给了tail

由于01已被占用,所以,正式数据的下标从2开始,即idx=2

/**
 * 功能:初始化
 */
void init() {
    r[0] = 1, l[1] = 0, idx = 2;
}

三、实现代码

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;

int e[N];       // 存储数值
int l[N], r[N]; // 左指针,右指针
int idx;        // 数组下标的索引值

void init() {
    r[0] = 1, l[1] = 0, idx = 2;
}

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

void remove(int k) {
    r[l[k]] = r[k], l[r[k]] = l[k];
}
int main() {
    init();
    int m, k, x;
    cin >> m;
    while (m--) {
        string op;
        cin >> op;
        if (op == "L") {
            cin >> x;
            // 最左端插入数x
            // 最左端就是表示在0的右侧插入一个数据
            add(0, x);
        } else if (op == "R") {
            cin >> x;
            // 最右端插入数x
            add(l[1], x); // 1号端点的左侧就是最右端
        } else if (op == "D") {
            cin >> k;
            remove(k + 1); // idx从2开始所以下标需要k+1传入才对
        } else if (op == "IL") {
            cin >> k >> x;
            add(l[k + 1], x); // 在这个k的左侧那个元素的右侧插入数据x
        } else {
            cin >> k >> x;
            add(k + 1, x); // 正常调用
        }
    }
    // 注意双链表的输出方法,0和1是一头一尾idx从2开始换言之
    //  从r[0]就是开始进行遍历出现1就结尾了
    for (int i = r[0]; ~i; i = r[i]) printf("%d ", e[i]);
    return 0;
}