《数据结构》复习之二叉树

1.二叉树的性质

1.1满二叉树和完全二叉树

  在一棵二叉树中,如果所有的分支节点都有左孩子和右孩子,并且叶子节点都集中在二叉树的最下一层,则这样的二叉树被称为满二叉树
  如果一棵深度为k有n个节点的二叉树进行编号后,各结点的编号与深度为k的满二叉树中相同位置山的结点的编号军相投,那么这棵二叉树就是一颗完全二叉树

1.2二叉树的主要性质

  1. 总分支数=总结点数-1(这条结论对任何树都适用,不止是二叉树)
    证明:在二叉树中除根节点之外,每一个结点都有唯一的一个分支指向它,由此可证。
  2. 非空二叉树上叶子节点数等于双分支节点数+1
    证明:由上一条性质可证。设二叉树叶子节点数为n0,单分支节点数为n1,双分支节点数为n2,则总结点数为n0+n1+n2。总分支数为2*n2+n1。由上一条性质可得,n0+n1+n2-1=2*n2+n1。化简得:n0=n2+1。(注意,这种证明方法常常被用到
  3. 二叉树的第i层上最多有2i-1(i>=1)个节点。
    证明:等比数列。
  4. 高度为k的二叉树最多有2k-1(K>=1)个节点。换句话说满二叉树中前k层的结点个数为2k-1。
    证明:等比数列求和问题。
  5. 有n个阶段的完全二叉树,对各节点从上到下,从左到右依次编号(编号范围1~n),则节点之间有如下关系。
    若i为某节点a的编号,则:
    如果i!=1,则双亲节点的编号为i/2向下取整。
    如果2i<=n,则左孩子的编号为2i;如果2i>n,则a无左孩子。
    如果2i+1<=n,则右孩子的编号为2i+1;如果2i+1>n,则a无右孩子。

    这些性质中最常用的还是1-4条性质。

2.二叉树的数据结构

  二叉树也有顺序存储结构和链式存储结构。顺序存储结构是用数组存储,下标遵循上面第5条性质,注意下标从1开始。链式存储结构是最常用的存储二叉树的结构,如下图所示。
  二叉树链式存储结构
  其中data表示节点数据域,用与存储对应的数据元素;lchild和rchild分别表示左指针域和右指针域,分别用于存储左孩子结点和右孩子结点的位置。
  定义如下:

typedef struct BTNode
{
    char data;
    struct BTNode *lchild;
    struct BTNode *rchild;
}BTNode

3.二叉树的算法

  二叉树的算法主要是遍历算法,包括深度遍历(先序遍历,中序遍历,后序遍历)和广度遍历(层次遍历)。这也是解大多数二叉树题目的关键。
  三种遍历(先序遍历,中序遍历,后序遍历)代码如下 

void PreOrderTraverse(BiTree T) //先序遍历
{
    if(T!=NULL)
    {
        cout<<T->data<<" ";
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}

void InOrderTraverse(BiTree T)  //中序遍历
{
    if(T!=NULL)
    {
        InOrderTraverse(T->lchild);
        cout<<T->data<<" ";
        InOrderTraverse(T->rchild);
    }
}

void PostOrderTraverse(BiTree T)   //后序遍历
{
    if(T!=NULL)
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        cout<<T->data<<" ";
    }
}

  层次遍历的伪代码如下
  

根节点入队
while(队不空)
{
    节点出队,并访问
    if(左子树不为空)
        左子树入队
    if(右子树不为空)
        右子树入队
}

  c++代码如下:
  

void LevelOrderTraverse()
{
    int front=0,rear=0;   //定义循环队列
    BiTNode *que[Maxsize];
    front=rear;
    BiTNode *q;
    if(T!=NULL)          //如果传过来的树不为空
    {
        rear=(rear+1)%Maxsize;
        que[rear]=T;                //根节点入队
        while (front!=rear)    //队列不为空
        {
            front=(front+1)%Maxsize;
            q=que[front];        //队头出队
            cout<<q->data<<" ";    //访问队头
            if (q->lchild!=NULL)       //如果左子树不空,则左子根入队
            {
                rear=(rear+1)%Maxsize;
                que[rear]=q->lchild;
            }
            if (q->rchild!=NULL)       //如果右子树不空,则右子根入队
            {
                rear=(rear+1)%Maxsize;
                que[rear]=q->rchild;
            }   
        }
    }
}

  这4个算法(其实只算两个)就像模板一样,大多数二叉树题目只要会套这个模板就能解决,因此它非常重要。

4.补充

  下面的程序是我大二数据结构课设时写的,现在看起来有许多不足和幼稚的地方,但仍然具有一定的参考价值,将它放在这里。
  


#define Maxsize 100
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#include<fstr
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值