• 啊哈算法--堆排序 (python)


    向下调整

    在·一个最下根堆中,如果将堆顶的元素删除并新增一个数,那么此时就不再符合最小根堆的性质了,因此这个时候就需要将这个数进行向下调整的操作,直到找到合适位置为止。

    向下调整代码如下:

    1. # 向下调整代码,初始堆h为小根堆
    2. def siftdown(i): # 从堆的i结点开始向下调整, 注意i结点的子结点为2*i和2*i+1
    3. global t
    4. flag = 0 # 用于判断是否需要向下调整
    5. while i*2 <= n and flag == 0:
    6. if h[i] > h[2*i]: # 首先判断它与左孩子的关系, 并用t记录较小的节点编号
    7. t = 2*i
    8. else:
    9. t = i
    10. if i*2+1 <= n:
    11. if h[t] > h[2*i+1]: # 如果有右孩子,且右孩子更小,更新较小的值
    12. t = 2*i + 1
    13. if t != i: # 如果最小结点不是自己本身, 说明子结点中有比父结点更小的值
    14. h[t], h[i] = h[i], h[t] # 进行交换
    15. i = t # 从t开始继续向下调整
    16. else: # 否则不需要进行向下调整了,因为子结点中没有比父结点更小的值
    17. flag = 1

    向上调整

    有向下调整的操作那么就有向上调整的操作:

    向上调整代码如下:

    1. # 向上调整代码, 初始堆h为小根堆 ,
    2. def siftup(i): # i的父节点为i//2
    3. flag = 0 # 用于判断是否需要向上调整
    4. if i == 1:
    5. return # 如果i结点为堆顶,就不能继续往上调整了
    6. while i!=1 and flag == 0:
    7. if h[i] < h[i//2]:
    8. h[i], h[i//2] = h[i//2], h[i]
    9. else:
    10. flag = 1
    11. i = i//2

    堆的创建

    • 利用向下调整的操作进行堆的创建

    利用向下调整的操作进行堆的创建我们可以从最后一个非叶子结点(n//2)开始到根结点(1),逐个扫描所有结点,根据需要将当前向下调整。该算法的时间复杂度为O(n)

    1. # 创建堆
    2. def create():
    3. # 从最后一个叶子结点依次向下调整
    4. for s in range(n//2,0,-1):
    5. siftdown(s)
    6. return
    • 利用向上调整的操作进行堆的创建

    利用向上调整的操作进行堆的创建,可以直接从结点1到n依次向上调整,该算法的时间复杂度为O(NlogN)。

    1. # 创建堆2 从空堆开始,然后依次往推中插入每个元素
    2. def create2():
    3. for s in range(1,n+1):
    4. siftup(s)

    堆排序

    堆排序的原理:

    1. 建立小根堆
    2. 每次删除堆顶元素作为输出或者放入一个新的数组中,直到堆为空为止。
    1. # 删除堆顶的元素
    2. def removetop():
    3. global n
    4. t = h[1]
    5. h[1] = h[n]
    6. n -= 1
    7. siftdown(1)
    8. return t

    完整代码

    1. h = [0 for _ in range(101)]
    2. n = 0
    3. # 向下调整代码,初始堆h为小根堆
    4. def siftdown(i): # 从堆的i结点开始向下调整, 注意i结点的子结点为2*i和2*i+1
    5. global t
    6. flag = 0 # 用于判断是否需要向下调整
    7. while i*2 <= n and flag == 0:
    8. if h[i] > h[2*i]: # 首先判断它与左孩子的关系, 并用t记录较小的节点编号
    9. t = 2*i
    10. else:
    11. t = i
    12. if i*2+1 <= n:
    13. if h[t] > h[2*i+1]: # 如果有右孩子,且右孩子更小,更新较小的值
    14. t = 2*i + 1
    15. if t != i: # 如果最小结点不是自己本身, 说明子结点中有比父结点更小的值
    16. h[t], h[i] = h[i], h[t] # 进行交换
    17. i = t # 从t开始继续向下调整
    18. else: # 否则不需要进行向下调整了,因为子结点中没有比父结点更小的值
    19. flag = 1
    20. # 向上调整代码, 初始堆h为小根堆 ,
    21. def siftup(i): # i的父节点为i//2
    22. flag = 0 # 用于判断是否需要向上调整
    23. if i == 1:
    24. return # 如果i结点为堆顶,就不能继续往上调整了
    25. while i!=1 and flag == 0:
    26. if h[i] < h[i//2]:
    27. h[i], h[i//2] = h[i//2], h[i]
    28. else:
    29. flag = 1
    30. i = i//2
    31. # 删除堆顶的元素
    32. def removetop():
    33. global n
    34. t = h[1]
    35. h[1] = h[n]
    36. n -= 1
    37. siftdown(1)
    38. return t
    39. # 创建堆
    40. def create():
    41. # 从最后一个叶子结点依次向下调整
    42. for s in range(n//2,0,-1):
    43. siftdown(s)
    44. return
    45. # 创建堆2 从空堆开始,然后依次往推中插入每个元素
    46. def create2():
    47. for s in range(1,n+1):
    48. siftup(s)
    49. if __name__ == '__main__':
    50. num = int(input())
    51. n = num
    52. for i in range(1,num+1):
    53. h[i] = int(input())
    54. create2()
    55. for i in range(1, num + 1):
    56. print(h[i], end=' ')
    57. print()
    58. for _ in range(1,num+1):
    59. print(removetop(), end = ' ')

  • 相关阅读:
    2530. 执行 K 次操作后的最大分数
    QT发送Get请求并返回内容
    git方面的知识
    debian/ubuntu/linux如何快速安装vscode
    VoLTE基础自学系列 | VoLTE呼叫流程之VoLTE及PSTN
    读《高性能MySQL》笔记---MySQL架构
    通过WSL在阿里云上部署Django项目MySQL
    Smallest number(dfs全排列)
    【13】加法器:如何像搭乐高一样搭电路(上)?
    全面总结 Vue 3.0 的新特性!手把手教你如何入门Vue3.0(适合小白的保姆级教程)【尚硅谷vuejs3.0笔记】
  • 原文地址:https://blog.csdn.net/qq_43211230/article/details/125427013