‘壹’ 完全二叉树的完全二叉树特点
叶子结点只可能在最大的两层上出现,对任意结点,若其右分支下的子孙最大层次为L,则其左分支下的子孙的最大层次必为L 或 L+1;
出于简便起见,完全二叉树通常采用数组而不是链表存储,其存储结构如下:
var tree:array[1..n]of longint;{n:integer;n>=1}
对于tree[i],有如下特点:
(1)若i为奇数且i>1,那么tree的左兄弟为tree[i-1];
(2)若i为偶数且i<n,那么tree的右兄弟为tree[i+1];
(3)若i>1,tree的双亲为tree[i div 2];
(4)若2*i<=n,那么tree的左孩子为tree[2*i];若2*i+1<=n,那么tree的右孩子为tree[2*i+1];
(5)若i>n div 2,那么tree[i]为叶子结点(对应于(3));
(6)若i<(n-1) div 2.那么tree[i]必有两个孩子(对应于(4))。
(7)满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。
完全二叉树第i层至多有2^(i-1)个节点,共i层的完全二叉树最多有2^i-1个节点。
完全二叉树的特点是:
1)只允许最后一层有空缺结点且空缺在右边,即叶子结点只能在层次最大的两层上出现;
2)对任一结点,如果其右子树的深度为j,则其左子树的深度必为j或j+1。 即度为1的点只有1个或0个
‘贰’ 顺序存储是二叉树常用的存储结构吗
二叉树的存储结构
二叉树是非线性结构,即每个数据结点至多只有一个前驱,但可以有多个后继。它可采用顺序存储结构和链式存储结构。
1.顺序存储结构
二叉树的顺序存储,就是用一组连续的存储单元存放二叉树中的结点。因此,必须把二叉树的所有结点安排成为一个恰当的序列,结点在这个序列中的相互位置能反映出结点之间的逻辑关系,用编号的方法从树根起,自上层至下层,每层自左至右地给所有结点编号,缺点是有可能对存储空间造成极大的浪费,在最坏的情况下,一个深度为k且只有k个结点的右单支树需要2k-1个结点存储空间。依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映出结点之间的逻辑关系,这样既能够最大可能地节省存储空间,又可以利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。图5-5(a)是一棵完全二叉树,图5-5(b)给出的图5-5(a)所示的完全二叉树的顺序存储结构。
(a) 一棵完全二叉树 (b) 顺序存储结构
图5-5 完全二叉树的顺序存储示意图
对于一般的二叉树,如果仍按从上至下和从左到右的顺序将树中的结点顺序存储在一维数组中,则数组元素下标之间的关系不能够反映二叉树中结点之间的逻辑关系,只有增添一些并不存在的空结点,使之成为一棵完全二叉树的形式,然后再用一维数组顺序存储。如图5-6给出了一棵一般二叉树改造后的完全二叉树形态和其顺序存储状态示意图。显然,这种存储对于需增加许多空结点才能将一棵二叉树改造成为一棵完全二叉树的存储时,会造成空间的大量浪费,不宜用顺序存储结构。最坏的情况是右单支树,如图5-7 所示,一棵深度为k的右单支树,只有k个结点,却需分配2k-1个存储单元。
(a) 一棵二叉树 (b) 改造后的完全二叉树
(c) 改造后完全二叉树顺序存储状态
图5-6 一般二叉树及其顺序存储示意图
(a) 一棵右单支二叉树 (b) 改造后的右单支树对应的完全二叉树
(c) 单支树改造后完全二叉树的顺序存储状态
图5-7 右单支二叉树及其顺序存储示意图
结构5-1二叉树的顺序存储
#define Maxsize 100 //假设一维数组最多存放100个元素
typedef char Datatype; //假设二叉树元素的数据类型为字符
typedef struct
{ Datatype bt[Maxsize];
int btnum;
}Btseq;
2.链式存储结构
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。
通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。其结点结构为:
其中,data域存放某结点的数据信息;lchild与rchild分别存放指向左孩子和右孩子的指针,当左孩子或右孩子不存在时,相应指针域值为空(用符号∧或NULL表示)。利用这样的结点结构表示的二叉树的链式存储结构被称为二叉链表,如图5-8所示。
(a) 一棵二叉树 (b) 二叉链表存储结构
图5-8 二叉树的二叉链表表示示意图
为了方便访问某结点的双亲,还可以给链表结点增加一个双亲字段parent,用来指向其双亲结点。每个结点由四个域组成,其结点结构为:
这种存储结构既便于查找孩子结点,又便于查找双亲结点;但是,相对于二叉链表存储结构而言,它增加了空间开销。利用这样的结点结构表示的二叉树的链式存储结构被称为三叉链表。
图5-9给出了图5-8 (a)所示的一棵二叉树的三叉链表表示。
图5-9二叉树的三叉链表表示示意图
尽管在二叉链表中无法由结点直接找到其双亲,但由于二叉链表结构灵活,操作方便,对于一般情况的二叉树,甚至比顺序存储结构还节省空间。因此,二叉链表是最常用的二叉树存储方式。
结构5-2二叉树的链式存储
#define datatype char //定义二叉树元素的数据类型为字符
typedef struct node //定义结点由数据域,左右指针组成
{ Datatype data;
struct node *lchild,*rchild;
}Bitree;
‘叁’ 什么样的二叉树适合用数组存储
完全二叉树适合用数组存储,它在使用时可以没有存储单元的浪费。
‘肆’ 完全二叉树为什么最适合顺序存储结构
顺序存储充分利用满二叉树的特性,即每层的节点数分别为1、2、4、8等等2i+1,一个深度为i的二叉树最多只能包含2i-1个节点,因此只要定义一个长度为2i-1的数组即可存储这颗二叉树。
对于普通的不是满二叉树的,那些空出来的节点对应的数组元素留空即可,因此顺序存储会造成一定的空间浪费。如果是完全二叉树,就不会有空间浪费的情况;若是只有右子树,那么会造成相当大的浪费。
二叉树算法思路:
1、如果树为空,则直接返回错。
2、如果树不为空:层序遍历二叉树。
3、如果一个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列。
4、如果遇到一个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树。
5、如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点;该树才是完全二叉树,否则就不是完全二叉树。
‘伍’ 二叉树的存储方式有哪些
二叉树的存储方式通常有动态存储。用结构体表示二叉树的一个节点。用数据域保持保存节点的值,用链接语保存两个孩子的指针。还有就是采用满二叉树的顺序存储方式。
‘陆’ 什么是二叉树的顺序存储
二叉树的顺序存储是将二叉树的所有结点,按照一定的次序,存储到一片连续的存储单元中
二叉树的顺序存储必须将结点排成一个适当的线性序列,使得结点在这个序列中的相应位置能反映出结点之间的逻辑关系。这种结构特别适用于近似满二叉树。
在一棵具有n个结点的近似满二叉树中,当从树根起,自上层到下层,逐层从左到右给所有结点编号时,就能得到一个足以反映整个二叉树结构的线性序列。其中每个结点的编号就作为结点。
(6)满二叉树数组是最合适的存储方式扩展阅读:
二叉树的性质:
1、二叉树第i层上的结点数目最多为2{i-1}(i≥1)。
2、深度为k的二叉树至多有2{k}-1个结点(k≥1)。
3、包含n个结点的二叉树的高度至少为log2(n+1)。
4、在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。
参考资料来源:网络-二叉树
‘柒’ 完全二叉树的顺序存储
选C。
要简单的你就画个图。要复杂的请见严蔚敏老师的《数据结构(C语言版)》124页倒数第5行到125页最后一行。
‘捌’ 完全二叉树用什么数据结构实现最合适,为什么
一般的二叉树用带有两个指向自身结构类型变量的指针的多个结构体组成最合适。
如果该二叉树不会变化,可以用数组实现,每个数组元素表示一个节点,因为是完全的,所以长度一定是2的n次方-1,n为树的深度,也可以很方便地算出某个元素与树根节点、父节点等的关系,因此不用指针反而可以减少存储开销及查询效率。
‘玖’ 满二叉树和完全二叉树按什么进行顺序存储
可以按层序进行顺序存储。
‘拾’ 数组不适合作为任何二叉树的存储结构
这话不对,数组可以用来存储一棵满二叉树,也可以用它存储普通的二叉树(会浪费一些存储空间),还可以以下标形式模拟链式存储任意的二叉树(用表示下标的数字来代替lchild和rchild指针)。