[问题描述]
Dr.Kong设计了一件艺术品,该艺术品由N个构件堆叠而成,N个构件从高到低按层编号依次为1,2,……,N。艺术品展出后,引起了强烈的反映。Dr.Kong观察到,人们尤其对作品的高端部分评价甚多。
狂热的Dr.Kong一激动,对组成该艺术品的N个构件重新组合,比如:把第6层到第12层的构件搬下来,想一想,然后整体放到剩下构件的第7层下面;过一会儿,又把第2层到第9层的构件搬下来,整体放到剩下构件的第1层下面等等。于是,Dr.Kong在进行了连续若干次“搬来搬去”后,还是这N个构件,又诞生了一件新的艺术品。
编程:请输出新的艺术品最高十层构件的编号。
【标准输入】
第一行: N K 表示构件的总数和“搬来搬去”的总次数
第2~K+1行:A B C 表示要搬动的构件(即从第A层到第B层)整个放在第C层下面;
如果C等于0,则要搬动的构件将放到最高层。
【标准输出】
由十行组成,分别为组成新艺术品的第一层到第十层构件的编号。
【约束条件】
(1) 10≤N≤20000 1≤k≤1000
(2) 1≤A≤B≤N, 0≤C≤N-(B-A+1)
【 样 例 】
提示:样例中仅是常规的测试数据输入及对应结果,特殊情况需要全面考虑,自己设计测试数据验证算法的健壮性。
标准输入(测试数据):
13 3
6 12 1
2 9 0
10 13 8
标准输出结果:
6
7
8
9
10
11
12
2
3
4
[实现提示]
适宜于用带表头结点的单链表实现,涉及单个结点或连续多个结点的插入与删除。
主要思想:
将n个艺术品看成长度为n的链表。创建一个带头结点的单链表,使用“前插法”将编号存储在每个结点的数据域里。保存断开链中第一个结点,第一个结点的前一个结点的位置,最后一个结点的位置以及保存将要插入结点处的位置。运用插入知识将各个结点连接起来。对于要插入处为头结点处的情况,直接将头指针保存下来。最后将前10个编号输出。
调试分析:
1、曾在初始化时将p的指向搞错,对于指向头结点还是首元结点,没有一个清晰的判断。今后应当注意这个知识点的理解与掌握。
2、在保存断开链中第一个结点的位置时,没有注意指针的连动性,导致没有保存成功。今后临时保存指针时,应当特别注意这一点。
代码实现
#include<iostream>
using namespace std;
typedef int ElemType;
typedef struct LNode{
ElemType data;//结点的数据域
struct LNode *next;//结点的指针域
}LNode,*LinkList;
int main(){
int N,K,a1,a2,a3,i;
LinkList q1,q11,q2,q3,L,p;
L=new LNode;//创建一个带头结点的单链表
L->next=NULL;
cin>>N>>K;
for(int i=N;i>0;i--){//编号存储在每个结点的数据域里
p=new LNode;
p->data=i;
p->next=L->next;//前插法
L->next=p;
}
while(K--){
cin>>a1>>a2>>a3;
p=L;//初始化,p指向头结点
i=1;
if(a3==0)//插入到最高层时,特殊处理
q3=L;
while(i!=N&&p){//遍历链表
p=p->next;
if(i==(a1-1))
{
q1=p;//保存断开链中第一个结点的前一个结点的位置
q11=q1->next;//保存断开链中第一个结点的位置
}
else if(i==a2)
q2=p;//保存断开链中最后一个结点的位置
else if(i==a3)
q3=p;//保存将要插入结点处的位置
i++;
}
q1->next=q2->next;//把断开的链连接起来
q2->next=q3->next;
q3->next=q11;
}
p=L->next;//p指向首元结点
i=10;
while(i--&&p){
cout<<p->data<<endl;//输出前10个的编号
p=p->next;
}
return 0;
}