数组模拟双链表

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

(1) 在最左侧插入一个数;

(2) 在最右侧插入一个数;

(3) 将第k个插入的数删除;

(4) 在第k个插入的数左侧插入一个数;

(5) 在第k个插入的数右侧插入一个数

初始化

双链表,需要开三个数组。
e[]存放该节点的数值,
l[] 数组存放该节点左边的节点,
r[]数组存放该节点右边的节点。

初始化:使用哨兵节点0和1,下标为0的节点记为头结点head,下标为1的节点记为尾节点tail。

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

插入节点

在下标为k的节点右边插入节点数值为x,该节点的下标为idx,首先需要e[idx]=x;然后分为四步,
step1:看该节点的右节点
step2:看该节点的左节点
step3:看原来的右节点的左节点
step4:看k的右节点

需要注意的是:step3和step4不能交换顺序,这是因为r[k]存在被提前更新的风险。

void add(int k,int x){
	e[idx]=x;
	r[idx]=r[k];
	l[idx]=k;
	l[r[k]]=idx;//该步在前,防止r[k]被提前更新
	r[k]=idx;
	idx++;
}

在这里插入图片描述
在k节点左边插入一个节点,数值为x,相当于求 l [ k ] l[k] l[k] 的右节点,只需要调用上述的add函数,将k改为k左边的节点 l [ k ] l[k] l[k]

删除节点

删除下标为k的节点,只需要使得k的左节点 l [ k ] l[k] l[k]的右节点为 r [ k ] r[k] r[k],相反,k的右节点 r [ k ] r[k] r[k]的左节点变为 l [ k ] l[k] l[k]

void remove(int k){
	r[l[k]]=r[k];
	l[r[k]]=l[k];
}

在这里插入图片描述

本题需要注意:
因为0和1号节点已经占用,所用第k个节点对应的是下标为k+1的节点。比如第1个节点,对应的下标是2.

ac代码

#include<iostream>
using namespace std;
const int maxn=1e5+10;

int l[maxn],r[maxn],e[maxn],idx;

//初始化
void init(){
    //0表示左端点,1表示右端点
    r[0]=1,l[1]=0;
    idx=2;//因为0和1已经被占用
}

//在下标为k的节点的右边,插入一个点

int 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(){
    init();
    int m,k,x;
    string op;
    cin>>m;
    while(m--){
        cin>>op;
        //cout<<op<<endl;
        if(op=="R"){
            cin>>x;
            add(l[1],x);
        }
        else if(op=="L"){
            cin>>x;
            add(0,x);
            
        }
        else if(op=="D"){
            cin>>k;
            remove(k+1);
        }
        else if(op=="IL"){
            cin>>k>>x;
            add(l[k+1],x);
            
        }
        else if(op=="IR"){
            cin>>k>>x;
            add(k+1,x);
        }
        
        
    }
    for(int i=r[0];i!=1;i=r[i]) cout<<e[i]<<" ";
    return 0;
    
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页