zoukankan      html  css  js  c++  java
  • 二叉树

    更多二叉树相关概念请看http://blog.csdn.net/zhang_xinxiu/article/details/12904635

    一、二叉树相关概念:

    1. 路径:对于节点n1 n2 n3….nk从n1到nk的路径长度为k-1
    2. 节点的层数:只有一个根节点,则层数为1,其余节点的层数为双亲节点的层数加1
    3. 树的深度:树中所有节点的最大层数称为树的深度,只有根节点深度为1。
    4. 满二叉树:所有分支节点存在左子树和右子树,并且所有的叶子节点都在同一层上。
    5. 完全二叉树:对于树中的节点从上至下、从左到右顺序进行编号,且与满二叉树的位置编号相同。完全二叉树特点:叶子节点只能出现在最下层和次下层,且最下层的叶子节点集中在树的左边,满二叉树肯定是完全二叉树,反之不一定。如果完全二叉树中子节点个数分别为0、1、2的节点数分别用n0 n1 n2表示,节点总数n=n0+n1=n2,且n1只能为0或者1。

    二、二叉树相关性质:

    1. 一颗深度为k的二叉树中,最多有2的k次方-1个节点(满二叉树),最少有k个节点
    2. 对于一颗非空二叉树,度为0的节点总是比度为2的几点多一个,即:n0=n2+1;
    3. 具有n个节点的完全二叉树的深度为【logn】+1,【】为向下取整;
    4. 对于n个节点从1开始编号的完全二叉树,对于节点编号i的节点:

        (1)如果2i<=n,则序号为i的节点的左孩子节点的序号为2i;如果2i>n,则序号为i的节点无左孩子;

           (2)如果2i+1<=n,则i节点有孩子序号为2i+1,如果2i+1>n,则i无右孩子。

                                                                                                                                                                     

    三、二叉树的遍历:

      1、先序遍历:先序遍历是先输出根节点,再输出左子树,最后输出右子树。上图的先序遍历结果就是:ABCDEF

      2、中序遍历:中序遍历是先输出左子树,再输出根节点,最后输出右子树。上图的中序遍历结果就是:CBDAEF

      3、后序遍历:后序遍历是先输出左子树,再输出右子树,最后输出根节点。上图的后序遍历结果就是:CDBFEA

    #include <iostream>
    using namespace std;
    struct TNode
    {
        TNode * LeftChild;
        TNode * RightChild;
        char data;
    };
    
    TNode *CreateTree()
    {
        TNode *pRoot=NULL;
        char data=0;
        cin>>data;
        if (data=='#')
        {
            pRoot=NULL;
        }
        else
        {
            pRoot=(TNode*)malloc(sizeof(TNode));
            pRoot->data=data;
            pRoot->LeftChild=CreateTree();
            pRoot->RightChild=CreateTree();
        }
        return pRoot;
    }
    
    void PreTraverse(TNode *pRoot)
    {
        if (pRoot==NULL)
        {
            return;
        }
        cout<<pRoot->data<<' ';
        PreTraverse(pRoot->LeftChild);
        PreTraverse(pRoot->RightChild);
    }
    
    void InTraverse(TNode *pRoot)
    {
        if (pRoot==NULL)
        {
            return;
        }
        InTraverse(pRoot->LeftChild);
        cout<<pRoot->data<<' ';
        InTraverse(pRoot->RightChild);
    }
    
    void LastTraverse(TNode *pRoot)
    {
        if (pRoot==NULL)
        {
            return;
        }
        LastTraverse(pRoot->LeftChild);
        LastTraverse(pRoot->RightChild);
        cout<<pRoot->data<<' ';
    }
    void main()
    {
        TNode *root=CreateTree();
        cout<<"first order is:  ";
        PreTraverse(root);
        cout<<endl;
        cout<<"middle order is: ";
        InTraverse(root);
        cout<<endl;
        cout<<"last order is:   ";
        LastTraverse(root);
        cout<<endl;
    }

     输出结果如下图:

    四、二叉树删除操作

     

      如右图,要删除B节点,要将D节点放入B的左孩子最右下孩子之后,也就是D’的位置。

        A.left=B.left;

        p=B.left;//也就是C

        while(p.right!=null)

               p=p.right;

        p.right=B.right;

        free(B);

    五.建立完全二叉树

             建立完全二叉树之前先给出遍历类型,例如,先序遍历:那么就用#

    来代替空值,例如如下序列:ABC###DEF##G###就表示如下的树型:

    六.遍历树的推导

      对于一颗二叉树可以根据前序遍历中序遍历推测出后续遍历,也可以根据中序遍历后续遍历推测出前序遍历,但是不可以根据前序遍历和后续遍历推测出中序遍历。

      我们用D来表示父节点,L表示左孩子,R来表示右孩子。

        前序遍历就是DLR

        中序遍历就是LDR

        后续遍历就是LRD

      例如一棵树的前序遍历是ABDECF 中序遍历为DBEAFC如何求后续遍历?

               前序遍历第一个字母A肯定是树根,然后根据中序遍历可以划分左右子树,DBE|A|FC,接下来再看左子树DBE,根据前序遍历第一个字母是B可以推断B是左子树的树根,  再看其中续遍历DBE,可以推断出D是其左子树,E是其右子树。同理可以推测出FC。结果显而易见。

    七、二叉分类树

             如果一棵树是二叉分类树,那么对于任何节点,其左儿子<=父节点<右儿子,对该树进行中序遍历可以得到顺序序列。

    八、扩充二叉树

             将原来每个节点的空指针都指向一个特殊的节点—外节点,这样的二叉树称为扩充二叉树。

             对于有n个节点的二叉树,含有2n个指针域,但是总共只有n-1条路径,所以占用n-1个指针域,剩余指针域为2n-n+1=n+1个,

       所以

          外节点个数=内节点个数+1.

          外路径长度=内路径长度+2n

    九、平衡二叉树

             当且仅当每个节点的左右子树高度至多相差1时,我们称这样的树为平衡树。

             如果BF的绝对值小于等于1,那么就是平衡二叉树。         平衡因子:BF=左子树高度-右子树高度

             对于右面这棵树BF(A)=-2;BF(E)=-1;BF(F)=0;

             所以该树不是平衡二叉树。

          当用一个数字序列构造平衡二叉树的时候,如果有结点出现BF=-2,那么调节离插入节点最近的BF=-2的节点,如右图,如果A<E<F            可能使E为树根,A、F分别为左右子树.

    十、哈弗曼树

      详见http://blog.csdn.net/zhang_xinxiu/article/details/12704337

  • 相关阅读:
    vue 文件分段上传
    深度clone
    js 导出excel
    js 校验
    设计模式原则
    多态
    数据库sql
    Redis快速入门
    C#中使用Redis学习二 在.NET4.5中使用redis hash操作
    在c#中使用servicestackredis操作redis
  • 原文地址:https://www.cnblogs.com/mu-tou-man/p/3908350.html
Copyright © 2011-2022 走看看