二叉树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
