在单链表上实现插入排序

37 篇文章 0 订阅
11 篇文章 0 订阅

问题

给单链表排序(升序排列,要保持稳定性),要求通过改变结点的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; 
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值