经典排序—归并排序思想及实现

归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取。

实现原理:

1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

2、设定两个指针变量,最初位置分别指向两个已经排好序的数组序列的起始位置;

3、比较两个指针所指向的元素,选择相对小的元素放入到申请的合并空间里,并移动此指针到下一位置;

4、继续重复步骤3直到某一指针达到序列尾;

5、当一个指针到达一个序列尾时,将另一序列剩下的所有元素直接复制到合并序列尾。

代码(Java):

public class MergeSort {

public static void mergeSort(int[] data, int left, int right)

{
          if (left >= right)
                    return ;
    // 找出中间索引
        int center = (left + right) / 2;
   // 对左边数组进行递归
         mergeSort(data, left, center);
   // 对右边数组进行递归
      mergeSort(data, center + 1, right);
   // 合并
      merge(data, left, center, right);

}

/**
    * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
  *
  * @param data
  * 数组对象
  * @param left
  * 左数组的第一个元素的索引
  * @param center
  * 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
  * @param right
  * 右数组最后一个元素的索引
  */
  public static void merge(int[] data, int left, int center, int right) {
    // 申请临时数组
    int[] tmpArr = new int[data.length];
  // 右数组第一个元素索引
    int mid = center + 1;
     // third 记录临时数组的索引
    int third = left;
 // 缓存左数组第一个元素的索引
    int tmp = left;
  while (left <= center && mid <= right) {
   // 从两个数组中取出最小的放入临时数组
   if (data[left] <= data[mid])

{
      tmpArr[third++] = data[left++];

} else

{
      tmpArr[third++] = data[mid++];
   // count+=center-left+1;
  }
}
   // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
     while (mid <= right) {
    tmpArr[third++] = data[mid++];
    }
  while (left <= center) {
    tmpArr[third++] = data[left++];
   }
   // 将临时数组中的内容拷贝回原数组中
    // (原left-right范围的内容被复制回原数组)
   while (tmp <= right)

{
         data[tmp] = tmpArr[tmp++];
        }
    }
}

利用归并排序的思想可以解决如数组逆序对的问题等等

时间: 2024-10-14 10:36:43

经典排序—归并排序思想及实现的相关文章

经典排序算法 - 归并排序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#实现所有经典排序算法

C# 实现所有经典排序算法 1 .选择排序 选择排序 原理: 选择排序是从冒泡排序演化而来的,每一轮比较得出最小的那个值,然后依次和每轮比较的第一个值进行交换. 目的:按从小到大排序. 方法:假设存在数组:72, 54, 59, 30, 31, 78, 2, 77, 82, 72 第一轮依次比较相邻两个元素,将最小的一个元素的索引和值记录下来,然后和第一个元素进行交换. 如上面的数组中,首先比较的是72,54,记录比较小的索引是54的索引1.接着比较54和59,比较小的索引还是1.直到最后得到最

经典排序算法的PHP实现类

近期广受笔试摧残,对于各种排序也是晕头转向. 更坑爹的是貌似大多都是用C++.Java实现相关算法,让我搞PHP的情何以堪,更何况,PHP本身就有排序函数sort(),其实来说,是很简单的,这也可能是为什么不用PHP进行排序吧. 但考虑到PHP毕竟也是一门面向对象的语言吧,我们利用原生的语法,也是可以实现经典排序算法的,先不说性能如何,切不要妄自菲薄吧. 下面为具体的经典排序算法的PHP实现类. <?php /** * Author: helen * CreateTime: 2016/4/15

算法系列15天速成——第三天 七大经典排序【下】

原文:算法系列15天速成--第三天 七大经典排序[下] 今天跟大家聊聊最后三种排序: 直接插入排序,希尔排序和归并排序. 直接插入排序: 这种排序其实蛮好理解的,很现实的例子就是俺们斗地主,当我们抓到一手乱牌时,我们就要按照大小梳理扑克,30秒后, 扑克梳理完毕,4条3,5条s,哇塞......  回忆一下,俺们当时是怎么梳理的. 最左一张牌是3,第二张牌是5,第三张牌又是3,赶紧插到第一张牌后面去,第四张牌又是3,大喜,赶紧插到第二张后面去, 第五张牌又是3,狂喜,哈哈,一门炮就这样产生了.

七种经典排序算法最全攻略

经典排序算法在面试中占有很大的比重,也是基础.包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序.希望能帮助到有需要的同学.全部程序采用JAVA实现. 本篇博客所有排序实现均默认从小到大. 一.冒泡排序 BubbleSort 介绍: 冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. 步骤: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对第0个到第n-1个数据做同样的工作.这时,最大的数就"浮"到了

九种经典排序算法汇总

/*********************************************************** 总结各种排序算法包括但不限于: 1. 插入排序类 1.1 直接插入排序 1.2 二分插入排序 1.3 希尔排序 2. 交换排序类 2.1 冒泡排序 2.2 快速排序 3. 选择排序 3.1 直接选择排序 3.2 堆排序 4. 归并排序 5. 基数排序 以上所有排序算法的实现均为将整形数组data递增排序 ************************************

常见经典排序算法学习总结,附算法原理及实现代码(插入、shell、冒泡、选择、归并、快排等)

博主在学习过程中深感基础的重要,经典排序算法是数据结构与算法学习过程中重要的一环,这里对笔试面试最常涉及到的7种排序算法(包括插入排序.希尔排序.选择排序.冒泡排序.快速排序.堆排序.归并排序)进行了详解.每一种算法都有基本介绍.算法原理分析.算法代码. 转载请注明出处:http://blog.csdn.net/lsh_2013/article/details/47280135 插入排序 1)算法简介 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过

C/C++中的经典排序算法总结

C/C++中的经典排序算法总结 在C/C++中,有一些经典的排序算法,例如:冒泡排序.鸡尾酒排序或双向冒泡排序(改进的冒泡排序).选择排序.直接插入排序.归并排序.快速排序.希尔排序和堆排序等等.下面对这些排序算法进行一一解析并给出示例代码以共享之. 1.冒泡排序 冒泡排序是最基本的排序算法,之所以称之为冒泡排序是因为在冒泡排序的过程中总是大数往前放,小数往后放,相当于气泡上升. 冒泡排序的基本原理是:依次比较相邻的两个数,将大数放在前面,小数放在后面. 影响冒泡排序算法性能的主要部分就是循环和

经典排序算法的零基础通俗讲解

一.几种经典排序算法的排序过程及时间复杂度 冒泡:时间复杂度O(n²) 第一个数和第二个数比较,大的放在后边,然后第二个数再和第三个数比较,大的放在后面.以此类推. 选择:时间复杂度O(n²): 0到n-1里找最小值放位置0上:1到n-1里找最小值放位置1上 以此类推 插入:时间复杂度O(n²) 一个数 和他前边的数比较 如果大于那个数就放在那个数后面 如果比那个数小就一直往前比较 直到比某个数大就放在那个数后面.如果都没有就放在首位置. 时间复杂度:O(N*logN) : 归并排序,快速排序,