归并排序
没有伞的孩子必须努力奔跑!
归并排序的思想:
归并排序:将数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并到一起,这样整个数组就都是有序的了。
归并排序使用的就是分治思想。分治,顾名思义就是分而治之,将一个大问题分解成小的问题来解决。小的问题解决了,大问题也就解决了。
分治是一种解决问题的处理思想,递归是一种编程技巧
大规模问题,肯定有一个对应的小问题,这个小问题应该可解。 那么就想怎么将大问题拆分为小问题。 然后是怎么将小问题再合并和复原为大问题。
完整代码如下:
public static void mergeSort(int[] arr,int left,int right,int[] temp){
if (left<right){
int mid = (left+right)/2;//中间索引
//向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归进行分解
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,right,mid,temp);
}
}
/**
* 合并的方法
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param right 右边索引
* @param temp 做中转的索引
* @param mid 中间索引
*/
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;//指向temp数组的当前索引
//(一)
//先把左右两边有序的数据按照规则填充到temp数组
//直到左右两边的有序序列,有一边处理完毕为止
while (i<=mid && j<=right){//继续
//如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
//即将左边的当前元素,填充到temp数组
//然后t++,i++
if (arr[i]<=arr[j]){
temp[t++] = arr[i++];
}else {
temp[t++] = arr[j++];
}
}
//(二)
//把有剩余数据的一遍的数据依次全部填充到temp
while (i<=mid){//左边的有序序列还有剩余的元素,就全部填充到temp
temp[t++] = arr[i++];
}
while (j<=right){//右边的有序序列还有剩余的元素,就全部填充到temp
temp[t++] = arr[j++];
}
//(三)
//将temp数组的元素拷贝到arr
//注意,并不是每次都拷贝所有
t=0;
int tempLeft = left;
//第一次合并tempLeft = 0,right = 1
while (tempLeft<=right){
arr[tempLeft++] = temp[t++];
}
}
以上代码使用递归的思想实现的,最好亲自debug一下,才能看清代码的每一步。(尤其是递归实现的那一部分代码)