《数据结构(C语言版)》- 树和二叉树

本文将讨论非线性数据结构中的树型结构。树型结构中树和二叉树最常用,直观来说,树是以分支关系定义的层次结构,树结构在客观世界中广泛存在,如人类社会的族谱,最上面是族长,然后下面依次是族长的孩子,孙子等等。这就可以用树来更加形象的表示。树在计算机领域中也有十分广泛地应用,如在编译程序中,可用树来表示源程序的语法结构。

1. 树的定义

树的形状如下图:

这里写图片描述

树(Tree)是n( n0 )个结点的有限集。树需要满足的条件如下:

  • 有且仅有一个特定的称为(Root)的结点,如图中的结点A就是这棵树的根节点;

  • n>1 时,其余结点可分为m( m>0 )个互不相交的有限集 T1T2...,Tm ,其中每一个集合又可以作为一棵树,并称为根的子树(SubTree);

2. 树结构中的基本术语

下面将列出树结构中的一些基本术语:

  • 树的结点所拥有的子树的个数称为结点的度(Degree)。如上图中,A的度为6,D的度为1,P的度为0;

  • 度为0的结点称为叶子(Leaf)或终端结点。 如上图中,B,C,H,I,P,Q,K,L,M,N都是叶子结点;

  • 树的度是树内各结点的度的最大值。如上图中,树的度为4;

  • 结点的子树的根称为该结点的孩子(Child),该结点同样称为孩子的双亲(Parent)。如上图中,E为A的子树的根,则E为A的孩子,而A则是E的双亲;

  • 同一个双亲的孩子之间互称兄弟(Sibling)。如上图中,B,C,D,E,F,G互为兄弟;

  • 结点的祖先是从根到该结点所经过分支上的所有结点。反之,以某结点为根的子树中的任一结点都称为该结点的子孙。如上图中,P的祖先为A,E,J,E的子孙为I,J,P,Q;

  • 结点的层次(Level)从根开始定义起,根为第一层,根的孩子为第二层,以此类推。

  • 结点双亲都在同一层的结点互为堂兄弟。如上图中,H,I,J,K,L,M,N互为堂兄弟。

  • 树中结点的最大层次称为树的深度(Depth)或高度。如上图中,树的深度为4;

  • 如果将树中结点的各子树看成从左至右是有次序的(即不能互换),则称该树为有序树,否则称为无序树。如上图中,如果将A的以D为根的子树和以E为根的子树互换位置后和原先的树表示两颗树,则称该树为有序树,如果表示同一棵树,则称该树为无序树。在有序树中最左边的子树的根称为第一个孩子,最右边的称为最后一个孩子;

  • 森林(Forest)是m( m0 )棵互不相交的树的集合。

3. 二叉树的定义

二叉树(Binary Tree)是另一种树型结构,它的特点是每个结点至多只有两颗子树,也就是说,二叉树不存在度大于2的结点,并且二叉树的子树有左右之分,其次序不能任意颠倒。

一颗深度为 k 且有2k1 个结点的二叉树称为满二叉树,即满二叉树的每一层的结点数都是最大结点树。

如果对满二叉树的结点进行连续编号,约定遍号从根节点起,自上而下,自左至右。其中,深度为 k 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为 k 的满二叉树中编号从1至n的结点一一对应时,称之为完成二叉树。

如下图,(a)和(b)分别为完成二叉树和满二叉树,而(c)和(d)为非完成二叉树:

这里写图片描述

抽象数据类型二叉树的定义如下

这里写图片描述
这里写图片描述
这里写图片描述

4. 二叉树的性质

