二叉树的几个重要性质、抽象数据类型定义、存储结构、构造

眉间皱痕 提交于 2020-04-01 08:32:06

  二叉树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 }
扩充先序序列构造二叉树

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!