归并排序 
  归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。这里仅对内排序的两路归并方法进行讨论。 
1.两路归并排序算法思路
①把 n 个记录看成 n 个长度为1的有序子表;
②进行两两归并使记录关键字有序,得到 n/2 个长度为 2 的有序子表; 
③重复第②步直到所有记录归并成一个长度为 n 的有序表为止。
【例】 有一组关键字 {4,7,5,3,2,8,6,1},n=8, 将其按由小到大的顺序排序。 两路归并排序操作过程如图 9.12 所示,其中i 为子表长度。

2.算法实现
  此算法的实现不像图示那样简单,现分三步来讨论。首先从宏观上分析,首先让子表表长 L=1 进行处理;不断地使 L=2*L ,进行子表处理,直到 L>=n 为止,把这一过程写成一个主体框架函数 mergesort 。然后对于某确定的子表表长 L ,将 n 个记录分成若干组子表,两两归并,这里显然要循环若干次,把这一步写成一个函数 mergepass ,可由 mergesort 调用。最后再看每一组(一对)子表的归并,其原理是相同的,只是子表表长不同,换句话说,是子表的首记录号与尾记录号不同,把这个归并操作作为核心算法写成函数 merge ,由 mergepass 来调用。假设我们有一个没有排好序的序列,那么首先我们使用分割的办法将这个序列分割成一个一个已经排好序的子序列,然后再利用归并的方法将一个个的子序列合并成排序好的序列。分割和归并的过程可以看下面的图例。


3.算法主要思想
template<class T>
  void merge( T r[],T r2[],int s,int mid,int t)
  //s为第一个子表首元素的下标,mid为第一个子表末元素的下标
  //t为第二个子表末元素的下标
   { int i,j,k;
     i=s;j=mid+1;k=s;   //k是r2的初始指针
     while((i<=mid)&&(j<=t))
       { k=k+1;
         if(r[i].key<=r[j].key){r2[k]=r[i];i++;}
         else{r2[k]=r[j];j++;}
       }
     while(i<=mid){k++;r2[k]=r[i];i++;}
     while(j<=t){k++;r2[k]=r[j];j++;}
  }   //merge

4. 算法的Java实现

Java实现的二路归并排序的算法如下:

package algorithms;

public class myMergeSort {
static int number=0;
public static void main(String[] args) {
int[] a = {26, 5, 98, 108, 28, 99, 100, 56, 34, 1 };
printArray("排序前:",a);
MergeSort(a);
printArray("排序后:",a);
} private static void printArray(String pre,int[] a) {
System.out.print(pre+"\n");
for(int i=0;i<a.length;i++)
System.out.print(a[i]+"\t");
System.out.println();
} private static void MergeSort(int[] a) {
// TODO Auto-generated method stub
System.out.println("开始排序");
Sort(a, 0, a.length - 1);
} private static void Sort(int[] a, int left, int right) {
if(left>=right)
return; int mid = (left + right) / 2;
//二路归并排序里面有两个Sort,多路归并排序里面写多个Sort就可以了
Sort(a, left, mid);
Sort(a, mid + 1, right);
merge(a, left, mid, right); } private static void merge(int[] a, int left, int mid, int right) { int[] tmp = new int[a.length];
int r1 = mid + 1;
int tIndex = left;
int cIndex=left;
// 逐个归并
while(left <=mid && r1 <= right) {
if (a[left] <= a[r1])
tmp[tIndex++] = a[left++];
else
tmp[tIndex++] = a[r1++];
}
// 将左边剩余的归并
while (left <=mid) {
tmp[tIndex++] = a[left++];
}
// 将右边剩余的归并
while ( r1 <= right ) {
tmp[tIndex++] = a[r1++];
} System.out.println("第"+(++number)+"趟排序:\t");
// TODO Auto-generated method stub
//从临时数组拷贝到原数组
while(cIndex<=right){
a[cIndex]=tmp[cIndex];
//输出中间归并排序结果
System.out.print(a[cIndex]+"\t");
cIndex++;
}
System.out.println();
} }

运行后的输出结果如下所示:

排序前:

开始排序
第1趟排序: 第2趟排序: 第3趟排序: 第4趟排序: 第5趟排序: 第6趟排序: 第7趟排序: 第8趟排序: 第9趟排序: 排序后:
 

