十、树

时间:2020-01-24 15:39:57   收藏:0   阅读:65

10.1 树的基本概念

10.2 指针

10.2.1 指针的概念

10.2.2 指针变量的定义

10.2.3 指针的初始化

10.2.4 指针变量的引用

10.2.5 空指针

10.2.6 指针的运算

10.2.7 指针与数组

10.2.8 指针与结构体

10.2.9 指针例题

10.3 树结构的存储

10.4 二叉树

10.4.1 二叉树的定义

10.4.2 满二叉树

10.4.3 完全二叉树

10.4.4 斜树

10.4.5 二叉树性质

  1. 每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。
  2. 左子树和右子树是有顺序的,次序不能任意颠倒。
  3. 即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。
  4. 在二叉树的第i层上最多有 \(2^{i-1}\) 个结点 。(\(i\ge 1\))
  5. 二叉树中如果深度为k,那么最多有\(2^k-1\)个结点。(\(k>=1\))
  6. \(n_0=n_2+1 , n_0\)表示度数为0的结点数,\(n_2\)表示度数为2的结点数。
    • 证明:
      • 二叉树中所有结点的度数均不大于2,令结点总数为:n,度数为0,1,2结点数:\(n_0,n_1,n_2\),则:
        • \(n=n_0+n_1+n_2\) ……(式子1)
      • 度为1的结点有一个孩子,度为2结点有两个孩子,故二叉树中孩子结点总数是:
        • \(n_1+2*n_2\)
      • 树中只有根结点不是任何结点的孩子,故二叉树中的结点总数又可表示为:
        • \(n=n_1+2*n_2+1\) ……(式子2)
      • 由式子1和式子2得到:
        • \(n_0=n_2+1\)

10.4.6 二叉树的存储

  1. 顺序存储
    • 二叉树的顺序存储结构就是使用一维数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标索引。

    • 技术分享图片
    • 技术分享图片
    • 由上图可以看出,当二叉树为完全二叉树时,结点数刚好填满数组。那么当二叉树不为完全二叉树时,采用顺序存储形式如何呢?

      技术分享图片
      技术分享图片

      • 其中浅色结点表示结点不存在。其中,∧表示数组中此位置没有存储结点。此时可以发现,顺序存储结构中已经出现了空间浪费的情况。
      • 最坏的情况,比如右斜树
      • 技术分享图片技术分享图片
      • 技术分享图片
      • 顺序存储一般适用于完全二叉树。
  2. 二叉链表
    • 由二叉树定义可知,二叉树的每个结点最多有两个孩子。因此,可以将结点数据结构定义为一个数据和两个指针域。

      技术分享图片

      struct Node{
          char data;//数据
          Node *lchild,*rchild;
      };
    • 存储结构如下图所示

      技术分享图片

      技术分享图片

10.4.7 二叉树遍历

  1. 前序遍历
    • 访问结点,再从左到右按照前序遍历思想递归遍历各棵子树
    • 上图前序遍历的结果为:ABDHIEJCFG
      1. 从根结点出发,则第一次到达结点A,故输出A;
      2. 继续向左访问,第一次访问结点B,故输出B
      3. 按照同样规则,输出D,输出H
      4. 当到达叶子结点H,返回到D,此时D的左子树已访问结束,进而访问D的右子树I
      5. 按照同样的访问规则,继续输出E,J,C,F,G
  2. 中序遍历
    • 遍历子树,访问结点,遍历子树。
    • 上图中序遍历的结果为:HDIBJEAFCG
      1. 从根结点出发,访问结点A,A存在左子树B,则递归访问左子树B,依次递归直到H
      2. 到达HH左子树为空,则输出结点H,访问H右子树,为空,返回H子树根结点D
      3. 返回至D,此时D的左子树访问完毕,输出D,访问D的右子树I
      4. 结点I左子树为空,则输出I,右子树为空则返回父结点D
      5. 按照同样规则继续访问,输出B,J,E,A,F,C,G
  3. 后序遍历
    • 遍历各棵子树,访问结点。
    • 上图后序遍历的结果为:HIDJEBFGCA
      1. 从根结点A出发,A左右子树非空,先递归访问左子树B
      2. 以此类推到达HH左、右子树为空,则输出H
      3. H返回至DD左子树访问结束,递归访问其右子树I
      4. I左右子树均为空,输出I
      5. 返回至D,此时D左、右子树均访问结束,故输出D;
      6. 按照同样规则继续访问,输出J,E,B,F,G,C,A
  4. 层次遍历
    • 按层次从小到大逐个访问,同一层次按照从左到右的次序。
    • 上图层次遍历的结果为:ABCDEFGHIJ

10.4.8 例题

10.4.8.1 树的遍历
10.4.8.2 普通树转二叉树

10.5 二叉搜索树

10.5.1 定义

10.5.2 二叉搜索树的插入

10.5.3 二叉搜索树的查找

10.5.4 二叉搜索树的前驱和后继

10.5.5 二叉搜索树的删除

  1. 删除叶子结点

    • 删除叶子结点的方式最为简单,只需查找到该结点,直接删除即可。

      技术分享图片

      • 上图中的叶子结点37、结点51、结点60、结点73和结点93的方式是相同的。
  2. 删除的结点只有左子树

    • 删除的结点若只有左子树,将结点的左子树替代该结点位置。

    技术分享图片

  3. 删除的结点只有右子树

    • 删除的结点若只有右子树,将结点的右子树替代该结点位置。这种情况与删除左子树处理方式类似,不再赘述。
  4. 删除的结点既有左子树又有右子树。

    • 若删除的结点既有左子树又有右子树,这种结点删除过程相对复杂。其流程如下:
      1. 遍历待删除结点的左子树,找到其左子树中的最大结点,即删除结点的前驱结点;
      2. 将最大结点代替被删除结点;
      3. 删除左子树中的最大结点;
      4. 左子树中待删除最大结点一定为叶子结点或者仅有左子树。按照之前情形删除即可。

10.6 二叉堆

10.6.1 二叉堆的定义

10.6.2 二叉堆的存储

10.6.3 二叉堆的插入

10.6.4 二叉堆的删除

10.6.5 堆排序

10.7 Trie 树

10.7.1 Trie字典树的基本概念

10.7.2 Trie字典树的基本操作

struct Node {
    bool isWord;//为1表示从根到当前结点是一个单词
    Node *son[N];//const int N=26;
    Node(){
        isWord = false;
        memset(son, 0, sizeof(son));
    }
};

技术分享图片

  1. 如果单词的除了最后一个字母,其他的字母有多个分支
    • 这种情况,需要找到最下面的分支结点,将以下的单词部分删掉,如下图所示:
      技术分享图片

原文:https://www.cnblogs.com/hbhszxyb/p/12232217.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!