归并排序
核心思想
将数组一分为2,对其左边归并排序,对其右边归并排序,然后将左右两边进行归并,合二为一。
图示
小小说明:为了不让图片界面显得杂乱,所以在前半部分注释分解的过程,后半部分注释归并的部分。
应为csdn不能放超过5M的图片所以进行了n+1ci的压缩,画质有点模糊了,我在哔哩哔哩上传了视频,大家可以前往观看
点击此处前往哔哩哔哩
分布详解
1. 将数列一分为二,分别排序。
提示: 使用递归可以很简单的实现。
思考: 递归退出条件是什么?
从上图便可以看出,当一组数列排序完成或是数列中只有一个数时,本层函数就可以结束了。
代码实现
public int[] mergeSort(int left,int right) {
//递归退出条件:当函数中的数组长度为1是退出。
if (!(left<right-1)) {
return null;
}
//将数列一分为二。分别排序。
int madian = left+(right-left)/2;
this.mergeSort(left, madian);
this.mergeSort(madian, right);
//将数列合二为一,并排序。
this.merge(left, right);
return this.array;
}
先来看看这个视频,更直观的了解一下分治和归并的过程
归并排序算法可视化
视频原地址
将数列合二为一且进行排序。
提示: 两个数列已经是有序的,只需要合并成一个有序序列就可以了。
难点 : 嗯······嗯·······嗯·····,好像没有难点哎,不过要注意数组越界的问题哦。
步骤
- 创建两个指针,分别指向两数列的头部。
- 若指针指向的数小,就把那个数放入一个临时数组中,并将该指针后移
- 若数列的某一方已经遍历完成,则将另一方数列的值全部写入临时数组中。
- 将临时数组中的值写入,带排序数组中。
代码实现
private void merge(int left , int right) {
int [] temp = new int [right-left];
int madian = left+(right-left)/2;
//1. 创建两个指针,分别指向两数列的头部。
int L = left ,R = madian;
int count = 0;
while(L<madian&&R<right) {
//2. 若指针指向的数小,就把那个数放入一个临时数组中,并将该指针后移
if (this.array[L]<this.array[R]) {
temp[count++] = this.array[L++];
}else {
temp[count++] = this.array[R++];
}
}
//3. 若数列的某一方已经遍历完成,则将另一方数列的值全部写入临时数组中。
for (int i = L; i < madian; i++) {
temp[count++] = this.array[i];
}
for (int i = R; i < right; i++) {
temp[count++] = this.array[i];
}
//4. 将临时数组中的值写入,带排序数组中。
count = 0;
for (int i = left; i < right; i++) {
this.array[i] = temp[count++];
}
}
总结
排序算法是一种即简单,执行效率也比较高的稳定型排序算法了,是分治算法的一个典型应用,它也是hadoop中MapRedus的削减版。
若想感受一下归并排序的魅力
【Java是世界上最好的语言】归并排序可视化 Java实现 绘图使用StdDraw
附录
package hello;
import java.util.Arrays;
class MergeSort{
private int[] array;
public MergeSort(int[] array) {
this.array = array;
}
public int[] mergeSort(int left,int right) {
//递归退出条件:当函数中的数组长度为1是退出。
if (!(left<right-1)) {
return null;
}
//将数列一分为二。分别排序。
int madian = left+(right-left)/2;
this.mergeSort(left, madian);
this.mergeSort(madian, right);
//将数列合二为一,并排序。
this.merge(left, right);
return this.array;
}
private void merge(int left , int right) {
int [] temp = new int [right-left];
int madian = left+(right-left)/2;
//1. 创建两个指针,分别指向两数列的头部。
int L = left ,R = madian;
int count = 0;
while(L<madian&&R<right) {
//2. 若指针指向的数小,就把那个数放入一个临时数组中,并将该指针后移
if (this.array[L]<this.array[R]) {
temp[count++] = this.array[L++];
}else {
temp[count++] = this.array[R++];
}
}
//3. 若数列的某一方已经遍历完成,则将另一方数列的值全部写入临时数组中。
for (int i = L; i < madian; i++) {
temp[count++] = this.array[i];
}
for (int i = R; i < right; i++) {
temp[count++] = this.array[i];
}
//4. 将临时数组中的值写入,带排序数组中。
count = 0;
for (int i = left; i < right; i++) {
this.array[i] = temp[count++];
}
}
}
public class HelloWord {
public static void main(String[] args) {
int[] array = new int[] {4,2,3,1,5,8,6,7,9};
MergeSort aMergeSort = new MergeSort(array);
Arrays.stream(aMergeSort.mergeSort(0, array.length)).forEach(System.out::println);
}
}
大家学会了吗?若是还不太懂请前往码云,我为大家准备了源码和ppt。欢迎大家前往下载:
点击此处前往码云
最后还有最重要的一点
!!!!!!!!!!
别忘了点个赞再走哦。