二叉树

作者: 一只揣着梦想远行的飞鸟 | 来源:发表于2018-12-30 00:16 被阅读0次

    定义

    二叉树(Binary Tree)是一种特殊的
    特点:
    1.每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点)。
    2.二叉树的子树有左右之分,其次序不能任意颠倒。

    五种基本形态

    性质

    性质1
    第i层上至多有2i-1个结点(i>=1)。
    性质2
    深度为K的二叉树至多有2k-1个结点。
    性质3
    对于任何一棵二叉树T,如果其终端结点数为n_{0},度为2的结点为n_{2},则n_{0}=n_{2}+1

    拓展

    完全二叉树和满二叉树是树的两种特殊形态的二叉树
    一棵深度为k且有2k-1个结点的二叉树称为满二叉树

    满二叉树.
    深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一 一对应时,称之为完全二叉树
    完全二叉树
    性质4
    具有n个结点的完全二叉树的深度为[ log_{2}n ]+1。
    性质5
    如果对一棵有n个结点的完全二叉树(其深度为[ log_{2}n ]+1)的结点按层序编号(从第1层到第[ log_{2}n ]+1层,每一层从左到右),则对任一结点i(1<=i<=n),有

    1.如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲Parent(i)是结点[i/2]。

    2.如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子Lchild(i)是结点2i。

    3.如果2i+1>n,则结点i无右孩子;否则其右孩子Rchild(i)是结点2i+1。


    二叉树两种存储结构

    1.顺序存储结构
    仅适用于完全二叉树。最坏的情况下,一个深度为k且只有k个结点的单支树(树中不存在度为2的结点)却需要长度为2k-1的一维数组。
    2.链式存储结构
    设计不同的结点结构可构成不同形式的链式存储结构。二叉树的链表中的结点至少包含3个域:数据域和左、右指针域。
    拓展:线索链表


    拓展

    遍历二叉树
    线索二叉树


    遍历二叉树
    以下是二叉树链式存储结构,以及先序、中序、后序递归遍历输出结点的代码。
    前期就先把代码放这了,后期就放到我的GitHub上去

    #include <iostream>
    #include <cmath>    /* 包含OVERFLOW */
    #include <malloc.h> /* 包含malloc()函数 */
    
    
    using namespace std;
    
    typedef char TElemType; //二叉树结点内部数据类型 
    
    
    /* 链式存储二叉树结构定义 */
    typedef struct BiTNode
    {
        TElemType data; //数据域
        struct BiTNode *lchild, *rchild; //指针域
    } BiTNode, *BiTree;
     
    
    /* #表示空,以先序序列构造二叉树 */
    void CreateBiTree(BiTree *T)
    {
        TElemType ch;
        cin>>ch;
        if(ch=='#')
            *T = NULL;
        else
        {
            *T = (BiTree)malloc(sizeof(BiTNode));
            if(!*T)
                exit(OVERFLOW);
            (*T)->data = ch;
            CreateBiTree(&(*T)->lchild);    //继续构建左孩子结点
            CreateBiTree(&(*T)->rchild);    //继续构建右孩子结点 
        }
    }
    /* 先序序列输出 */ 
    void PreOrderTraverse(BiTree T)
    {
        if(T == NULL)
            return;
        cout<<T->data;
        PreOrderTraverse(T->lchild);    //遍历左子树
        PreOrderTraverse(T->rchild);    //遍历右子树 
    }
    /* 中序序列输出 */ 
    void InOrderTraverse(BiTree T)
    {
        if(T == NULL)
            return;
        InOrderTraverse(T->lchild);     //遍历左子树
        cout<<T->data;
        InOrderTraverse(T->rchild);     //遍历右子树 
    }
    /* 后序序列输出 */ 
    void PostOrderTraverse(BiTree T)
    {
        if(T == NULL)
            return;
        PostOrderTraverse(T->lchild);   //遍历左子树
        PostOrderTraverse(T->rchild);   //遍历右子树
        cout<<T->data; 
    }
    /* 判断二叉树是否为空 */
    bool IsEmpty(BiTree T)
    {
        if(T != NULL)
            return false;
        else
            return true;
    }
    /* 销毁二叉树 */
    bool DestroyBiTree(BiTree *T)
    {
        BiTree lchild, rchild;  //临时保存左右孩子结点 
        if(*T == NULL)
            return false;
        lchild = (*T)->lchild;      //临时保存左孩子结点 
        rchild = (*T)->rchild;      //临时保存右孩子结点 
        (*T) = NULL;    //将被销毁结点内容提前赋值为NULL 
        free(*T);   //销毁当前结点,销毁后地址内容不会改变 
        DestroyBiTree(&lchild); //销毁左孩子结点 
        DestroyBiTree(&rchild); //销毁右孩子结点 
        return true;
    }
    
    int main()
    {
        /* 测试用例1  abc##d##e#f## */
        /* 测试用例2  abcd#####*/
        BiTree T;
        CreateBiTree(&T);
        cout<<"先序序列为:";
        PreOrderTraverse(T);
        putchar('\n');
        cout<<"中序序列为:";
        InOrderTraverse(T);
        putchar('\n');
        cout<<"后序序列为:";
        PostOrderTraverse(T);
        putchar('\n');
        
        if(IsEmpty(T) == true)
            cout<<"二叉树为空!\n";
        else
            cout<<"二叉树不为空!\n";
        if(DestroyBiTree(&T) == true)
            cout<<"二叉树销毁成功!\n";
        if(IsEmpty(T) == true)
            cout<<"二叉树为空!\n";
        else
            cout<<"二叉树不为空!\n";
        return 0;
    }
     
    

    相关文章

      网友评论

          本文标题:二叉树

          本文链接:https://www.haomeiwen.com/subject/lpuylqtx.html