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 }
