开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
前序
上一篇: 希尔排序
归并排序
理论
首先关于归并排序之前写的几个排序都不太一样。 归并: 将一组测试数据分割成两组然后对两组中的数据进行分别判断处理 ,然后讲两组数据在合并成一组数据,就是分而治之,也是 分治法 (Divide and Conquer)
分治法: 分土地 交公粮..... 商鞅变法——> 地主
动态演示图 :
实践
coding
/***
* mergeSort 归并排序测试
*/
@Test
public void mergeSortTest() throws Exception {
int[] ints = {1, 3, 5, 8, 2, 2, 7, 7, 6, 88, 23, 56, 21, 15};
System.out.println("原始数组数据");
for (int i = 0; i < ints.length; i++) {
System.out.print(ints[i] + ",");
}
long l = System.nanoTime();
ints = mergeSort(ints);
// 使用纳秒计算时间信息
System.out.println("耗时" + (System.nanoTime() - l));
System.out.println("排序之后的数据");
for (int i = 0; i < ints.length; i++) {
System.out.print(ints[i] + ",");
}
}
/**
* 排序
* @param ints 初始数组
* @return xx
* @throws Exception
*/
public int[] mergeSort(int[] ints) throws Exception {
if (ints.length >= 2) {
int middle = ints.length / 2;
int[] left = Arrays.copyOfRange(ints, 0, middle);
int[] right = Arrays.copyOfRange(ints, middle, ints.length);
//递归分治法
// 首先 注意这块数中 对于自身数组 进行了递归排序 在最终merge 的时候数据已经是有序的了
// 因为最后都是单个或者两个数进行比较的 分解因子是 / 2
return merge(mergeSort(left), mergeSort(right));
} else {
return ints;
}
}
/**
* 核心分治法
*
* @param left 左数组
* @param right 右 数组
* @return xx
*/
private int[] merge(int[] left, int[] right) {
// 两个数组合并成一个
int[] result = new int[left.length + right.length];
int i = 0;
//进行数据对比 进行数据排序交换
// 这个算法 比较中 数组如果存在剩余的话 那么他其实就是剩下最大的数据集
// 算法 示例 left:1356 right: 4789 right: 剩余7 8 9
// left: 4679 right: 1358 left 剩余 9
while (left.length > 0 && right.length > 0) {
//如果左边的小于右边的第一个 那么暂时将 临时数组的第一个暂时放左边的 ,
//反之 将右边小的放在 临时数组的第一个
// 然后一直 while 进行比较
if (left[0] <= right[0]) {
result[i++] = left[0];
// 设置完成之后 将 原本 left数组的 0 位置的数据进行剔除 然后 进行重新 在后面进行数据比较
left = Arrays.copyOfRange(left, 1, left.length);
} else {
result[i++] = right[0];
// 设置完成之后 将 原本 rift数组的 0 位置的数据进行剔除 然后 进行重新 在后面进行数据比较
right = Arrays.copyOfRange(right, 1, right.length);
}
}
//上面会一直剔除 最后如果左边的还有数的话 就表明右边的数据全部都比较完成 然后呢 就剩下 左边还有数据 ,然后呢 右边的数据都比较完成了
// 并且通过上面的排序 左右两边的数据都是已经有序了 左边还剩下的 就是左边都比临时数组大的 并且有序的数据 它有序是递归的时候已经进行了排序
while (left.length > 0) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
}
// 这个和上面的逻辑一样 右边剩下的也是 大的数据
while (right.length > 0) {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
return result;
}
测试结果
总结
其实大家可以看见 所以整个归并排序来说它的数据效果对于之前前四篇的 效率不是很高,但是这个是因为我测试的数据量太小导致 的所以在实际情况下 ,分治法是一个很好的问题解决思路。 就好比我在这个算法里面有很多copy 数组的操作 ,这个是很耗时的,然后实际在开发过程中 可能不是这样的操作 ,然后呢,其实不知道大家有没有接触过 complatefuture 这个相关的高并发处理场景,这个流式计算其实也可以想想 也可以按照内容一个个执行处理 。
分治法: 这个是一个很重要的思想,分工而作,个人跟个人事,效率高。
这里说明一下,该算法中借用了多次临时数组的情况所以比较消耗内存以及时间 ,所以上图
OUT_PLACe
Ending
排序算法系列下一篇: 快速排序