首页 > 技术文章 > 快速排序

HuiH 2019-11-02 17:49 原文

算法步骤:

  1.在待排序的元素任取一个元素作为基准(通常选第一个元素,但最佳的选择方法是在待排序数组中随机选取一个作为基准),成为基准元素。

  2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边。

  3.对左右两个分区重复以上步骤直到所有元素都是有序的。

  

时间复杂度:快速排序在最好情况下时间复杂度为O(nlogn),最坏情况下时间复杂度为O(n2);

稳定性分析:

  要分析稳定性,那么就需要关注快速排序中对基准元素相等的数的处理方式。在快速排序中,左右哨兵搜索时,对于相等数并不敏感,两边遇到相等数后都会选择无视,然后继续搜索下一个数,这样问题就出现了:

  以基准数为第一个数为例,那么相等的数是位于基准数右边的,与原先的基准数、相等数二者之间次序相同,是稳定的;另一方面,如果左边哨兵发现了相等数,也不对其进行操作,那么相遇点肯定就在相等数的右边了,最终基准数被交换到相等数的右边,此时相等数与基准数之间的次序改变了,是不稳定的。

  综上所述,快速排序是一种不稳定的排序算法。

代码实现:

第一种方法:

 1 public class QuickSort {
 2     public static void quickSort(int arr[],int _left,int _right){
 3         int left = _left;
 4         int right = _right;
 5         int temp = 0;
 6         if(left <= right){   //待排序的元素至少有两个的情况
 7             temp = arr[left];  //待排序的第一个元素作为基准元素
 8             while(left != right){   //从左右两边交替扫描,直到left = right
 9                 while(right > left && arr[right] >= temp)  
10                      right --;        //从右往左扫描,找到第一个比基准元素小的元素
11                   arr[left] = arr[right];  //找到这种元素arr[right]后与arr[left]交换
12                 while(left < right && arr[left] <= temp)
13                      left ++;         //从左往右扫描,找到第一个比基准元素大的元素
14                   arr[right] = arr[left];  //找到这种元素arr[left]后与arr[right]交换
15             }
16             arr[right] = temp;    //基准元素归位
17             quickSort(arr,_left,left-1);  //对基准元素左边的元素进行递归排序
18             quickSort(arr, right+1,_right);  //对基准元素右边的进行递归排序
19         }        
20     }
21     public static void main(String[] args) {
22         int array[] = {10,5,3,1,7,2,8};
23         System.out.println("排序之前:");
24         for(int element : array){
25             System.out.print(element+" ");
26         }        
27         quickSort(array,0,array.length-1);
28         System.out.println("\n排序之后:");
29         for(int element : array){
30             System.out.print(element+" ");
31         }
32     }
33 }

 

第二种方法:

 1 public void sort(int[] a,int low,int high){
 2     int start = low;
 3     int end = high;
 4     int key = a[low]; 
 5     while(end>start){
 6         //从后往前比较
 7         while(end>start&&a[end]>=key) 
 8         //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
 9             end--;
10         if(a[end]<=key){
11             int temp = a[end];
12             a[end] = a[start];
13             a[start] = temp;
14         }
15         //从前往后比较
16         while(end>start&&a[start]<=key)
17         //如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
18         start++;
19         if(a[start]>=key){
20             int temp = a[start];
21             a[start] = a[end];
22             a[end] = temp;
23         }
24         //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
25     }
26     //递归
27     if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
28         if(end<high) sort(a,end+1,high);//右边序    列。从关键值索引+1 到最后一个
29     }
30 }

推荐阅读