P 1025 链表反转

转跳点:🐏

1025 反转链表

给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转。例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4;如果 K 为 4,则输出应该为 4→3→2→1→5→6,即最后不到 K 个元素不反转。

输入格式:

每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤)、以及正整数 K (≤),即要求反转的子链结点的个数。结点的地址是 5 位非负整数,NULL 地址用 − 表示。

接下来有 N 行,每行格式为:

Address Data Next

其中 Address 是结点地址,Data 是该结点保存的整数数据,Next 是下一结点的地址。

输出格式:

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
  我果然还是太弱了,这道题写了两天都没写出来,废了废了。按照题目的意思就是一部分一部分的链表进行逆序,本来应该很简单,这个逆序就把我写废了(つ﹏⊂)。
按照我的思路这道题因该是这样的:
  1、照地址给原数组排序,记录有效数据个数
  2、对节点数进行求余、求商操作,
  3、对链表进行反转
思路是很简单,但是吧反转这里我一直没写对,好吧,刚刚终于写对了我的天,我也太菜了。
这是我写出来的的反转的代码:
  
 1     for (int i = 0; i < Quotient; i++)
 2     {
 3         for (int j = 0; j < K / 2; j++)
 4         {//因为不是和冒泡那样的连续赋值而是交换所以只要一般的的次数
 5 
 6             //交换
 7             ListNode temp = List[K * i + j];
 8             List[K * i + j] = List[K * (i + 1) - j - 1];
 9             List[K * (i + 1) - j - 1] = temp;
10         }
11     }

  为什么交换次数是K/2,举个栗子:1 2 3 4 5,要逆序,最暴力的方法就是从第一个数开始一个个往后移动,这无疑浪费了大量的时间在交换上,认真观察会发现,其实交换将1 和 5交换 2 和 4 就可以达到效果。奇数的时候就是中间位不用动,偶数的时候刚好对半分。所以不分奇偶。

  大佬们可以跳过下面这一段(写一个小姐姐看的)被划掉了,看不见看不见。

  那为什么是k*I+J和K * (i + 1) - j - 1交换,将I去掉后,不难发现就是将数组第一位和第K位交换,数组第二位和第K-1位上的数交换,以此类推*I是因为这是第I组刚好也相当于下标

    i = 0的时候

      0 和 k-1 换,

      1 和 k-2 换,

      ……

      k/2-1 和 k/2+1

    i = 2时      

      k 和 2k-1 换,

      k+1 和 2k-2 换,

      ……

      2k/2-1 和 2k/2+1

    ……

    i = n 时

      nk 和 2k-1 换,

      nk+1 和 nk-2 换,

      ……

      nk/2-1 和 nk/2+1

最后就是代码了:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define MAXSIZE 100011
 4 typedef struct
 5 {
 6     int Address;
 7     int Data;
 8     int Next;
 9 } ListNode;
10 
11 int main(void)
12 {
13     int head, n, K;
14     ListNode List[MAXSIZE];
15     scanf("%d%d%d", &head, &n, &K);
16 
17     for (int i = 0; i < n; i++)
18     {
19         scanf("%d %d %d", &List[i].Address, &List[i].Data, &List[i].Next);
20     }
21 
22     //线找到首地址
23     for (int i = 0; i < n; i++)
24     {
25         if (List[i].Address == head)
26         {
27             ListNode temp = List[i];
28             List[i] = List[0];
29             List[0] = temp;
30             break;
31         }
32     }
33 
34     //整理链表顺序
35     for (int i = 0; i < n; i++)
36     {
37         if (-1 == List[i].Next)
38         {
39             n = i + 1;
40             break;
41         }
42         for (int j = i + 1; j < n; j++)
43         {
44             if (List[j].Address == List[i].Next)
45             {
46                 ListNode temp = List[i + 1];
47                 List[i + 1] = List[j];
48                 List[j] = temp;
49                 break;
50             }
51         }
52     }
53 
54     //取出需要交换的次数
55     int Quotient = n / K;
56 
57     for (int i = 0; i < Quotient; i++)
58     {
59         for (int j = 0; j < K / 2; j++)
60         {//因为不是和冒泡那样的连续赋值而是交换所以只要一般的的次数
61 
62             //交换
63             ListNode temp = List[K * i + j];
64             List[K * i + j] = List[K * (i + 1) - j - 1];
65             List[K * (i + 1) - j - 1] = temp;
66         }
67     }
68 
69     //重写地址
70     for (int i = 0; i < Quotient * K; i++)
71     {
72         List[i].Next = List[i + 1].Address;
73     }
74     List[n - 1].Next = -1;
75 
76     
77     for (int i = 0; i < n; i++)
78     {
79         if (-1 == List[i].Next)
80         {//特殊处理-1;
81             printf("%05d %d %d\n", List[i].Address, List[i].Data, List[i].Next);
82             continue;
83         }
84         printf("%05d %d %05d\n", List[i].Address, List[i].Data, List[i].Next);
85     }
86 
87     return 0;
88 }

这几组是我自己的测试数据可以拿去试试(还有一组丢了,有无效数据不能整除的)这几组数据过了之后,应该就能A了

有无效数据      能整除         不能整除

00100 10 2                      00100 10 2                         00100 10 4
0000 4 99999                  0000 4 99999                     0000 4 99999
00100 1 12309                00100 1 12309                   00100 1 12309
68237 6 -1                       68237 6 89001                   68237 6 89001
33218 3 00000                33218 3 00000                   33218 3 00000
99999 5 68237                99999 5 68237                   99999 5 68237
12309 2 33218                12309 2 33218                   12309 2 33218
89001 7 89100                89001 7 89100                   89001 7 89100
89100 8 89200                89100 8 89200                   89100 8 89200
89200 9 89300                89200 9 89300                   89200 9 89300
89300 10 89400              89300 10 -1                        89300 10 -1

  PTA不易,诸君共勉!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值