java排序算法三(归并排序算法)

本文介绍了一种高效的排序算法——归并排序。通过递归将数组分成小部分进行排序,然后合并这些部分。虽然该算法的时间复杂度为O(NlogN),但需要额外的线性空间。文中还提供了一个Java实现示例。

归并排序


       递归可以用来开发亚平方时间的算法。具体的,分治算法把问题拆分为两个一半规模的问题递归解决,每个自问题的开销是O(N),结果整个算法就是O(NlogN)的。归并排序就是这样的算法。至少在理论上,归并算法提供了比谢尔排序算法生成的限度更好的限度值。

       归并排序算法包括三个步骤:

1.如果待排序的项数为0或1,返回

2.对等分的两部分分别递归排序

3.将已经排好序的两部分归并为一个有序组


基本的归并算法有两个有序的输入数组A和B,以及一个输出数组C

假如A为:4,6,9,10,21

假如B为:3,6,8,12,23


那么C的产生过程如下:

第一步:

比较A的4和B的3,3小于4,于是C第一个元素填进3。

C:3


第二步:

比较A的4和B的6,4小于6,于是C第二个元素填进4。

C:3,4


第三步:

比较B的6和A的6,相等,于是C的第三个元素填进6。

C:3,4,6


第四步:

比较A的6和B的8,6小于8,于是第四个元素填进6。

C:3,4,6,6


第五步:

比较B的8和A的9,8小于9,于是第五个元素填进8。

C:3,4,6,6,8


以此类推,最后得到:

C:3,4,6,6,8,9,10,12,21,23


下面是一个归并算法的java实例:

public class Sort3 {
    //生成长度为10的整形数组nums
	private static int[] nums = new int[10];
    //nums的下标
	private static int low = 0;
	//nums的上标
    private static int high = nums.length - 1;
    
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        //初始化数组nums
		initNums(nums);
		
		//打印输出数组nums
		System.out.println("未排序的数组为:");
        printNums(nums);
        
        //归并排序
        sortNums(nums, low, high);
        
        //打印输出排过序的数组nums
        System.out.println("排过序的数组为:");
        printNums(nums);
	}
	/**
	 * 初始化数组,随机生成1~9的整数进行赋值
	 * @param nums
	 * @return
	 */
	private static int[] initNums(int[] nums){
		Random r = new Random();
		for(int i = 0; i < nums.length; i++){
			nums[i] = r.nextInt(10);
		}
		return nums;
	}
	/**
	 * 打印输出数组
	 * @param nums
	 */
	private static void printNums(int[] nums){
		for(int i = 0; i < nums.length; i++){
			System.out.print("  " + nums[i]);
		}
		System.out.println();
	}
	/**
	 * 归并排序算法
	 * @param nums
	 * @param low
	 * @param high
	 * @return
	 */
	private static int[] sortNums(int[] nums, int low, int high){
		int mid = (low + high) / 2;
		if(low < high){
			//左侧递归
			sortNums(nums, low, mid);
			//右侧递归
			sortNums(nums, mid + 1, high);
			//归并
			merge(nums, low, mid, high);
		}
		return nums;
	}
	/**
	 * 内部方法,将两个有序子序列合成为一个
	 * @param nums
	 * @param low
	 * @param mid
	 * @param hogh
	 */
	private static void merge(int[] nums, int low, int mid, int hogh){
		int[] tempArray = new int[high - low + 1];
		int i = low;
		int j = mid + 1;
		int k = 0;
		
        //比较并将排序结果存入数组tempArray中
		while(i <= mid && j <= high){
			if(nums[i] <= nums[j]){
				tempArray[k++] = nums[i++];
			}
			else{
				tempArray[k++] = nums[j++];
			}
		}
		
		//加上左边序列的剩余元素
		while(i <= mid){
			tempArray[k++] = nums[i++];
		}
		
		//加上右边序列的剩余元素
		while(j <= high){
			tempArray[k++] = nums[j++];
		}
		
		//更新数组nums
		for(int l = 0; l < tempArray.length; l++){
			nums[l + low] = tempArray[l];
		}
	}

}

输出结果:



       尽管归并排序的运行时间是O(NlogN),但它有一个严重的问题,归并两个有序表需要线性的额外内存。将数组元素拷贝到临时数组再拷贝回原始数组的额外工作贯穿整个算法中,极大地降低了排序的速度。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值