6.归并排序
(1)基本思想:
利用归并的思想实现排序方法。该算法采用分治策略。(分治法将问题分成一些小问题,然后递归求解,而治的阶段就是降分的阶段得到的各答案“修补”在一起,即分而治之)。
(2)归并排序思想示意图:
图解说明:
a.第一步——>分:mid=left+right,将整个待排序列分为左子树 [left,mid] 和右子树 [mid+1,right]两个待排序列,再继续将[left,mid]和 [mid+1,right]递归分成更多的子序列,递归终止条件为:left > right
b.第二步——>治:
① 将已经递归分成的最小的左子树序列(只含有一个待排数据)与最小的右子树序列从第一个元素进行数据比较,如果左边有序序列的当前元素数据小于右边有序序列的当前元素数据,则将左边有序序列的当前元素填充到temp[]数组中;反之,则将右边有序序列的当前元素数据填充到temp[]数组中。
② 若左边的有序序列的元素已经全部填充到temp[] 数组中,则将右边有序序列剩余的元素按照顺序逐个放入temp[]数组中;若右边有序序列的元素已经全部填充到temp[] 数组中,则将左边有序序列剩余的元素按照顺序逐个放入temp[]数组中
c.第三步:将temp[]数组 copy 原来的数组中。【注意并不是copy最后一次的temp[]数组,而是每次递归时都要进行copy】
(3)代码实现
//归并排序
public void mergetSort(int[] arr,int left,int right,int[] temp) {
//分+和:
int mid = (left +right) / 2;
//分:
if(left < right) {
//左边序列:
mergetSort(arr,left,mid,temp);
//右边序列:
mergetSort(arr,mid + 1,right,temp);
//和:
merget(arr,left,right,mid,temp);
}
}
//合并:
/**
* 合并成为有序的序列:
* @param arr 待排的序列
* @param left 左边序列的初始索引【左边序列的第一个元素】
* @param right 右边序列的初始索引【右边序列的最后一个元素】
* @param mid 中间索引【左边序列的最后一个元素】
* @param temp 中转的数组
*/
public void merget(int[] arr,int left,int right,int mid,int[] temp) {
int i = left; //初始化为i,左边有序序列的初始索引
int j = mid + 1; //初始化为j,右边有序序列的初始索引
int t = 0;//指向中转数组的当前索引
//第一步
//先将左右两边的数据按照规则填充到中转数组temp[]中
//直到左右两边有一边的数据已经全部填充完了
while (i <= mid && j <= right) {
//左右两边的数据进行比较,如果左边有序序列的当前元素,小于右边有序序列的当前元素
//则将左边的当前元素填充到中转数组temp[]中
//然后t++,i++
if(arr[i] < arr[j]) {
temp[t] = arr[i];
t += 1;
i += 1;
}else { //如果右边的当前元素小于左边的当前元素,则同理。//然后 j++,t++
temp[t] = arr[j];
t += 1;
j += 1;
}
}
//当右边的有序序列已经全部填充在中转数组中,左边有序序列还有元素剩余
//就将左边的所有元素按照原本的有序顺序依次填充到中转数组中
while(i <= mid) {
temp[t] = arr[i];
t += 1;
i += 1;
}
//当右左边的有序序列已经全部填充在中转数组中,右边有序序列还有元素剩余
//同理
while(j <= right) {
temp[t] = arr[j];
t += 1;
j += 1;
}
//第二步
//再将中转数组temp[]中的元素全部copy到原来的数组中
//注意并不是每次都是copy所有,不是每次都是拷贝left到right的所有元素
t = 0;
int tempLeft = left;
//第一次合并:tempLeft = 0,right = 1;第二次合并:tempLeft = 2,right = 3;·····
//最后一次合并:tempLeft = left,right = right;
while(tempLeft <= right) {
arr[tempLeft] = temp[t];
tempLeft += 1;
t += 1;
}
}
其他排序算法请转 小何小何h的博客_CSDN博客-领域博主