排序算法之选择排序2—快排

本文详细介绍了快速排序算法的基本原理,包括其分区过程及递归特性,并提供了三种不同的分区函数实现方式,通过实例验证了算法的有效性。

快速排序也叫分区排序,其基本思想是在特定范围内对于某个基准值,将小于这个基准值的元素全部移到这个值的前面,大于这个值的元素全部移到这个值的后面,然后再对前后范围的元素递归进行分区,最终得到一个有序序列。快速排序的时间复杂度为O(nlgn),空间复杂度为O(lgn),当数组元素数量较大时,快速排序要比其他排序都要好,但是当数量级较小时,快速排序的性能可能没有其他排序好。
下面给出快排的实现:

#include <iostream>
using namespace std;
#include <cassert>
#include <ctime>
#include <cstdlib>
template <typename T>
struct Less
{
    bool operator()(T &left, T &right)const
    {
        return left < right;
    }
};

template <typename T>
struct Greater
{
    bool operator()(T &left, T &right)const
    {
        return left > right;
    }
};

template <typename T>
void SelectMid(T *array, int left, int right)    //三数取中函数
{
    assert(NULL != array && left >= 0 && right >= 0);
    if(right - left <= 1)
        return;
    int mid = left + ((right-left)>>1);

    int buf[3] = { left, mid, right-1 };
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 2-i; j++)
        {
            if(Greater<T>()(array[buf[j]], array[buf[j+1]]))
                swap(buf[j], buf[j+1]);
        }
    }
    if(array[buf[1]] != array[right-1])
        swap(array[buf[1]], array[right-1]);
}

template <typename T>
int Partition1(T *array, int left, int right)      //分区函数1,也是最容易想到的
{
    assert(NULL != array && left >= 0 && right >= 0);
    assert(right - left > 1);
    int start = left;
    int tail = right-1;
    T key = array[right-1];
    while(start < tail)
    {
        while((Less<T>()(array[start], key)||array[start]==key) && start < tail)
            start++;
        while((Greater<T>()(array[tail], key)||array[tail]==key) && start < tail)
            tail--;
        if(start < tail)
            swap(array[start], array[tail]);
    }
    if(start != right-1)
        swap(array[start], array[right-1]);
    return start;
}
template <typename T>
int Partition2(T *array, int left, int right)   //分区函数2,也称为挖坑法
{
    assert(NULL != array && left >= 0 && right >= 0);
    assert(right - left > 1);
    int start = left;
    int tail = right-1;
    T key = array[right-1];
    while(start < tail)
    {
        while((Less<T>()(array[start], key)||array[start]==key) && start < tail)
            start++;
        if(Greater<T>()(array[start], key))
            array[tail] = array[start];
        while((Greater<T>()(array[tail], key)||array[tail]==key) && start < tail)
            tail--;
        if(Less<T>()(array[tail], key))
            array[start] = array[tail];
    }
    if(start < right)
        array[start] = key;
    return start;
}
template <typename T>
int Partition3(T *array, int left, int right)     //分区函数3
{
    assert(NULL != array && left >= 0 && right >= 0);
    assert(right - left > 1);
    int start = left-1;
    int tail = left;
    T& key = array[right-1];
    while(tail < right-1)
    {
        start++;
        tail++;
        while(Less<T>()(array[start], key) && tail < right-1)
        {
            start++;
            tail++;
        }
        while(Greater<T>()(array[tail], key) && tail < right-1)
            tail++;
        if(tail < right && Greater<T>()(array[start], array[tail]))
            swap(array[start], array[tail]);
    }
    return start;
}
template <typename T>
void _quickSort(T *array, int left, int right)
{
    assert(NULL != array && left >= 0 && right >= 0);
    if(right - left <= 1)
        return;
    SelectMid(array, left, right);      //利用三数取中法将基准元素移到最右边
    int keysub = Partition3(array, left, right);
    _quickSort(array, left, keysub);
    _quickSort(array, keysub+1, right);
}

template <typename T>
void QuickSort(T *array, const int size)
{
    assert(NULL != array && size > 0);
    if(size == 1)
        return;
    _quickSort(array, 0, (int)size);
}

测试函数:

void test7()
{
    int arr[100] = { 0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    srand((unsigned int)time(0));
    for(int i = 0; i < sz; i++)    //Assign values with random numbers
    {
        arr[i] = rand() % sz;
    }
    for(int i = 0; i < sz; i++)    //print array
        cout << arr[i] << " ";
    cout << endl << endl << endl << "sort:" << endl;
    QuickSort(arr, sz);             //sort
    for(int i = 0; i < sz; i++)    //print array
        cout << arr[i] << " ";
    cout << endl;
    for(int i = 1; i < sz; i++)  //check that the sort is correct
    {
        if(Less<int>()(arr[i], arr[i-1]))
            cout << "sort error! " << arr[i] << endl;
    }
}

三个分区函数实现算法不同,达到效果一样。因此这里就仅贴一种分区函数的测试结果图:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值