NYOJ 题目511 移动小球(双向循环链表)
来源:互联网 发布:网络拓扑图怎么简单画 编辑:程序博客网 时间:2024/04/28 22:32
http://acm.nyist.net/JudgeOnline/problem.php?pid=511
移动小球
- 描述
- 给你n个小球,从左到右编号依次为1,2,3,4,5,6.........n,并规定小球1的左边的球号为n,小球n的右边的球号为1.现在有以下3种操作:A x y表示把编号为x小球移动到编号为y的小球的左边,B x y表示把编号为x小球移动到编号为y的小球的右边,Q 1 m为询问编号为m的小球右边的球号,Q 0 m为询问编号为m的小球左边的球号。
- 输入
- 第一行有一个整数n(0<n<10000),表示有n组测试数据,随后每一组测试数据第一行是两个整数N,M,其中N表示球的个数(1<N<10000),M表示操作的的次数(0<M<10000)
随后的M行,每行有三个数 s x y,s表示操作的类型,x,y为小球号。当s为Q时,若x为1,则询问小球y右边的球号,x为0,则询问小球y左边的球号。 - 输出
- 输出每次询问的球号
- 样例输入
16 3A 1 4B 3 5Q 1 5
- 样例输出
3
注意:用以下形式结构体构建双向循环链表时,连接一个节点时要把该节点的左指针和前一个节点的右指针同时连起来 ,否则构建双向循环链表不成功。
struct Node
{
int data;
struct Node *llink,*rlink;
}num[MAX+10];
#include<stdio.h>#define MAX 10000struct Node {int data;struct Node *llink,*rlink;}num[MAX+10];struct Node *L,*R,*p;void Build(int n){//用结构体链表构建双向循环链表时,连接一个节点时要把该节点的左指针和前一个节点的右指针同时连起来 int i; for(i=1;i<n;i++) { num[i].data=i; num[i].rlink=&num[i+1]; num[i+1].llink=&num[i]; } num[1].llink=&num[n]; num[n].rlink=&num[1]; num[n].data=n;}void A(int x,int y){//-----删除x节点-----// p=&num[x];L=p->llink;R=p->rlink;L->rlink=R;R->llink=L;//-------------------////-----将x移到y的左边-----//struct Node *s=&num[x];p=&num[y];L=p->llink; s->rlink=p;p->llink=s;s->llink=L;L->rlink=s;//------------------------// }void B(int x,int y){ //-----删除x节点-----// p=&num[x];L=p->llink;R=p->rlink;L->rlink=R;R->llink=L;//-------------------////-----将x移到y的右边-----//struct Node *s=&num[x];p=&num[y];R=p->rlink; s->rlink=R;R->llink=s; s->llink=p;p->rlink=s;//------------------------//}void Q(int x,int y){ p=&num[y];if(x==0)printf("%d\n",p->llink->data);else if(x==1)printf("%d\n",p->rlink->data);}int main(){int N,n,m,i,x,y;char c;scanf("%d",&N);while(N--){scanf("%d %d",&n,&m);Build(n);//创建双向循环链表while(m--){getchar();scanf("%c %d %d",&c,&x,&y);if(c=='A')A(x,y);//将x移到y的左边 else if(c=='B')B(x,y);//将x移到y的右边 else if(c=='Q') Q(x,y); }}return 0;}
(1) (2)
struct Node struct Node
{ {
int data; int data;
struct Node *llink,*rlink; struct Node *llink,*rlink;
}; }num[10010];
上面代码定义链表节点时用的是(2),这样定义的好处是需要对某个节点操作时就可以直接操作,而如果用(1)方法定义,若想对某一个节点进行操作,必须从头结点一直找到想要操作的节点,增加了额外的时间,这就是(2)方法的优点。
下面的代码就是用(1)方法,在建立循环链表时,当需要新节点时就申请。但在对某个节点进行操作时,就要先找到该节点,这样就大大增加了时间,所以提交超时。把它也贴出来,提醒自己这两种定义的不同,以后要认真思考分析。
//因为没有考虑到在链表查找到某一元素时要进行线性遍历,所以超时 #include<stdio.h>#include<string.h>#include<malloc.h>struct Node{//循环链表节点 int data;struct Node *llink;struct Node *rlink;};int main(){int N,n,m,i,j,k,x,y;char c;scanf("%d",&N);while(N--){scanf("%d %d",&n,&m);//==========构造双向循环链表==========// //-----创建头结点-----//struct Node *head;head=(struct Node *)malloc(sizeof(struct Node));head->data=1;head->llink=NULL;head->rlink=NULL;//--------------------//struct Node *p=head;for(i=1;i<=n;i++){if(i==1) continue;else if(i>1&&i<=n){//-----创建新节点-----//struct Node *s;s=(struct Node *)malloc(sizeof(struct Node));s->data=i;s->llink=NULL;s->rlink=NULL;//--------------------//p->rlink=s;s->llink=p;p=p->rlink; }}p->rlink=head;head->llink=p;//==========构造双向循环链表成功==========//while(m--){getchar();scanf("%c %d %d",&c,&x,&y);struct Node *L,*R; if(c=='A'){p=head;while(!(p->data==x)) //(1)这里对链表遍历会超时 p=p->rlink;//-----删除X节点-----// L=p->llink;L->rlink=L->rlink->rlink;R=p->rlink;R->llink=R->llink->llink; //-------------------////-----将x移到y的左边-----//p=head;while(!(p->data==y)) //(2)这里对链表遍历会超时 p=p->rlink; L=p->llink; struct Node *s; s=(struct Node *)malloc(sizeof(struct Node)); s->data=x; s->rlink=p; p->llink=s; s->llink=L; L->rlink=s; //------------------------// } else if(c=='B') { p=head; while(!(p->data==x)) //(3)这里对链表遍历会超时 p=p->rlink; //-----删除X节点-----// L=p->llink;L->rlink=L->rlink->rlink;R=p->rlink;R->llink=R->llink->llink; //-------------------////-----将x移到y的右边-----//p=head;while(!(p->data==y)) //(4)这里对链表遍历会超时 p=p->rlink; R=p->rlink; struct Node *s; s=(struct Node *)malloc(sizeof(struct Node)); s->data=x; s->rlink=R; R->llink=s; s->llink=p; p->rlink=s; //------------------------// } else if(c=='Q') { p=head; while(!(p->data==y)) //(5)这里对链表遍历会超时 p=p->rlink; if(x==0) { p=p->llink; } else if(x==1) { p=p->rlink; } printf("%d\n",p->data); }} } return 0;}
- NYOJ 题目511 移动小球(双向循环链表)
- nyoj 511 移动小球(链表的简单使用)
- NYOJ 511 移动小球
- NYOJ 511 移动小球
- NYOJ-511-移动小球
- NYOJ 511 移动小球
- NYOJ-511 移动小球【模拟】
- NYOJ 511 - 移动小球 链表版
- nyoj 551 移动小球
- NYOJ 551 移动小球
- NYOJ-移动小球
- NYOJ 题目278 排队(循环链表)
- nyoj 511 双向静态链表
- 双向循环链表
- 双向循环链表
- 双向循环链表
- 双向循环链表
- 双向循环链表
- 漫谈栈队列及后缀表达式,后缀中缀表达式间的转换
- maven私服:用nexus搭建企业级私有仓库
- map容器的使用
- HDU2139 Calculate the formula【水题】
- Android的数据存储方式-----------sqlite
- NYOJ 题目511 移动小球(双向循环链表)
- 排序算法十:计数排序
- ListView ViewPager ScrollView 修改边界色
- 虚拟机随用随建的特征便于测试环境
- JVM内存分析与垃圾回收相关
- Android本地应用程序应用方式介绍
- 第四章 数据链路层
- 我是菜鸟,我该怎么做?
- Android的数据存储方式------------网络存储数据