quicksort / quickselect

Quicksort

  • not stable
  • in place
  • faster than other sorting algorithms for small data set

Quickselect

quickselect is a selection algorithm to find the kth smallest element in an unordered list.

It requires only constant memory overhead if tail call optimization is available, or if eliminating the tail recursion with a loop

 

Partition Method I

int partition(vector<int> &a, int low, int high){
    int pivot=a[low];
    while (low<high){
        while (low<high && a[high]>=pivot) --high;
        if (low<high) a[low++]=a[high];
        while (low<high && a[low]<=pivot) ++low;
        if (low<high) a[high--]=a[low];
    }
    a[low] = pivot;
    return low;
}

void quicksort(vector<int> &a, int low, int high){
    if (low>=high) return;
    int pivotIndex=partition(a,low,high);
    quicksort(a,low,pivotIndex-1);
    quicksort(a,pivotIndex+1,high);
}

int quickselect(vector<int> &a, int low, int high, int k){
    if (low==high) return a[low];
    int pivotIndex=partition(a,low,high);
    int len=pivotIndex-low+1;
    if (k==len) return a[pivotIndex];
    else if (k<len) return quickselect(a,low,pivotIndex-1,k);
    else return quickselect(a,pivotIndex+1,high,k-len);
}

int main() {
    vector<int> a={1,5,8,3,2};
    int n=a.size();
    quicksort(a,0,n-1);
    for (auto x:a) cout<<x<<' ';
    cout << endl;
    for (int k=1;k<=n;++k) cout<<quickselect(a,0,n-1,k)<<' ';
    return 0;
}

 

Partition Method II

#include <iostream>

int partition(vector<int> &a, int low, int high){
    int pivot=a[high];
    int k=low;
    for (int i=low;i<high;++i){
        if (a[i]<=pivot) swap(a[i],a[k++]);
    }
    swap(a[high],a[k]);
    return k;
}

void quicksort(vector<int> &a, int low, int high){
    if (low>=high) return;
    int pivotIndex=partition(a,low,high);
    quicksort(a,low,pivotIndex-1);
    quicksort(a,pivotIndex+1,high);
}

int quickselect(vector<int> &a, int low, int high, int k){
    if (low==high) return a[low];
    int pivotIndex=partition(a,low,high);
    int len=pivotIndex-low+1;
    if (k==len) return a[pivotIndex];
    else if (k<len) return quickselect(a,low,pivotIndex-1,k);
    else return quickselect(a,pivotIndex+1,high,k-len);
}

int main() {
    vector<int> a={1,5,8,3,2};
    int n=a.size();
    quicksort(a,0,n-1);
    for (auto x:a) cout<<x<<' ';
    cout << endl;
    for (int k=1;k<=n;++k) cout<<quickselect(a,0,n-1,k)<<' ';
    return 0;
}

 

Time Complexity

Sensitive to the pivot that is chosen.

If the pivot is mid of the array (best case), T(n) = O(n) + 2T(n/2) => O(nlogn) for quicksort,  T(n) = O(n) + T(n/2) => O(n) for quickselect.

On average, quicksort O(nlogn), quickselect O(n)

In the worst case, both O(n^2)

posted @ 2019-10-26 02:48  約束の空  阅读(259)  评论(0编辑  收藏  举报