1. 程式人生 > >在單鏈表上實現插入排序

在單鏈表上實現插入排序

問題

給單鏈表排序(升序排列,要保持穩定性),要求通過改變結點的next指標從而改變結點的位置,而不是隻交換結點的值來使得其有序!時間複雜度為O(N^2),空間複雜度為O(1)。已知連結串列結點的實現如下:

struct ListNode
{
    int value;
    ListNode* next;
    ListNode(int v)
    : value(v), next(NULL) {}
};

思路

這裡很明顯就是要我們做插入排序了,當然,冒泡也不是不可以,只是冒泡寫起來麻煩,且效能是最差的。

插入排序怎麼寫呢?
這個演算法的思想是這樣的:
1. 維護兩部分,一是已排序的部分,一是待排序的部分;
2. 一開始已排序部分為NULL;
3. 每次取出待排序部分的第一個元素A,和已排序的部分逐個比較(從頭往後或從後往前都可以,不過單鏈表只能夠從頭往後比較),找到第一個大於A的元素B;
4. 將A插在B的前面一個位置(這時需要注意了,如果B原來是連結串列頭,那麼A將變成新的連結串列頭,此時要記得更新連結串列頭指標)。

程式碼

#include <iostream>
#include <string>
using namespace std;


struct ListNode
{
    int value;
    ListNode* next;
    ListNode(int v)
    : value(v), next(NULL) {}
};


ListNode* sortList(ListNode* head) {
    // 注意這樣寫,是不需要額外判斷head是否為NULL的
    ListNode *newHead = NULL, *toInsert =
head; while (toInsert != NULL) { ListNode *current = newHead, *last = NULL, *next = toInsert->next; // 從頭往後找到第一個大於toInsert->value的元素 while (current != NULL && current->value <= toInsert->value) { last = current; current = current->
next; } if (last == NULL) { // 如果比任何已排序的數字都要小,那麼就成為新的頭部 toInsert->next = newHead; newHead = toInsert; } else { // 否則插入到last的後面 toInsert->next = last->next; last->next = toInsert; } toInsert = next; } return newHead; } // 列印連結串列 void display(ListNode* head) { while (head != NULL) { cout << head->value << ' '; head = head->next; } cout << endl; } int main() { ListNode* head = new ListNode(5); head->next = new ListNode(4); head->next->next = new ListNode(3); head->next->next->next = new ListNode(2); head->next->next->next->next = new ListNode(1); display(head); ListNode* head2 = sortList(head); display(head2); return 0; }