<算法笔记>链表

        链表是用一组位于任意位置的存储单位存储线性表的结构,它与数组不同在于,数组是的存储单元是连续的,而链表可以连续,也可以不连续,因此,在有关插入、删除的操作中,我们使用链表会更加方便快捷。

        链表分为单向链表和双向链表,使用链表时,可以直接使用STL list,也可以自己实现,通常实现方法有动态链表和静态链表。在算法竞赛中,选手通常使用STL list减少编译时间和书写时间,有时也会手动实现静态链表,而对于能及时释放空间的动态链表,则往往不会使用,这是因为它需要管理空间,容易出错,且大多算法竞赛并不会对内存要求过于苛刻。因此,在下面就不给出相关代码了,有兴趣的同学可以自行查找相关资料。

        接下来分别给出静态链表、STL链表的实现代码:(以洛谷P1160:队列安排为例)

1.用结构体实现双向静态链表:

#include<bits/stdc++.h>
using namespace std;
const int N = 200000;
struct node{
    int data;
    int next;
    int prev;
}nodes[N];
int n,k,p,m,x,head;
bool st[N];
void insert(int i,int k,int p)	//插入 
{
	nodes[i].data = i;
	if(p) {
		nodes[i].next = nodes[k].next;
		nodes[i].prev = k;
		nodes[k].next = i;
		nodes[nodes[i].next].prev = i;
	}
	else if(!p) {
		nodes[i].prev = nodes[k].prev;
		nodes[i].next = k;
		if(nodes[i].prev == -1) head = i;
		else nodes[nodes[i].prev].next = i; 
		nodes[k].prev = i;
	}
}
void remove(int i)	//删除 
{
	nodes[nodes[i].prev].next = nodes[i].next;
	nodes[nodes[i].next].prev = nodes[i].prev;
}
int main()
{
    scanf("%d",&n);
    head = 1;
    nodes[1].data = 1, nodes[1].next = -1, nodes[1].prev = -1;	//初始化 
    for(int i = 2; i <= n; i++) {
    	scanf("%d%d",&k,&p);
    	insert(i,k,p); 
	}
	scanf("%d",&m);
	for(int i = 0; i < m; i++)
	{
		scanf("%d",&x);
		if(!st[x])	{
			remove(x);
			st[x] = true;
		}
	}
	for(int i = head; i!=-1; i=nodes[i].next) 	cout<<nodes[i].data<<" ";
	return 0;
}

2.用一维数组实现双向链表:

#include<bits/stdc++.h>
using namespace std;
#define N 200000
int n,m,k,p,x;
int e[N],r[N],l[N],idx,st[N];
int head;
void init()
{
    r[0] = 1, l[1] = 0;
    idx = 2;
}
void add(int k,int x,int p)
{
    if(p==1)
    {
        e[idx]=x;
        r[idx]=r[k],l[r[k]]=idx;
        l[idx]=k,r[k]=idx++;
    }
    else
    {
        e[idx]=x;
        l[idx]=l[k],r[l[k]]=idx;
        r[idx]=k,l[k]=idx++;
    }
}
void remove(int k)
{
    r[l[k]]=r[k];
    l[r[k]]=l[k];
}

int main()
{
	init();
    cin>>n;
    add(r[0],1,0);
    for(int i=2;i<=n;i++)
    {
        cin>>k>>p;
        add(k+1,i,p);
    }
    cin>>m;
    while (m -- )
    {
        cin>>x;
        if(st[x+1]==0) remove(x+1);
        st[x+1]=1;
    }
    for(int i=r[0];i!=1;i=r[i]) cout<<e[i]<<" ";
}

3.使用STL list实现:

#include<bits/stdc++.h>
using namespace std;
const int N = 200000;
int n,k,p,m,x;
bool st[N];
list<int> mylist;
list<int>::iterator iter[N],neit,it;
int main()
{
    scanf("%d",&n);
    mylist.push_back(1);
    iter[1] = mylist.begin();
    for(int i = 2; i <= n; i++) {
    	scanf("%d%d",&k,&p);
    	if(p)	
		{
			neit = iter[k];
			iter[i] = mylist.insert(++neit,i);
		} 
    	else if(!p)	
		{
			iter[i] = mylist.insert(iter[k],i);
		}
	}
	scanf("%d",&m);
	for(int i = 0; i < m; i++)
	{
		scanf("%d",&x);
		if(!st[x]) {
			mylist.erase(iter[x]);
			st[x] = true;
		}
	}
	for(it = mylist.begin();it!=mylist.end();it++) cout<<*it<<" ";
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值