树tree

一,概念:
    结点n为0的树叫空树,n大于0时,有一个结点称为根。
    结点的子树的个数称为结点的度,树的度是结点度的最大值,度为0的结点称为叶子结点。
    子树间是存在次序的树称为有序树,反之为无序树。
    n个互不相交的树的集合称之为森林。对于每个结点而言,其子树的集合即为森林。
 
二,树的存储结构:
    1,树的表示方法:
        1)双亲表示法,即在结点中不止存在数据,还存在指向父结点的指针,由于跟结点没有双亲,则将根结点的双亲设置为-1;这样的存储很容易找到节点的父亲,但是很难找到字节点,因为如果需要找字节点,则需要遍历整个结构才行,不过可以增加左孩子指针,和右兄弟指针来解决这些问题
        2)孩子表示法,可以用顺序表实现,使用hashcode来实现,顺序表中每个结点存储一个数据域和一个指向子结点链表的指针,子结点链表的每个结点保存一个位置值,和一个next指针,指向自己的兄弟,即链表中的一个链中的所有结点都是顺序表中一个结点的孩子结点,但链表哈夫曼树中只有位置索引和下一个节点指针两个值。但是这种结构很难找到自己的双亲结点,不过可以在顺序表的每个结点中再增加一个指向父结点的索引
        3)孩子兄弟表示法,这种结构的每个结点都保留一个指向左孩子节点的指针,和一个指向右兄弟结点的指针,这种节点方便查找所有的孩子,并且直接把树转化为了二叉树存储结构表示,并且还可以使用二叉树的算法。

    2,二叉树:
        1)性质:二叉书不存在子结点树大于两个的结点
            左子树和右子树是有次序的
            即使某结点只有一个子树,也需要区分左子树和右子树

            ×××二叉树的第i层上最多有2的(i-1)次幂个结点
            ×××深度k的二叉树最多有(2的k次幂)-1个结点,即满二叉树的结点数
            ×××任意二叉树,度为0的结点为n0,度为2的结点为n2,则n0=n2+1
            ×××非叶子结点数为 总结点数(n-1)/2
            ×××n个结点的完全二叉树的深度为 |lgn + 1|,根据第二条反推
            ×××如果把结点编号,编号为i的结点,i/2的结点为他的父结点,2×i为结点的左子树,2×i+1为结点的右子树,如果2×i大于n,则结点不存在左子树

        2)特殊二叉树:斜树,要不每个结点都只有子结点,要不每个节点都只有父结点;   结点个数也等于树的深度;
            满二叉树,所有分支结点都存在左子树和右子树,并且叶子节点都在同一层;   叶子只能出现在最下层,非叶子结点度一定为2,深度相同的二叉树中,满二叉树的结点最多
            完全二叉树,满二叉树是一种特殊的完全二叉树,完全二叉树的编号是连续的;   叶子结点只能出现在最下两层,最下层结点一定集中在左侧,如果结点的度数为1,则此结点只能有左孩子,同样结点数的二叉树,完全二叉树的深度最小

    3,四叉树/八叉树:游戏中在进行空间查找时,比如说距离灯10米内的结点会变亮,而且距离越近越亮,如果正常要进行发亮的点查找,二维游戏地图的时间复杂度为O(n2),三维的时间复杂度为O(n3),这样对于精细的地图来说,估计游戏要卡个半死。所以用到了四叉树(2维)和八叉树(3维)的结构,拿二维世界来说,如果每个结点分别有指向自己上下左右的四个结点的四个指针,那么我想访问和我距离三米的所有结点,我只需要递归3次,并且能保证所有遍历的结点都是需要的结点,而八叉树和四叉树同理

    4,二叉树的存储结构:
        顺序存储结构:完全二叉树用数组实现,则i的子树即为2×i和2×i+1,并且不会出现空结点。但一般只有完全二叉树用顺序表,因为特别稀疏的二叉树会浪费很多空间
        二叉链表:一个数据域,两个指针域,分别指向左孩子和右孩子,如果有需要,还可以增加一个双亲指针,这样就称为三叉链表

