快速排序

一、快速排序描述

快速排序是一种分治排序算法。广泛认为它是解决一般问题的最佳排序算法。同插入排序一样,快速排序也属于比较排序的一种,而且不需要额外的存储空间。在处理中到大型数据集时,快速排序是一个比较好的选择。

二、稳定性

快速排序是不稳定的排序方法。

三、复杂度

时间复杂度:O(nlogn),n为要被排序的元素个数。

空间复杂度:O(1)。

四、基本思想

由于快速排序是一种分治算法,因此可以用分治的思想将排序分为三个步骤:

(1)分:设定一个分割值并将数据分为两部分。

(2)治:分别在两部分用递归的方式继续使用快速排序法。

(3)合:对分割部分排序直至完成。

※考虑到其流行程度,快速排序最坏情况下的性能不会比插入排序情况好。而事实上,通过一点点修改,可以大大改善快速排序最坏情况的效率,使其表现得与其平均情况相当。关键取决于如何选择分割值。

如果选择的分割值会将大部分的元素放到其中一堆中,那么此时快速排序的性能会非常差。所以选择分割值需要尽可能地将元素平均分开。

选择分割值的一种行之有效的方法是通过随机选择法来选取。据统计,即便试图故意让算法陷入瘫痪,随机选择也能够有效地防止被分割的数据极度不平衡。同时,还可以改进这种随机选择算法,方法是首先随机选择三个元素,然后选择三个元素中的中间值。这就是所谓的中位数方法,可以保证平均情况下的性能。由于这种分割方法依赖随机数的统计特性,从而保证快速排序的整体性能,因此快速排序是随机算法的一个好例子。

五、实现一

/*
函数功能:
    分割数据
参数说明:
    [IN OUT] void *data:分割数据
    [IN] int size:分割数据元素个数
    [IN] int esize:分割数据元素大小
    [IN] int i:当前分割开始位置
    [IN] int k:当前分割结束位置
    [IN] int (*compare)(const void *key1, const void *key2):自定义比较函数
返回值:
    如果排序成功返回分割位置k;否则返回-1.
功能描述:
    函数分割data中处于i和k之间的元素(其中i小于k),采用中位数法选取一个分割值.
*/
static int partition(void *data, int esize, int i, int k, int(*compare)(const void *key1, const void *key2))
{
    char *pData = (char*)data;
    void *pVal  = malloc(esize);
    void *pTemp = malloc(esize);
    int r = 0;

    if (pVal == NULL)
    {
        return -1;
    }

    if (pTemp == NULL)
    {
        free(pVal);
        return -1;
    }

    r = (rand() % (k - i + 1)) + i; // 初始分割位置

    memcpy(pVal, &pData[r * esize], esize);

    i--;
    k++;

    while (1)
    {
        do 
        {
            k--;
        } while (compare(&pData[k * esize], pVal) > 0);

        do 
        {
            i++;
        } while (compare(&pData[i * esize], pVal) > 0);

        if (i >= k)
        {
            break;
        }
        else
        {
            memcpy(pTemp, &pData[i * esize], esize);
            memcpy(&pData[i * esize], &pData[k * esize], esize);
            memcpy(&pData[k * esize], pTemp, esize);
        }
    }

    free(pVal);
    free(pTemp);

    return k;
}

/*
函数功能:
    快速排序
参数说明:
    [IN OUT] void *data:排序数组
    [IN] int size:排序元素个数
    [IN] int esize:排序元素大小
    [IN] int i:当前排序开始位置
    [IN] int k:当前排序结束位置
    [IN] int (*compare)(const void *key1, const void *key2):自定义比较函数
返回值:
    如果排序成功返回0;否则返回-1.
函数描述:
    利用快速排序将数组data中的元素进行排序。数组中的元素个数由size决定。
    而每个元素的大小由esize决定。参数i和k定义当前进行排序的两个部分,其值分别初始化为0和size-1.
    函数compare会指向一个用户定义的函数来比较元素大小。
    当quicksort返回时,data包含已经排序的元素。
*/
int quicksort(void *data, int size, int esize, int i, int k, int (*compare)(const void *key1, const void *key2))
{
    int j;

    while (i < k)
    {
        if ((j = partition(data, esize, i, k, compare)) < 0)
        {
            return -1;
        }

        if (quicksort(data, size, esize, i, j, compare) < 0)
        {
            return -1;
        }

        i = j + 1;
    }

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值