二叉树T:一个有穷的结点集合。 这个集合可以为空 若不为空,则它是由根结点和称为其左子树TL和右子树TR的 两个不相交的二叉树组成。
一、二叉树的几个重要性质
1、设二叉树的根结点为第一层,二叉树第i层的最大结点数是2i-1,i>=1;设二叉树的根结点深度为1,深度为k的二叉树,最大结点总数为2k-1,k>=1
(关于树的层、深度,上面是浙大数据结构的说法,也有定义根结点的层数为0,深度为0,从上向下增长;叶结点高度为0,从下向上增长。)
2、对于任何非空二叉树,叶子结点的个数,等于度为2的非叶子结点的个数+1,即n0 = n2 + 1
3、满二叉树(full binary trees),在树中,每个中间结点有且仅有两个孩子结点。
4、完全二叉树(complete binary trees),具有n个结点的完全二叉树的深度为log2n + 1
若对n个结点的完全二叉树从上到下且从左到右进行1至n编号,则对完全二叉树中任意一个编号为i的结点:
1、)若i = 1,则该结点是二叉树的根,无双亲结点,否则 i/2 的结点为其双亲结点;
2、)若2i<=n,则,编号为2i的结点为其左孩子结点,否则,该结点无左孩子结点;
3、)若2i+1<=n,则,编号为2i+1的结点为其右孩子结点,否则,该结点无右孩子结点;
二、二叉树的抽象数据类型定义
类型名称:二叉树
数据对象集:一个有穷的结点集合。 若不为空,则由根结点和其左、右二叉子树组成。
操作集: BT ∈ BinTree, Item ∈ ElementType,重要操作有:
1、Boolean IsEmpty( BinTree BT ): 判别BT是否为空;
2、void Traversal( BinTree BT ):遍历,按某顺序访问每个结点;
3、BinTree CreatBinTree( ):创建一个二叉树。
三、二叉树的存储结构
1、顺序存储结构
完全二叉树:按从上至下、从左到右顺序存储,n个结点的完全二叉树的结点父子关系: 非根结点(序号 i > 1)的父结点的序号是 i / 2; 结点(序号为 i )的左孩子结点的序号是 2i, (若2 i <= n,否则没有左孩子); 结点(序号为 i )的右孩子结点的序号是 2i+1, (若2 i +1<= n,否则没有右孩子);
一般二叉树也可以采用这种结构,但会造成空间浪费
2、链式存储结构
typedef int ElementType; typedef struct TreeNode *BinTree; typedef BinTree Position; struct TreeNode{ ElementType Data; BinTree Left; BinTree Right; };
四、设深度为d(只有一个根结点时,d为1)的二叉树只有度为0和2的结点,则此类二叉树的结点数至少为2d-1
d为1的时候,至少有1个,2*1 -1;
d为2的时候,没有度为1的点,情况为至少为3个 = 2*2 -1;
d大于2的时候,由于没有度为1的点,所以每增加一层,每层至少增加两个;
设d-1层的公式:2*(d -1) - 1,第d层的就是2*(d -1) - 1 +2,所以d层结点数至少为2*d - 1
五、二叉树构造
用先序序列或后序序列和中序序列可以构造唯一一棵二叉树,用扩充先序序列或扩充的后序序列可以构造唯一一棵二叉树(不同的二叉树可能具有相同的先序\中序\后序序列,因此,仅一个先、中、后序序列不能构造唯一一棵二叉树;用扩充中序序列不能构造唯一一棵二叉树)
1、后序序列+中序序列,构造一棵二叉树
1 /* 2 a数组存储树的后序序列, b数组存储中序序列 3 2 3 1 5 7 6 4 //a数组 4 1 2 3 4 5 6 7 //b数组 5 */ 6 7 BinTree BuildTree(int a[],int b[],int i,int j,int s,int e) 8 { /* i,j树的后序序列的起止, s,e树的中序序列的起止 */ 9 int k; 10 BinTree p; 11 if( i > j ) return NULL;//递归终止 12 13 p = NewNode(a[j]); /* 后序的根a[j]创建结点 */ 14 15 k = s; /* 寻找树根位置 */ 16 while( ( k <= e ) && ( b[k] != a[j] ) ) k++; 17 18 if( k > e ) exit(ERROR); 19 20 p->Left = BuildTree(a, b, i, i+(k-s)-1, s, k-1); /* 左子树 */ 21 p->Right = BuildTree(a, b, i+(k-s), j-1, k+1, e); /* 右子树 */ 22 23 /* 24 //a为先序序列, b为中序序列 25 p->Left = BuildTree(a, b, i+1, i+(k-s), s, k-1); 26 p->Right = BuildTree(a, b, i+(k-s)+1, j-1, k+1, e); 27 */ 28 return p; 29 }
2、扩充的先序序列构造二叉树,先序遍历二叉树时,如果当前要访问的结点不空,就记下这个结点值;如果为空,就记下“空”字所得 到的遍历序列,比如:A,B,D,0,H,0,0,E,0,I,0,0,C,F,0,0,G,J,0,K,0,0,0,
1 #include <stdio.h> 2 #include <malloc.h> 3 4 /* 二叉树结点结构体 */ 5 typedef char ElementType; 6 typedef struct TNode* BinTree; 7 struct TNode{ 8 ElementType Data; 9 BinTree Left; 10 BinTree Right; 11 }; 12 13 /* 创建结点 */ 14 BinTree NewNode(int x) 15 { 16 BinTree t = (BinTree)malloc(sizeof(struct TNode)); 17 t->Data = x; 18 t->Left = t->Right = NULL; 19 return t; 20 } 21 22 /* 扩充的先序序列构造二叉树 */ 23 BinTree PreCreate() 24 { 25 char ch; 26 scanf(" %c,",&ch); 27 /* 输入'0'符号即 NULL */ 28 if(ch=='0') 29 return NULL; 30 /* 根结点 */ 31 BinTree t = NewNode(ch); 32 /* 递归左右子树结点 */ 33 t->Left = PreCreate(); 34 t->Right = PreCreate(); 35 return t; 36 } 37 38 /* 先序遍历 */ 39 void PreorderTraversal( BinTree BT ){ 40 if(BT){ 41 printf("%5c",BT->Data); 42 PreorderTraversal(BT->Left); 43 PreorderTraversal(BT->Right); 44 } 45 } 46 /* A,B,D,0,H,0,0,E,0,I,0,0,C,F,0,0,G,J,0,K,0,0,0, */ 47 int main() 48 { 49 BinTree BT = PreCreate(); 50 PreorderTraversal(BT); 51 return 0; 52 }
来源:https://www.cnblogs.com/GoldenEllipsis/p/11315826.html