給定一個常數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(<= 105)、以及正整數K(<=N),即要求反轉的子鏈結點的個數。結點的地址是5位非負整數,NULL地址用-1表示。
接下來有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
題目大意:題目給出一條n個節點的鏈表,以及一個整數k,要求將鏈表中每k個節點反轉輸出,剩餘不足k個的節點順序輸出。
主要思路:此題用數組來存放鏈表的每個節點,每個節點包含地址,值,下一個地址,由於輸入的節點並不是按順序的,所以需要用一個數組接收所有的輸入,然後根據首節點將所有節點按順序放入一個新的數組(這裏注意輸入中可能會有無效的節點,所以鏈表長需要重新計算)。然後利用循環,在每個週期內倒序輸出節點,除首節點外,每個節點需要輸出兩次自己的地址,第一次表示的是前一個節點的next。( 如果利用c++ algorithm頭文件裏面的reverse函數可以使代碼更簡單,對順序放置鏈表的數組每k個節點進行倒置,然後通過一次遍歷順序輸出所有節點)
#include <stdio.h>
struct node {
int ad;
int val;
int next;
} node1[100000], node2[100000];
int main(void) {
int first, count, k, i, j;
int n = 0; //節點數量,輸入中可能有無效節點,n <= count
int m, r;
struct node x;
scanf("%d%d%d", &first, &count, &k);
for (i = 0; i < count; i++) {
scanf("%d%d%d", &x.ad, &x.val, &x.next);
node1[x.ad] = x;
}
for (i = 0, j = first; j != -1; j = node1[j].next, i++) {
node2[i] = node1[j];
n++; //節點數量需要重新計算
}
m = n / k; //週期數
r = n % k; //剩餘不足一週期的節點數(正序輸出)
//先把需要倒序的m個週期節點輸出
for (i = 0; i < m; i++) {
for (j = (i+1)*k-1; j >= i*k; j--) {
//首節點只需要輸出該節點地址和值
if (j == k-1)
printf("%05d %d ", node2[j].ad, node2[j].val);
//其餘節點要輸出兩次地址(其中一次作爲上一個的next)和一次值
else
printf("%05d\n%05d %d ", node2[j].ad, node2[j].ad, node2[j].val);
}
}
//處理剩餘正序輸出的r個節點
for (j = m * k; j < n; j++) {
//當 n < k 時,全部正序輸出,首節點只需輸出一個地址
if (j != 0) printf("%05d\n", node2[j].ad);
printf("%05d %d ", node2[j].ad, node2[j].val);
}
printf("-1\n"); //尾節點的next
return 0;
}