PTA 單鏈表分段逆轉


6-9 單鏈表分段逆轉 (25 分)
 

給定一個帶頭結點的單鏈表和一個整數K,要求你將鏈表中的每K個結點做一次逆轉。例如給定單鏈表 1→2→3→4→5→6 和 K=3,你需要將鏈表改造成 3→2→1→6→5→4;如果 K=4,則應該得到 4→3→2→1→5→6。

函數接口定義:

void K_Reverse( List L, int K );

其中List結構定義如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存儲結點數據 */
    PtrToNode   Next; /* 指向下一個結點的指針 */
};
typedef PtrToNode List; /* 定義單鏈表類型 */

L是給定的帶頭結點的單鏈表,K是每段的長度。函數K_Reverse應將L中的結點按要求分段逆轉。

裁判測試程序樣例:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存儲結點數據 */
    PtrToNode   Next; /* 指向下一個結點的指針 */
};
typedef PtrToNode List; /* 定義單鏈表類型 */

List ReadInput(); /* 裁判實現,細節不表 */
void PrintList( List L ); /* 裁判實現,細節不表 */
void K_Reverse( List L, int K );

int main()
{
    List L;
    int K;

    L = ReadInput();
    scanf("%d", &K);
    K_Reverse( L, K );
    PrintList( L );

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例:

6
1 2 3 4 5 6
4

輸出樣例:

4 3 2 1 5 6


 1 void K_Reverse( List L, int K ){
 2    PtrToNode r, p, end1,end2 ,H = L->Next;//_ 1 2 3 4 5 6 7 8 9 10  11 12    
 3     /**end1和end2是用來連接兩個逆置后的分段;
 4        一開始我們令end1指向頭節點,end2指向數據1所在的節點,為什么這樣做呢?
 5        因為前四個數據我們都要把他以頭插入方式插到L后面,也就是end1后面;
 6        當我們遍歷到節點5的時候我們需要令end1 = end2;end2 = 5所在的節點;
 7        然后我們需要將5 6 7 8再以頭插入的方式插入到1節點的后面,也就是end1的后面
 8        也就是說我們一直將節點以頭插入的方式插入到end1后面,而end2使用來記錄下一個
 9        分段的第一個節點,也就是下一個end1,就這樣不斷更新end1就可以實現將整個鏈表
10        分段逆置;這是end1和end2的作用
11     */
12     end1 = L;
13     end2 = L->Next;
14     r = L->Next;    //用來遍歷鏈表
15     p = r->Next;    
16     int count = 0;      
17     /**
18         count用來記錄鏈表節點總數;
19         為什么要記錄總數?
20         因為我們要知道鏈表最后一個分段是不足K個節點,還是剛好K個節點;
21         如果不足就不用逆置,如果剛好也要把這一分段逆置了;
22     */
23     if (K>=1)            //這里就是我上面說的考慮K的情況
24     {    
25         //記錄總數
26         while (H)        
27         {            
28         count++;            
29         H = H->Next;        
30         }
31                 
32         //判斷,如果總數小於K就不變鏈表
33         if (count>=K)        
34         {
35                /**count/K是我們總共需要循環幾個分段,因為count/K結果去商,
36                   所以如果count不能被K整除,即最后一個分段不足K個,我們就不循環
37                   也就是不動它。
38                */            
39             for (int j = 0;j<count/K;j++)            
40             {                
41                 //每個分段循環K次
42                 for(int i = 0; i < K; i++)                
43                 {                    
44                     r->Next = end1->Next;    //頭插入
45                     end1->Next = r;
46                     r = p;
47                     /**
48                      這里為什么要判斷p不為空呢?
49                      因為我一開令r = L->Next;
50                              p = r->Next;
51                      所以最后p會指向鏈表最后的Next域,而Next為空,就不
52                      存在p的Next域,如果不判斷的話程序運行到此處就不會再運行下去
53                      而程序一開始編譯的時候不會報錯,所以這一點很重要,即判斷越界
54                      問題,我也是找了很長時間才找點這一點。
55                     */                      
56                     if(p)
57                         p = p->Next;                
58                  }
59                 end1 = end2;    //更新end1和end2                
60                 end2 = r;            
61             }            
62             end1->Next = r;    //最后將尾節點Next域置空。
63         }
64     }
65 
66 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM