18925 试卷排序(双向链表)

这篇博客介绍了如何利用哈希映射和双向链表数据结构解决试卷重新排序的问题,通过输入样例解释了算法的实现过程,包括插入操作和遍历输出。解题思路强调了避免使用高复杂度的算法,并提供了两种不同的C++代码实现,一种是简单的链表遍历,另一种是标准的双循环链表方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

老师要将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;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值