1. 程式人生 > >PAT乙級練習題B1025.反轉連結串列

PAT乙級練習題B1025.反轉連結串列

題目描述

給定一個常數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; }