详解Redis源码中的部分快速排序算法(pqsort.c)

本文详细解析Redis源码中的部分快速排序算法pqsort.c,介绍了pqsort()与_pqsort()函数,以及相关辅助函数如med3、min等。文章深入探讨了部分快排的实现细节,包括选取模糊中位数、一趟排序和基准交换等步骤,旨在帮助读者更好地理解和应用快速排序算法。
摘要由CSDN通过智能技术生成

  看标题,你可能会疑惑:咦?你这家伙,怎么不讲解完整的快排,只讲一部分快排……-。- 哎,冤枉。“部分快排”是算法的名字,实际上本文相当详细呢。本文几乎与普通快排无异。看懂了本文,你对普通的快排也会有更深的认识了。

  快速排序算法(qsort)的原理我们大都应该了解。本文介绍的是部分快速排序算法。其实其算法本质是一样的,只不过限定了排序的左右区间,也就是只对一个数字序列的一部分进行排序,故称为“部分快速排序算法”,简称:pqsort

  Redis项目中的pqsort.c 文件实现了pqsort()函数,其源码见本文最后一节 pqsort.c源码 。 另外补充一句:长文慎入 :-)  


导读

外部资料

维基百科

  快排基本流程不了解的童鞋,请移步 快速排序wiki

论文

  实际上pqsort.c的快排流程是改编自一个经典实现,该实现被许多的实现所使用。请参考Bentley & McIlroy所著论文 “Engineering a Sort Function”

源码结构

主要函数 pqsort()
静态函数 _pqsort()、swapfuc()、med3()
宏函数 min()、swap()、swapcode()、vecswap()、SWAPINIT()

  总体来说,pqsort.c文件对外只提供了一个函数—— pqsort() ,但它的算法逻辑其实是由_pqsort()实现的,其他的静态(static)函数和宏也都是为了该函数服务的。
  接下来的介绍中,我会简单介绍宏函数和几个静态函数,把重点放在静态函数_pqsort()上。它才是整个算法的核心部分。

pqsort()与qsort()

  C标准库中有一个快排的函数qsort(),它与本文介绍的pqsort()所提供的编程接口极为相似,请看两者声明:

void qsort (void *a, size_t n, size_t es, int (*cmp)(const void *, const void *));
void pqsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *), 
            size_t lrange, size_t rrange);

参数解读

参数 说明
a 待排序数组的首地址
n 待排序元素的个数
es element size:每个元素的字节大小
cmp 回调函数,定义了比较的规则,直接影响排序结果是递增排序或递减排序,并支持非标准类型的排序
lrange 待排序的左边界
rrange 待排序的右边界

pqsort()与_pqsort()

pqsort()源码

void
pqsort(void *a, size_t n, size_t es,
    int (*cmp) (const void *, const void *), size_t lrange, size_t rrange)
{
    _pqsort(a,n,es,cmp,((unsigned char*)a)+(lrange*es),
                       ((unsigned char*)a)+((rrange+1)*es)-1);
}

  可以看出我们的qpsort()其实是在调用_pqsort()来完成排序功能的。这两个函数很像,差别在于参数上。

看一下两者的函数原型:

void 
pqsort (void *a, size_t n, size_t es, int (*cmp)(const void *, const void *), 
        size_t lrange, size_t rrange);
static void
_pqsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *), 
        void *lrange, void *rrange)

差异的关键在于:

  • pqsort() 的参数中的左右边界值,其含义值下标
  • _pqsort()的参数中的左右边界值,其含义是指针

这样pqsort()源码就不足为奇了。所以我前面说该文件的核心部分是_pqsort()

预备知识

  看一下除了_pqsort()之外的源码部分,这些都是_pqsort()函数实现的辅助。

med3

static inline char *
med3(char *a, char *b, char *c,
    int (*cmp) (const void *, const void *))
{

    return cmp(a, b) < 0 ?
           (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
}

  根据回调函数cmp指定的比较规则,则求出变量a,b,c中处于中间大小的变量。换句话说:就是在求 中位数

min

#define min(a, b)   (a) < (b) ? a : b

  这是个简单的宏,看一眼就呵呵就行了。

SWAPIN

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

果冻虾仁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值