二叉树知识点

1、定义

二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集,或者由一个根节点和两棵互不相关的、分别称为左子树和右子树的二叉树组成。

2、二叉树的特点

a、每个结点最多有两棵子树,所以二叉树不存在度大于1的结点

b、左子树和右子树是有顺序的,次序不能任意颠倒

c、即使某个结点只有一棵子树,也要区分是左子树还是右子树

3、二叉树的基本形态

1、定义

二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集,或者由一个根节点和两棵互不相关的、分别称为左子树和右子树的二叉树组成。

2、二叉树的特点

a、每个结点最多有两棵子树,所以二叉树不存在度大于1的结点

b、左子树和右子树是有顺序的,次序不能任意颠倒

c、即使某个结点只有一棵子树,也要区分是左子树还是右子树


3、二叉树的基本形态

4、二叉树的性质

  1. 在二叉树的第i层最多有2i-1个结点(i>=1)
  2. 深度为k的二叉树至多有2k-1个结点(k>=1)
  3. 任何一棵二叉树,其叶子节点与度为2的结点之间的关系是n0=n2+1
  4. 具有n个结点的完全二叉树的深度为[log2n]+1([]表示向下取整)
  5. 一棵有n个结点的完全二叉树,对任一结点i有:

如果i=1,则结点i为二叉树的根节点,否则其双亲的结点为[i/2]

如果2i>n,则结点i无左孩子,否则其左孩子是结点2i

如果2i+1>n,则结点i无右孩子,否则其右孩子为2i+1

5、二叉树的存储

  1. 顺序存储结构—一维数组

下标:

1

2

3

4

5

6

7

8

9

 

A

B

C

Ʌ

E

F

Ʌ

Ʌ

J

Ʌ表示不存在的结点

  1. 二叉链表

lchild

data

rchild

data为数据域,lchild和rchild为指针域,分别指向左右孩子指针

二叉链表的结构定义代码:

//二叉树的二叉链表结点结构定义

typedef int TElemType; //树结点的数据类型,目前暂定为整型

typedef struct BiTNode   //结点结构

{

        TElemType data;

        struct BiTNode *rchild, *lchild;

} BiTNode, *BiTree;

6、二叉树的遍历

把树中的结点变成某种意义上的线性序列

   前序遍历                      中序遍历                      后序遍历                     层序遍历

//前序遍历递归算法  先双亲再左再右

void PreOrderTraverse(BiTree T)

{

        if(T == NULL)

        return;

       

        printf("%c", T->data); //显示结点数据,可以更改为对结点的其他操作,例如修改

        PreOrderTraverse(T->lchild); //再遍历左子树

        PreOrderTraverse(T->rchild); //再遍历右子树

 }

 

//中序遍历递归算法   先左再双亲再右

void InOrderTraverse(BiTree T)

{

        if(T == NULL)

        return;

       

        InOrderTraverse(T->lchild); //先中序遍历左子树

        printf("%c", T->data); //显示结点数据,可以更改为对结点的其他操作,例如修改

        InOrderTraverse(T->rchild); //再中序遍历右子树

 }

 

 //后序遍历递归算法   先左再右最后双亲

void PostOrderTraverse(BiTree T)

{

        if(T == NULL)

        return;

                  

        PostOrderTraverse(T->lchild); //先后序遍历左子树

        PostOrderTraverse(T->rchild); //再后序遍历右子树

        printf("%c", T->data); //显示结点数据,可以更改为对结点的其他操作,例如修改

 }

由上述的代码可知,遍历二叉树根据不同的顺序遍历时,只是调节数据结点的数据和遍历左右子树三者的先后顺序,其实现的基本原理都是递归。

 

7、遍历二叉树的性质:

A、已知前序和中序遍历序列,可以唯一确定一棵二叉树

//已知前序和中序确定一棵二叉树

class Solution {

public:

