排序算法---(4)快速排序---Java实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/May_3/article/details/79594717

写在前面:

    快速排序是冒泡排序的升级,他的排序思想为:对于给定的一组记录,选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分,直到序列中的所有记录均有序为止。


例如:数组int [] arr = {4,3,5,6,1,2},选取基准点为第一个元素4,基准点与最右边j=5开始比较

  1. 第一次比较,与右边比较:4>2,arr[i++]=2          【 2,3,5,6,1,2】
  2. 第二次比较,与左边比较:4>3,i++                       【 2,3,5,6,1,2】
  3. 第三次比较,与左边比较:4<5,arr[j--]=5           【 2,3,5,6,1,5】
  4. 由于i<j,所以继续循环
  5. 第四次比较,与右边比较:4>1,arr[i++]=1            【 2,3,1,6,1,5】
  6. 第五次比较,与左边比较:4<6,arr[j--]=6            【 2,3,1,6,6,5】
  7. i=j=3,所以结束第一轮排序。令arr[i]=index            【 2,3,1,4,6,5】

    这样我们就完成了第一轮排序,接下里会继续递归,原数组以基准点4为界限。分成了2个数组:

    左边数组-----2,3 ,1           右边数组-----6,5       这样左边的元素都<基准点4,右边的都>基准点4。然后,对两边的数组继续快速排序,直到序列中的所有记录均有序为止。

代码实现:

    

[java]  view plain  copy
  1. package test3;  
  2.   
  3. import java.util.Arrays;  
  4.   
  5. public class Test {  
  6.   
  7.     public static void main(String[] args) {  
  8.         int[] arr = { 435612 };  
  9.         quicksort(arr);  
  10.         System.out.println(Arrays.toString(arr));  
  11.     }  
  12.   
  13.     private static void quicksort(int[] arr) {  
  14.         sort(arr, 0, arr.length - 1);  
  15.     }  
  16.   
  17.     private static void sort(int[] arr, int low, int height) {  
  18.         int i;// 记录左边的指针  
  19.         int j;// 记录右边的指针  
  20.         int index;// 记录基准点的值  
  21.         if (low > height) {  
  22.             return;  
  23.         }  
  24.         i = low;  
  25.         j = height;  
  26.         index = arr[i];// 基准点设置为左边第一个元素  
  27.         while (i < j) {  
  28.             while (i < j && index < arr[j]) {  
  29.                 j--;  
  30.             }  
  31.             if (i < j) {  
  32.                 arr[i++] = arr[j];  
  33.             }  
  34.             while (i < j && index > arr[i]) {  
  35.                 i++;  
  36.             }  
  37.             if (i < j) {  
  38.                 arr[j--] = arr[i];  
  39.             }  
  40.         }  
  41.         // 第一轮分组结束  
  42.         arr[i] = index;  
  43.         sort(arr, low, i - 1);  
  44.         sort(arr, i + 1, height);  
  45.     }  
  46.   
  47. }  

基准点选取:

    基准点的选取一般有两种方式:

    (1)选取待排序数组的第一个元素,中间元素,最后一个元素,取三者的中间元素。

    (2)取low和height的一个随机数,left<m<height,取arr[m]为基准点,这种方式称为随机的快速排序。

时间复杂度分析:

    最坏情况:即每一次排序之后,分成的数组,以基准点为分界,左边或右边的数组为空,而另一边,只比排序之前少了一项。也就是说,选择的基准点恰好是数组中最大的元素或者最小的元素。这时就要经过n次比较,和n次移动,T(n)=(n-1)+(n-2)+..........+1,所以时间复杂度为O(n^2)。

    最好情况:即每一次排序之后,分成的数组,以基准点为分界,左边或右边的数组元素个数相等或者只相差一个。也就是说,选择的基准点恰好是数组元素的中间值。这时的递归的深度为O(log N),每次处理需要n次计算(比较+移动),所以时间复杂度为O(nlogn)。

空间复杂度分析:

    快速排序的过程中,需要借助一个栈空间。在最好情况下,每次将数组分为等长的2部分,所以递归的深度为O(log N),空间复杂度为O(nlogn)。

    在最坏情况下,每次快速排序,只能交换一个元素,退化为冒泡排序,所以空间复杂度为O(n^2)。

猜你喜欢

转载自blog.csdn.net/May_3/article/details/79594717