5.算法分析
(1)稳定性
      归并排序是一种稳定的排序。
(2)存储结构要求
     可用顺序存储结构。也易于在链表上实现。
(3)时间复杂度
     对长度为n的文件,需进行 趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
(4)空间复杂度
     需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
  注意:
     若用单链表做存储结构,很容易给出就地的归并排序。

MergeSort(归并排序)算法Java实现的更多相关文章

  1. 归并排序算法 java 实现

    归并排序算法 java 实现 可视化对比十多种排序算法(C#版) [直观学习排序算法] 视觉直观感受若干常用排序算法 算法概念 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Di ...

  2. 归并排序算法Java实现

    一. 算法描述 归并排序采用了分治策略(divide-and-conquer),就是将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解. 归并排序将待排序数组 ...

  3. MergeSort 归并排序(java)

    MergeSort 归并排序 排序思想:1,分解待排序的n个元素为两个子列,各为n/2个元素 2,若子列没有排好序,重复1步骤,每个子列继续分解为两个子列,直至被分解的子列个数为1 3,子列元素个数为 ...

  4. 归并排序算法-Java实现

    简介: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序 基本思想: 将一个无序数组,利用 ...

  5. 排序系列 之 归并排序算法 —— Java实现

    基本思想: 归并排序法是分治法的典型实例,分为分割和归并两部分. 把一个数组分为大小相近的子数组(分割),分别把子数组排好序后,通过合成一个大的排好序的数组(归并). 实例: 先分割成每个子序列只有一 ...

  6. 【排序算法】归并排序算法 Java实现

    归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 基本思想 可以将一组数组分成A,B两组 依次类推,当分出来的小组只有一 ...

  7. 算法-java代码实现归并排序

    归并排序 对于一个int数组,请编写一个归并排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] ...

  8. java实现归并排序算法

    归并排序算法思想:分而治之(divide - conquer);每个递归过程涉及三个步骤第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.第二, 治理: ...

  9. 排序算法-归并排序(Java)

    package com.rao.sort; import java.util.Arrays; /** * @author Srao * @className MergeSort * @date 201 ...

随机推荐

  1. Hibernate检索策略之延迟加载和立即加载

    延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询.避免了无谓的性能开销. 延迟加载分类:  1.类级别的查询策略 2.一对多和多对多关联的查询策略 3.多对 ...

  2. Maya 建模完成后的整理

    我们在使用Maya建模完成后可能会进行发布,为了自己或他人的方便使用,我们需要对建立好的模型进行些处理: 1. 删除历史记录:选择模型,Edit -> Delete by Type -> ...

  3. Jquery超简单遮罩层实现代码

    看了很多代码,下面跟大家分享一下我认为最简单的遮罩层实现方式: 1.样式如下设置: CSS代码: <style type="text/css"> .mask { pos ...

  4. Struts2中上传图片案列

    1.HTML代码 <body> <!--上传一个文件   enctype="multipart/form-data" 上传文件必须设置这个属性和属性值--> ...

  5. zk 隐藏网页文件后缀

    前台(test.zul): <a label="隐藏地址" href="/Bandbox/test.html"/> web.xml添加 <se ...

  6. WebApp 设计要素

    从去年开始就负责公司WebApp的产品跟设计工作,最近整体大改了两个版本,也算累积了一些实际的经验.在不断学习的过程中,发现对于WebApp可以直接用于项目上的资料比较零碎,在这里总结一下,供初做 W ...

  7. Hibernate和Mybatis的对比

    http://blog.csdn.net/jiuqiyuliang/article/details/45378065 Hibernate与Mybatis对比 1. 简介 Hibernate:Hiber ...

  8. IEnumerable和IQueryable区别、优缺点

    转自 http://www.cnblogs.com/fly_dragon/archive/2011/02/21/1959933.html IEnumerable接口 公开枚举器,该枚举器支持在指定类型 ...

  9. 重新启动 Apache 以加载上面安装的模块

    尽管Ubuntu 是一种新兴的Linux分支,但Ubuntu 组织却为Apache提供了丰富的支持软件,这些软件都可以从发行版的光盘获取,也可以从官方站点轻松下载.所以,Ubuntu非常适合作为Web ...

  10. Android课程---单选框与复选框的实现

    <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...