单链表与双链表的创建与使用C++

单链表

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

1.向链表头插入一个数;

2.删除第k个插入的数后面的一个数;

3.在第k个插入的数后插入一个数。

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

注意:题目中第k个插入的数并不是指当前链表的第k个数。例如操作过程中一共插入了n个数,则按照插入的时间顺序,这n个数依次为:第1个插入的数,第2个插入的数,…第n个插入的数。//idx代表的就是当前插入的是第几个数,而不是他的坐标,所以在每次进行插入操作后都需要加1

输入格式

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

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

1.H x,表示向链表头插入一个数x

2.D k,表示删除第k个插入的数后面的数(当k0时,表示删除头结点)。

3.I k x,表示在第k个插入的数后面插入一个数x(此操作中k均大于0)。

输出格式

共一行,将整个链表从头到尾输出。

数据范围

1≤M≤1000001≤��≤100000
所有操作保证合法。//比如再删掉某一个已经插入的数后,因为每次插入标注是按照idx来标记,所以如果删掉了,那证明对应的idx也消失了,那么后面输入的操作数就不能在以idx这个数据代表的节点上进行操作,这就是所说的合法性。

Eg:

#include <iostream>

using namespace std;

const int N = 100010;

 

//head表示头结点的下标,这个head就只是一个坐标,没有具体数值

//e[i]表示节点i的值

//ne[i]表示当前节点i的next指针是多少

//idx存储当前已经用到了那个点

int head,e[N],ne[N],idx;

//初始化

void init()

{

    head = -1;

    idx = 0;

}

//将x插入到头结点,就是说插入成为第一个点。

void add_to_head(int x)

{

    e[idx] = x;

    ne[idx] = head;

    head = idx;

    idx++;

}

//移除坐标为K的后面的节点,在这里表示移除idx为k的后面的节点

void remove(int k)

{

    ne[k] = ne[ne[k]];

}

//将x插入到坐标为k的节点,在这个题目语境中,代指将x插入到idx为k的节点。

void add(int k,int x)

{

e[idx] = x;  

ne[idx] = ne[k];

ne[k] = idx;

idx++;

}

int main()

{

    int m;

    cin>>m;

    

    init();//初始化

    

    while(m--)

    {

        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);//因为这里idx是从0开始,也就是说第一个节点的idx为0,而题目中默认第一个节点的idx为1,所以这里要减一才能满足我们所写代码需求。

        }

        else

        {

            cin>>k>>x;

            add(k-1,x);

        }

    }

    for(int i = head;i!=-1;i = ne[i]) cout<<e[i]<<' ';//最后一个节点的指针指向空节点,就是-1.

    cout<<endl;

    return 0;

}

双链表

相比于单链表,双链表设置了开头和结尾两个指针,对应的idx分别为0和1,这使得在添加头节点时候能与普遍添加节点共用一套代码,更加方便。

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

1.在最左侧插入一个数;//相当于是在左指针右边添加一个头节点

2.在最右侧插入一个数;//相当于是在右指针右边添加一个头节点

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

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

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

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

注意:题目中第k个插入的数并不是指当前链表的第k个数。例如操作过程中一共插入了n个数,则按照插入的时间顺序,这n个数依次为:第11个插入的数,第22个插入的数,…第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≤1000001≤��≤100000
所有操作保证合法。

#include <iostream>

using namespace std;

#include <string>

const int N = 100010;

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

//初始化双链表,idx为0是左指针,1为为右指针

void init()

{

    r[0] = 1;l[1] = 0;

    idx = 2;

}

//在idx为k的点右侧插入x

void add(int k,int x)

{

    e[idx] = x;

    l[idx] = k;

    r[idx] = r[k];

    l[r[k]] = idx;

    r[k] = idx;

    idx++;

}

//删掉某一个节点

void de(int k)

{

    r[l[k]] = r[k];

    l[r[k]] = l[k];

}

int main()

{

    int m;cin>>m;

    init();

    while(m--)

    {

        string c;cin>>c;

        if(c[0]=='D') {int k;cin>>k;de(k+1);}

        else if(c[1]=='R') {int k,x;cin>>k>>x;add(k+1,x);}

        else if(c[1]=='L') {int k,x;cin>>k>>x;add(l[k+1],x);}//因为第一个节点是从2开始的,而题目默认开始节点为1,所以需要加1

        else if(c[0]=='L')  {int x;cin>>x;add(0,x);}

        else if(c[0]=='R')  {int x;cin>>x;add(l[1],x);}

    }

    for(int i = r[0];i!=1;i = r[i]) cout<<e[i]<<' ';

    cout<<endl;

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值