笔记
本节主要给出(二叉)堆的定义。堆是一种用数组保存的完全二叉树。完全二叉树的意思是,除了树的最底层,其他层都完全充满的。树中的元素按照从上到下、从左到右的顺序保存在数组中。下图给出了堆的一个例子,左图是完全二叉树的形式,右图是堆在数组中的表示。
如果用
表示堆所在的数组,那么
表示数组的容量,即数组最多可容纳的元素的个数;
表示堆中的元素个数。显然有
。树的根结点是元素
。
给定一个结点的下标
,根据下式可以得到它的父结点、左孩子和右孩子的下标:
以上3个公式成立的前提是数组下标从1开始,这是《算法导论》这部书的约定。我们写C/C++代码时,数组下标是从0开始的。在这种情况下,上面3个公式应当变为
二叉堆分两种:最大堆和最小堆。在最大堆中,除了根以外的所有结点
都要满足以下性质。即对于任意一棵子树,子树的根结点一定是子树的最大元素。
相反地,在最小堆中,除了根以外的所有结点
都要满足以下性质。即对于任意一棵子树,子树的根结点一定是子树的最小元素。
练习
6.1-1 在高度为
的堆中,元素个数最多和最少分别是多少?
解
高度为
的堆一共有
层。第一层有
个元素,第二层有
个元素,第三层有
个元素,以此类推。除最后一层外,第
层有
个元素。
最后一层为第
层,最少有
个元素,最多有
个元素。因此,高度为
的堆中,最少元素个数为
;而最多元素个数为
。
6.1-2 证明:含
个元素的堆的高度为
。
解
利用练习6.1-1的结论,高度为
的堆中元素最少有
个,最多有
个,即
。在
的这个取值范围内,必然有
。
6.1-3 证明:在最大堆的任一子树中,该子树所包含的最大元素在该子树的根结点上。
略
6.1-4 假设一个最大堆的所有元素都不相同,那么该堆的最小元素应该位于哪里?
解
最小元素可以位于任意一个叶子结点上。
6.1-5 一个已排好序的数组是一个最小堆吗?
解
如果一个数组已按升序排好序,那么它就是一个最小堆。如果数组按降序排序,那么它是一个最大堆。
6.1-6 值为<23, 17, 14, 6, 13, 10, 1, 5, 7, 12>的数组是一个最大堆吗?
解
如果画出二叉树,我们会发它并不是一个最大堆。
6.1-7 证明:当用数组表示存储
个元素的堆时,叶结点下标分别为
。
解
考虑最后一个结点,其下标为
,它的父结点
必然是最后一个非叶结点,而之后的结点必然都为叶结点。所以叶结点下标为
。