zoukankan      html  css  js  c++  java
  • 快速排序

    1. 快排的基本原理:
          (1)在数据集之中,选择一个元素作为"基准"(pivot)。
       (2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
       (3)对"基准"左边和右边的两个子集,不断重复上述过程,直到所有子集只剩下一个元素为止。
     
    2. 快排的特点:
          快速排序是一种不稳定的排序,在最坏情况下时间复杂度为O(n2),平均时间复杂度为O(nlogn)。
          快速排序适用的情况是:数据是杂乱无章的,每次选择基准后,小于和大于基准的元素数量基本相同,此时快排的速率最优,时间复杂度O(nlogn)
          快速排序不适用的情况是:在数据有序或者逆序的情况下,选择基准后,左右两边元素数量极不均衡,此时快排的速率最差,时间复杂度O(n*n)
     
    3.对于基准的选取,采用取数组首元素的二分Partition算法,C++代码如下:
    /*采用partition算法分割数组,比枢纽小的在数组左边,比枢纽大的在数组右边,返回枢纽所在位置*/
    int Partition(vector<int> &A, int start, int end)
    {
        int pivot = A[start];    //枢纽取第一个元素
        while(start < end)
        {
            while(start<end && A[--end]>=pivot);
            A[start] = A[end];
            while(start<end && A[++start]<=pivot);
            A[end] = A[start];
        }
        A[start] = pivot;
        return start;     //返回位置!!!
    }
    
    int quicksort(vector<int> &A, int start, int end)
    {
        if(start < end)
        {
    //用partition算法分割数组,小于枢纽在左,大于枢纽在右,返回枢纽所在的位置
            int pos = Partition(A,start,end);
    //递归地再次排序比枢纽小的元素集合和比枢纽大的元素集合
            quicksort(A,start,pos);
            quicksort(A,pos+1,end);
        }
    }
    
    void QuickSort(vector<int> &A)
    {
        int start = 0;
        int end = A.size();
        quicksort(A,start,end);
    }
     
    4. 对于基准的选取,可以采用“三位取中”的做法,C++代码如下:
    int GetPivot(std::vector<int> & a, int left, int right)
    {
        int center = (left+right)/2;
        if(a[left] > a[center])
            std::swap(a[left],a[center]);
        if(a[left] > a[right])
            std::swap(a[left],a[right]);
        if(a[center] > a[right])
            std::swap(a[center],a[right]);
        //下面这个交换一定要做!!!
        if(a[center] != a[right-1])
            std::swap(a[center],a[right-1]);
        return a[right-1];
    }
    
    void quicksort(std::vector<int> & a, int left, int right)
    {
        static int count_quick = 1;
        if(left < right)
        {
            std::cout<<"进行第 "<<count_quick++<<" 次快速排序
    ";
         //取 { a[left]、a[right]、a[(left+right)/2] } 三数中,中间那个数作为基准
            int pivot = GetPivot(a,left,right);  
            int i = left;
        //真正的基准值放在right-1的位置,即rigt-1不用比较,直接从right-2向右比较
            int j = right-1;
        //比枢纽大的在右边,比枢纽小的在左边
            while(i<j)
            {
                while(a[++i] < pivot);
                while(a[--j] > pivot);
                if(i<j)
                    std::swap(a[i],a[j]);
            }
         //此时i一定比基准值大,将其与基准值调换位置
            std::swap(a[i],a[right-1]);
         //分治思想:递归枢纽的左边数组和右边数组
            quicksort(a,left,i-1);
            quicksort(a,i+1,right);
        }
    }
    
    void QuickSort(std::vector<int> & a)
    {
        quicksort(a,0,a.size()-1);
    }
  • 相关阅读:
    多任务GUI窗口系统(类window,有源码,支持汉字显示、顶层、非矩形和透明窗口)gicell源码
    怎样判断treeview当前节点为treeview显示出来的第一个节点和最后一个节点?
    用 dbgrid 或 dbgrideh 如何让所显示数据自动滚动
    vue路由懒加载及组件懒加载
    vue 中使用rem布局
    纯css实现移动端横向滑动列表&&overflow:atuo;隐藏滚动条
    分布式一致性算法Raft
    HDU_1753 大明A+B
    POJ——3630 Phone List
    HDU_2647 Reward (拓扑排序)
  • 原文地址:https://www.cnblogs.com/ladawn/p/8449127.html
Copyright © 2011-2022 走看看