堆排和快排比较 为什么在同样空间复杂度下快排相对更快
作者:互联网
其实在比较排序的情况下 所有的下界都是O(nlogn)
而为什么 在相同的空间复杂度的情况下 快排的速度要比堆排快呢?
因为所有的空间复杂度都砍掉了常系数 如果一个1*nlongn 一个 1000*nlongn 谁快谁慢一目了然
为什么堆排的常系数高呢?
首先堆排先建立大根堆 (小根堆) 建立好之后最顶元素是最大(最小)
第二步 让最顶元素与末尾位置元素进行交换 ,之后排除末尾元素 再建立大根堆 找出次大元素。以此类推直至最后
那么让堆排降速的远洋就出现在第二步,快排每一次排序都是让目标元素向正确位置逼近(分治方法),而堆排一旦交换
元素之后,可以想象产生了多少无用的比较(无用的比较指的是:你末尾位置元素基本可以肯定比你的根的左右孩子元素中的一个小),这样交换后,再次建立大根堆(小根堆)时并没有使得你的目标元素靠近真确位置,反而增加了无用比较。
//堆排序
//空间复杂度 O(nlbn)
//时间复杂度 O(1)
//不稳定
public static void heapSort(int[] array){
buildMaxHeap(array);
for (int i = 0; i < array.length; i++){
int tmp = array[0];
array[0] = array[array.length-1-i];
array[array.length-1-i] = tmp;
adjust(array,0,array.length-1-i);
}
}
private static void buildMaxHeap(int[] array){
for (int i = array.length/2 - 1; i >=0; i--){
adjust(array,i,array.length);
}
}
private static void adjust(int[] array,int start,int length){
int tmp = array[start];
int i;
for ( i = start*2+1; i < length; i = i*2+1) {
if (i < length-1 && array[i+1] > array[i]){
i++;
}
if (array[i] <= tmp){
break;
}else {
array[start] = array[i];
start = i;
}
}
array[start] = tmp;
}
//快排
//时间复杂度O(nlbn)
//空间复杂度O(lbn)
//不稳定
public static void quickSort1(int[] array){
quick(array,0,array.length-1);
}
private static int selectPivot(int[] array, int low, int high){
int tmp = array[low];
while (low < high){
while (low < high && array[high] >= tmp){
high--;
}
if (low == high){
break;
}else {
array[low] = array[high];
}
while (low < high && array[low] <= tmp){
low++;
}
if(low == high){
break;
}else {
array[high] = array[low];
}
}
array[low] = tmp;
return low;
}
private static void swap(int[] array, int low, int high){
int tmp = array[low];
array[low] = array[high];
array[high] = tmp;
}
private static void medianOfThree(int[] array, int low, int high){
int mid = (low + high)/2;
// array[mid] < array[low] < array[high]
if (array[low] > array[high]){
swap(array,low,high);
}
if (array[mid] > array[high]){
swap(array,mid,high);
}
if (array[low] < array[mid]){
swap(array,low,mid);
}
}
private static void quick(int[] array,int low, int high){
//尾递归的形式 递归只要分支庞大
/*从时间和空间效率上看,尾递归和传统递归差不多。递归运算效率低主要是分支巨大,像阶乘这类单分支的递归,效率并不低。递归运算的深度和运算总量大致成指数关系,return多次并不会造成显著的性能损失。
一言以蔽之,传统递归越深,距离目标越近;尾递归越深,距离起点越远。
尾递归适用于运算对当前递归路径有依赖的问题,传统递归适用于运算对更深层递归有依赖的问题。*/
int par;
while(low < high){
par = selectPivot(array, low, high);
quick(array, low, par - 1);
low = par + 1;
}
/* if (low >= high){
return;
}
//优化 三数取中法
medianOfThree(array,low,high);
int par = selectPivot(array, low,high);
if (low < par-1){
quick(array,low,par-1);
}
if (par < high-1){
quick(array,par+1,high);
}*/
}
标签:堆排,递归,下快,复杂度,high,int,length,low,array 来源: https://blog.csdn.net/qq_42381855/article/details/89762347