合并排序—排序系列

分治策略

分治策略:将原问题分解成为若干个规模较小而结构与原问题相似地子问题,递归地解决这些子问题,然后再合并其结果,就得到原问题的解。

这形而上的解释并不能让你立刻理解什么是分治?这就像武功秘籍的总纲,只告诉你了这武学的精髓,但是你要能真正理解并运用它还需要具体的招式口诀。要真正掌握分治还得不断地练习,学习一些运用了分治策略地经典算法,就像这合并排序算法。

合并排序算法思想
  1. 将n个元素分成各含n/2个元素的子序列
  2. 递归执行步骤1,直到每个序列元素只有一个
  3. 至下而上地将序列两两排序合并
如何递归地将数组一分为二

俗话说的好,离开代码讲算法都是耍流氓(手动滑稽)。先列出部分代码。

	// n=0,m=10
	public static void sort1(int[] arr,int n,int m){
		if(n<m) {
			int p = (m+n)/2;	   // 语句1
			sort1(arr,n,p);        // 递归1
			sort1(arr,p+1,m);      // 递归2
			merge(arr,n,p,m);      // 这行先不看
		}
	}

这个方法体现了分治策略,将数组不断地一分为二,以n<m为结束条件,当n>=m时说明每个子序列中仅有一个元素。

本方法的实现流程如图所示:
在这里插入图片描述

合并/排序子序列

合并和排序的思想:由于sort方法已经将子序列分割,当然不是实际的分割,只是逻辑上的,传入的参数p,q,r将一段序列分为两份已排序的子序列,把这两个子序列排序合并成一个序列。

合并代码:

public static void merge(int[] arr,int p,int q,int r) {
		int max = Integer.MAX_VALUE;
		int n1 = q-p+1;
		int n2 = r-q;
		int[] L = new int[n1+1];
		int[] R = new int[n2+1];
		for(int i = 0 ;i < n1;i++) {
			L[i] = arr[p+i];
		}
		for(int j = 0;j < n2;j++) {
			R[j] = arr[q+j+1];
		}
		L[n1] = max;
		R[n2] = max;
		int i = 0;
		int j = 0;
		for(int k = p;k <= r;k++) {
			if(L[i] <= R[j]) {
				arr[k] = L[i];
				i++;
			}else {
				arr[k] = R[j];
				j++;
			}
		}
	}
合并排序算法总代码
import java.util.Arrays;

public class Demo8 {
	public static void main(String[] args) {
		int[] arr = new int[] {1,3,5,7,4,2,9,8,10,6};
		Util.sort1(arr,0,9);
		System.out.println(Arrays.toString(arr));
	}
}

class Util{
	public static void merge(int[] arr,int p,int q,int r) {
		int max = Integer.MAX_VALUE;
		int n1 = q-p+1;
		int n2 = r-q;
		int[] L = new int[n1+1];
		int[] R = new int[n2+1];
		for(int i = 0 ;i < n1;i++) {
			L[i] = arr[p+i];
		}
		for(int j = 0;j < n2;j++) {
			R[j] = arr[q+j+1];
		}
		L[n1] = max;
		R[n2] = max;
		int i = 0;
		int j = 0;
		for(int k = p;k <= r;k++) {
			if(L[i] <= R[j]) {
				arr[k] = L[i];
				i++;
			}else {
				arr[k] = R[j];
				j++;
			}
		}
	}
	public static void sort1(int[] arr,int n,int m){
		if(n<m) {
			int p = (m+n)/2;
			sort1(arr,n,p);
			sort1(arr,p+1,m);
			merge(arr,n,p,m);
		}
	}
}

如果有表达错误希望大家能告诉我,对你有帮助地话点个赞哦。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值