快速排序的思想
快速是这个算法的特点,所以为了效率出现频度也会很高。快速排序:基准元素+二分思想,分治的标准是相比于基准元素值的大小(比如相比于基准元素大的放右边,小的放左边),分治思想的执行提高了执行效率。
快速排序代码
public class QuickSort {//快速排序的递归排序
public static void main (String args[]){
//初始化要排序的数组
int[] sum={2,7,99,55,2,21};
//实现排序的方法
quickSort(sum,0,sum.length-1);
//循环输出
for (int i: sum){
System.out.print(i+" ");
}
}
/**
* 分治方法的递归实现
* @param attr 需要排序的数组
* @param left 最左边元素下标
* @param right 最右边元素下标
*/
public static void quickSort(int []attr, int left, int right){
//如果左边元素下标大于等于右边元素下标,即时同一元素,则结束递归
if (left>=right)
return;
//获得定位元素的位置,也就是左右分界线元素的下标
int q = partition(attr, left, right);
//左边部分递归实现,范围为[left,q-1]
quickSort(attr, left, q-1);
//右边部分递归实现,范围为[q+1,right]
quickSort(attr, q+1, right);
}
/**
* 归位基本元素,返回划分元素的位置
* @param attr 划分的数组
* @param left 最左元素下标
* @param right 最右元素下标
* @return 返回归位的位置
*/
public static int partition(int []attr, int left, int right){
//基准元素,要归位的元素
int sign = attr[left];
//要排序序列最左元素下标
int i = left;
//要排序序列的最右元素的下标加1,因为下边循环我们是--操作
int j = right+1;
//置换中间变量
int temp;
//如果待比较元素数目大于2则继续比较
while (i < j){
//基准元的素下一元素小于基准元素 并且 基准元素位置小于要排序的元素数目 则继续(++操作找到比基准元素大的那个元素)
while (attr[++i] < sign && i< right);
//要排序的数组最后一位元素的值大于基准元素则继续(--操作找到比基准元素小的元素为止)
while(attr[--j] > sign);
//如果位置正确,置换上边寻找到的两个元素
if (i < j){
temp = attr[i];
attr[i] = attr[j];
attr[j] = temp;
}
}
//待比较元素不大于2,即两元素比较的位置相遇了,置换基准元素到相遇的位置,完成归位
attr[left] = attr[j];
attr[j] = sign;
//返回归位的位置
return j;
}
}
快速排序的时间复杂度
1.快速排序每次将待排序数组二分为两个部分,在理想状况下,每一次都将待排序数组划分成等长两个部分,则需要logn次划分。
2.在最坏情况下,即数组已经有序或大致有序的情况下,每次划分只能减少一个元素,快速排序将不幸退化为冒泡排序,所以快速排序时间复杂度下界为O(nlogn),最坏情况为O(n^2)。
3.在实际应用中,快速排序的平均时间复杂度为O(nlogn)。优于冒泡排序,在各大算法中算是时间较小的。
快速排序的稳定性
在基准元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法。
总结
可以看到,快速排序的代码量与冒泡排序相比,庞大了不少,思路就是不断的实现二分和归位目标元素,来完成整个排序算法,递归的使用让我们不必再担心循环的次数了。
快速排序升级版–挖坑排序
挖坑排序
挖坑排序也算是快速排序,相比快速排序,代码量缩减很多。挖坑排序的思想也是分治+递归+基准元素归位实现的,但是挖坑是顺序填补元素的,也就是目标元素顺序填补从所给数据倒序符合的元素,反过来同理倒序填补所给元素顺序查找符合的元素。可以看到代码量也是比较简短的。
挖坑排序代码
public class Quick {
public static void main(String[] args) {
//初始化要排序的数组
int[] sum={2,7,99,55,2,21};
//实现排序的方法
quick_sort(sum,0,sum.length-1);
//循环输出
for (int i: sum){
System.out.print(i+" ");
}
}
/**
* @param s 目标数组
* @param l 要排序数组最左元素下标
* @param r 要排序数组最右元素下标
*/
static void quick_sort(int attr[], int l, int r){
if (l < r){
int i = l;
int j = r;
int sign = attr[l]; //要归位的元素
while (i < j){
while(i < j && attr[j] >= sign) // 从右向左找第一个小于基准数sign的数
j--;
if(i < j)
attr[i++] = attr[j]; //顺序填补倒序查找到的元素
while(i < j && attr[i] < sign) // 从左向右找第一个大于等于基准数sign的数
i++;
if(i < j)
attr[j--] = attr[i]; //倒序填补顺序查找到的元素
}
//基准元素归位
attr[i] = sign;
quick_sort(attr, l, i - 1); // 递归调用
quick_sort(attr, i + 1, r);
}
}
}
详细图文介绍请参考大神博文:http://www.cnblogs.com/morewindows/archive/2011/08/13/2137415.html