算法学习 - 链表之归并排序_O(1)空间_O(NlogN)时间_C++

归并排序

归并排序我在之前已经讲过了,并且给了在数组的数列的情况下的归并排序方法,而排序的时间复杂度为O(NlogN).想看的话链接如下:

归并排序,快排,冒泡排序

但是这个归并排序有一个缺点:需要O(n)的额外空间。

那么这个缺点在什么情况下会解决呢?就是数列是以链表形式存储的时候!就不需要额外的申请O(n)级别的空间。

那么我们为什么要用归并排序呢? 不是还有快排,堆排么?都是速度很快的排序。其实在链表中是不适合的!因为在快排的时候,查找标杆是O(1)级别的,但是在链表中只能得到head节点,得到标杆需要O(n)级别的。那么复杂度就上升到(nnlogn)级别的了。

代码实现

所以在链表的情况下需要使用归并排序,复杂度NlogN, 而且不需要申请额外空间。

//
//  main.cpp
//  MergeList
//
//  Created by Alps on 14/12/6.
//  Copyright (c) 2014年 chen. All rights reserved.
//

#include <iostream>
using namespace std;

struct ListNode{
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL){}
};

class Solution{
public:
    ListNode *sortList(ListNode* head){
        if (head == NULL || head->next == NULL) {
            return head;
        }

        ListNode* mid = getMid(head);
        ListNode* right = NULL;
        if (mid != NULL) {
            right = mid->next;
            mid->next = NULL;
        }
        head = sortList(head);
        right = sortList(right);
        head = MergeList(head, right);
        return head;
    }

    ListNode* getMid(ListNode* node){
        if (node == NULL || node->next == NULL) {
            return node;
        }
        ListNode* l1 = node;
        ListNode* l2 = node->next;
        while (l2 && l2->next) {
            l1 = l1->next;
            l2 = l2->next->next;
        }
        return l1;
    }

    ListNode* MergeList(ListNode* left, ListNode* right){
        if (left == NULL) {
            return right;
        }
        if (right == NULL) {
            return left;
        }
        ListNode* temp = NULL;
        if (left->val >= right->val) {
            temp = right->next;
            right->next = left;
            left = right;
            right = temp;
        }
        left->next = MergeList(left->next, right);
        return left;
    }
};

int main(int argc, const char * argv[]) {
    Solution sl;
    ListNode *head = new ListNode(4);
    head->next = new ListNode(2);
    head->next->next = new ListNode(1);
    head->next->next->next = new ListNode(3);
    sl.sortList(head);
    return 0;
}
时间: 2024-12-13 22:39:56

算法学习 - 链表之归并排序_O(1)空间_O(NlogN)时间_C++的相关文章

算法学习 - 链表的游标实现~ C++

链表的游标实现,就是用另外一种方法来访问链表,模拟游标. 在我学习的理解中,就是创建一个节点数组,模拟内存的排列,然后从其中来申请内存和释放内存.但是实际的内存没有被释放~ 下面直接贴代码了: // // main.cpp // CursorList // // Created by Alps on 14-7-27. // Copyright (c) 2014年 chen. All rights reserved. // #include <iostream> #define CursorSp

经典算法学习——链表实现冒泡排序

我在之前一篇博客<经典算法学习--冒泡排序>中简单实现了使用数组进行冒泡排序.这篇博客我们将来实现使用链表如何排序,其实整体的思路是一样的.示例代码上传至: https://github.com/chenyufeng1991/BubbleSortLinkedList . 算法描述如下: (1)比较相邻的前后两个数据,如果前面数据大于后面的数据,就将两个数据交换: (2)这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就到了最后一个位置,也就是下标为N-1的位置(沉到了水底).

经典算法学习——链表中倒数第k个节点

这是剑指Offer中非常经典的一道题,也是在面试笔试中高频出现.题目的详细描述如下:输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,从1开始计数,即链表的尾结点是倒数第一个节点. 本题有一个非常直观的解法,就是对链表扫描两遍,第一遍用来记录链表长度为n,第二次从链表头部走(n-k+1)步后,找到的那个节点就是倒数第k个节点.这种算法的问题就是需要扫描链表两遍,显得不是特别聪明. 其实多想想,这个算法模型和栈的形式非常像,我们只要从头开始扫描链表,把扫描到的每一个节点放入栈中,扫

归并排序算法学习

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MegreSort { class Program { static void Main(string[] args) { int[] A = { 8, 2, 1, 3, 5, 6, 4, 7, 9, 0 }; //int[] A = { 8, 2, 1, 3 }; PrintArray(A); int e

C++:探究纯虚析构函数以及实现数组的快速排序与链表的归并排序

C++:探究纯虚析构函数以及实现数组的快速排序与链表的归并排序 by 小威威 1.介绍 本篇博文将通过课后作业的(15 C++ Homework) D&A 5 Collection with Inheritance来讲解一些重要的排序与零散的知识.而且,本人以科学严谨的态度,对抽象类中析构函数的调用情况进行了分类讨论并一一试验,最终得出了"抽象类最好要定义纯虚析构函数"的结论,并不是凭空捏造,或者是从网上拷贝而来.但是,这仍然代表本人观点,不具有权威性,如有错误,欢迎大家批评指

算法学习笔记

对于一个软件人员来说,算法和数据结构是无法逃避的,越是逃避说明越是需要继续学习和巩固.加深.转载一篇github上有关算法的文章,以便于进行继续学习和理解.当然并不是说非得全部掌握所有算法至少达到需要的时候会找,找到了会使,使完了能明白是什么东西才能更好的进行coding.这篇文章是有关C的 下次再弄个Java语言的算法部分.学无止境嘛,不能光看java也要学习学习C 学习方法 把所有经典算法写一遍 看算法有关源码 加入算法学习社区,相互鼓励学习 看经典书籍 刷题 原文地址:https://gi

数据结构与算法——学习整理记录

===注:此文由本人结合网上资源整理总结而来,仅代表个人的学习与理解,如有错漏,欢迎指正!=== # 1. 数据结构 ## 1.1 数据结构是什么? 数据结构,直白地理解,就是研究数据的逻辑关系与存储方式的一门学科. 可以简单的分为:数据的逻辑结构(逻辑关系)和数据的存储结构(物理结构). 它是以某种形式将数据组织在一起的集合,它不仅存储数据,还支持访问和处理数据的操作. ### 1.1.1 数据的逻辑结构 数据的逻辑结构,简单地理解,就是指的数据之间的逻辑关系. 数据之间的逻辑关系可简单的分为

算法学习 - 01背包问题(动态规划C++)

动态规划 01背包 问题描述 求解思路 代码实现 放入哪些物品 代码 动态规划 我在上一篇博客里已经讲了一点动态规划了,传送门:算法学习 - 动态规划(DP问题)(C++) 这里说一下,遇到动态规划应该如何去想,才能找到解决办法. 最主要的其实是要找状态转移的方程,例如上一篇博客里面,找的就是当前两条生产线的第i个station的最短时间和上一时刻的时间关系. minTime(station[1][i]) = minTime(station[1][i-1] + time[i], station[

最短路径算法学习总结

Dijkstra最短路径算法: dijkstra 算法的优点在于可以求出从一点到所有其他点的最短距离: input: 5 71 2 101 3 201 5 302 5 102 3 54 5 204 3 30 output: 0 10 15 40 20//这是求的在这颗树中,1到所有点的最短距离 1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int N=1100; 5 const int