三,二叉树的遍历:
    1,前,中,后序遍历:要知道前中后都是指的父结点,即前序遍历就是先遍历父结点,再去左孩子,右孩子。中序就是先遍历左孩子,在遍历父结点,右孩子。后序遍历就是先遍历左孩子,右孩子,再遍历父结点,都是相对父结点来说的,
    2,层序遍历,一层一层的遍历,先遍历根结点,再去遍历根的两个孩子,再去遍历两个孩子的四个孩子,,等等等,,一层一层的遍历下去。

    3,前序遍历算法:
    void PreOrderTraverse(BiTree T)
    {
        if(T == NULL)
        return;
        /////////
        此处处理父结点的逻辑
        /////////
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
    中序后序算法直接依靠前序处类旁通;

    4,推导二叉树的遍历:常常会出现这种题:已知一棵二叉树的前序遍历序列为ABCDEF,中序遍历为CBAEDF,则这棵二叉树的后序遍历结果是多少。
        前序为ABCDEF,则根结点一定是A,中序为CBAEDF,则CB一定在A的左侧,DEF一定在A的右侧。
        结构为                  A
                      (BC)     (DEF)
        又因为前序的BC,所以C一定是B的子结点或右兄弟,又因为中序的CB,所以C一定为B的左孩子。
        当前结构为         A
                            B    (DEF)
                      C
        又因为前序为DEF,所以D一定是A的右孩子,E一定为D的左孩子,F一定是E的孩子结点或者右兄弟。而因为中序遍历为EDF,所以F是E的右兄弟结点
        所以最终为          A
                              B        D
                       C            E        F
    5,线索二叉树:
    我们会发现,一个真实的二叉树存储,有很多结点是没有左孩子,和右孩子的,比如叶子结点,和度为1的结点,浪费的指针个数将近会占到总指针个数的一半,那么这些存储不是白白浪费了吗?还能不能做些什么呢?
    恰好刚刚可以通过这些空闲的左右指针来记录中序遍历,左孩子指针指向中序遍历的前驱,右孩子指针指向中序遍历的后继,这样刚刚好记录了中序遍历的结果,而又没有影响原来的存储逻辑,但是确实还有有影响的,比如在遍历的时候,我怎么知道存储的是我的后继,还是我的右孩子呢,可以设置两个bool值来解决,仅仅占两bit的存储,一个bool表示是否符合中序遍历的后继,一个bool表示是否符合右孩子。这样问题就解决了,即满足了原有的左右子树二茶树的特性,有满足了线索二叉树的特性。

四,树,森林,二叉树的转换
    二叉树每个结点最多有两个孩子,普通树对孩子的个数是没有限制的,而森林就是很多棵树,也可以理解为一个树失去了根结点
    二叉树的结构在数据处理上有着天生的优势,如果能把普通树转换为二叉树,甚至把森林转化为二叉树,那树和森林的算法就简单多了
    1,树转换为二叉树:
        先加线,使左右两个兄弟之间必有一连线,即每个结点都有一个右兄弟指针;
        再减线,只保留一个左孩子指针和兄弟指针,即满足孩子兄弟表示法。
        这时候在存储层次上树已经就转化为了二叉树,每个结点只有一个左孩子结点指针,和指向右兄弟的结点指针

    2,森林转为二叉树:
        先把森林的每棵树转换为二叉树
        因为第一棵树根结点没有兄弟,所以根结点的右兄弟结点指针为空,这时候把森林的第一颗树的右兄弟结点指针指向第二棵树的根结点,
        同理,第二棵树的根结点没有右兄弟,则把第二棵树的右兄弟结点指针指向第三棵树的根结点,依次类推,,森林就已经转为了一棵二叉树

    3,二叉树转为树:
        先加线,父结点指向左孩子,和左孩子的所有兄弟
        在减线,减去所有的兄弟之间的线
        这样二叉树又转回了最开始的树

    4,二叉树转为森林:
        把根结点的右孩子结点删掉,独立出一棵树
        对新独立出来的树再重复刚才过程,删掉独立出来树的根的右孩子,继续独立出一棵树
        等等等,直到新独立出来的树根没有右孩子为止
        最后将所有分离出来的二叉树转换为树即可

    树和森林的遍历:
    树的先序遍历:先遍历树根,在递归遍历每棵子树
    树的后序遍历:先访问每一棵子树,在访问根
    森林的先序遍历:先依次访问每棵树根,在去递归每棵树的子树
    森林的后序遍历:先对第一颗树进行后续遍历,在对第二棵树进行后续遍历,依次对后序所有树进行后续遍历

    但是对二叉树进行前序遍历和 森林和树 进行前序遍历结果相同
    对二叉树的中序遍历和 森林和树 的后序遍历的结果相同
    所以树和森林可以通过二叉树来进行遍历
 

发布了22 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Skying_/article/details/84325382