`
canofy
  • 浏览: 829777 次
  • 性别: Icon_minigender_1
  • 来自: 北京、四川
社区版块
存档分类
最新评论

排序之合并排序(归并排序)

阅读更多
合并排序

package algorithm;

/**
 * May 26, 2009 
 * version 1.1
 * @author qinshuangping
 */

public class MergeSort {

	/**
	 * 合并排序(也称归并排序)
	 * 归并操作的工作原理如下(网上找的这个原理和这个例子似乎对不大上,不过大体上差不多吧):
   	 * 1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
   	 * 2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
   	 * 3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
   	 * 4. 重复步骤3直到某一指针达到序列尾
   	 * 5. 将另一序列剩下的所有元素直接复制到合并序列尾
   	 */
	
   	 /** 
   	  * 主要是对数组进行细分,应用了递归
	 * @param ia 待排序的数组
	 * @param p  数组的开始位置(第一次调用时为0)
	 * @param r  数组的结束位置(第一次调用时为数组长度-1)
	 */
	void mergeSort(int ia[], int p, int r){
	    if(p<r ){
	        int q = (p+r)/2;
	        mergeSort(ia, p, q);
	        mergeSort(ia, q+1, r);
	        merge(ia, p, q, r);//排序主方法
	    }
	}

	/**
	 * 对已排序数组的两段合并成一段最终的排序
	 * 如:数组a[] = {8,9,14,17,1,2,3,4,7};p=0;r=8;q=3;
	 * 则调用该方法为merge(a,0,3,8)
	 * 通过merge()方法后数组a变成{1,2,3,4,7,8,9,14,17}
	 * 排序步骤:
	 * 1.新建两个数组
	 * 2.对两个数组赋值,
	 * 		a.ia1为ia[p]--ia[q],为前段数组,数组长度为[q-p+1]
	 * 		b.ia2为ia[q+1]--ia[r],为后段数组,数组长度为[r-q]
	 * 3.设置k=p,主要是为了对待排序的数组进行赋值
	 * 4.当k<r时进行循环,即带排序的数组还没有排好序
	 * 5.对ia1中的数组和ia2中的数组进行比较,即是进行排序,并把结果放进ia中,k++
	 * @param ia 需要进行排序的数组
	 * @param p  数组的开始位置
	 * @param q  数组的中间位置(p+r)/2
	 * @param r  数组的结束位置
	 */
	public void merge(int ia[], int p, int q, int r){
	    int n1 = q - p + 1;     // n1 = [p, q]
	    int n2 = r - q;         // n2 = (q, r]
	    int ia1[]=new int[n1+1];
	    int ia2[]=new int[n2+1];
	    for(int i=0; i<n1; i++){
	        ia1[i] = ia[p+i];
	    }
	    //哨兵?
	    ia1[n1] = 0x7FFFFFFF;   // sentinel
	    for(int i=0; i<n2; i++){
	        ia2[i] = ia[q+1+i];
	    }
	    ia2[n2] = 0x7FFFFFFF;   // sentinel

	    int i, j, k;
	    i = j = 0;
	    k = p;
	    
	    while( k <= r ){
	        if( ia1[i]<=ia2[j] ){
	            ia[k] = ia1[i];
	            i++;
	        }else{
	            ia[k] = ia2[j];
	            j++;
	        }
	        k++;
	    }
	}

	public static void main(String[] args){
		int a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
		 MergeSort ms=new MergeSort();
		 ms.mergeSort(a, 0, a.length-1);
		 for(int i=0; i<a.length; i++){
			 System.out.print(a[i]+",");
		 }
//		int a[] = {8,9,14,17,1,2,3,4,7};
//		 MergeSort ms=new MergeSort();
//		 ms.merge(a, 0, 3, a.length-1);
//		 for(int i=0; i<a.length; i++){
//			 System.out.print(a[i]+",");
//		 }
	}
}

分享到:
评论
1 楼 dmhorse 2010-07-02  
//哨兵? 
        ia1[n1] = 0x7FFFFFFF;   // sentinel 
        for(int i=0; i<n2; i++){ 
            ia2[i] = ia[q+1+i]; 
        } 
        ia2[n2] = 0x7FFFFFFF;   // sentinel 


这一段看不懂.

相关推荐

    MATLAB实现插入排序、二分归并排序、归并排序.rar

    不同之处在于,归并排序不使用二分查找,而是将数组分为两半,然后对每一半进行排序,再合并。归并排序在MATLAB中实现时,也需要递归地将数组划分为更小的部分,直到每个部分仅包含一个元素,然后逐步合并这些元素,...

    归并排序C语言实现

    3. **合并操作**:在归并排序中,合并是将两个已经排序的子数组合并成一个有序数组的过程。这个过程中需要用到额外的存储空间,通常是一个与原数组同样大小的临时数组。比较两个子数组的元素,依次将较小的元素放入...

    直接插入排序 冒泡排序 快速排序 直接选择排序 堆排序 二路归并排序 C#源代码

    6. **二路归并排序**:将数组分成两半,分别对左右两部分进行排序,然后合并两个已排序的部分。C#实现中,通常需要额外的空间来存储中间结果,所以是稳定的排序算法。二路归并排序的时间复杂度在所有情况下都保持在O...

    选择排序、插入排序、冒泡排序以及快速排序和归并排序的C语言实现,绝对可用

    选择排序、插入排序、冒泡排序以及快速排序和归并排序的C语言实现,绝对可用

    归并排序 归并排序示例

    - **过程**:计算中间位置 `m`,递归地对左侧和右侧的子数组进行归并排序,然后调用 `guibing` 函数完成合并。 3. **主函数 `main`**: - 定义了一个包含乱序整数的数组 `ary`,调用 `merge_sort` 对数组进行排序...

    插入排序、选择排序、希尔排序、堆排序、冒泡、双向冒泡、快速排序、归并排序、递归的归并排序、基数排序

    9. 递归的归并排序:归并排序通常使用递归实现,通过递归调用自身对数组的前半部分和后半部分进行排序,然后用归并操作合并结果。这种递归方式使算法具有清晰的逻辑结构。 10. 基数排序:基数排序是一种非比较型...

    java实现归并排序

    Java 实现归并排序是一种常用的排序算法,通过分治策略将原始数组分成小组,然后对每个小组进行排序,最后将排序好的小组合并成一个有序数组。下面是 Java 实现归并排序的知识点总结: 基本思想 归并排序的基本...

    冒泡排序,选择排序,插入排序,希尔排序,堆排序,归并排序,快速排序源码实现

    以下是关于"冒泡排序,选择排序,插入排序,希尔排序,堆排序,归并排序,快速排序"这七种常见排序算法的源码实现及相关知识点的详细解释: 1. **冒泡排序**:冒泡排序是一种简单的排序算法,它重复地遍历待排序的...

    数据结构堆排序 快速排序 归并排序

    本文将深入探讨三种常见的高效排序算法:堆排序、快速排序和归并排序。它们都是基于不同的原理和策略,具有各自的优势和适用场景。 首先,堆排序是一种基于比较的排序算法,利用了二叉堆的数据结构。二叉堆是一个...

    三路归并_C语言_三路归并排序_三路归并_

    **三路归并排序**是一种高效的排序算法,尤其在处理含有大量重复元素的序列时表现优秀。该算法基于归并排序的思想,但将其分为三个部分处理,而不是传统的两个部分。在本文中,我们将深入探讨三路归并排序的原理、...

    归并排序算法实现

    归并排序是一种经典的排序算法,采用分治法的思想,将待排序数组分为若干个子序列,这些子序列是已排序的,然后再按照一定的方式合并这些子序列得到最终排序后的数组。归并排序在实际应用中非常广泛,尤其在处理大...

    数据结构 排序算法之归并排序

    在归并排序中,我们首先将待排序的序列拆分为两半,分别对这两半进行排序,然后再将两个已排序的子序列合并成一个完整的有序序列。这一过程可以递归进行,直到每个子序列只包含一个元素,此时它们自然都是有序的。...

    快速排序、归并排序、堆排序 并比较排序时间

    快速排序、归并排序和堆排序都是经典且高效的排序算法,它们各自具有独特的实现方式和性能特点。这篇文章将详细探讨这三个排序算法,并对比它们的时间复杂度。 首先,我们来看快速排序。快速排序由C.A.R. Hoare在...

    7大排序算法实现程序(快速排序,冒泡排序,选择排序,归并排序,插入排序,希尔排序,堆排序)

    4. 归并排序:同样基于分治策略,将数组分成两半,分别进行排序,然后合并两个已排序的子数组。归并排序是稳定的排序算法,时间复杂度为O(n log n)。 5. 插入排序:对于未排序的元素,依次将其插入到已排序部分的...

    归并排序插入排序C++代码

    1. **基本原理**:归并排序将待排序的序列分为两半,对每一半递归地进行归并排序,然后将两个已排序的半部分合并成一个完整的有序序列。这个过程就像合并两个已经排好序的书架上的书籍。 2. **分治策略**:归并排序...

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

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

    算法设计实验报告-快速排序和归并排序

    - **空间复杂度**:O(n),因为归并排序需要额外的空间用于临时存储合并后的子序列。 **3. C++实现代码** ```cpp void Merge(int r[], int r1[], int s, int m, int t) { int i, j, k; i = s; j = m + 1; k = s; ...

    归并排序算法实现(排序算法系列1)

    归并排序的工作原理可以分为三个主要步骤:分割、归并和合并。首先,将待排序的序列分割成两个相等(或近乎相等)的部分;然后对每一部分递归地进行排序;最后,将两个已排序的部分合并成一个有序序列。这一过程确保...

    快速排序,堆排序,归并排序,插入排序,选择排序

    归并排序是分治策略的典型应用,将数组分成两个子数组,分别进行排序,再合并成一个有序数组。它保证了稳定性和O(n log n)的时间复杂度,但需要额外的空间来存储子数组,空间复杂度为O(n)。 4. **插入排序**: 插入...

    java 排序算法 选择排序,插入排序,自顶向上合并排序,合并排序,快速排序

    合并排序与自顶向上归并排序类似,都是基于分治策略。区别在于,合并排序可以是自底向上或自顶向下实现。这里主要介绍自底向上的方法: - 从长度为1的子序列开始,逐步合并相邻的子序列,形成长度为2、4、8...的...

Global site tag (gtag.js) - Google Analytics