快速排序(Quick Sort)

快速排序(Quick Sort)

​ 快速排序是利用分治法的分区交换排序。将待排数组分成两个子数组,再分别对这两个子数组递归地进行快排。该算法由C.A.R.Hoare于1962年发表在Computer Journal5第一期。

快速排序(Quick Sort)_第1张图片

库函数

在C语言中

void qsort(void * base,size_t num,size_t size,
            int* compar)(const void *const void *));//数组名(指向数组的第一个元素的指针),元素个数,元素大小(sizeof),比较函数的指针

在C++中

std::sort
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
//比较函数可以省略 默认升序,
//这个函数实际为了避免递归过深,在分组小于16后使用堆排序或归并排序

算法分析

流程

  • 若数组大小为0或1,返回
  • 选择一个枢轴(privot),也可以叫:基准、基数、中间值……
  • 将待排数组分为小于枢轴和大于枢轴的两个子数组
  • 对子数组重复上述的过程(或利用栈迭代)

关键问题

  • 如何选择中间值(privot)?
    • 选择第一个元素
    • 选择最后一个元素
    • 选择中间元素
    • 随机选择

选择第一个或最后一个基本相同。

  • 如何分区(partition)?

    • 利用额外空间,最后进行拼接

    • 原地交换(in-place)

      • 单向划分

      • 双向划分

C++代码

单向划分原地交换 && 选择第一个元素作为privot,当数组为升序或所有元素相同,时间复杂度为O(n2

//双向划分 && 最后一个元素作为privot && 原地交换
template<typename T>
void QuickSort(T arr[], int start, int end){
    if(start >= end)
        return;
    int left = start;
    int right = end - 1;
    int privot = arr[end];
    while(left < right){
        while(arr[left] < privot && left<right) ++left;
        while(arr[right] >= privot && left<right) --right;
        std::swap(arr[left],arr[right]);
    }
    if(arr[left] > privot)//三种情况:1.没有小于privot的数,2.有小于也有大于,3.全都小于
        std::swap(arr[left],arr[end]);
    else
        ++left;
    QuickSort(arr, start, left-1);
    QuickSort(arr, left+1, end);
}

算法效率

随机顺序的数组

时间复杂度: O(nlogn)

空间复杂度:O(logn)栈空间,

有序数组

时间复杂度:O(n2)

你可能感兴趣的:(经典数据结构与算法)