洛谷日记 Day 6

5 篇文章 1 订阅
2 篇文章 0 订阅

洛谷P1160 队列安排

思路解析

这题涉及大量的插入、删除操作,一开始想使用简单的数组模拟,但是后面涉及插入和删除操作,就彻底放弃了这个念头,于是乎决定使用双端循环链表去解决这题。

需要注意的是文中提及到的front指针和front结点;next指针和next结点的区别,这里提一下,在下面的阅读中请注意区别。

  1. front结点和front指针的区别:是指当前某一节点k的指向的前一个结点,具有实际意义的指针变量,而front指针为当前结点k的一个指针,仅表示指向前一节点的地址。
  2. next结点和next指针的区别:是指当前某一节点k的指向的下一个结点,具有实际意义的指针变量,而next指针为当前结点k的一个指针,仅表示指向下一节点的地址。

    结点构造,一个整型数据 no 表示当前结点的编号,另两个 front 和 next 指针分别指向当前结点的前一个结点和后一个结点。

    struct node{
    	int no;
    	node *front=NULL,*next=NULL;
    };

    需要注意的是结点的插入,将i结点插入到k结点的前一个结点。先将k结点与front结点分离,即front结点的next指针指向i结点(I),然后将i结点的front指针指向que[k]的front结点指向k的front结点(II),将k结点的front指针指向i结点(III),最后将i结点的next指针指向k结点(IV)注:请严格遵守I、II必须在III之前,IV的顺序不存在限制。

    que[k].front->next=&que[i];//I
    que[i].front=que[k].front;//II
    que[k].front=&que[i];//III
    que[i].next=&que[k];//IV

    ,将i结点插入k结点的后一个结点插入步骤参考将i结点插入k结点之前的操作,只是将front指针/结点变为next指针/结点。顺序规则相同。

    que[k].next->front=&que[i];//I
    que[i].next=que[k].next;//II
    que[i].front=&que[k];//III
    que[k].next=&que[i];//IV

    删除结点操作:需要将当前结点的front结点和next结点相互连接在一起,并将k结点的front和next指针指向NULL值。具体操作为:

    1. 将k结点的front结点的next指针指向k结点的next结点;
    2. 将k结点的next结点的front指针指向k的front结点。
    3. 将k结点的front指针和next指针指向NULL。
    que[k].front->next=que[k].next;
    que[k].next->front=que[k].front;
    que[k].front=que[k].next=NULL;

    这里是完整代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=1e6+10;//最大数据规模
    
    //双向链表结点
    struct node{
    	int no;//当前结点得编号
    	node *front=NULL,*next=NULL;//前结点指针、后结点指针
    };
    node que[MAXN];//双向链结点表数组
    bool visit[MAXN];//访问元素数组
    int main(){
    
    	memset(visit,false,sizeof(visit));
    	int n,m;
    	cin>>n;//数据规模
    	//给结点数组编号赋值
    	for(int i=1;i<=n;i++){
    		que[i].no=i;
    	}
    	//将1号结点得前结点指针、next指针都指向que【1】结点
    	que[1].front=que[1].next=&que[1];
    	int p,k;
    	int head=1;//head表示标记头结点位置
    	
    	for(int i=2;i<=n;i++){
    		cin>>k>>p;//输入当前结点得
    		if(p==0){//p为0,将i插入k左边
    			que[k].front->next=&que[i];//先将k结点的front结点的next指针结点指向i结点
    			que[i].front=que[k].front;//将i结点的front指针指向k结点的front结点
    			que[k].front=&que[i];//k结点的front指针指向i结点
    			que[i].next=&que[k];//i结点的next指针指向k结点
    			if(k==head)//k与head重合时重定向head指针
    				head=i;
    		}else if(p==1){//p为1,将i结点插入k结点右边
    			que[k].next->front=&que[i];//k结点的next结点的前一节点指向i
    			que[i].next=que[k].next;//i结点的next指针指向k的next结点
    			que[i].front=&que[k];//i结点的front指针指向k
    			que[k].next=&que[i];//k结点的next指针指向i
    		}
    	}
    	cin>>m;//输入m次删除结点
    	for(int i=0;i<m;i++){
    		cin>>k;//删除结点k
    		if(visit[k])//如果已经删除结点k就跳过
    			continue;
    		visit[k]=true;//标记节点k已删除
    		que[k].front->next=que[k].next;//将k结点的front结点的next指针指向k的next结点
    		que[k].next->front=que[k].front;//将k结点的next结点的front指针指k的front结点
    		que[k].front=que[k].next=NULL;//将k的front指针和k的next指针指向NULL
    	}
    	k=head;//k标记为当前结点的下标
    	cout<<que[head].no<<" ";//输出当前结点的no
    	k = que[head].next->no;//k为当前结点的next结点的no
    	while(k!=head){//k不为head结点时
    		cout<<que[k].no<<" ";//输出当前结点k的no
    		k = que[k].next->no;//k为当前结点的下一节点的no;
    	}
    	cout<<endl;
        return 0;
    }

     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值