-
二叉树的定义
1)每个节点最多只有两颗子树,即二叉树中结点的度只能为0、1、2;
2)子树有左右之分,不能颠倒。二叉树的五种基本状态:
1)空二叉树
2)只有根节点
3)只有左子树,右子树为空
4)只有右子树,左子树为空
5)既有左子树,又有右子树满二叉树: 所有的分支结点都有左孩子和右孩子结点,并且叶子结点都集中在二叉树的最下一层
完全二叉树: 通俗的说,一颗完全二叉树一定是由一颗满二叉树从右至左从下至上,挨个删除结点所得到的。 -
二叉树的主要性质
-
性质1: 非空二叉树上叶子结点数等于双分支结点数加1. 即:n0=n2+1
推导过程 根据两个公式(n0表示度数为0的节点 n2表示度数为2的节点)
1)n=n0+n1+n2 n表示二叉树中的节点总个数,n1表示度数为1的节点个数
2)n-1=2n2+n1 通过观察二叉树我们可知,除了根节点之外,其余的任何节点都有一个入口分支,那么节点的总分支数等于节点个数减一。度数为2的节点有2个出口分支,度数为一的有1个出口分支,度数为0的节点没有出口分支 所以总的分支个数为 2n2+n1 -
性质2: 二叉树的第i层上最多有2^(i-1)个结点
-
性质3: 高度(或深度)为k的二叉树最多有2^k-1个结点(k>=1)
-
性质4: 有n个结点的完全二叉树,对各结点从上到下、从左到右依次编号(范围为1~n),各节点之间有如下关系:
(1) 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 [i/2] 的结点为其双亲结点;
(2) 若 2i>n,则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;
(3) 若 2i+1>n,则该结点无右孩子结点, 否则,编号为2i+1 的结点为其右孩子结点。 -
性质5: 具有n个结点的完全二叉树的高度(或深度)为[log2n]+1,其中[log2n]是向下取整。
-
-
二叉树的存储结构
-
顺序存储
顺序存储结构即用一个数组来存储一个二叉树,这种存储方式最适合于存储完全二叉树,而用于存储一个非完全二叉树则会浪费很多空间。
将这种存储结构要求数组下标从1开始存储树中的结点,这样下标就可以表示二叉树中结点的编号(如性质中所说,从上到下、从左到右编号为1~n),而数组中的内容表示结点的内容。这样,结点之间的关系就可以用下标来表示,下标满足性质4。如下图中的完全二叉树,假设数组为a,如果已知结点A的下标为1,要想访问其左子结点B,只需直接访问a[1*2]即可。类似的,如果已知某结点编号为i,要想访问其右子结点,如果2i+1不大于n,则其右子结点为a[2i+1]。
-
二叉树的顺序存储与树的顺序存储
需要注意的是,树的顺序存储结构与二叉树的顺序存储结构的区别。在树的存取结构中下标表示的是结点的编号(这点与二叉树相同),不同是下标上所指的内容,在前边我们说过树的顺序存储中,数组中的内容表示的是其双亲结点的位置,也就是树结点之间的关系;而在二叉树的顺序存储中我们的下标虽然也是结点的编号,但同时也可以用编号找到其子结点或双亲结点,而数组的内容表示的是结点保存的内容。也就是说二叉树的顺序存储中,数组的下标既表示结点的编号,也指示了结点间的关系。#define Maxsize 100 //假设一维数组最多存放100个元素 typedef char Datatype; //假设二叉树元素的数据类型为字符 typedef struct { Datatype bt[Maxsize]; int btnum; }Btseq;
-
链式存储
链式存储是我们在树和二叉树的存储中最常见的存储结构,即对于每个结点用一个链结点来存放,结点内容包括结点的数据域和两个指针域,其中指针分别指向其左子结点和右子结点。其他这里就不多赘述了。以下为结点的类型定义:
struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight; };
以上,参考文章二叉树的存储结构.
-