回顾上节课我们讲了3个排序,冒泡排序,插入排序,插入排序,选择排序,他们的时间复杂度都是O(n^2),适用于小规模的数据集,今天我们讲一下比前3者更加高效的排序,归并排序和快排,他们的时间复杂度是O(nlogn),适用于大数据集.归并排序和快排都用到了分而治之思想,
1》归并排序的原理,对于一个数据进行排序,把这个数组从中间进行划分为前后2个部分.,分别对前后2个部分进行排序,再将前后排序的2个部分进行合并,就得到排序完整的数据,这就是归并排序的核心.下面由图来解释一下.
归并排序的主要就是分治思想,将一个大的问题划分为好多小问题,分别处理这些小问题,再将这些小问题进行合并,大的问题就处理完毕.
2>归并排序的实现代码
public class MergeSort{
public static void main(String[] args){
int[] a = {3,4,5,2,5,6,1,8,7}
mergeSort(a);
}
public static void mergeSort(int[] arr){
mergeSort(arr,new int[arr.length],0,arr.length-1)
}
public static void mergeSort(int[] arr,int[] temp,int left,int right){
if(left < right){
int center = (left +right)/2
mergeSort(arr,temp,left,center)//左边数据
mergeSort(arr,temp,center+1,right)//右边数据
merge(arr,temp,left,center+1,right)//合并2个有序
}
public static void merge(int[] arr,int[] temp,int leftPos,int rightPos,int rightEnd){
int leftEnd = rightPos-1;//左边下标结束
int temPos = leftPos;//从左边开始计算
int numEle = rightEnd-leftPos+1;//元素个数
while(leftPos <= leftEnd && rightPos <= rightEnd){
if(arr[leftPos] <= arr[rightPos])
temp[tempPos++] =arr[leftPos++];
else
temp[tempPos++] = arr[rightPos++];
}
while(leftPos <= leftEnd){//左边如果有剩余
temp[tempPos++] = arr[leftPos++];
}
while (rightPos <= rightEnd) { // 右边如果有剩余
temp[tempPos++] = arr[rightPos++];
}
// 将temp复制到arr
for (int i = 0; i < numEle; i++) {
arr[rightEnd] = temp[rightEnd];
rightEnd--;
}
}
}
}
3>归并排序的性能分析?
归并排序在排序期间,相同2个值的先后位置仍然不会改变,所以归并排序是稳定排序,
归并排序的时间复杂度是O(nlogn),且在任何情况下时间复杂度为O(nlogn)
归并排序在排序之后有个合并的操作,每次进行合并,都要开辟新的内存空间,尽管如此,直到最后合并结束。中间新开辟的内存空间都会被回收,所以最终的归并排序的空间只是取决于最后一次的合并操作,需要申请与原数组同大的内存空间。所以归并排序的空间复杂度是O(n)
4>归并排序使用什么场景
他主要适用于数据量比较,而且他有一个很好的优点,就是在任何情况下他的时间复杂度都是nlogn,主要存在的缺点,是它不是原地排序,在合并的过程中会频繁的申请空间.