老师要将N张试卷重新排序,每张试卷都有编号为1∼N,采取如下的方法: 先将编号1的试卷放进队列,剩下从第2张到第N张依次放入队列, 放入的时候老师会把编号i的试卷插入到编号为x试卷之前或之后(x<i), 在老师完成这N-1次操作之后,请输出试卷序列的最终编号。
输入格式
第1行为一个正整数N,表示了有N张试卷。 第2-N行,第i行包含两个整数x,p,其中x为小于i的正整数,p为0或者1。 若p为0,则表示将编号为i的试卷放入编号为x试卷的左边,为1则放入x试卷的右边。
输出格式
输出N个整数,表示完成插入后试卷系列中试卷的编号(1<=N<=100000)。
输入样例
4 1 0 2 1 1 0
输出样例
2 3 4 1
解题思路:数据规模看不能使用O(n^2)算法,此题目试卷可以插入x试卷左右两侧,为降低插入导致的元素移动,可用双向链式结构。因为试卷编号固定是整数,所以直接用数组下标存储数据编号,这种用数据直接映射数组下标的方法就是哈希法。即便试卷编号是字符串或其他类型(非整型),仍可以使用哈希法(map)实现映射。
#include <iostream>//ASI
#include<cstdio>
using namespace std;
int n,m,pre[100005],nex[100005];/**< 全局数据默认初值0 */
int main()
{
int x,y,i,j,q,p;
cin>>n;
nex[0]=1;/**< 第一个试卷编号1,它前驱后继都是0,不用单独初始化处理 */
for(i=2; i<=n; i++)
{
scanf("%d%d",&x,&y);
if(y) /**< 新元素i将插入到p,q之间。 */
p=x,q=nex[x];
else
p=pre[x],q=x;
nex[i]=q;/**< 将i插入p和q之间 */
pre[i]=p;
nex[p]=i;
pre[q]=i;
}
i=0;
while(i=nex[i]) /**< 一种简单的链表遍历写法 */
printf("%d ",i);
return 0;
}
2022-3-18 补充下标准双循环链表的写法,用循环链表时,最后一个元素后面插入和其他元素操作相同,非循环链表需要写特判语句。
#include <iostream>
using namespace std;
struct LNode
{
int data;
struct LNode * pre,*nex;
};
int main()
{
ios::sync_with_stdio(false);
LNode *L=new LNode,*p,*q,*r;
LNode * d[100005];
L->pre=L->nex=L;
p=new LNode;
p->data=1;
d[1]=p;
L->nex=p,L->pre=p;
p->nex=p->pre=L;
int i,j,n,x,y;
cin>>n;
for(i=1;i<n;i++)
{
cin>>x>>y;
if(y==0)
{
p=d[x]->pre;
q=d[x];
}
else
{
p=d[x];
q=d[x]->nex;
}
r=new LNode;
r->data=i+1;
d[i+1]=r;
r->pre=p,r->nex=q;
p->nex=r,q->pre=r;
}
p=L->nex;
while(p!=L)
{
cout<<p->data<<' ';
p=p->nex;
}
return 0;
}