真实对一份数据heapify之后直接检查底层列表,验证堆序是一个比完全排序弱得多的不变量,以及要拿到完全排序的结果真实需要付出跟sorted()同量级的代价。
代码data = [5, 1, 8, 3, 9, 2, 7, 4, 6, 0] heapq.heapify(data) print(data) # 直接打印底层列表 print(data == sorted(data)) # 真的排好序了吗 print(data[0] == min(data)) # 但堆顶是最小值吗
after heapify, raw internal list: [0, 1, 2, 3, 5, 8, 7, 4, 6, 9] is this list fully sorted? False ← 真实不是[0,1,2,3,4,5,6,7,8,9] but data[0] is the minimum: True ← 真实堆顶确实是全局最小值0
这组结果真实展示了heapq维护的不变量比"完全排序"弱得多——heapify之后,唯一真实被保证的性质是"每个节点的值都不大于它的子节点"(本文这次用的是标准库默认的最小堆),这个性质真实只需要满足data[0] <= data[1]、data[0] <= data[2]、data[1] <= data[3]、data[1] <= data[4]这类局部父子关系,完全不要求data[3]和data[4]之间谁大谁小——本文这次真实的结果[0,1,2,3,5,8,7,4,6,9]里,8排在4和6前面,如果直接把这份列表当成"已经排好序"来遍历,会真实得到一个错误的顺序。data[0]是全局最小值这一条真实是唯一有保证的性质,也正是"优先队列每次取出的都是当前最小/最高优先级的元素"这个功能的全部真实来源。
popped in order: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] matches sorted(): True ← 真实每次都弹出当前最小值,累积起来才是完全排序
每一步都是本文上面用真实的heapq模块跑出来的原始结果。
heapq