排序算法跳转总目录
归并排序
归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
>>思路:
归并排序总体分为两大部分:分:将需要排序的数组分成若干子列(采取递归方式)如:
[8,9,6,3]
递归: / \
[8,9] [6,3]
递归: / \ / \
[8] [9] [6] [3]
治:
[8] [9] [6] [3]
治 治
[8,9] [3,6]
治
[3,6,8,9]
第一次治: [8] 和 [9] ==》[8,9]
第二次治: [6] 和 [3] ==》[3,6]
第三次治: [8,9] 和 [6,3] ==》[3,6,8,9]
治具体分三步:1. 两个子列之间依靠指针进行比较,将结果放于新的数组中
2. 将两个子列中未排序的直接放入新的数组后面
问:为什么可以直接放入?不管顺序吗?
答:因为前面的递归会先将数组分成一个一个的子列,
当一个一个子列进行反复操作的时候,提供给下一次两两比较的子列是有序的
3. 将每次得到的不完整的数组都拷贝到arr数组,直到最后一轮的子列比较后,就得到了顺序数组
步骤:
治:
1. 给三个指针:分别是:第一个子列的从头开始的指针,称,指针1
第二个子列的从头开始的指针,称,指针2
为辅助数组遍历值的指针,称,指针3
2. 指针1与指针2对应的数组元素比较,小的用指针3遍历在辅助数组中,同时该指针+1;很明显这里有两种情况
3. 注意:这里可能会出现一种情况,就是已经比较完了,可是某一组中还有剩余元素,但这些剩余元素是有规律的,所以直接加入;当然也是存在两种情况
4. 然后就是将辅助数组复制到arr上
代码:
public class MergeSort {
public static void main(String[] args) {
int[] arr = RandomArr.randomArr(8, 10);//这是作者写的一个产生随机数组的方法,不必理会
System.out.println(Arrays.toString(arr));
int[] temp=new int[arr.length];//归并排序所需要的一个辅助数组
mergeSort(arr,0,arr.length-1,temp);//调用归并排序
System.out.println(Arrays.toString(arr));
}
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,mid,right,temp);
}
}
public static void merge(int[] arr,int left,int mid,int right,int[] temp){//合并的方法
int l=left;//第一组的指针
int r=mid+1;//第二组的指针指针
int te=0;//辅助数组的指针
while (l<=mid&&r<=right){
if (arr[l]<=arr[r]){//比较,将小的放入辅助数组
temp[te]=arr[l];
te++;
l++;
}else {
temp[te]=arr[r];
te++;
r++;
}
}
while (l<=mid){//将剩余的未填充到temp数组的元素填充
temp[te]=arr[l];
te++;
l++;
}
while (r<=right){//将剩余的未填充到temp数组的元素填充
temp[te]=arr[r];
te++;
r++;
}
//将临时数组复制到arr上
te=0;
int tempLeft=left;//定义一个原数组的指针
while (tempLeft<=right){
arr[tempLeft]=temp[te];//将temp的有序序列覆盖在arr上
te++;
tempLeft++;
}
}
值得一提的是,本人测试了八千万个八万内的数据排序,归并居然比快排快了将近一半的时间