我写的一个 C++ 快速排序算法

这几天在读程杰的《大话数据结构》,上面有介绍快速排序算法。关于排序算法一直没有下功夫研究过,全都是用现成的,这次花了点时间自己动手写了写,顺便也检验了自己对 C++11 的掌握程度。

快速排序原理上很简单,一个数组分成前后两部分,保证前边的数都比后面的小。之后递归的再这么分下去就行了。

下面是代码,首先需要一个能交换两个元素的 swap 函数,这个 swap 用到了 C++ 11 的 auto 关键字。说实话要是没有 auto 这个代码我还真不会写。。。

template<typename RandomIterator>
inline void swapValueByIterator(RandomIterator p, RandomIterator q)
{
    auto t = *p;
    *p = *q;
    *q = t;
}

之后要有个函数能将数组分成前后两部分,后面的比前面的大。
这个函数需要注意的是 end 开始时指向的是一个最后一个元素的下一个元素,所以需要向前移动一下。之所以这样设计是为了与 C++ 中的 iterator 一致。

template<typename RandomIterator, typename LessThan>
RandomIterator partition(RandomIterator start, RandomIterator end, LessThan func)
{
    --end;
    while(start != end)
    {
        while (start != end && func(*start, *end))
        {
            --end;
        }
        swapValueByIterator(start, end);
        while(start != end && !func( *end, *start ))
        {
            ++start;
        }
        swapValueByIterator(start, end);
    }
    return start;
}

之后就是主角了:

template<typename RandomIterator, typename LessThan>
void quickSort(RandomIterator start, RandomIterator end, LessThan func)
{
    if(start != end)
    {
        RandomIterator pivot = partition(start, end, func);
        quickSort(start, pivot, func);
        quickSort(pivot + 1, end, func);
    }
}

下面是个例子:

template<typename T>
bool my_less(T& x, T& y)
{
    return x < y;
}

template<typename RandomIterator>
void print( RandomIterator start, RandomIterator end)
{
    if(start != end) cout << *start;

    while(++start != end)
    {
        cout <<  ", " << *start;
    }
    cout << endl;
}
int main(int argc, char *argv[])
{
    (void) argc;
    (void) argv;

    double test[] = {5,1, 6,7, 1,4, 8,4, 3,9, 6,4 ,2,1, 5, 34, 4, 3, 5, 8, 5,9,4,2};
    print(std::begin(test), std::end(test));
    quickSort(std::begin(test), std::end(test), my_less<double>);
    print(std::begin(test), std::end(test));
}

当然这个代码还可以优化,比如数组元素比较少时应该用 insertSort:

template<typename RandomIterator, typename LessThan>
void insertSort(RandomIterator start, RandomIterator end, LessThan func)
{
    for( ;start < end; ++start)
    {
        auto min = *start;
        RandomIterator min_pos = start;
        for (RandomIterator p = start + 1; p != end; ++p) // 寻找最小的元素
        {
            if( func(*p, min) )
            {
                min = *p;
                min_pos = p;
            }
        }
        swapValueByIterator(start, min_pos);
    }
}

const int INSERT_SORT_N = 15;
template<typename RandomIterator, typename LessThan>
void quickSort2(RandomIterator start, RandomIterator end, LessThan func)
{
    if(end - start > INSERT_SORT_N)
    {
        RandomIterator pivot = partition(start, end, func);
        quickSort(start, pivot, func);
        quickSort(pivot + 1, end, func);
    }
    else
    {
        insertSort(start, end, func);
    }
}

quickSort 还可以写成 尾递归的形式,我们知道编译器会对尾递归进行优化。

template<typename RandomIterator, typename LessThan>
void quickSort3(RandomIterator start, RandomIterator end, LessThan func)
{
    if(end - start > INSERT_SORT_N)
    {
        while(start != end )
        {
            RandomIterator pivot = partition(start, end, func);
            quickSort(start, pivot, func);
            start = pivot + 1;
        }
    }
    else
    {
        insertSort(start, end, func);
    }
}

至此,一个 quicksort 函数就基本完成了。当然还可以进一步的优化,不过那都是些细枝末节的优化了。对我们学习快速排序的原理意义不大。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值