    BiTree* reConstructBinaryTree(vector<int> pre,vector<int> vin) {

                 //输入合法性判断,不能为空,先序和中序的长度要一致

                 if(pre.empty()|| in.empty()|| pre.size()!= in.size()) {

                         return NULL;

                 }

                 //在前序遍历pre中查找根节点,并确定其在in的位置

                 size_t index=0;

                 for(;index <=in.size(); index++){

                         if(in[index]==pre[0]){  //在in中找到根节点时退出,此时index就是其在in中的位置

                                  break;

                         }

                 }

                

                 //创建新的根节点,并为其赋值

                 BiTree* node=new BiTree(pre[0]);

                 //根据中序遍历将根节点左右两侧一分为二,根节点的左侧为左子树,右侧为右子树

                 vector<int> pl,pr;

                 vector<int> vl,vr;

                 //将前序、中序中根节点的左右子树记录下来

                 for(size_t j=0; j<index; j++){

                         pl.push_back(pre[j+1]);

                         vl.push_back(in[j]);

                 }

                 for(size_t j=index+1; j<in.size(); j++){

                         pr.push_back(pre[j]);

                         vr.push_back(in[j]);

                 }

                

                 //递归调用构建当前节点的左子树

                 node->left=reConstructBinaryTree(pl,vl);

                 //递归调用构建当前节点的右子树

                 node->right=reConstructBinaryTree(pr,vr);

                 return BiTNode;

                  

        }

};

 

B、已知后序和中序遍历序列,可以唯一确定一棵二叉树

//已知后序和中序确定一棵二叉树

class Solution {

public:

    BiTree* reConstructBinaryTree(vector<int> post,vector<int> vin) {

                 //输入合法性判断,不能为空,后序序和中序的长度要一致

                 if(post.empty()|| in.empty()|| post.size()!= in.size()) {

                         return NULL;

                 }

                 //在前序遍历post中查找根节点,并确定其在in的位置

                 size_t index=0;

                 size_t plen = post.size();

                 size_t ilen = in.size();

                 for(;index <=ilen; index++){

                         if(in[index]==post[plen-1]){  //在in中找到根节点时退出,此时index就是其在in中的位置

                                  break;

                         }

                 }

                

                 //创建新的根节点,并为其赋值

                 BiTree* node=new BiTree(post[plen-1]);

                 //根据中序遍历将根节点左右两侧一分为二,根节点的左侧为左子树,右侧为右子树

                 vector<int> pl,pr;

                 vector<int> il,ir;

                 //将后序、中序中根节点的左右子树记录下来

                 for(size_t j=0; j<index; j++){

                         pl.push_back(post[j]);

                         vl.push_back(in[j]);

                 }

                 for(size_t j=index+1; j<ilen; j++){

                         pr.push_back(post[j]);

                         vr.push_back(in[j]);

                 }

                

                 //递归调用构建当前节点的左子树

                 node->left=reConstructBinaryTree(pl,il);

                 //递归调用构建当前节点的右子树

                 node->right=reConstructBinaryTree(pr,ir);

                 return BiTNode;

                  

        }

};

C、已知前序和后序不能确定一棵二叉树
例如已知前序为ABC,后序为CBA,可能结果有

 

8、二叉树的建立

//按前序输入二叉树中结点的值(字符)构造二叉树链表表示二叉树T#表示空树

void CreatBiTree(BiTree T)

{

        TElemType ch;

        scanf("%c",&ch);

        if(ch == '#');

                 *T = NULL;

        else{

                 *T = (BiTree)malloc(sizeof(BiTNode)); //分配一个结点的空间

                 if(!*T)

                         exit(OVERFLOW); //分配失败

                 (*T)->data = ch; //生成根节点

                 CreatBiTree(&(*T)->lchild); //构造左子树

                 CreatBiTree(&(*T)->rchild);  //构造右子树

        }

 }

 

参考资料:《大话数据结构》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值