排序(五)归并排序

定义:合并排序就是通过将两个有序的序列合并为一个大的有序的序列的方式来实现排序。

合并排序是一种典型的分治算法:首先将序列分为两部分,然后对每一部分进行循环递归的排序,然后逐个将结果进行合并。

合并排序最大的优点是它的时间复杂度为O(nlgn)。他还是一种稳定性排序,也就是相等的元素在序列中的相对位置在排序前后不会发生变化。他的唯一缺点是,需要利用额外的N的空间来进行排序。

效果图:

如果以排序38,27,43,3,9,82,10为例,将合并排序画出来的话,可以看到如下图:

    void Combin(vector<int>& Vector,vector<int>& tmp, int left, int middle, int right)  //合并两个有序区间
    {
        int start1 = left;
        int start2 = middle + 1;
        int index = left;
        while (start1 != middle + 1 && start2 != right + 1)
            tmp[index++] = Vector[start1] < Vector[start2] ? Vector[start1++] : Vector[start2++];
        if (start1 == middle + 1)
        {
            while (start2 != right + 1)
                tmp[index++] = Vector[start2++];
        }
        else
        {
            while (start1 != middle + 1)
                tmp[index++] = Vector[start1++];
        }

        while (left != right + 1)
        {
            Vector[left] = tmp[left];
            left++;
        }

    }

    void Section(vector<int>& Vector, vector<int>& tmp, int left, int right)   //分段排序
    {
        int middle = left + (right - left) / 2;
        if (middle - left + 1 > 13)    //优化 1
            Section(Vector,tmp,left, middle);
        else
            InsertSort(Vector, left, middle);
        if (right - middle > 13)
            Section(Vector,tmp, middle + 1, right);
        else
            InsertSort(Vector, middle + 1, right);     if(Vector[middle] > Vector[middle+1])       //优化 2
        Combin(Vector,tmp, left, middle, right);
    }

    void MergeSort(vector<int>& Vector)
    {
        vector<int> tmp;
        tmp.resize(Vector.size());
        Section(Vector, tmp, 0, Vector.size() - 1);
    }

算法分析:

1. 合并排序的平均时间复杂度为O(nlgn)

我们对数组N进行MergeSort的时候,是逐级划分的,这样就形成了一个满二叉树,树的每一及子节点都为N,树的深度即为层数lgN+1

所以时间复杂度为:  O(N)=(lgN+1)N=NlgN+N=NlgN

2.在合并排序中,我们要创建一个大小为N的辅助排序数组来存放初始的数组或者存放合并好的数组,所以需要长度为N的额外辅助空间。

所以空间复杂度为: S(N) = N

改进:

1. 当划分到较小的子序列时,通常可以使用插入排序替代合并排序

2.当已排好序的左侧的序列的最大值<=右侧序列的最小值的时候,表示整个序列已经排好序了。

3. 并行化

用途:

合并排序和快速排序一样都是时间复杂度为nlgn的算法,但是和快速排序相比,合并排序是一种稳定性排序,也就是说排序关键字相等的两个元素在整个序列排序的前后,相对位置不会发生变化,这一特性使得合并排序是稳定性排序中效率最高的一个。在Java中对引用对象进行排序,Perl、C++、Python的稳定性排序的内部实现中,都是使用的合并排序。

时间: 2024-08-01 06:48:07

排序(五)归并排序的相关文章

“《算法》第4版第2章‘排序’”:归并排序

归并排序(Merge Sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 归并操作(Merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作.归并排序有多路归并排序.两路归并排序 , 可用于内排序,也可以用于外排序.这里仅对内排序的两路归并方法进行讨论. 归并排序的步骤如下: 1)Divide: 将待排序序列(原问题)分成两个规模大致相等的子序列(子问题

排序(6)---------归并排序(C语言实现)

归并排序: 归并操作,也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作. 归并操作的过程如下: (1) 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 (2) 设定两个指针,最初位置分别为两个已经排序序列的起始位置 (3) 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 (4) 重复步骤3直到某一指针到达序列尾 (5) 将另一序列剩下的所有元素直接复制(抄)到合并序列尾 简单的说,就是将一个序列不断的进行

排序算法——归并排序

归并排序是分治法的典型举例. 分治法的思想是,将原有问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治模式在每层递归时都有三个步骤: 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例. 解决这些子问题,递归地求解各子问题.然而,若子问题的规模足够小,则直接求解. 合并这些子问题的解成原问题的解. 归并排序算法完全遵循分治模式.直观上其操作如下: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列. 解决:使用

经典排序算法 - 归并排序Merge sort

经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 4 1 5 9] 先看一下每一个步骤下的状态,完了再看合并细节 第一步 [6 2 4 1 5 9]原始状态 第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步 [1 2 4 6] [5 9]继续两组两组合并 第四步 [1 2 4 5 6 9]合并完成,排序完成 输出结

处理海量数据的三大排序之——归并排序(C++)

代码实现                                                                                                                                                                                   #include "stdafx.h" #include <iostream> #include <cti

单链表的排序 快速排序 归并排序 quicksort mergesort

原理都很简单,关键是某些边界能否正确写对: #include<iostream> #include<stdio.h> using namespace std; class Node { public: int val; Node* next; Node(int val = 0):val(val),next(NULL){ } }; Node* quicksort(Node* head, Node* tail) { Node *res1 = NULL, *res2 = NULL; No

阿布学排序之归并排序

// test_max.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <cv.h> #include <highgui.h> #include <ml.h> #include <cxcore.h> #include <iostream> using namespace std; int main() { // step 1: //训练数据的分类标记,即4类 float

C# 插入排序 冒泡排序 选择排序 高速排序 堆排序 归并排序 基数排序 希尔排序

以下列出了数据结构与算法的八种基本排序:插入排序 冒泡排序 选择排序 高速排序 堆排序 归并排序 基数排序 希尔排序,然后是測试的样例.代码位置:http://download.csdn.net/detail/luozuolincool/8040027 排序类: public class Sortings { //插入排序 public void insertSort(int[] array) { int temp = 0; int index = 0; for (int i = 0; i <

在路上---学习篇(一)Python 数据结构和算法 (4) --希尔排序、归并排序

独白: 希尔排序是经过优化的插入排序算法,之前所学的排序在空间上都是使用列表本身.而归并排序是利用增加新的空间,来换取时间复杂度的减少.这俩者理念完全不一样,注定造成的所消耗的时间不同以及空间上的不同. 归并排序涉及到递归的使用,需要理解其中精髓才能更好了解归并排序,以及其他应用到递归的算法.理解其本质才能更好的应用. 希尔排序 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shell于195

链表排序之归并排序

链表排序之归并排序: public static ListNode mergeSortList(ListNode head){ if (null == head || null == head.next){ return head; } ListNode slow = head; ListNode fast = head; ListNode pre = head; while (null != fast && null != fast.next){ pre = slow; slow = s