数组模拟链表(单链表和双链表)

在创建单链表时如果使用使用动态的单链表,那么每创建一个结点时就会使用new 当数据比较大的时候,程序运行的时间很长 所以在写题的时候 往往会那数组来模拟一个链表;

先进行如下定义:
head为头结点的头指针;
idx为当前记录到那个结点;
那数组e【N】和ne[N]来模拟一个静态链表,数组e用来储存当前结点的值,ne表示下一个结点的下标;

初始化

初始化时将头节点的头指针指向-1,此时idx=0,因为要下一个处理下标为0的结点

void init()//初始化链表 
{
	head=-1;
	idx=0;
}

插入操作
向头节点后面插入一个数
在这里插入图片描述

void push_head(int x)
{
	e[idx]=x;
	ne[idx]=head;
	head=idx;
	idx++;
}

向第k个结点后插入一个结点(第k个表示的是第k个插入的数,不是位置上的第k个
在这里插入图片描述

void push_k(int k,int x)
{
	e[idx]=x;
	ne[idx]=ne[k];
	ne[k]=idx;
	idx++;
}

删除
将第k个结点删除

当k为0时表示删除头节点

void pop_head()
{
	head=ne[head];
}

不为0时
在这里插入图片描述

void pop_k(int k)
{
	ne[k]=ne[ne[k]];
}

例题:
在这里插入图片描述
在这里插入图片描述
代码

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100010;

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

void init()
{
    head=-1;
    idx=0;
}

void push_head(int x)
{
    e[idx]=x;
    ne[idx]=head;
    head=idx++;
}

void push_k(int k,int x)
{
    e[idx]=x;
    ne[idx]=ne[k];
    ne[k]=idx++;
}

void pop_k(int k)
{
    ne[k]=ne[ne[k]];
}

int main()
{
    cin>>n;
    init();
    while(n--)
    {
        char op;
        int k,x;
        cin>>op;
        
        if(op == 'H')
        {
            cin>>x;
            push_head(x);
        }
        else
            if(op == 'I')
            {
                cin>>k>>x;
                push_k(k-1,x);
            }
            else
            {
                cin>>k;
                if(k==0)
                {
                    head=ne[head];
                }
                else
                {
                    pop_k(k-1);
                }
            }
    }
    for(int i=head;i!=-1;i=ne[i])
    {
        cout<<e[i]<<" ";
    }
}

双向链表

在上面的单向链表中我们可以看出单项链表在遍历时只能沿这一个方向去遍历,而双向链表可以沿两个方向去遍历 这样 就大大的提高了 链表的效率

在模拟双向练表时 可以先模拟两个临界 分别代表左端点和右端点

先说明以下定义
l[N]和r[N]是当前结点的前一个结点的下标和后一个节点的下标;
idx表示当时用到了那一个结点;
e[N]表示当前结点的值

初始化
在这里面的l【1】和r【0】相当于双链表的右左哨兵

void init()//初始化链表 
{
	l[1]=0;
	r[0]=1;
	idx=2;
}

插入(向k结点的右侧插入一个数)

void push_k(int k,int x)
{
	e[k]=x;
	l[r[k]]=idx;
	r[idx]=r[k];
	l[idx]=k;
	r[k]=idx++;
}
这个代码不仅可以实现向双链表k结点的右侧插入还可以实现双链表的最左侧,最右侧,k结点的左侧
向最左侧:只需要让k=r【0】;
向最右侧:只需要让k=l【1】;
向k结点的左侧:只需要让k=l【k】;

删除操作

删除第k个结点
void pop_k(int k)
{
    r[l[k]]=r[k];
    l[r[k]]=l[k];
}

例题

在这里插入图片描述

在这里插入图片描述
代码

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100010;

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

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

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

int main()
{
    cin>>m;
    r[0]=1,l[1]=0,idx=2;
  while(m--)
    {
        int x,k;
        string op;
        cin>>op;
        if(op=="L")
        {
            cin>>x;
            push_rx(0,x);
        }
        if(op=="R")
        {
            cin>>x;
            push_rx(l[1],x);
        }
        if(op=="D")
        {
            cin>>k;
            pop_k(k+1);
        }
            if(op=="IL")
        {
            cin>>k>>x;
            push_rx(l[k+1],x);
        }
        if(op=="IR")
        {
            cin>>k>>x;
            push_rx(k+1,x);
        }
    }
    for(int i=r[0];i!=1;i=r[i])
    cout<<e[i]<<" ";
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值