• 快速排序的一种优化算法(三向切分)


    快速排序:

    时间复杂度O(N*logN),最坏情况为O(N^2)

    空间复杂度O(1)

    但是堆栈深度一般情况为O(logN),最坏情况为O(N)


    快速排序实现:

    partition划分算法:

    int Partition(SeqList R,int i,int j)
    {
        //调用Partition(R,low,high)时,对R[low..high]做划分,
        //并返回基准记录的位置
        ReceType pivot=R[i]; //用区间的第1个记录作为基准 '
        while(i<j){ //从区间两端交替向中间扫描,直至i=j为止
            while(i<j&&R[j].key>=pivot.key) //pivot相当于在位置i上
                j--; //从右向左扫描,查找第1个关键字小于pivot.key的记录R[j]
            if(i<j) //表示找到的R[j]的关键字<pivot.key
                R[i++]=R[j]; //相当于交换R[i]和R[j],交换后i指针加1
            while(i<j&&R[i].key<=pivot.key) //pivot相当于在位置j上
                i++; //从左向右扫描,查找第1个关键字大于pivot.key的记录R[i]
            if(i<j) //表示找到了R[i],使R[i].key>pivot.key
                R[j--]=R[i]; //相当于交换R[i]和R[j],交换后j指针减1
        } //endwhile
        R[i]=pivot; //基准记录已被最后定位
        return i;
    } //partition 

    然后,对整个数组进行递归排序:

    QUICKSORT(A, p, r)
        if p < r
            then q ← PARTITION(A, p, r)   //关键
        QUICKSORT(A, p, q - 1)
        QUICKSORT(A, q + 1, r)

    算法导论中提到的快速排序的优化版本:就地重排

    PARTITION(A, p, r)
        x ← A[r]         //以最后一个元素,A[r]为主元
        i ← p - 1
        for j ← p to r - 1    //注,j从p指向的是r-1,不是r。
            do if A[j] ≤ x
                then i ← i + 1
                exchange A[i] <-> A[j]
        exchange A[i + 1] <-> A[r]
        return i + 1

    本文重点:三向切分

    快速排序什么时候不适用?元素重复率特别高的时候。
    如何优化?三向切分。前后各俩指针,总共四个指针。俩额外的指针指向跟待选元素相同的元素,最后全部置换到中间。
    三向切分的好处?重复率高的时候,避免相同元素来回交换,节省交换次数。对于包含大量重复元素的数组,这个算法将排序时间从线性对数级降到了线性级别。
    代码:
    #include <iostream>  
    using namespace std;  
    template <typename T>  
    void sawp(T a[],int first,int second){  
        T temp;  
        temp = a[first];  
        a[first] = a[second];  
        a[second] = temp;  
    }  
    template <typename T>  
    int sort(T a[],int low,int high){  
        if(low < high){  
            int lt = low,i=low+1,gt = high;  
            int temp = a[low];  
            while(i <= gt){  
                if(a[i] < temp){  
                    sawp(a,lt++,i++);  
                }else if(a[i] > temp){  
                    sawp(a,i,gt--);  
                }else{  
                    i++;  
                }  
            }  
            sort(a,low,lt-1);  
            sort(a,gt+1,high);  
        }   
    }  
    int main() {  
        int a[] = {2,2,2,2,2,0,0,0,0,0,0,1,5};  
        //int a[] = {2,0,1,5};  
        int len = sizeof(a)/sizeof(int);  
        sort(a,0,len-1);  
        for (int i = 0; i < len; ++i)  
            cout << a[i] << " ";  
        cout << endl;  
    }  
     
  • 相关阅读:
    Go语言 函数return值的几种情况
    VSCode 常用快捷键 Mac
    Java异常处理
    Java面向对象《三》
    C++类模板
    C++函数模板
    盛最多水的容器
    实现 Trie (前缀树)
    排序链表
    类似某团app搜索城市界面中 点击右侧城市首字母,对应城市区域置顶的功能(uniapp)
  • 原文地址:https://www.cnblogs.com/zlcxbb/p/5753509.html
Copyright © 2020-2023  润新知