算法笔记-----归并排序

归并排序

介绍

归并排序(MERGE SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide- and- conquer)策略(分治法将问题分(divide) 成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案”修补”在一起,即分而治之)。

也就是该算法的核心思想是分治思想

动态图解

这里写图片描述

这里写图片描述我们发现我们的分并没有做什么其他的功能,只是将我们的数组拆分开来

为我们下面的治提供条件

我们再来看看他的复杂度,我们是8个数据,但是合并总共是7次

所以说他的复杂度是线性增长,不像其他的拍需要算法那样是平方增长

我们看最后一次合并做了什么

这里写图片描述

这里写图片描述

也就是说我们的归并排序是需要一个辅助数组的,这也是我们代码中最复杂的一部分

代码实现

package 数据结构;

import java.lang.reflect.Array;
import java.util.Arrays;

//归并排序
//@author  王庆华
public class MergetSort {
    
    
	public static void main(String[] args) {
    
    
		//创建数组
		int arr[] = {
    
    8,4,5,7,1,3,6,2};
		int temp[] = new int[arr.length];//归并排序需要一个额外的空间的
		megeSort(arr, 0, arr.length-1, temp);
		System.out.println("归并排序后"+Arrays.toString(arr));
		
	}
	
	//分解+合并方法 
	public static void megeSort(int[] arr,int left,int right, int[] temp){
    
    
		if(left<right){
    
    
			int mid = (left+right)/2;//中间索引
			//向左递归进行分解
			megeSort(arr, left, mid, temp);
			//向右递归分解
			megeSort(arr, mid+1, right, temp);
			//每分解一次就合并一次
			merge(arr, left, right, mid, temp);
		}
	}
	
	
	//合并的方法
	/**
	 * 
	 * @param arr   需要排序的初始的数组
	 * @param left 左边有序子序列的初始索引
	 * @param right  右边有序子序列的索引
	 * @param mid	中间索引
	 * @param temp	辅助数组
	 */
	public static void merge(int[] arr,int left,int right,int mid,int[] temp){
    
    
		int i = left;//初始化i   表示左边有序子序列的初始索引
		int j = mid + 1;//j是我们右边子序列的初始索引
		int t = 0;  //这个是我们辅助数组的当前索引,来帮助我们在那个地方插入值
		
		//(1)先把左右两边(有序)的数据按照规则填充到辅助数组temp中
		//直到左右两边的有序序列有一边处理完毕为止
		while(i <= mid && j <= right){
    
    
			if(arr[i] <= arr[j]){
    
    
				//左边有序子序列的当前元素<=右边有序序列的当前元素
				//左边的元素填充到辅助数组
				temp[t] = arr [i];
				t+=1;
				i+=1;
			}else{
    
    
				//反之就是右边进行拷贝操作
				temp[t] = arr[j];
				t+=1;
				j+=1;
			}
		}
		
		
		//(2)
		//把有剩余数据的一边,依次填充到辅助数组中
		while(i <= mid){
    
    
			//说明左边有序子序列有剩余元素
			temp[t] = arr[i];
			t+=1;
			i+=1;
		}
		while(j <= right){
    
    
			//右边有序子序列有剩余
			temp[t] = arr[j];
			t+=1;
			j+=1;
		}
		
		//(3)将辅助数组中的数据拷贝到arr中
		//注意并不是每一次都是拷贝所有的元素
		t = 0;
		int tempLeft = left;//
		while(tempLeft <= right){
    
    
			//第一次合并时  tempLeft=0 , right = 1
			//第二次			tempLeft = 2 riht = 3
			//最后一次tempLeft = 0 ,right = 7
			arr[tempLeft] = temp[t];
			t+=1;
			tempLeft+=1;
		}
	}
}

我们需要注意的是,拷贝数组的时候我们是用递归的,也就是说我们一开始是两个两个合并,所以辅助数组一开始不是直接拷贝8个数据的,也就是我们的tempLeft和right并不是0和7,而是0 1 2 3 然后合并成为0 3 也就是前四个数据,后面肯定会有4 7 合并,最后才是我们的0 7 整个数组

猜你喜欢

转载自blog.csdn.net/qq_22155255/article/details/112620258