在单链表上实现插入排序

来源:互联网 发布:the weeknd earned it 编辑:程序博客网 时间:2024/06/03 21:19

问题

给单链表排序(升序排列,要保持稳定性),要求通过改变结点的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; }
1 0
原创粉丝点击