PAT 乙級-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(<= 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章