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;
}
总结:
链表可以进行频繁的删除和插入,但是查找需要遍历
数组不太适合频繁删除插入,但是可以通过标记的方式来记录是否删除,而且查找很快捷。