PAT乙級練習題B1025.反轉連結串列
阿新 • • 發佈:2019-02-06
題目描述
給定一個常數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
題目解析
將連結串列按順序每K個節點反轉一次,需要注意反轉後第K個節點的next的指向,因為第K個節點後的K個節點也反轉了,所以第K個節點的next要指向後面K個節點反轉後的第一個節點。我原來沒注意,程式碼提交後只有兩個報錯,我在這裡卡了半天,現在想想可能只有那兩個測試點是把K的反轉迴圈跑了兩遍以上的,所以迴圈還是要自己手推走兩遍。 還有一個需要注意的地方是,給出的節點中可能存在無用節點,所以不要用N作為反轉的迴圈判定條件。 這裡我使用map來儲存節點,能夠比較好的模擬真實的連結串列,可以按需求申請記憶體,記憶體佔用要小些。 我看其他人的程式碼,發現大家基本上是把連結串列按順序存到vector或數組裡面,反轉後可以直接把節點的next指向陣列中順序的下一個節點地址,所以沒有遇到我上面講的第一個問題。不過我感覺這樣就失去了對連結串列操作的本意,真實情況下若是連結串列大小超過了記憶體,這樣做就不行了。
程式碼
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
struct node
{
int value;
int next;
};
int main()
{
int first, N, K, address;
cin >> first >> N >> K; //讀入首行資料
if (first == -1)
{
cout << -1 << endl;
system("pause");
return 0;
}
map<int, node> L;
node nod;
for (int i = 0; i < N; ++i) //讀入節點資料
{
cin >> address >> nod.value >> nod.next;
L[address] = nod;
}
if (K != 1) //K不等於1則開始反轉連結串列
{
vector<int> list(K);
address = first;
int last;
for (int i = 0; address != -1; i = 1) //到最後節點則停止,注意這裡不要使用N作為條件,因為所給的節點中可能包含無用節點
{
bool break_flag = 0;
for (int j = 0; j < K; ++j) //讀取K個節點進行反轉
{
list[j] = address; //按連結串列順序將節點地址讀入陣列
address = L[address].next;
if (address == -1 && j != K - 1) //若讀不滿K個節點則停止
{
break_flag = 1;
break;
}
}
if (break_flag)
{
break;
}
reverse(list.begin(), list.end()); //將節點地址陣列反轉
for (int j = 0; j < K - 1; ++j)
{
L[list[j]].next = list[j + 1];
}
L[list[K - 1]].next = address;
if (i == 0)
{
first = list[0];
}
else
{
L[last].next = list[0]; //注意,後面一組K個節點的反轉會導致前面一組K個節點的最後一個節點的next指向錯誤,需要修正
}
last = list[K-1];
}
}
address = first;
while (address != -1) //輸出連結串列
{
nod = L[address];
if (nod.next != -1)
{
printf("%05d %d %05d\n", address, nod.value, nod.next);
}
else
{
printf("%05d %d %d", address, nod.value, nod.next);
cout << endl;
}
address = nod.next;
}
system("pause");
return 0;
}