【题目来源】
https://www.acwing.com/problem/content/828/
【题目描述】
实现一个单链表,链表初始为空,支持三种操作:
- 向链表头插入一个数;
 - 删除第 k 个插入的数后面的数;
 - 在第 k 个插入的数后插入一个数。
 
现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。
注意:++题目中第 k 个插入的数并不是指当前链表的第 k 个数++ 。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,...第 n 个插入的数。
【输入格式】
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
- H x,表示向链表头插入一个数 x。
 - D k,表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)。
 - I k x,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 0)。
 
【输出格式】
共一行,将整个链表从头到尾输出。
【数据范围】
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
【算法分析】
本题利用数组模拟实现单链表。利用数组模拟单链表常见的核心操作代码如下所示:
            
            
              cpp
              
              
            
          
          // head   头结点的下标
// e[i]   结点i的值
// ne[i]  结点i的next指针
// idx    当前可用结点的下标,可看做指针
int head, e[N], ne[N], idx;
void init() { //初始化
    head=-1; //head指向空
    idx=0;
}
void add_to_head(int x) { //将x插入到首元结点
    e[idx]=x;
    ne[idx]=head;  // idx指向head指向的结点
    head=idx++;     // head指向idx
}
void add(int k,int x) { //将x插到到下标为k的结点后面
    e[idx]=x;
    ne[idx]=ne[k];
    ne[k]=idx++;
}
void remove(int k) { //将下标为K后面的点删除
    ne[k]=ne[ne[k]];
}
        学习过链式前向星(https://blog.csdn.net/hnjzsyjyj/article/details/126474608)的会发现这些模拟单链表的变量及数组很熟悉。这是因为,链式前向星也是用数组模拟单链表,不过是要模拟多个单链表。链式前向星常见的核心操作代码如下所示:
其中:
val[idx] 表示第 idx 条边的权值。
e[idx] 表示第 idx 条边的终点。
ne[idx] 表示与第 idx 条边同起点的最近一次被添加的边的编号。
h[a] 表示以结点 a 为起点的最近一次被添加的边的编号。这个表述是在使用 ne[idx]=h[a] 时,也即使用 h[a]=idx++ 更新 h[a] 之前而言的。要特别注意这个语境。
很明显,h[a] 中存储的是以 a 为起点的所有边中编号最大的那个。且在遍历时,把这条边作为以 a 为起点的所有边中的第一条边进行遍历。即边的遍历顺序与输入顺序恰好是相反的。而网上常见的表述"e[idx] 表示第 idx 条边的终点,ne[idx] 表示与第 idx 条边同起点的**++下一条边++** 的存储位置,h[a] 表示以 a 为起点的++第一条边++的存储位置",是按边的遍历顺序进行表述的。
在上述约定下,则有:
● 链式前向星的核心代码如下:
            
            
              cpp
              
              
            
          
          void add(int a,int b) {
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
        如果是有权图,需多设置一个数组 val[] 存储权值。有权图的链式前向星的核心代码如下:
            
            
              cpp
              
              
            
          
          void add(int a,int b,int w) {
    val[idx]=w,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
        ● 基于链式前向星的深度优先搜索(DFS)的核心代码如下:
            
            
              cpp
              
              
            
          
          void dfs(int u) {
    cout<<u<<" ";
    st[u]=true;
    for(int i=h[u]; ~i; i=ne[i]) { //~i; equivalent to i!=-1;
        int j=e[i];
        if(!st[j]) {
            dfs(j);
        }
    }
}
        ● 基于链式前向星的广度优先搜索(BFS)的核心代码如下:
            
            
              cpp
              
              
            
          
          void bfs(int u) {
    queue<int>q;
    st[u]=true;
    q.push(u);
    while(!q.empty()) {
        int t=q.front();
        q.pop();
        cout<<t<<" ";
        for(int i=h[t]; ~i; i=ne[i]) { //~i; equivalent to i!=-1;
            int j=e[i];
            if(!st[j]) {
                q.push(j);
                st[j]=true; //need to be flagged immediately after being queued
            }
        }
    }
}
        【算法代码】
            
            
              cpp
              
              
            
          
          #include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
// head   头结点的下标
// e[i]   结点i的值
// ne[i]  结点i的next指针
// idx    当前可用结点的下标,可看做指针
int head, e[N], ne[N], idx;
void init() { //初始化
    head=-1; //head指向空
    idx=0;
}
void add_to_head(int x) { //将x插入到首元结点
    e[idx]=x;
    ne[idx]=head;  // idx指向head指向的结点
    head=idx++;     // head指向idx
}
void add(int k,int x) { //将x插到到下标为k的结点后面
    e[idx]=x;
    ne[idx]=ne[k];
    ne[k]=idx++;
}
void remove(int k) { //将下标为K后面的点删除
    ne[k]=ne[ne[k]];
}
int main() {
    int T;
    cin>>T;
    init();
    while(T--) {
        int k,x;
        char op;
        cin>>op;
        if(op=='H') {
            cin>>x;
            add_to_head(x);
        } else if(op=='D') {
            cin>>k;
            if(!k) head=ne[head]; //对删除头结点特判
            remove(k-1);
        } else {
            cin>>k>>x;
            add(k-1,x);
        }
    }
    for(int i=head; i!=-1; i=ne[i]) cout<<e[i]<<" ";
    return 0;
}
/*
in:
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
out:
6 4 6 5
*/ 
        【参考文献】
https://www.acwing.com/blog/content/2141/
https://blog.csdn.net/hnjzsyjyj/article/details/126474608