PAT(乙级)2019年冬季考试 7-5 区块反转 (25分)

7-5 区块反转 (25分)  

给定一个单链表 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;
}

 







上一篇:PAT-2019年冬季考试-甲级 7-2 Block Reversing (25分) (链表转置)


下一篇:991_MISRA C规范学习笔记4