给定一个单链表 L,我们将每 K 个结点看成一个区块(链表最后若不足 K 个结点,也看成一个区块),请编写程序将 L 中所有区块的链接反转。例如:给定 L 为 1→2→3→4→5→6→7→8,K 为 3,则输出应该为 7→8→4→5→6→1→2→3。
输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤)、以及正整数 K (≤),即区块的大小。结点的地址是 5 位非负整数,NULL 地址用 − 表示。
接下来有 N 行,每行格式为:
Address Data Next
其中 Address
是结点地址,Data
是该结点保存的整数数据,Next
是下一结点的地址。
输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218
输出样例:
71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1
代码讲解:此题我用了俩种办法解,第一种办法,首先处理可能有余
的情况,把它们先换一下,换的时候由于余的少,第一个k大,导致
需要整个数组前移,他俩解决了,其他就好办了。。。剩余的组,俩俩
相互交换。。。代码写起来还是有点麻烦的,远不如第二种办法。。。
第二种办法比较简单,首先把各个组都组内逆转,包括不够的那组,之后
全员再次整体逆转。。。你就会发现,结果完成了。。。特别像循环右移
代码一:
1 #include<stdio.h> 2 typedef struct 3 { 4 int address; 5 int data; 6 int next; 7 }l; 8 l lnode[100000];l s[100000]; 9 void swap(l a[],l b[],int k) //将俩组k调换的函数 10 { 11 int i; 12 l temp; 13 for(i=0;i<k;i++) 14 { 15 temp=a[i]; 16 a[i]=b[i]; 17 b[i]=temp; 18 } 19 20 } 21 int main() 22 { 23 int i,j,start,n,k,address,data,next,temp,m,flag; 24 scanf("%d %d %d",&start,&n,&k); 25 26 l t; 27 for(i=0;i<n;i++) 28 { 29 scanf("%d %d %d",&address,&data,&next); 30 lnode[address].address=address; 31 lnode[address].data=data; 32 lnode[address].next=next; 33 } 34 next=start; 35 n=0; 36 while(next!=-1) //重新统计数n 37 { 38 s[n].address=next; 39 s[n].next=lnode[next].next; 40 s[n++].data=lnode[next].data; 41 next=lnode[next].next; 42 } 43 if(k>=n) //k是有可能大于n的 44 { 45 for(i=0;i<n-1;i++) 46 { 47 printf("%05d %d %05d\n",s[i].address,s[i].data,s[i].next); 48 } 49 printf("%05d %d -1\n",s[i].address,s[i].data); 50 } 51 else 52 { 53 temp=n%k; //先把最前面和最后面解决 54 m=0; 55 if(temp>0) 56 { 57 for(i=n-temp;i<n;i++) 58 { 59 t=s[i]; 60 s[i]=s[m]; 61 s[m]=t; 62 m++; 63 } 64 65 while(m<k) 66 { 67 s[i++]=s[m++]; 68 } 69 70 for(i=n%k;i<n;i++) //因为余的值少,前面留了空,所以前移 71 { 72 s[i]=s[i+k-n%k]; 73 } 74 75 for(i=0;i<(n/k-1)/2;i++) 76 { 77 swap(s+n%k+i*k,s+n-(i+2)*k,k); 78 } 79 } 80 else 81 { 82 for(i=0;i<(n/k)/2;i++) 83 { 84 swap(s+i*k,s+n-(i+1)*k,k); 85 } 86 } 87 for(i=0;i<n-1;i++) //把链连上 88 { 89 s[i].next=s[i+1].address; 90 } 91 for(i=0;i<n-1;i++) //输出 92 { 93 printf("%05d %d %05d\n",s[i].address,s[i].data,s[i].next); 94 } 95 printf("%05d %d -1\n",s[i].address,s[i].data); 96 97 } 98 99 return 0; 100 } 101
代码二:
#include<stdio.h> typedef struct { int data; int next; }lnode; void reverse(int a[],int k) //逆转函数 { int i,temp; for(i=0;i<k/2;i++) { temp=a[i]; a[i]=a[k-i-1]; a[k-i-1]=temp; } } lnode l[100001]; int s[100001]; int main() { int n,start,k,temp,data,next,count; scanf("%d %d %d",&start,&n,&k); int i; for(i=0;i<n;i++) { scanf("%d %d %d",&temp,&data,&next); l[temp].data=data; l[temp].next=next; } n=0; next=start; while(next!=-1) { s[n++]=next; //保存的是各个节点的地址,相邻位置就是链表的前后关系 next=l[next].next; } for(i=0;i<n;i+=k) { if(i+k>=n) count=n-i; //要注意count不能越界,因为最后可能少。。 else count=k; reverse(s+i,count); } reverse(s,n); //全部逆转 for(i=0;i<n;i++) { if(i==0) printf("%05d %d ",s[i],l[s[i]].data); else printf("%05d\n%05d %d ",s[i],s[i],l[s[i]].data); } printf("-1\n"); return 0; }