八大排序之快速排序
一、基本思想
快速排序是 一种基于交换的排序算法,是对冒泡排序的改进。它的基本思想是,通过一趟快速排序,将待排记录分割成独立的两部分,其中一部分的关键字均比另一部分小;在分别对这两部分进行排序排序,直至整个序列有序。
二、操作步骤
1.将待排记录分隔成独立的两部分,其中一部分的关键字均比另一部分小。选取第一个元素的关键字为支点,即进一次快速排序后,支点左边的元素的关键字均不大于支点的关键字,支点右边的元素的关键字不小于支点的关键字。将这部分操作封装成一个函数。
1).用一个临时变量储存支点,这样,就有一个空位在左边,即支点的位置,用以存放从右侧选取的小于支点的元素。
2).从右边开始,寻找比支点大的元素,找到之后将其放到左边的空位上,这样,空位就到右边了,用以存放从左侧选取的大于支点的元素。
3).从左边开始,寻找比支点小的元素,找到之后将其放到右边的空位上,这样,空位就到了左边,用以存放从右侧选取的小于支点的元素。
4).重复2)3)操作,知道整个记录遍历。最后将支点放回到空位上。
进行上述操作后,待排记录就分割成了满足条件的两部分,支点也移动到了合适的位置。
2.分别对上述两部分继续分割直至区间为一。这是一个递归的过程。
三、实现代码
测试工具类 点击这里
package sort; import sort.util.*; /* 快速排序思路: 1.以某个元素为支点,改变支点位置,使得支点左边的值都不大于它,右边的值都不小于它 2.对以支点划分的两个区间进行上述操作,直到区间长度为0 时间复杂度:O(nlog2(n)),在数组基本有序时退化为O(n2) 空间复杂度:O(log2(n)),递归需要栈空间 稳定性: 不稳定,跳跃式移动 */ public class QuickSort implements ISort { //划分,默认以a[left]为支点,返回划分后支点的位置 private int partition(int[] a , int left , int right) { int t = a[left]; while(left < right) { //挖坑填数法 while(left < right && a[right] >= t) {right--;} //一开始,坑在a[left],所以先找右边符合条件的数来填 if(left < right) {a[left++] = a[right];} //填坑a[left] ,现在坑在a[right]了 while(left < right && a[left] <= t) {left++;} if(left <right){a[right--] = a[left];} } a[left] = t; return left; } //递归调用划分,直到区间长度为0 private void quicksort(int[] a , int left , int right) { if(left < right){ int dividePoint = this.partition(a , left , right); quicksort(a , left , dividePoint - 1); quicksort(a , dividePoint + 1 , right); } } //便于统一接口回调 public void sort(int[] a) { this.quicksort(a , 0 , a.length - 1); } public static void main(String[] args) { int[] array = RandomArrayGenerator.getRandomArray(100 , 30); SortTestHelper.test(new QuickSort() , array); } }
测试结果:
四、总结分析
时间复杂度:O(nlog n ),当待排记录有序时会退化为O(n2)
空间复杂度:O(1)
快速排序综合而言是比较优秀的排序算法,但由于跳跃式的记录交换,导致不稳定。