北京看白癜风比较好专科医院 https://wapjbk.39.net/yiyuanzaixian/bjzkbdfyy/jxxbdf/完全二叉树的定义、性质以及算法见正文,这里补充一点:完全二叉树是效率很高的数据结构,堆是一种完全二叉树或者近似完全二叉树,所以效率极高,像十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能优化,几乎每次都要考到的二叉排序树的效率也要借助平衡性来提高,而平衡性基于完全二叉树。
1判断完全二叉树
完全二叉树:除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。
2完全二叉树定义
完全二叉树(CompleteBinaryTree)
若设二叉树的深度为h,除第h层外,其它各层(1~h-1)的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树。
3完全二叉树特点
叶子结点只可能在最大的两层上出现,对任意结点,若其右分支下的子孙最大层次为L,则其左分支下的子孙的最大层次必为L或L+1;
出于简便起见,完全二叉树通常采用数组而不是链表存储,其存储结构如下
/p>
tree[n]:int{tree[0],tree[1]...tree[n-1]}
对于tree,有如下特点:
(1)若i为奇数且i1,那么tree的左兄弟为tree[i-1];
(2)若i为偶数且in,那么tree的右兄弟为tree[i+1];
(3)若i1,tree的双亲为tree[idiv2];
(4)若2*i=n,那么tree的左孩子为tree[2*i];若2*i+1=n,那么tree的右孩子为tree[2*i+1];
(5)若indiv2,那么tree为叶子结点(对应于(3));
(6)若i(n-1)div2.那么tree必有两个孩子(对应于(4))。
(7)满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。
完全二叉树第i层至多有2^(i-1)个节点,共i层的完全二叉树最多有2^i-1个节点。
4算法
如果一棵具有n个结点的深度为k的二叉树,它的每一个结点都与深度为k的满二叉树中编号为1~n的结点一一对应,这棵二叉树称为完全二叉树。
可以根据公式进行推导,假设n0是度为0的结点总数(即叶子结点数),n1是度为1的结点总数,n2是度为2的结点总数,由二叉树的性质可知:n0=n2+1,则n=n0+n1+n2(其中n为完全二叉树的结点总数),由上述公式把n2消去得:n=2n0+n1-1,由于完全二叉树中度为1的结点数只有两种可能0或1,由此得到n0=(n+1)/2或n0=n/2。
总结起来,就是n0=[n/2],其中[]表示上取整。可根据完全二叉树的结点总数计算出叶子结点数。
5小根堆
小根堆一般指最小堆
堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。(注意,这里对同兄弟结点没有要求)
最大堆和最小堆是二叉堆的两种形式。
最大堆:根结点的键值是所有堆结点键值中最大者。
最小堆:根结点的键值是所有堆结点键值中最小者。
而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。
最大-最小堆是最大层和最小层交替出现的二叉树,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。
以最大(小)层结点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。
6原理过程
如何建立这个堆呢。可以从空的堆开始,然后依次往堆中插入每一个元素,直到所有数都被插入(转移到堆中为止)。因为插入第i个元素的所用的时间是O(logi),所以插入所有元素的整体时间复杂度是O(NlogN),
其实我们还有更快得方法来建立堆。它是这样的。
直接把整数放入一个完全二叉树中(这里我们还是用一个一维数组来存储完全二叉树),然后通过直接的堆调整来完成排序,如下图(注:这里的图片来自哈工大李建中《算法设计与分析》课件)
现在要完成6个整数{6,5,14,7,8,1}的大根堆排序;
这里左侧是建立完全二叉树,然后调整为大根堆结构;开始的位置是第一个非叶节点及其子节点;
上图是要排序时,将大根堆的根节点(这里是14)从二叉树中去掉,然后用最后一个叶子节点(这里是1)填充,变成了上图左侧的结构,然后再调整为大根堆,就是上图右侧二叉树;
下面几幅图操作相同.
通过这个例子不难看出,主要思想是将大根堆的堆顶取出,放到数组的最后一个位置,将最后一个位置原来的数放到堆顶,然后对堆顶做调整;