• 堆是一种二叉树,通常是一棵完全二叉树,其中所有节点均满足如下性质: 任意一个节点的值都大于等于其任意一个子节点的值.又称大根堆, 小根堆则是任意一个节点的值都小于等于其任意一个子节点的值。

    堆的表示

    可以用链表或者数组表示堆,要保证堆的平衡,用数组表示,如果将序列{k1,k2,.....kn}表示为一维数组A[n],则序列中元素的下表与数组中下标一致。即数组中下标为0的位置不存放数据元素,此时堆是一棵完全二叉树,节点k[j]对应的子节点分别是k[2*j]与k[2*j+1],除叶子节点外,任意节点都有左右子节点,即使没有值

    堆的初始化

    给定一个数组A[n],生成堆

    • 插入法:依次调用堆的插入算法插入数组中的每一个元素
    • 调整法:将数组视为一棵完全二叉树,从最后一个有子节点的节点到根节点依次执行下沉操作。根节点调整完后整棵树就变成了一个堆.  最后一个有子节点的节点是 A[n/2], 它的子节点是A[n],A[n/2]后的所有节点都是子节点

    clipboardclipboard[1]

    clipboard[2]

    堆中删除最大值的算法

    根据堆的性质,堆中最大值的节点是根节点A[1],因此总是删除根节点。接下来是如何调整堆.

    • 删除叶子节点A[n],然后把它的值x放到原先根节点的位置。
    • 不断的将x向树的下方移动,直到它到达某棵子树或叶子节点,这棵子树种x是最大值,这样整棵树便满足了堆的性质
    • 移动的方式是,将x与左右子节点的最大值比较,x小于最大值则与该节点交换

    最大比较次数是2lbn

    删除堆中任意值也是同理:

    clipboard[3]

    堆中插入元素

    • 首先将数组增大1,在数组最后插入新值,作为新的叶子节点
    • 比较这个新的叶子节点及其父节点,如果大于父节点的值则交换两个节点。
    • 直到它的值小于父节点或者到达根节点结束

    最大比较次数是lbn,恰好是树的高度

    clipboard[4]

    堆排序

    基本思想:

    • 将初始待排序关键字序列(R1,R2....Rn)构建成大根堆,此堆对应的数组为无序状态
    • 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
    • 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成

    源代码
  • 相关阅读:
    【JAVA】日志管理slf4j
    【JAVA】从java线程来看java内存模型
    【数据结构】---栈和队列
    【数据结构】---链表
    C++ 第10章 反省程序与C++标准模板库
    回忆C++知识点(1)
    C++ 第8章 多态性
    C++ 第7章 继承与派生
    C++ 第6章 数组、指针、字符串
    C++ 第5章 数据的共享与保护
  • 原文地址:https://www.cnblogs.com/phenixyu/p/5399211.html
Copyright © 2020-2023  润新知