`
zhouYunan2010
  • 浏览: 207508 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类

java中的归并排序

阅读更多
为什么使用归并排序?
java中的Arrays.sort(Object[] o)是对数组进行排序,它使用的是归并排序的方式,
快速排序要比归并排序更快一些,但为什么使用归并排序了?原因是归并排序是一种稳定的排序
方式,即归并排序不交换相同的元素,这就意味着,在按一种方式排序后同时可以按另外一种
方式进行排序。比如员工可以首先按工资排序,然后按名字排序,一种排序不会打乱另一种排序
的顺序。
下面分析下sort方法的简化版:
    /**
     * 归并排序 (递归实现)
     * 前提: 每个元素要有可比性,这里元素必须实现Comparable接口。
     * 基本原理为:1.拆分 假设有N个元素的列表,首先把它拆分成2个或2个
     * 以上的元素组成的新的列表(这里我的新列表长度不超过3),分别对对它们进行排序。
     * 2.归并。把所有的排好序的子类表两两归并,如此重复,直到归并成一个含N个
     * 元素的有序列表为止
     * 图解:(大于3就继续分解)
     *  大于3          8    7    6    5     4     3     2     1
     *                                分|解
     *                                  |
     *  大于3            8  7  6  5            4   3   2   1 
     *                     分|解                  分|解
     *                       |                      | 
     *  小于 3            8 7   6 5             4  3    2 1
     *  排序              7 8   5 6             3  4    1 2 
     *  归并                 |                       | 
     *                  7   8  5  6            3  4    1  2 
     *                       |                       |
     *  顺序保存        5   6  7  8            1  2    3  4
     *                                   |
     *  归并           5    6    7    8   1    2    3     4
     *  				 |
     *  顺序保存       1    2    3    4   5    6    7     8
     * @param src 临时中间数组,它是目标数组的拷贝
     * @param target 目标排序数组
     * @param low 需排序的起始索引
     * @param high 需排序的结束索引
     * 
     */
    public static void mergeSort(Object[] src,Object[] dest,int low,int high){
    	int length = high - low;
    	if(length < 3 ){	//对长度小于3的列表排序
    		//排序方法一:起泡排序(大数沉底)
//    		for(int i=low;i<high-1;i++){
//    			for(int j=low;j<high-1-i+low;j++){
//    				if(((Comparable) dest[j]).compareTo(dest[j+1]) > 0){
//        				swap(dest, j, j+1); 
//        			}
//    			}
//    		}
    		//排序方法二:这是起泡排序的一种变体(小数上浮)
    		for (int i = low; i < high; i++){
    			for (int j = i; j > low ; j--){
    				if(((Comparable) dest[j - 1]).compareTo(dest[j]) > 0){
    					swap(dest, j-1, j); 
    				}
    			}
    		}
    		return;
    	}
    	
    	int mid = (high + low)/2;	//拆分
    	mergeSort(dest, src, low, mid);	 //递归,可能会继续拆分(那么必然继续合并)
    	mergeSort(dest, src, mid, high);
    	
    	//开始归并,方法一
//    	for(int i=low,p=low,q=mid;i<high;i++){
//    		//第一个条件时为了添加剩余的值
//			if(q >= high || (p < mid &&((Comparable) src[p]).compareTo(src[q]) <= 0)){
//				dest[i] = src[p++];
//			}else{
//				dest[i] = src[q++];
//			}
//    	}
    	
    	//开始归并,方法二
    	int i = low;
    	int p = low;	//第一个列表指针
    	int q = mid;    //第二个列表指针
    	while(p < mid && q <high){
    		if(((Comparable) src[p]).compareTo(src[q]) <= 0){
    			dest[i++] = src[p++];
    		}else{
    			dest[i++] = src[q++];
    		}
    	}
    	//添加剩余的值
    	while(p < mid && i<high){
    		dest[i++] = src[p++];
    	}
    	while(q < high && i<high){
    		dest[i++] = src[q++];
    	}

    private static void swap(Object[] x, int a, int b) {
    	Object t = x[a];
    	x[a] = x[b];
    	x[b] = t;
    }
}



递归形式的算法在形式上比较简洁,但实用性不够好。
下面讲讲归并排序的非递归实现
public class MergeDemo{
	public static void main(String[] args) {
		String[] a= {"9","8","7","6","5","4","3","2","1"};
		Object[] aux = (Object[])a.clone();
		mergeSort(aux, a);
		for(int i=0;i<a.length;i++){
			System.out.println(a[i]);
		}
	}

    //每个拆分的列表元素个数<=3
    private static final int INSERTIONSORT_THRESHOLD = 3;
    /**
     * 
     * 归并排序(非递归实现)
     */
    public static void mergeSort(Object[] src,Object[] dest){
    	int spreCount = INSERTIONSORT_THRESHOLD;	 
    	int low,mid,high;
    	int len = src.length;
		if(len <= INSERTIONSORT_THRESHOLD*2){		//如果只能划分为两组,直接排序
			sort(dest,0,len);
			return;
		}
    	while(spreCount < len){
	    	for(int i=0;i<len;i=high){	//依次排序归并相邻两个列表
	    		low = i;	
	    		high = low + spreCount * 2 ;
	    		mid = low + spreCount;
	    		if(high >= len){
	    			high = len;
	    		}
	    		int l = high - low;
	    		if(l <= INSERTIONSORT_THRESHOLD){
	    			sort(src,low,high);
	    			break;
	    		}

	    		if(spreCount == 3){		//所有拆分的列表只进行一次排序
	    			sort(dest,low,mid);
	    			sort(dest,mid,high);
	    		}
	    		if(l == len)	//最后一次归并把src有次序的赋给dest
	    			Merge(src,dest,low,mid,high);
	    		else
	    			Merge(dest,src,low,mid,high);

	    	}
	    	spreCount *= 2;
    	}
    	
    }
    //对拆分的每个列表进行排序
    private static void sort(Object[] dest,int low,int high){
		for (int i = low; i < high; i++){
			for (int j = i; j > low ; j--){
				if(((Comparable) dest[j - 1]).compareTo(dest[j]) > 0){
					swap(dest, j-1, j); 
				}
			}
		}
    }
    
    //归并相邻两个列表并保存在dest中
	private static void Merge(Object[] src, Object[] dest, int low, int mid,
			int high) {
    	int i = low;
    	int p = low;	//第一个列表指针
    	int q = mid;    //第二个列表指针
    	while(p < mid && q <high){
    		if(((Comparable) src[p]).compareTo(src[q]) <= 0){
    			dest[i++] = src[p++];
    		}else{
    			dest[i++] = src[q++];
    		}
    	}
    	//添加剩余的值
    	while(p < mid && i<high){
    		dest[i++] = src[p++];
    	}
    	while(q < high && i<high){
    		dest[i++] = src[q++];
    	}
		
	}
	
    private static void swap(Object[] x, int a, int b) {
    	Object t = x[a];
    	x[a] = x[b];
    	x[b] = t;
    }
 

}

分享到:
评论

相关推荐

    java实现归并排序

    在上面的代码实现中,我们可以看到,归并排序的时间复杂度为 O(nlog2^n),这是因为我们需要将原始数组分割成小组,并对每个小组进行排序,然后将排序好的小组合并成一个有序数组。空间复杂度为 O(N),这是因为我们...

    如何使用Java实现归并排序算法,程序详细解读

    归并排序:如何使用Java实现归并排序算法,程序详细解读; 归并排序:如何使用Java实现归并排序算法,程序详细解读; 归并排序:如何使用Java实现归并排序算法,程序详细解读; 归并排序:如何使用Java实现归并排序...

    java 中归并排序算法详解

    Java 中归并排序算法详解 Java 中归并排序算法是一种时间复杂度为 O(N logN) 的排序算法,因而其在平常生活工作中应用非常广泛。下面是对 Java 中归并排序算法的详细解释: 算法思想 归并排序算法顾名思义,是一...

    归并排序Java_归并排序_

    在Java中实现归并排序,我们可以创建一个名为`MergeSort`的类来封装整个过程。归并排序的基本思想是将待排序的序列分成两个或更多的子序列,对每个子序列分别进行排序,然后将排序后的子序列合并成一个有序序列。这...

    Java实现归并排序

    在Java中实现归并排序,主要涉及到以下几个关键步骤: 1. **分割(Divide)**:将原始数组分为两个相等(或接近相等)的子数组。这通常通过取数组中间索引来完成。例如,如果数组长度为`n`,则可以将前`n/2`个元素...

    归并排序,消除递归归并排序,快排,Java实现

    这里有三个主要的排序算法:归并排序、消除递归的归并排序和快速排序,它们都是在Java编程语言中实现的。让我们深入探讨这些算法及其Java实现。 1. **归并排序(Merge Sort)** 归并排序是一种基于分治思想的排序...

    JavaSwing归并排序动画源码(含其他排序)

    在这个场景中,我们讨论的焦点是使用 Java Swing 来实现一个排序算法的动画展示,特别是归并排序。归并排序是一种高效的、稳定的排序算法,它的基本思想是将大问题分解为小问题来解决,通过递归地将两个或更多有序数...

    Java ArrayList实现的快排,归并排序,堆排序

    本篇将重点讲解如何利用ArrayList实现快速排序(Quick Sort)、归并排序(Merge Sort)和堆排序(Heap Sort)这三种经典的排序算法,并探讨它们的原理、优缺点以及在实际应用中的选择。 **快速排序(Quick Sort)**...

    [Java算法-排序]归并排序.java

    该资源提供了一份全面的指南,介绍了如何在Java中实现归并排序。文档中涵盖了归并排序的基本概念,包括如何对数组进行排序以及如何在Java中实现归并排序。此外,文档还包括一个逐步指南,介绍如何在Java中实现归并...

    java归并外排序

    在归并外排序中,每个块视为一个已排序的序列,而合并操作则是在多个块之间进行。 Java实现归并外排序时,通常会用到以下几个关键类和方法: - `FileReader` 和 `BufferedReader`:用于读取文件。 - `FileWriter` ...

    Java实现归并排序.rar

    在Java中实现归并排序,我们可以遵循以下步骤: **一、理解归并排序原理** 归并排序是将大问题分解成小问题来解决。它将待排序的序列分成两个子序列,分别对这两个子序列进行排序,然后将排好序的子序列合并成一个...

    java算法——归并排序

    归并排序 在排序前,先建好一个长度等于原数组长度的临时数组

    java实现归并排序代码

    归并排序 java实现归并排序

    归并排序(JAVA)

    4. **合并操作**:这是归并排序中的关键步骤。我们需要创建一个新的临时数组,比较两个子数组的元素,按顺序将它们添加到临时数组中。比较时,从两个子数组的起始位置开始,选择较小的元素放入新数组,直到其中一...

    插入排序和归并排序的实现java

    这里我们将深入探讨两种常见的排序算法:插入排序(Insertion Sort)和归并排序(Merge Sort),它们都是在Java环境下实现的。 **插入排序**是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序...

    java归并排序

    在Java中实现归并排序,我们可以分别实现递归版和非递归版,这两种方法各有其特点和适用场景。 ### 1. 分治策略 归并排序的核心是分治法,它将一个大数组分为两个相等或接近相等的子数组,分别对这两个子数组进行...

    Java实现归并排序算法(源代码)

    ### Java实现归并排序算法(源代码)知识点详解 #### 一、归并排序概述 归并排序是一种经典的排序算法,其核心思想是分而治之。它将一个大问题分解为若干个相同的小问题来解决,最终通过合并这些小问题的解来得到...

    各种java排序 归并排序 冒泡排序 选择排序

    本文将深入探讨四种常见的排序算法:快速排序、归并排序、冒泡排序和选择排序。这些算法不仅在理论上有其重要性,而且在实际编程项目中也经常被用到。 ### 快速排序 快速排序是由英国计算机科学家C.A.R. Hoare提出...

    归并排序Java源代码

    利用分治法思想实现归并排序,Java语言描述。

    java版冒泡排序,插入排序,堆排序,快速排序,归并排序,希尔排序,桶排序

    它将数组分为两半,分别对左右两半进行归并排序,然后再合并这两个已排序的子数组。Java中,可以使用两个辅助数组来辅助排序和合并的过程。 6. **希尔排序(Shell Sort)**: 希尔排序是插入排序的一种优化版本,...

Global site tag (gtag.js) - Google Analytics