你必须背下的几个经典算法

(一)外部排序算法

1.基础知识:二路归并排序
基本思想: 使用递归将队列分裂后的子队列中数据(原队列的一半和另一半)进行逐式比较,将较小的队首写入缓冲区,不断递归,直到使整个队列的数据在写入的缓冲区中是有序的。
(逐式比较: 将队列1和队列2的队首元素进行大小的比较,小的写入缓冲区数据队列的末尾,依次进行比较,直到两个队列元素全部写入缓冲区为止)
2.对于空间复杂度的思考
二路归并排序的空间复杂度是待排数据队列的大小,即O(n).但是这部分空间不需要在内存中开辟,在逐式比较时的只要对两个元素读入内存进行比较(对于k路归并,就是k个元素)。在逐式比较之后将较小者直接写入外部存储器,从而实现了外部排序。
3.对于排序方法的思考
在上面的方法中,对每一层分割得到的两个待排序的队列都分别又采取了二路归并排序,因而是完全的彻底的二路归并排序算法; 但实际上当分割后剩下的两个部分长途足够小,内存可以装下时,就可以采用效率更高的内部排序算法,对该队列进行内部排序,然后再递归回溯到上一层,继续回到二路归并排序,实现算法的最优解。
4.对于归并分路数目的思考
二路归并排序只对两个元素进行比较,每一趟比较叫做一趟归并,二路归并排序递归过程的最底层(第一次)是两两进行比较,比较的趟数最多,每一趟都要进行外存的读写; 如果对每一次所做的比较,增加比较元素的个数(即增大k),就可以减少归并的趟数,减少外存读写,提高时间上的效率。但是随着k的增大,比较的次数也会增加,时间上的效率不再提高; 采用败者树,对待比较的分割后的小序列进行比较上的选择,可以让比较次数与k无关,从而真正提高效率。败者树在每一次对k个元素进行比较时都要创建,k个元素被写入k个叶子节点,
5.关于败者树
败者树是一个完全二叉树,它的作用是选出所有叶子节点中的最小者,过程如下:将叶子节点中的数据与它的兄弟比较,大的作为败者,记录在父亲节点中,小的作为胜者,上升到上一层进行下一次比较。最终的胜出者脱离二叉树(一般被保存在数组的第0位置,而根节点被保存在1位置),从而最小的叶子节点被筛选出来。在归并排序中,将k个序列的队首作为叶子节点,建立败者树,筛选出最小的叶子节点,保证了比较次数不会随k增加。

(二)快速排序算法
快排算法的思想是分而治之,具体的来说,是用数组的一个元素值作为分界,下标更小的元素值都小于或等于分界值,下标更大的元素都大于分界值,用两个下标分别(1)表示较小(或者相等)元素的最大下标,(2)表示尚未比较的元素的最小下标。下标(1)初始值是待排最小元素下标减一,下标(2)初始值是待排最小元素的下标。将最后一个元素值作为分界,从(2)下标处开始比较,小或等于则将更大元素区间的最小元素同新元素互换,然后(2)下标自增一,大于则(2)下标直接自增一;直到(2)比较了所有为比较的元素,然后将最后一个元素与(1)指向的元素互换,完成一次以最后元素为分界值的分割PARTITION(返回值是较小元素中的最大元素下标加一)。快速排序的完整步骤是对所有元素做一次分割后,再对两边的部分继续分割,直到递归结束。
QUICKSORT(A, p, r)
    if p < r
        q = PARTITION(A, p, r)
        QUICKSORT(A, p, q - 1)
        QUICKSORT(A, q + 1, r)
PARTITION(A, p, r)
    x = A[r]
    i = p - 1
    for j = p to r - 1
            if A[j] <= x
                      i = i + 1
                      switch(A[i], A[j])
    switch(A[i+1], )
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值