排序之归并排序

       归并排序是分治法中的一个实例,分治法是世界上最著名的通用算法设计技术之一。分治法的基本思想是:首先将带求解实例分解为相同规模的较小实例,然后对较小实例求解,最后将较小实例的解合并,得到整个实例的解。
       所谓“归并”,就是将两个或两个以上的有序表合成一个有序表,这是归并排序中的核心操作。归并排序的基本思想分为三步(以数组排序为例):1、分,将待排序数组一分为二;2、排,对子数组采用同样的方法进行排序;3、和,将两个有序数组合并为一个有序数组。具体分析如下:
       分:将待排序数组一分为二,若子数组的长度还大于1,则继续分。在这一步中,要将一个数组拆分成两个子数组,需要额外的存储空间。两个子数组的长度和等于待排序数组的长度,先要为两个子数组分配空间,然后将待排序数组的前一半复制给数组1,后一半复制给数组2。数组的复制容易,可以自己写一个数组复制的方法,也可以直接使用java中提供的数组复制的方法  System.arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length); 其中的参数分别表示  起始数组、起始下标、目的数组、目的起始下标、复制长度。
       排:对子数组使用同样的方法进行排序,大多数情况下使用递归,若子数组的长度大于1,继续分,直到长度等于1为止,进行下面的和并。
       和:将有序的子数组合并为一个有序的数组,这是归并排序算法中的核心操作。完成这一步的思想是:设两个指针指向两个数组的起始下标,然后将两个元素进行比较,将较小的移入大数组中,并且这个指针往后移一位,重复这个步骤,直到其中一个子数组遍历完全,再将剩下的元素复制到大数组末尾。
       伪代码如下:
void mergeSort(int[] a){
//使用归并排序算法对数组a进行排序
//输入:可排序数组a[0...n]
//输出:有序数组a[0...n]
if(a.length>1){  //当数组长度大于1时用归并排序进行排序
       arrayCopy(a[0...n/2],b[0...n/2]);  //将待排序数组一分为二
       arrayCopy(a[n/2+1....n],c[0...n/2];
       //对子数组用递归方式进行排序
       mergeSort(b);
       mergeSort(c);
       merge(b,c,a);  //将两个子数组再合并到原数组中
}


}

void merge(int[] a,int[] b,int[] c){
//将两个有序的子数组合并到数组c中
      i←0;j←0;k←0;
      while i<a.length && j<b.length {
             if(a[i]<b[j]) {
                     c[k]←a[i];
                     k++;i++;
      }else{
                     c[k]←b[j];
                     k++;j++;
       }

}
     //循环结束后要判断还有哪个数组由剩余
      if  i == a.length    //表明数组a已经遍历完全
           copy b[j...] to c[k....]
       else     copy a[i...] to c[k...]

}
package com.poe.sort;

import java.util.Scanner;

/**
 * 归并排序:简单地说就是分与和,分:将待排序数组一分为二,再对其子数组用同样的方法排序 和:将相邻两个有序数组合并为一个有序数组 一般用递归的形式来表示
 * 归并排序是稳定的,而快速排序和堆排序是不稳定的 归并排序缺点:需要额外的存储空间(要注意这个额外数组的分配位置,不能放在Merge中)
 * 
 * @author Sam
 * 
 */
public class MergeSort {
	private static int[] array; // 待排序数组,由命令行输入
	private static int[] tempArray;// 额外的数组

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in); // 命令行输入类
		array = new int[11]; // 为待排序数组分配空间
		System.out.println("请输入元素");
		for (int i = 0; i < array.length; i++) {
			System.out.print("a[" + i + "]=");
			array[i] = sc.nextInt();
			System.out.println();
		}
		System.out.print("排序前数组为:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " ");
		}
		System.out.println();
		// 输完之后得到待排序数组array[0...9],调用归并排序方法进行排序
		mergeSort(array);
		System.out.print("排序后数组为:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " ");
		}
		System.out.println();
		//下面是使用System类中提供的数组复制的方法
//		int[] t = new int[3];
//		System.arraycopy(array, 3, t, 0, 3);
//		for(int i = 0;i<3;i++){
//			System.out.print("t["+i+"]="+t[i]+"   ");
//		}
	}

	/**
	 * 合并算法,将两个有序数组合并为一个有序数组
	 * 
	 * @param a1有序数组一
	 * @param a2有序数组二
	 * @param a3合并成的新的数组
	 */
	public static void merge(int[] a1, int[] a2, int[] a3) {
		int i = 0;// i指向数组a1
		int j = 0;// j指向数组a2
		int k = 0;// k指向数组a3
		while (i < a1.length && j < a2.length) { // 两个子数组都还有元素
			if (a1[i] <= a2[j]) { // 将小的元素移入合并的数组中,指针后移
				a3[k] = a1[i];
				k++;
				i++;
			} else {
				a3[k] = a2[j];
				k++;
				j++;
			}
		}
		// 循环结束后要判断还有哪个数组还有剩余,将剩余元素复制到新合并的数组中
		if (i == a1.length) { // 表明数组a1已遍历完全,a2还有剩余
			for (j = j; j < a2.length; j++) {
				a3[k] = a2[j]; // 将a2中剩余的元素复制到a3末尾
				k++;
			}
		} else {
			for (i = i; i < a1.length; i++) {
				a3[k] = a1[i];
				k++;
			}
		}
		// 到此,两个数组a1,a2已合并成一个有序数组a3
	}
	/**
	 * 用归并排序算法对数组进行排序
	 * @param a为待排序数组
	 */
	public static void mergeSort(int[] a) {
		if (a.length > 1) {
			int[] temp1 = new int[a.length / 2];  //创建一个临时数组,长度为a的一半
			int[] temp2 = new int[a.length-temp1.length];  //创建两个临时数组,总长度为待排序数组的长度
			//1、分:将待排序数组一分为二
			aCopy(a, temp1, 0, a.length/2-1);	
			aCopy(a, temp2, a.length/2, a.length-1);
			//2、对子数组递归调用同样方法进行排序
			mergeSort(temp1);
			mergeSort(temp2);
			//3、和:将两个有序子数组合并为一个有序数组
			merge(temp1, temp2, a);
		}
	}

	// /**
	// * 对相邻两个有序数组合并成一个有序数组
	// * @param a1有序数组一
	// * @param a2有序数组二
	// * @param first
	// * @param mid
	// * @param end
	// */
	// public static void merge(int[] a1,int[] a2,int first,int mid,int end){
	//
	// }
	//
	// /**
	// * 用归并排序算法对数组进行排序
	// * @param a表示待排序数组
	// * @param orign表示待排序数组的起始下标
	// * @param end表示待排序数组的终止下标
	// */
	// public static void mergeSort(int[] a,int[] atemp,int orign,int end){
	// if(orign
    
    

  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值