P1160 队列安排(洛谷)

1.用循环队列实现(链表形式)

结果有几个样例tle了(链表实现会面临时间复杂度的问题)

#include<iostream>//对删除的方式进行一下改进,为减少时间复杂度,不如不删除,而是将删除的进行一下标记
using namespace std;
struct node
{
	node* llink;
	node* rlink;
	int data;
	int v;//记录是否被删除
	node(int x, node* l = NULL, node* r = NULL)
	{
		data = x; llink = l; rlink = r; v = 0;
	}
	node(node* l = NULL, node* r = NULL)
	{
		llink = l; rlink = r; v = 0;
	}
};
struct list//双向链表
{
	node* head;
	list()
	{
		head = new node(0);
		head->rlink = new node(1);
		head->rlink->rlink = head;
		head->rlink->llink = head;
		head->llink = head->rlink;
	}
	bool insert(int k, int p, int i)//k是基准位置,p是插入方式,i是插入的数字 
	{
		node* current = find(k);//基准的位置
		if (current == NULL)return false;
		node* q = new node(i);
		if (p == 0)
		{
			q->llink = current->llink;
			current->llink = q;
			q->llink->rlink = q;
			q->rlink = current;
		}
		else if (p == 1)
		{
			q->rlink = current->rlink;
			current->rlink = q;
			q->rlink->llink = q;
			q->llink = current;
		}
		return true;
	}
	node* find(int &k)
	{
		node* p = head->rlink;
		while (p->data != k && p != head)
			p = p->rlink;
		if (p != head)return p;//若找到则就返回地址
		else return NULL;//若找不到,就返回空
	}
	bool pop(int k)
	{
		node* p = find(k);
		if(p!=NULL)p->v = 1;
	}
};
int main()
{
	list l;
	int N, k, p, M, x;
	cin >> N;
	for (int i = 2; i <= N; i++)
	{
		cin >> k >> p;
		l.insert(k, p, i);
	}
	cin >> M;
	while (M--)
	{
		cin >> x;
		if (l.find(x))l.pop(x);
	}
	node* current = l.head->rlink;
	while (current != l.head)
	{
		if(!current->v)cout << current->data << " ";
		current = current->rlink;
	}
	return 0;
}

这个find()函数调用多次,让代码效率降低了。

2.用数组模拟队列实现

数组里可以直接存储下标(相当于位置),对于find()的时间复杂度为1

对于删除操作,虽然说数组的删除操作很复杂,但是可以定义变量进行标记

#include<iostream>
using namespace std;
struct node
{
	int l, r;
	int v=0;//记录删没删除
};
int N;//同学个数
node* d = new node[N];
void add(int k,int p,int i)//添加结点
{
	if (p)
	{
		d[i].r = d[k].r;
		d[i].l = k;
		d[k].r = i;
		d[d[i].r].l = i;
	}
	else {
		d[i].l = d[k].l;
		d[i].r = k;
		d[k].l = i;
		d[d[i].l].r = i;
	}
}
int main()
{
	cin >> N;
	d[0].l = d[0].r = 0;
	add(0, 1, 1);
	int k, p;
	for (int i = 2; i <= N; i++)
	{
		cin >> k >> p;
		add(k, p, i);
	}
	int m,x;
	cin >> m;
	while (m--)
	{
		cin >> m;
		d[m].v = 1;
	}
	for (int i = d[0].r; i != 0; i = d[i].r)
	{
		if (!d[i].v)continue;
		cout << i << " ";
	}
	return 0;
}

总结:

链表可以进行频繁的删除和插入,但是查找需要遍历

数组不太适合频繁删除插入,但是可以通过标记的方式来记录是否删除,而且查找很快捷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值