美文网首页
2020-07-26

2020-07-26

作者: 未时日 | 来源:发表于2020-07-26 18:03 被阅读0次

    # 1.树的概念

    ## 1.1 树的定义

    * 自由树:

    $T_{f} = (V, E)$ $(V=\{v_{21}, v_{2}, ...v_{n}\}$ $E=\{(v_{i}, v_{j})|v_{i},v_{j}\in V, 1 \leq i,j \leq n

    \})$,其中,集合$E$的元素个数为 $n-1$, $(v_{i}, v_{j})$称为边或分支, $T_{f}$为连通图

    * 有根树:

    $T=\begin{cases}\phi,\qquad n=0\\

    \{r,T1, T2, T3,...,T_{m}\}, \qquad n>0

    \end{cases}$<br>$n=0$时称为空树,$T_{1},T_{2},...T_{m}$称为子树<br>根节点没有前驱,除此之外每个节点有且只有一个前驱;所有节点有零个或多个后继

    * 目录结构、集合文氏图、凹入表表示、广义表表示

    ## 1.2 常见术语

    * 结点:包含数据项和其他结点的分支

    * 度:拥有子树的个数,树的度是结点的最大度

    * 叶结点:度为0的点,终端结点

    * 分支节点:除叶结点以外的点,非终端节点

    * 子女节点:若结点$x$有子树,子树的根结点即$x$的子女

    * 父结点:结点$x$为其子女结点的父结点

    * 兄弟结点:同一父结点的子女护卫兄弟

    * 祖先结点:对结点$x$,根结点到这个结点唯一路径上的任意结点

    * 子孙结点:子女结点的子女

    * 层次:根到该结点的子树个数,记根结点为层次为1,子结点层次为父结点加1

    * 深度:最远结点的层次,空树为0,自顶向下

    * 高度:叶结点高度为1,其父结点的高度为最高子女高度+1,树的高度为根结点高度,自底向上,数值上与深度相等。

    * 有序树、无序树:各棵子树能够交换,例如有序树中$T_{1}, T_{2}...$被称为第一棵子树、第二棵子树...

    * 森林:$m \geq0$棵互不相交的树,树$\to$森林:删去一棵非空树的根结点(空森林也是森林) 森林$\to$树:增加一个结点,让每一棵树的根结点都称为这个结点的子女结点

    ## 1.3 树的性质

    * 结点数等于度数和加1

    * 度为$m$的树第$i$层至多有$m^{i-1}个结点$

    * 高度为$h$的$m$叉树(度为$m$)至多有 $\sum_{i=1}^hm^{i-1}=\frac{(m^{h}-1)}{(m-1)}$ 

    * 设度为$m$的树($m$叉树)结点个数为$n$,由上一个性质,我们推出:

    $$

      \begin{gathered}

        n \leq\,\frac{(m^{h}-1)}{m-1}\\

        \qquad h \geq \lceil\log_{m}(n(m-1)+1)\rceil

        \end{gathered}

    $$

    # 2.二叉树

    ## 2.1 二叉树定义

    $$

      T=

      \begin{cases}

        \phi \qquad n=0\\  

        \{r, \,T_{l}, \,T_{r} \} \qquad n \geq 1

      \end{cases}

    $$

        树的度至多为2(即最多两个子女结点),左右子树能交换(有序的)

    ## 2.2 二叉树的性质

    * 第$i$层至多$2^{i-1}$个结点

    * 高为$k$至多$2^{k}-1$个结点,至少$k$个结点(每层一个)

    * 考虑两个等式:

      $$

      \begin{gathered}

        n = n_{0} + n_{1} + n_{2} \\

        e = n-1 = n_{1} + 2 * n_{2}   

      \end{gathered}

      $$

      故有:$n_{0} = n_{2} +1$

    * 满二叉树:每一层都达到最大结点个数;完全二 叉树:每一个结点都与具有相同高度的满二叉 树对应(上面$k-1$层是满的,仅第$k$层从右向左却若干个)

    * $n$个结点的完全二叉树最小深度为$\lceil \log(n+1)\rceil$

    * 对于完全二叉树,编号为$1,2,3...n$,结点 $i$ 的父结点编号为 $\lfloor\frac{n}{2}\rfloor$ ,结点 $i$ 的左子女结点为 $2*i$,右子女结点为 $2*i+1$ ,(检查结点是否超过 $n$ ),深度 $\lfloor\log(i)\rfloor + 1$ <br/></br>

    # 3.二叉树存储

    ## 3.1 二叉树数组表示

    * 适用场景:二叉树大小和形态不发生剧烈动态变化

    * 将二叉树存储在一组连续的存储单元(即数组内),要体现树的逻辑结构。

    * 完全二叉树数组存储:自顶向下,自左向右顺序编号为 $1,2,3,4...,n$,按照这个序列把完全二叉树放入一维数组中(根结点在索引为$1$处)。**这种方式最简单、最省存储空间**

    * 一般二叉树存储:仿照完全二叉树编号,遇到空子树时假定有子树编号。这样的做法会浪费存储空间(eg.只有右子树)

    ## 3.2 二叉树的链表表示

    * 适用一般二叉树,变化剧烈

    * 二叉树的每一个结点可以有两个分支,分别指向左、右子树,因此至少有三个域,分别存放结点的数据、左右子女结点指针。**很方便的找到子女结点,但找到父结点很困难**

    * 为了找到父结点,可以再加一个父指针域,称为三叉链表

    * 对于 $n$ 个结点的二叉链表中,共有 $2*n$ 个指针域,由于二叉树中共有 $n -1$ 条边,故**二叉链表中有 $n+1$ 个空指针域**,同理,三叉链表中有 $n+2$ 个空指针域(根结点的父结点域为空)

    * 这两种链表形式都可以是静态链表结构,即把链表存放在一个一维数组中,每个一维数组元素是一个结点,包括三个域:数组域、左子女域、右子女域,还可以增加父指针域,指针域指向数组中的下标:

      ```

                         A

                        /  

                       B

                      / \

                     C   D

                        /

                       E

      ```

      |index| data| Parent | LeftChild| RightChild|

      |-----|-----|------- |----------|-----------|

      |0    | A   |-1(root)|  1(B)    | -1(NULL)  |

      |1    | B   | 0(A)   |  2(C)    | 3(D)      |

      |2    | C   | 1(B)   |  -1(NULL)| -1(NULL)  |

      |3    | D   | 1(B)   |  4(E)    | -1(NULL)  |

      |4    | E   | 3(D)   |  -1(NULL)| -1(NULL)  |

    </br>

    # 4.二叉树的遍历及应用

    ## 概述

      &emsp;&emsp;二叉树遍历是指遵从某种次序,遍历二叉树中所有的结点,使得每个结点访问且只访问一次,且不破坏树的数据结构,产生的结构是一个线性队列。<br>&emsp;&emsp;考虑自身、左右三个结点的顺序,总共的遍历方式有 $A_{3}^{3}= 6$ 种,规定先左后右,共有三种方式。常见的遍历方式有先序(NLR)、中序(LNR)、后序(LRN)三种。

    ## 三种遍历算法

    * 递归访问

      ```cpp

      /*先序遍历*/

      void PreOrder(BiTNode* T){

        if(T!=NULL){

          visit(T);

          PreOrder(T->lchild);

          PreOrder(T->rchild);

        }

      }

      /*中序遍历*/

      void InOrder(BitNode* T){

        if(T!=NULL){

          InOrder(T->lchild);

          visit(T);

          InOrder(T->rchild);

        }

      }

      /*后序遍历*/

      void PostOrder(BitNode* T){

        if(T!=NULL){

          PostOrder(T->lchild);

          PostOrder(T->rchild);

          visit(T);

        }

      }

      ```

    * 先序非递归遍历

    相关文章

      网友评论

          本文标题:2020-07-26

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