高级排序算法之三路快速排序

三路快速排序算法分析

双路快速排序算法把等于v的数据分为两部分,方式了数据量一边倒的情况,三路排序算法把排序的数据分为三部分,分别为小于v,等于v,大于v,这样三部分的数据中,等于v的数据在下次递归中不再需要排序,小于v和大于v的数据也不会出现某一个特别多的情况(如下图所示),通过此方式三路快速排序算法的性能更优。

三路快速排序主要关注三个标志,分别为lt,i,gt,这三个标志会把数据分为四部分,arr[l+1...lt]的数据全部小于v,arr[lt+1...i-1]的数据等于v,arr[i...gt-1]的为待排序的数据,arr[gt...r]的数据大于v,具体的代码实现如下:

template<typename T>
void _quickSort3Ways(T arr[], int l, int r)
{
    //小规模数据使用插入排序
    if(r-l <= 15)
    {
        insertionSort(arr, l, r);
        return;
    }

    // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
    swap( arr[l], arr[rand()%(r-l+1)+l ] );
    T v = arr[l];

    int lt = l; //arr[l+1...lt] < v
    int gt = r+1; //arr[gt...r] > v
    int i = l+1;  //arr[lt+1...gt-1] == v
    while(i < gt)
    {
        if(arr[i] < v)
        {
            swap(arr[i], arr[lt+1]);
            i++;
            lt++;
        }
        else if(arr[i] > v)
        {
            swap(arr[i], arr[gt-1]);
            gt--;
        }
        else    //arr[i] == v
            i++;
    }
    swap(arr[l], arr[lt]);

    _quickSort3Ways(arr, l, lt-1);
    _quickSort3Ways(arr, gt, r);
}

template<typename T>
void quickSort3Ways(T arr[], int n)
{
    srand(time(NULL));
    _quickSort3Ways(arr, 0, n-1);
}

三路快速排序算法对具有大量重复的数据排序性能很好。

排序算法性能对比

下边对比相同数据量下,几乎有序的数据、大量重复的数据情况下,归并排序、希尔排序、不同快速排序、双路快速排序、三路快速排序的性能:

通过初步对比百万数据量的排序得出以下几点结论:

1、随机的百万数据量排序中,快速排序算法性能相对较好。

2、对于百万几乎有序的数据量(不存在重复数据) ,希尔排序和归并排序性能最好,快速排序性能也不差。

3、对于百万具有大量重复数据的情况,之前未优化过的普通快速排序性能很差,三路快速排序算法性能最好。

以上是粗略测试,不同的数据可能具体结果会有差异,但是如果通过大量数据进行多轮测试,快速排序算法性能会最优,毕竟快速排序算法的时间复杂度为O(nlog(n))。

原文地址:https://www.cnblogs.com/baihl/p/10674427.html

时间: 2024-07-28 14:34:35

高级排序算法之三路快速排序的相关文章

高级排序算法之归并排序,快速排序

前言 承接上文基础排序算法-冒泡,插入,选择,相比之下,归并排序和快速排序更为高效,时间复杂度均为O(nlogn),相比简单排序的O(n^2)好了很多,下面介绍一下这两种算法的思路,实现和主要指标.主要思路来自<数据结构与算法之美> 正文 归并排序 主要思路 在归并排序采用分冶的思想,使用递归实现.描述如下 开始归并排序 如果数组元素小于两个,无需排序,结束 否则需要排序,归并排序数组左侧,归并排序数组右侧,按序合并左右侧 采用的是自顶至下的思路,例如[1,5,3,7,4,6],左侧为[1,5

高级排序算法之快速排序

快速排序是一个高级排序算法,算法核心思想:确定每一个值的正确位置,即该值左边为小,右边为大即可 这个算法实现上面也是需要经过递归,一般取第一个值开始进行排序 当然也有特别需要注意的地方 设 需要找正确位置的值 定义为 arr[ l ]  = v; 此时需要比较 值 e 与 v 的关系,无非两种(三种即多一个等于) 若e > v ,则无话可说,无需移动,继续移动游标比较arr[ i + 1]  与 v 的大小 若 e < v,则需要交换  e  和 arr [ j + 1 ] 的值,并需要将 j

javascript数据结构与算法--高级排序算法

高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法---- 希尔排序和快速排序. 一:希尔排序: 希尔排序的核心理念是:首先比较距离较远的元素,而非相邻的元素. 基本原理:通过定义一个间隔序列来表示在排序过程中进行比较的元素之间有多远的间隔. 下面我们来看看数组[0,9,1,8,7,6,2,3,5,4] 来使用希尔排序的原理:如下图: 代码分析如下: 1. 执行 "间隔序列=3的步骤" A.

数据结构之高级排序算法

一.希尔排序 希尔排序(缩小增量法) 属于插入类排序,由Shell提出,希尔排序对直接插入排序进行了简单的改进:它通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项大跨度地移动,当这些数据项排过一趟序之后,希尔排序算法减小数据项的间隔再进行排序,依次进行下去,进行这些排序时的数据项之间的间隔被称为增量,习惯上用字母h来表示这个增量. 具体代码实现: 1 package data.struct.algorithm; 2 3 //高级排序算法之希尔排序 4 class

图形化排序算法比较:快速排序、插入排序、选择排序、冒泡排序

图形化排序算法比较:快速排序.插入排序.选择排序.冒泡排序

排序算法学习之快速排序

快速排序基本思想:选取一个枢轴元素(图简单可选第一个),通过对序列一次遍历(中间涉及到数的交换),将该枢轴放置到序列合适位置,保证其左边数都比它小,右边数都比它大,然后利用递归思想对其左右两个子序列进行同样排序. 快熟排序的基本实现过程:将枢轴元素key备份,序列头尾各设置一个游标--i和j,尾部游标j先移动(如果选择的最后一个元素为枢轴则i先移),直到遇到比key小的元素,将其移到原枢轴处覆盖之,此时j处元素空着了,然后再对i进行移动,直到遇到比key大的元素,将其移到右边下表为j的空白处 v

高级排序算法之双路快速排序

双路快速排序算法分析 对于具有大量重复数据的排序按照之前的方式性能会很低,现在我们增加两个标志,想办法把大量重复的数据分到两部分,例如设置v作为标志数据,让等于v的数据分为两部分,如下图所示,这样可以避免两边的数据出现一边倒的情况. 根据以上算法的思想,代码修改如下: //双路快速排序算法:解决具有大量重复源数据排序慢的问题 template<typename T> int _partition2Ways(T arr[], int l, int r) { //优化点2:通过随机选择元素标志,防

js实现两种实用的排序算法——冒泡、快速排序

零:数据准备,给定数组arr=[2,5,4,1,7,3,8,6,9,0]; 一:冒牌排序 1思想:冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置       要实现上述规则需要用到两层for循环,外层从第一个数到倒数第二个数,内层从外层的后面一个数到最后一个数 2特点:排序算法的基础.简单实用易于理解,缺点是比较次数多,效率较低. 3实现: var times=0; var bubbleSort=function(arr){ for(var

排序算法系列:快速排序算法

概述 在前面说到了两个关于交换排序的算法:冒泡排序与奇偶排序. 本文就来说说交换排序的最后一拍:快速排序算法.之所以说它是快速的原因,不是因为它比其他的排序算法都要快.而是从实践中证明了快速排序在平均性能上的确是比其他算法要快一些,不然快速一说岂不是在乱说? 本文就其原理.过程及实现几个方面讲解一下快速排序算法. 版权声明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Coding-Naga 发表日期:2016年3月1日 链接:http://blog.csdn.n