分治——归并排序

归并排序:

核心思想:

  • 将一个序列划分为两个有序部分,然后合并(运用分治的思想)。

详细步骤:

  • 对于一个杂乱序列,我们需要对将序列递归一直划分,直到两个子序列中都只有一个元素时(此时可以认为左右两部分都是有序的),然后合并这两个子序列为一个有序序列。然后返回上一层,此时上一层的子序列就也是有序的了,所以再合并,再返回上一层,直到最顶层时将整个序列合为一个有序序列。

时间复杂度:

  • O(nlog2^n)
  • (一直二分,也类似一棵树结构,所以复杂度为O(nlog2^n))

稳定性:

  • 稳定(在合并两个子序列时,只要注意左边和右边相等时,先放左边即可使该算法排序稳定)

适用场景:

  • 在对空间没限制的时候,可以选择归并排序

扩充理解:

  • 分治概念:
    采用分治法解决的问题一般具有的特征如下:
  1. 问题的规模缩小到一定的规模就可以较容易地解决。
  2. 问题可以分解为若干个规模较小的模式相同的子问题,即该问题具有最优子结构性质。
  3. 合并问题分解出的子问题的解可以得到问题的解。
  4. 问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题
public class MergeSort {
	//和并方法,将左右两个有序部分合为一个有序部分
	public static void merge(int []a,int left,int right){
		int m=(right-left)/2+left;//中间值
		//左数组长度:left-m+1, 右数组长度:right-m
		int l[]=new int[m-left+1];
		int r[]=new int[right-m];
		//初始化左右数组
		for(int i=left;i<=m;i++){
			l[i-left]=a[i];
		}
		for(int i=m+1;i<=right;i++){
			r[i-m-1]=a[i];
		}
		int i=0,j=0,k=left;//i,j为左右指针,开始时分别指向左右数组的第一个元素。k指向原始数组中此次排序的首位置。我们要做的就是依次将左右部分数组中最小的放入元素数组中去,直到左右数组其中一个全部放完就跳出循环
		while(i<l.length&&j<r.length){
			if(l[i]<=r[j]){//这里一定记得时小于等于,若是小于的化,会导致排序不稳定(相同的数,右边的先放,就导致右边跟左边交换了位置)
				a[k]=l[i];
				i++;
				k++;
			}else{
				a[k]=r[j];
				j++;
				k++;
			}
		}
		//此时只有一个数组里面还未全部放完,所有对两个数组进行判断i,j的位置,若没放完就一直放到原始数组即可(因为左右数组已经排号序了)
		while(i<l.length){
			a[k]=l[i];
			i++;
			k++;
		}
		while(j<r.length){
			a[k]=r[j];
			j++;
			k++;
		}
	}
	//划分序列方法
	public static void mergeSort(int []a,int left,int right){
		if(left==right)return;//当划分到只有一个元素时跳出
		int m=(right-left)/2+left;//记录中间值
		//不断将序列划分 
		mergeSort(a,left,m);//一直递归将左半部分划分为左右两部分,每次返回该处时,左半部分都是有序的(第一次返回此处是只有一个元素,一个元素就直接是有序)
		mergeSort(a,m+1,right);	//同理,一直递归划分右部分为左右两部分,每次返回该处时,右半部分都是有序的(第一次返回此处是只有一个元素,一个元素就直接是有序)
		merge(a,left,right);//这个时候可以认为原序列被分为两部分,且两部分都已经排好序了,然后调用合并函数,将这两部分合并成一个有序序列。
		//执行完后返回上一层,此时上一层的左半序列(右半序列)也是有序的了
	}
	public static void main(String[] args) {
		//测试
				int []a={2,15,54,4,4,56,4,56,4,51,6,15,11,11,111,11,111,11,11,111,44,454,4554,4,548,};
				mergeSort(a,0,a.length-1);
				for(int t:a)System.out.println(t);
	}
}

猜你喜欢

转载自blog.csdn.net/Y734493585/article/details/89098187