走进数据结构和算法(c++版)(8)——二叉树

二叉树

  二叉树是一种应用十分广泛的树结构。我们先来看下二叉树的定义。

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

              1

1 图 1

二叉树特点

  1. 每个结点最多有两棵子树。
  2. 左子树和右子树是有顺序的,次序不能任意颠倒。
  3. 即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。

特殊二叉树

斜树

  所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树。
              2

2 图 2

满二叉树

  在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树
                3

3 图 3

完全二叉树

  对一棵具有 n n 个结点的二叉树按层序编号,如果编号为 i(1in) i ( 1 ⩽ i ⩽ n ) 的结点与同样深度的满二叉树中编号为 i i 的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树
                4

4 图 4

  要注意将完全二叉树与满二叉树区分开。完全二叉树是满二叉树最深层从最右边的结点开始缺失若干个连续编号的结点。

二叉树的性质

性质 1 :在二叉树的第 i i 层上至多有 2i1 2 i − 1 个结点 (i1) ( i ⩾ 1 )

性质 2: 深度为 k k 的二叉树至多有 2k1 2 k − 1 个结点 (k1) ( k ⩾ 1 )

性质 3: 对任何一棵二叉树 T T ,如果其终端结点数为n0,度为 2 的结点数为 n2 n 2 ,则 n0=n2+1 n 0 = n 2 + 1

性质 4: 具有 n n 个结点的完全二叉树的深度为 log2n+1 ⌊ log 2 ⁡ n ⌋ + 1 ( x ⌊ x ⌋ 表示不大于 x x 的最大整数)。

性质 5: 如果对一棵有n个结点的完全二叉树(其深度为 log2n+1 ⌊ log 2 ⁡ n ⌋ + 1 ) 的结点按层序编号(从第 1 层到第 log2n+1 ⌊ log 2 ⁡ n ⌋ + 1 层,每层从左到右) ,对任一结点 i(1in) i ( 1 ⩽ i ⩽ n ) 有:

  1. 如果 i=1 i = 1 ,则结点 i i 是二叉树的根,无双亲;如果 i>1 i > 1 ,则其双亲是结点 i/2 ⌊ i / 2 ⌋
  2. 如果 2i>n 2 i > n ,则结点 i i 无左孩子(结点 i i 为叶子结点) ;否则其左孩子是结点 2i 2 i
  3. 如果 2i+1>n 2 i + 1 > n ,则结点 i i 无右孩子 ;否则其右孩子是结点 2i+1 2 i + 1

二叉树遍历方法

前序遍历:规则是若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树, 再前序遍历右子树。图1中树的前序遍历顺序为ABDEGCF。
中序遍历:规则是若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点) ,中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。 如图1中树的中序遍历顺序为DBGEACF。
后序遍历:规则是若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。如图1中树的后序遍历顺序为DGEBFCA。
层序遍历:规则是若树为空, 则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中, 按从左到右的顺序对结点逐个访问。如图1中树的层序遍历顺序为ABCDEFG。

  • 己知前序遍历序列和中序遍历序列,可以唯一确定一棵二叉树。
  • 已知后序遍历序列和中序遍历序列,可以唯一确定一棵二叉树。
  • 已知前序和后序遍历,是不能确定一棵二叉树的。

  我们再来看下二叉树的代码结构:

class BTNode
{
public:
    BTNode();
    ~BTNode();
    void PreTraverseBTree();//前序遍历
    void InTraverseBTree();//中序遍历
    void PostTraverseBTree();//后序遍历
    friend void  CreateBTree(BTNode * T);//创建二叉树
private:
    char data;//数据元素
    BTNode * pLchild;//左孩子
    BTNode * pRchild ;//右孩子

};

  代码的具体实现:

#include "BTNode.h"
#include<iostream>
using namespace std;
BTNode::BTNode()
{
}


BTNode::~BTNode()
{
}
void BTNode::PreTraverseBTree()
{

    if(data)cout << data << " ";
    if (pLchild!=NULL)pLchild->PreTraverseBTree();
    if (pRchild!= NULL)pRchild->PreTraverseBTree();
}
void BTNode::InTraverseBTree()
{
    if (pLchild != NULL)pLchild->InTraverseBTree();
    if (data)cout << data << " ";
    if (pRchild != NULL)pRchild->InTraverseBTree();
}
void BTNode::PostTraverseBTree()
{
    if (pLchild != NULL)pLchild->PostTraverseBTree();
    if (pRchild != NULL)pRchild->PostTraverseBTree();
    if (data)cout << data << " ";
}

  二叉树的遍历是通过递归来实现的。

#include<iostream>
#include "BTNode.h"
using namespace std;
void  CreateBTree(BTNode * T);
int main()
{
    BTNode *T = new BTNode;
    CreateBTree(T);
    cout << "前序:";
    T->PreTraverseBTree();
    cout << endl;
    cout << "中序:";
    T->InTraverseBTree();
    cout << endl;
    cout << "后序:";
    T->PostTraverseBTree();
    cout << endl;
    system("pause");
    return 0;
}
void CreateBTree(BTNode * T)
{

    char ch;
    cin >>ch;
    if ('#' == ch)
    {
        T=NULL;
    }
    else{
        T->data = ch;
        T->pLchild = new BTNode;
        CreateBTree(T->pLchild);
        T->pRchild = new BTNode;
        CreateBTree(T->pRchild);
    }

}

  这里创建二叉树采用前序遍历来输入遇到用‘#’表示空树,如图1中的树可以输成ABD##EG###C#F##。在VS上运行结果如下:
5

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不放弃的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值