十大排序算法-快速排序

1. 算法步骤

从数列中挑出一个元素,称为 "基准"(pivot);

重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

2、时间复杂度

快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn)

3、代码实现

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * User: Andrew
 * Date: 2021/02/10
 * Time: 20:33
 * Description: No Description
 */
public class QuickSort {
    public static void main(String[] args) {
        int[] arr = new int[]{3,4,5,7,1,2,0,3,6,8};
        // 排序前数组
        System.out.println(Arrays.toString(arr));
        quickSort(arr,0,arr.length-1);
        // 排序后的数组
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr,int start,int end){
        if (start <end){
            // 把数组中的第0个元素作为标准数
            int stard = arr[start];
            // 记录需要排序的下标
            int low = start;
            int high = end;
            // 循环找比标准数大的数和比标准数小的数
            while (low<high){
                // 右边的数字比标准数大
                while (low<high && stard <=arr[high]){
                    high--;
                }
                // 使用右边的数字替换左边的数
                arr[low] = arr[high];
                // 如果左边的数字比标准数小
                while (low<high&&arr[low]<=stard){
                    low++;
                }
                arr[high]=arr[low];
            }
            // 把标准数赋值为低所在位置的元素
            arr[low] = stard;
            // 处理所有的小的数字
            quickSort(arr,start,low);
            // 处理所有的大的数字
            quickSort(arr,low+1,end);
        }
    }
}

  

/**
 * Created with IntelliJ IDEA.
 * User: Andrew
 * Date: 2021/02/10
 * Time: 20:42
 * Description: No Description
 */


object QuickSortDemo {
  def swap(array: Array[Int],index1:Int,index2:Int): Unit ={
    val temp = array(index1)
    array(index1) = array(index2)
    array(index2) = temp
  }
  /**
   * 快速排序
   *
   * @param arr   需要排序的数组
   * @param left  左扫描指针
   * @param right 右扫描指针
   */
  def quickPartition(arr: Array[Int], left: Int, right: Int): Int = {
    // 左扫描指针向右扫, 右扫描指针向左扫. 需要更改指针位置
    var l: Int = left
    var r: Int = right
    // 参考值: 保证左边的都小于 p, 右边的都大于等于 p
    val p: Int = arr(l)
    // 如果左扫描指针在左边就一直扫描
    while(l < r){
      // 左指针找到一个大于 p 的, 右指针找到一个小于等于p的, 然后交换
      while(l < right && arr(l) <= p){
        l += 1
      }
      while (r > left && arr(r) > p ){
        r -= 1
      }
      // 小于等于p 的去左边, 大于 p 的去右边
      if(l <= r){
        swap(arr, l, r)
      }
    }
    // 让参考元素去到正确的位置, 右指针已经到了小于 p 的区域, 所以可以和右指针的元素进行交互
    swap(arr, left, r)
    // 现在右指针就是分割位置
    r
  }


  def quickSortDemo(arr: Array[Int], left: Int, right: Int): Unit = {
    // 如果左指针超过或等于右指针, 则排序已经完成, 无序再排序
    if (left >= right) return
    // 把数组分区, 保证左边的都小于等于某一个参数值, 右边的都大于等于某一个参考值.
    // 返回参考值所在的位置, 作为划分数组的边界.
    val m: Int = quickPartition(arr, left, right)
    // 再分别对左数组和右数组进行排序
    quickSortDemo(arr, left, m - 1)
    quickSortDemo(arr, m + 1, right)

  }
  def main(args: Array[String]): Unit = {
    val array = Array(3, 4, 5, 7, 1, 2, 0, 3, 6, 8)
    println(array.toBuffer)
    quickSortDemo(array,0,array.length-1)
    println(array.toBuffer)
  }

}

  

posted @ 2021-02-10 21:07  Andrew037  阅读(148)  评论(0)    收藏  举报