下面叙述二叉树的重要性质:

  • 性质1 : 在二叉树的第i层上至多有 2i1 个结点( i1 )。

    • 性质2 : 深度为 k 的二叉树至多有2k1个结点( k1 )。

    • 性质3 :对任何一颗二叉树 T ,如果其叶子结点数为n0,度为2的结点数为 n2 ,则 n0=n2+1

    • 性质4 :具有 n 个结点的完全二叉树的深度为[log2n]+1

    • 性质5:如果对一颗有 n 个结点的完全二叉树的结点按层序编号,则对任一结点i(1in),有:

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

      (2) 如果 2i>n ,则结点 i 无左孩子(由于是完全二叉树,所以结点i是叶子结点);否则其左孩子是结点 2i

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

    • 5. 二叉树的Java实现

      下面是二叉树的Java实现:

      二叉树结构类:

      /**
       * Created by yuzhan on 2017/8/24.
       */
      public class TreeNode<T> {
          public T val;           //结点值
          public TreeNode<T> left;      //左结点的值
          public TreeNode<T> right;     //右结点的值
          public TreeNode(T data){
              this.val = data;
              this.left = null;
              this.right = null;
          }
          public TreeNode(){
      
          }
      }

      二叉树方法接口

      /**
       * 二叉树接口
       * Created by yuzhan on 2017/8/24.
       */
      public interface BinaryTree<T> {
      
          /**
           * 构造空二叉树
           */
          TreeNode InitBiTree();
      
          /**
           * 销毁二叉树
           */
          void DestroyBiTree(TreeNode tree);
      
          /**
           * 按Object[]构造二叉树
           */
          TreeNode CreateBiTree(Object[] array);
      
          /**
           * 将二叉树清为空树
           */
          void ClearBiTree(TreeNode tree);
      
          /**
           * 若二叉树存在,则返回TRUE,否则FALSE
           */
          Boolean BiTreeEmpty(TreeNode tree);
      
          /**
           * 返回二叉树的根
           * @return
           */
          T Root(TreeNode tree);
      
          /**
           * 先序遍历
           */
          void preOrderByRecurse(TreeNode node);
      
          /**
           * 中序遍历
           */
          void InOrderByRecurse(TreeNode root);
      
          /**
           * 后序遍历
           */
          public void PostOrderByRecurse(TreeNode root);
      
      }

      二叉树方法接口实现类

      import java.util.ArrayList;
      import java.util.List;
      /**
       * 二叉树接口实现类
       * Created by yuzhan on 2017/8/24.
       *
       */
      public class BinaryTreeImpl<T> implements BinaryTree<T>{
      
          /**
           *  构造空二叉树T
           */
          public TreeNode InitBiTree(){
              return new TreeNode();
          }
      
          /**
           * 销毁二叉树
           */
          public void DestroyBiTree(TreeNode tree){
              if(tree != null){
                  tree.val   = null;
                  tree.left  = null;
                  tree.right = null;
              }else{
                  throw new IllegalArgumentException("二叉树为空");
              }
          }
      
          /**
           * 按Object[]构造二叉树
           */
          public TreeNode CreateBiTree(Object[] array){
              if(array == null || array.length == 0){
                  throw new IllegalArgumentException("输入不合法");
              }else{
                  //将Object存入list中
                  List<TreeNode<T>> list = new ArrayList<>();
                  for(int i = 0;i < array.length;i++){
                      list.add(new TreeNode<T>((T) array[i]));
                  }
                  //为结点赋值(由于是完全二叉树构造方式,所以非叶子结点的数量为[n/2])
                  for(int j = 0;j < (list.size() /2);j++){
                      try {
                          //为左子树赋值 2*j + 1
                          if((2*j + 1) < list.size())
                              list.get(j).left = list.get(2 * j + 1);
                          else
                              list.get(j).left = null;
                          //为右子树赋值 2*j + 2
                          if((2*j + 2) < list.size())
                              list.get(j).right = list.get(2 * j + 2);
                          else
                              list.get(j).right = null;
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
                  TreeNode tree = new TreeNode();
                  //为根结点赋值
                  tree.val = list.get(0).val;
                  //为根结点的左子树赋值
                  if(list.get(0).left != null){
                      tree.left = list.get(0).left;
                  }else{
                      tree.left = null;
                  }
                  //为根结点的右子树赋值
                  if(list.get(0).right != null){
                      tree.right = list.get(0).right;
                  }else{
                      tree.right = null;
                  }
                  return tree;
              }
          }
      
          /**
           * 将二叉树清为空树
           */
          public void ClearBiTree(TreeNode tree){
              if(tree.val != null){
                  tree.val = null;
                  tree.right = null;
                  tree.left = null;
              }else{
                  throw new IllegalArgumentException("二叉树为空");
              }
          }
      
          /**
           * 若二叉树存在,则返回TRUE,否则FALSE
           */
          public Boolean BiTreeEmpty(TreeNode tree){
              if(tree.val != null){
                  return false;
              }else{
                  return true;
              }
          }
      
          /**
           * 返回二叉树的根
           * @return
           */
          public T Root(TreeNode tree){
              if(tree.val != null){
                  return (T) tree.val;
              }else{
                  throw new IllegalArgumentException("二叉树为空");
              }
          }
      
          /**
           * 先序遍历
           */
          public void preOrderByRecurse(TreeNode root) {
              if (root == null) {
                  return;
              }
              System.out.print(root.val+" ");
              preOrderByRecurse(root.left);
              preOrderByRecurse(root.right);
          }
      
          /**
           * 中序遍历
           */
          public void InOrderByRecurse(TreeNode root) {
              if (root == null) {
                  return;
              }
              InOrderByRecurse(root.left);
              System.out.print(root.val+" ");
              InOrderByRecurse(root.right);
          }
      
          /**
           * 后序遍历
           */
          public void PostOrderByRecurse(TreeNode root) {
              if (root == null) {
                  return;
              }
              PostOrderByRecurse(root.left);
              PostOrderByRecurse(root.right);
              System.out.print(root.val+" ");
          }
      }

      测试类

        public static void main(String[] args) {
              BinaryTree<Integer> bt = new BinaryTreeImpl<>();
              TreeNode tree;
              //tree = bt.InitBiTree();           // 初始化空二叉树
              //bt.DestroyBiTree(tree);           //销毁二叉树
              Object[] array = {1,2,3,4,5,6,7,8,9,10};
              tree = bt.CreateBiTree(array);      //构造二叉树
              //bt.ClearBiTree();                 //清空二叉树
              Boolean flag = bt.BiTreeEmpty(tree);//判断二叉树是否存在
              Integer root = bt.Root(tree);       //返回二叉树的根结点
              bt.preOrderByRecurse(tree);         //前序遍历
              System.out.println();
              bt.InOrderByRecurse(tree);          //中序遍历
              System.out.println();
              bt.PostOrderByRecurse(tree);        //后序遍历
          }
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值