zoukankan      html  css  js  c++  java
  • 高级排序算法之快速排序

    算法分析

    快速排序算法的时间复杂度为nlog(n)。

    基本思想:选择一个元素作为标志,比如下标为k的元素,经过排序使,arr[0,1,2....k-1]的元素小于arr[k],arr[k+1,k+2...n]的元素大于arr[k],然后对arr[0,1,2...k-1]和arr[k+1,k+2...n]两部分元素进行之前类似的操作。

    算法代码示例如下:

    template<typename T>
    int _partition(T arr[], int l, int r)
    {
        int v = arr[l];
    
        int j = l;      //arr[l+1...j] < v ; arr[j+1...r] > v
        for(int i = l + 1; i <= r; i++)
            if(v > arr[i])
                swap(arr[++j], arr[i]);   
    
        swap(arr[l], arr[j]);
        return j;
    }
    
    template<typename T>
    void _quickSort(T arr[], int l, int r)
    {
        if(l >= r)
            return ;
    
        int p = _partition(arr, l, r);
        _quickSort(arr, l, p-1);
        _quickSort(arr, p+1, r);
    }
    
    template<typename T>
    void quickSort(T arr[], int n)
    {
        _quickSort(arr, 0, n-1);
    }
    

    快速排序算法与插入排序、归并排序性能更好,但是对于几乎有序的数据,以上的快速排序性能会很差,时间复杂度可能会接近O(n^2)。

     算法优化

    针对以上的快速排序算法,对于有序的数据再进行排序,由于每次都选择第一个元素作为标志后,出现数据量一边倒的情况,导致快速排序的性能很差,时间复杂度为O(n^2),以下通过随机选择标志元素的方式避免这种情况,以下为优化过后的代码:

    template<typename T>
    int _partition(T arr[], int l, int r)
    {
        //优化点2:通过随机选择元素标志,防止对几乎有序的数据排序慢的问题
        srand(time(NULL));
        swap(arr[l], arr[rand()%(r-l+1)+l]);
        
        int v = arr[l];
    
        int j = l;      //arr[l+1...j] < v ; arr[j+1...r] > v
        for(int i = l + 1; i <= r; i++)
            if(v > arr[i])
                swap(arr[++j], arr[i]);   
    
        swap(arr[l], arr[j]);
        return j;
    }
    
    template<typename T>
    void _quickSort(T arr[], int l, int r)
    {
        //if(l >= r)
        //    return ;
        //优化点1:小规模数据使用插入排序
        if(r-l <= 15)
        {
            insertionSort(arr, l, r);
            return;
        }
    
        int p = _partition(arr, l, r);
        _quickSort(arr, l, p-1);
        _quickSort(arr, p+1, r);
    }
    
    template<typename T>
    void quickSort(T arr[], int n)
    {
        _quickSort(arr, 0, n-1);
    }

     经过优化以后,对于几乎有序的数据进行排序性能得到了提升,但是对于具有大量重复的数据排序,选择标志数据为v后,可能会出现大量等于v的数据,如下图所示,会出现排序的数据一边倒的情况,排序性能会很差。接下来我们继续对快速排序算法进行优化,以下优化过后的排序算法会有个新的名字,叫双路快速排序

  • 相关阅读:
    docker 部署 jenkins
    docker compose 常用命令
    docker compose 安装
    docker swarm 常用命令
    centos7 修改主机名
    docker 修改gwbridge ip address
    docker 创建私有镜像之 registry
    nginx 动静分离之 tomcat
    nginx lnmp之nginx+php
    nginx 配置状态监控
  • 原文地址:https://www.cnblogs.com/baihl/p/10666281.html
Copyright © 2011-2022 走看看