您的位置:首页 > 其它

快速排序分析

2017-11-14 23:35 148 查看
前言:

刚刚学习到快速排序,快速排序是个基础问题,去网上查了下,发现竟然没有一个让人满意的答案。

就连为什么快速排序比冒泡排序快这个基本的概念,也没人说清楚。

一般而言,网上对于为什么快速排序比冒泡快,有两种方向:

1.算时间复杂度

2.二分法的优越性

对于这两种解释,明显没有从根本上触及原理。

对于1.算时间复杂度

这是逻辑颠倒,恰恰是效率高导致时间复杂度低。所以说这种解释因果倒置。

对于2.二分法的优越性

这个我不知道说什么好。

这里预先我给出我的答案:冒泡法一轮比较,只确定了一个数的位置。而快速排序,可以确定一个点的同时,还将数组一分为二。冒泡排序由于是不同的数相比较而快速排序是和相同的数比较。相当于在比较中选择了最极端的模式,浪费了信息。冒泡排序可以算是每次都是最坏选择的快速排序。(实际操作中:为提高效率,快速排序一般是一分为二,而没有确定一个点的位置)

概念:

快速排序:对一个数组操作,将数组分成两部分,前面的一部分比后面的一部分小(同组之间乱序),然后继续分割两个小数组。。。

将数组分成两部分的操作:选取数组中的一个数,从两端开始比较,左端的话如果小于就说明这个数可以放左边,比较下一个,如果大于那么先待定;右边的话,如果大于基数那么说明这个数可以放右边,比较下一个,如果小于那么和刚刚那个数对换。这样依次确认位置,就能划分完整个数组。

如何通过比较和交换位置,达到左边的都比该数小,右边的都比该数大.
这里直接给出思路:

1.单边确认

规定:需要排序的数组为arr ,选取的第一个排序数为:arr[random](r表示在数组下标范围之内的随机数)

1.if(arr[0]>arr[random]){arr[0]和arr[length-1]交换位置(此操作等于确定了数组最后一个位置的值)}

2.if(arr[0]<arr[r]){比较下一个(此操作等于确定了数组第一个位置的值)}

基于以上思路,给出代码:

public static void sort(int[] arr,int left,int right) {
//设置递归结束条件
if (right-left<1) {
return ;
}
int l=left;
int r=right;
int sPoint=arr[left+new Random().nextInt(right-left+1)];//用随机位置确定比较的基数

while (l<=r) {//使用等于为了比较每一个数
if (arr[l]<=sPoint) {
l++;//这里就确定了一个左边位置
}else if(arr[l]>sPoint){
int temp=arr[r];
arr[r]=arr[l];
arr[l]=temp;
r--;
//这里是一个交换操作,不过用往后抛形容更恰当,因为这样操作一次,右边的位置就确定了一个
}
}

if (l-1>=0) {
sort(arr, left,l-1);
}
sort(arr, r+1, right);

}


此时我们发现:有很多交换操作是不必要的,例如:如果最后一个数是大于基数的就没必要换过来。以及对于等于的情况没有处理,所以无法排序有等值的数列。

2.双边排序+等值处理
public static void sort2(int[] arr,int left,int right) {
if (right-left<1) {
return ;
}
int l=left;
int r=right;
int index=left+new Random().nextInt(right-left+1);
int sPoint=arr[index];//用随机位置确定比较的基数
while (l<r) {
while (l<=r&&arr[l]<=sPoint) {
//等值处理,及:如果所有的数小于或等于基数,那么将基数移至最后,防止出现无法划分数组的情况
if(l==right){
if(arr[index]!=arr[right]){
int temp=arr[index];
arr[index]=arr[right];
arr[right]=temp;
}
break;
}
l++;//这里就确定了一个左边位置

}
while(arr[r]>sPoint&&l<r){
r--;
}
if (l<r) {
int temp=arr[r];
arr[r]=arr[l];
arr[l]=temp;
}
}
if (l-1>=0) {
sort2(arr, left,l-1);
}
sort2(arr, l, right);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息