堆排序——python

  1. 前面了解了堆概念,接下来看下堆排序的思想:(以大根堆为例):
    step1: 首先将待排序的数组构造出一个大根堆
    step2: 取出这个大根堆的堆顶节点(最大值),与堆的最下最右的元素进行交换,然后把剩余的元素再构造一个大根堆
    step3: 重复第二步,直到这个大根堆长度为1,完成排序
  2. 现在的关键问题是如何实现上述的算法,课本上直接使用了库函数,很方便,简洁,体现了python编程的优势,可以采用。但是我们想着自己整理一遍思路。
  3. 开始自己编写,首先待排序的数组是:A = [50, 16, 30, 10, 60, 90, 2, 80, 70],二叉树表示如下图:
    在这里插入图片描述
  4. 接下来执行step1,构造最大堆,调用我们已经设计的,上节课讲过的函数即可,结果是:After heap, the list is [0, 90, 80, 50, 70, 60, 30, 2, 10, 16]
  5. 接下来执行step2,取出最大的,和最下最右的元素交换,为了方便就采用循环吧,记住从右到左,从下到上的顺序,交换之后的序列为:After swap, the list is:[0, 16, 80, 50, 70, 60, 30, 2, 10, 90],最后一个元素可以从堆中删除了,然后堆剩余的元素The initial seq is [0, 16, 80, 50, 70, 60, 30, 2, 10]:,此时堆成了这样子的:
    在这里插入图片描述
    对上面剩余的元素继续最大堆操作,序列为:Remain elements are build heap as:[0, 80, 70, 50, 16, 60, 30, 2, 10],对应图为:
    在这里插入图片描述
  6. 接下来继续重复执行上面的step2,也就是把80和10交换,等等等等,就不用废话讲了吧,直到遍历完整个序列为止,最后输出的排序后的序列为:[2, 10, 16, 30, 50, 60, 70, 80, 90]
  7. 上王道,代码的干活:
class BinHeap:
    def __init__(self):
        self.heapList = [0]
        self.currentSize = 0
    def max_heapify_rec(self, i):
        if (i * 2) <= self.currentSize:
            mc = self.maxChild(i)
            if self.heapList[i] < self.heapList[mc]:
                tmp = self.heapList[i]
                self.heapList[i] = self.heapList[mc]
                self.heapList[mc] = tmp
                #print("%d-th -> %d-th node, seq is:%s" % (i, mc, self.heapList))
                self.max_heapify_rec(mc)

    def maxChild(self, i):
        leftchild = i * 2
        rightchild = i * 2 + 1
        if leftchild <= self.currentSize and self.heapList[leftchild] > self.heapList[i]:
            largest = leftchild
        else:
            largest = i
        if rightchild <= self.currentSize and self.heapList[rightchild] > self.heapList[largest]:
            largest = rightchild
        return largest
    def buildHeap(self, alist):
        mid = len(alist) // 2
        self.currentSize = len(alist)
        self.heapList = [0] + alist[:]
        print("The initial seq is %s:" % self.heapList)
        while (mid > 0):
            self.max_heapify_rec(mid)
            mid = mid - 1
        return self
    
def heap_sort(A):
    bh = BinHeap()
    bh = bh.buildHeap(A) #把序列A调整为一个大根堆
    temp = bh.heapList
    print('After heap, the list is %s' % temp)
    outlist = [] #存放删除的节点,其实就是排好序的序列了
    for i in range(len(temp) - 1): #把堆顶元素和堆末尾的元素交换,然后把剩余的元素调整为一个大根堆
        temp[1], temp[-1] = temp[-1], temp[1]
        print('After swap, the list is:%s' % temp)
        del temp[0] #删除开始的占位符0
        outlist.append(temp[-1])
        del temp[-1] #删除最后一个元素
        bh = bh.buildHeap(temp)
        temp = bh.heapList
        print('Remain elements are build heap as:%s' % temp)

    return reversed(outlist)

A = [50, 16, 30, 10, 60, 90, 2, 80, 70]
print(list(heap_sort(A)))
  1. 还有比较新颖的做法,思路一样一样滴,就不废话了,上王道:
from collections import deque


def swap_param(L, i, j):
    L[i], L[j] = L[j], L[i]
    return L


def heap_adjust(L, start, end):
    temp = L[start]

    i = start
    j = 2 * i

    while j <= end:
        if (j < end) and (L[j] < L[j + 1]):
            j += 1
        if temp < L[j]:
            L[i] = L[j]
            i = j
            j = 2 * i
        else:
            break
    L[i] = temp


def heap_sort(L):
    L_length = len(L) - 1

    first_sort_count = L_length / 2
    for i in range(first_sort_count):
        heap_adjust(L, first_sort_count - i, L_length)

    for i in range(L_length - 1):
        L = swap_param(L, 1, L_length - i)
        heap_adjust(L, 1, L_length - i - 1)

    return [L[i] for i in range(1, len(L))]


def main():
    L = deque([50, 16, 30, 10, 60,  90,  2, 80, 70])
    L.appendleft(0)
    print heap_sort(L)


if __name__ == '__main__':
    main()
  1. 教材上也有个好玩的,用库函数实现,看起来超级简单:
import heapq
def heapsort(alist):
    sortedh = []
    heapify(alist)
    while alist:
        sortedh.append(heappop(alist))
    return sortedh
from heapq import heappop, heapify
A = [90, 50, 80, 16, 30, 60, 70, 10, 2]
K = heapsort(A)
print(K)

10.总结:实现一个功能要多想想算法的思路,思路正确,代码写出来还是比较简单的,博客上面备课太累了,要写太多东东了,以后继续坚持把,虽然浪费时间,但是对大家学习应该很有帮助,这个比PPT应该实用多了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值