数据结构--二叉堆

二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。示意图如下:

二叉堆一般都通过"数组"来实现。数组实现的二叉堆,父节点和子节点的位置存在一定的关系。有时候,我们将"二叉堆的第一个元素"放在数组索引0的位置,有时候放在1的位置。当然,它们的本质一样(都是二叉堆),只是实现上稍微有一丁点区别。
假设"第一个元素"在数组中的索引为 0 的话,则父节点和子节点的位置关系如下:
(01) 索引为i的左孩子的索引是 (2*i+1);
(02) 索引为i的右孩子的索引是 (2*i+2);
(03) 索引为i的父结点的索引是 floor((i-1)/2);

假设"第一个元素"在数组中的索引为 1 的话,则父节点和子节点的位置关系如下:
(01) 索引为i的左孩子的索引是 (2*i);
(02) 索引为i的右孩子的索引是 (2*i+1);
(03) 索引为i的父结点的索引是 floor(i/2);

二、二叉堆的操作

堆一般使用数组来构建,假设为数组a[],结点通常存储在a[1],这样对于下标为k的结点a[k]来说,其左孩子的下标为2*k,右孩子的下标为2*k+1。

1、插入结点到堆中.

由于小根堆是由数组实现的完全二叉树,所以插入的位置应该是完全二叉树的最后一个位置(如下图所示),对于小根堆来讲,需要满足两个性质:(1)堆为完全二叉树;(2)堆中每个结点的值都不大于其左右结点的值。插入结点可能会破坏这两条性质,所以在插入结点后需要对堆进行调整。调整方法为:将插入的结点与其父结点比较,若小于其父结点的值,则交换两者。重复此操作,直至该结点不比其父结点小,或者该结点成为根结点。可以通过插入结点到一个已经存在的堆中,也可以通过不断插入结点来构建一个堆。

 

2、删除堆顶元素(堆排序)

删除堆顶元素(根结点)后,会得到左右两棵子树,此时将堆中最后一个元素移到堆顶,然后自上而下调整,将该结点与左右孩子结点比较,此时会有三种情况:

(1)结点的左右孩子均为空,此时调整结束;

(2)结点只有左孩子,此时将该结点与其左孩子比较。若结点大于其左孩子,则两者交换,否则调整结束;

(3)结点左右孩子都非空,则将该结点与左右孩子之间的较小者比较,若小于则交换,否则调整结束;

重复此过程,直到该结点不大于其左右孩子结点,或者该结点为叶子结点。

猜你喜欢

转载自www.cnblogs.com/277223178dudu/p/11452294.html