归并排序
归并算法的理解比较难,是一种区别于插入算法,选择算法和交换算法的一种独特算法,需要逐步理解。
核心思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
图解(网上盗用):
分治法
“分”的步骤:
“治”的步骤:
详细“治”的步骤:
(1)稳定性
归并排序是一种稳定的排序。
(2)存储结构要求
可用顺序存储结构。也易于在链表上实现。
(3)时间复杂度
对长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
(4)空间复杂度
需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
注意:若用单链表做存储结构,很容易给出就地的归并排序
归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。
算法实现代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int []data = new int[8];
for(int i= 0;i<data.length ;i++){
data[i] = sc.nextInt();
}
//归并排序
mergeSort(data ,0 ,data.length-1);
for(int i = 0;i<data.length ;i++){
System.out.print(data[i]+" ");
}
}
//归并排序
public static int[] mergeSort(int[] data,int low,int high){
int mid = (low+high)/2;
if(low<high){
mergeSort(data,low,mid);
mergeSort(data,mid+1,high);
//左右归并
merge(data,low,mid,high);
}
return data;
}
//归并排序的辅助方法
public static void merge(int[] data, int low, int mid, int high) {
int[] temp = new int[high-low+1];
int i = low;
int j = mid+1;
int k = 0;
// 把较小的数先移到新数组中
while(i<=mid && j<=high){
if(data[i]<data[j]){
temp[k++] = data[i++];
//说明:temp[k++] = temp[k] ,只是在temp[k++]之后k的值加1
//说明:temp[++k] = temp[k+1],temp[++k]之后k的值加1
}else{
temp[k++] = data[j++];
}
}
// 把左边剩余的数移入数组
while(i<=mid){
temp[k++] = data[i++];
}
// 把右边边剩余的数移入数组
while(j<=high){
temp[k++] = data[j++];
}
// 把新数组中的数覆盖nums数组
for(int x=0;x<temp.length;x++){
data[x+low] = temp[x];
}
}
}
转载:https://blog.csdn.net/cqx13763055264/article/details/81701419
查看评论