排序算法--归并排序

引言

    归并排序的时间复杂度是O(N*logN),额外空间复杂度是O(N),可以实现做的稳定性。

    归并排序的思想是把一个数组分成两半,把每一半都分成两个四分之一,把每个四分之一部分分成八分之一,依次类推,反复的分割数组,直到得到的子数组是只有一个数据项。然后把两个只有一个数据进行比较。创建等于其数据项大小的数组,把数据按大小顺序拷贝到新创建的数组中,把新的数组中的数据按顺序再拷贝回到原数组。排序就排列好了。

如下图


把数组分成两半后

   

先开始分左半部分 继续分两半 直到分到时单个数为止


    如图所示(图画的有点囧),先把数组的元素进行比较。元素1直接返回,右边元素8、7。先排序右侧部分,创建一个两个元素的数组,把元素8和7进行比较,然后按顺序进行排序,排序后就是7和8。再把7和8拷贝的原数组。然后再用元素1与7、8进行比较,左边1比7小 先拷贝1,然后再把7、8拷贝到新数组,在把这个次序按新数组的顺序拷贝到原来数组中去。依次类推,具体代码实现如下:

/**
 * 归并排序
 * @author whmAdmin
 *
 */
public class MergeSort {
	
	public static void mergeSort(int[] arr){
		if(null == arr || arr.length < 2){
			return;
		}
		
		mergeSortTest(arr, 0, arr.length-1);
	}

	public static void mergeSortTest(int[] arr, int L, int R) {
		// 如果左右下坐标相等,返回
		if(L == R){
			return;
		}
		
		// 获取中间下坐标
		int mid = L + (R - L) / 2;
		// 先排序左部分,左部分是L到mid中间这部分元素
		mergeSortTest(arr, L, mid);
		// 再排序右部分,右部分是mid中间后一位到R这部分元素
		mergeSortTest(arr, mid+1, R);
		// 对要排序的数组进行排序操作
		mergeSortArray(arr,L,mid,R);
		
	}

	public static void mergeSortArray(int[] arr, int L, int mid, int R) {
		//创建新数组
		int[] arrs = new int[R-L+1];
		//设置新数组开始坐标
		int i = 0;
		// 设置左部分开始指针
		int p1 = L;
		// 设置右部分开始指针
		int p2 = mid + 1;
		
		// 如果左指针坐标小于等于中间左边并且右指针坐标小于等于R最右坐标,继续循环。否则越界停止循环
		while(p1<=mid&& p2 <= R){
			// 比较左右两个指针上的元素大小,谁小就拷贝到新数组,并且指针位置++
			arrs[i++] = arr[p1] < arr[p2]?arr[p1++]:arr[p2++];
		}
		
		// 如果左指针位置比右指针所有位置元素都大,需要把剩余左部分全部拷贝到新数组
		while(p1<=mid){
			arrs[i++] = arr[p1++];
		}
		
		// 同理如果右指针位置比左指针所有位置的元素都大,需要把剩余右部分全部拷贝新数组
		while(p2<=R){
			arrs[i++] = arr[p2++];
		}
		// 以上左右指针拷贝只能出现一种
		
		// 把排序好的新数组元素拷贝到原数组中
		for (int j = 0; j < arrs.length; j++) {
			// L+1是要按原位置进行拷贝回去
			arr[L+j] = arrs[j];
		}
	}

}
    以上就是归并排序的实现,这种实现使用了递归的方式进行实现的,归并排序存在非递归实现版本。有兴趣的可以进行了解一下。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值