数据结构(六)——树结构(Tree) 基础

一.什么是树结构?

树(Tree)结构是一种描述非线性层次关系的数据结构。树是n个数据结点的集合,在该集合中包含一个根结点,根结点下分布着一些互不交叉的子集合,这些子集合是根结点的子树。

树结构的基本特征如下:

  • 在一个树结构中,有且仅有一个结点没有直接前驱,这个结点就是树的根结点。
  • 除根结点外,其余每个结点有且仅有一个直接前驱。
  • 每个结点可以有任意多个直接后继。
  • 一个树结构也可以是空,空树没有数据结点,也就是一个空集合。
  • 如果树结构中仅包含一个结点,那么这也是一个树,树根便是该结点自身。

二.树的基本概念

1.父结点和子结点:一个节点含有的子树的根节点称为该节点的子节点,相应的,该结点称为其子结点的父结点。

2.兄弟结点:具有同一父结点的子结点。

3.结点的度:一个节点所包含子树的数量。

4.树的度:是该树所有结点中最大的度。

5.叶结点:树中度为零的结点称为叶结点或终端结点。

6.分支结点:树中度不为0的结点称为分支结点或非终端结点。

7.结点的层数:结点的层数从树根开始计算,根结点为第1层,依次向下为第2、3、......、n层(树是一种层次结构,每个结点都处在一定层次上)。

8.树的深度:树中结点的最大层数称为树的深度。

9.有序树:若树中各结点的子树(兄弟结点)是按一定次序从左向右排列的,称为有序树。

10.无序树:若树中各结点的子树(兄弟结点)未按一定次序排列,称为无序树。

11.森林(forest):n(n>0)棵互不相交的树的集合。

三.二叉树

1.什么是二叉树?

二叉树是数据结构的一种特殊形式,它是n个结点的结合,每个结点最多只能有两个子结点。二叉树的子树仍然是二叉树。二叉树的一个结点上对应的两个子树分别称为左子树和右子树。由于子树有左右之分,因此二叉树是有序树。

  • 二叉树结点的最大度是2。
  • 二叉树有左右子树的区别。

2.特殊的二叉树

(1)满二叉树

         满二叉树即在二叉树中除最下一层的叶结点外,每层的结点都有两个子结点。而且结点总数为:2^n-1。n是树的高度。

(2)完全二叉树

          完全二叉树即在除二叉树最后一层外,其他各层的结点树都达到最大个数,且最后一层叶结点按照从左向右的顺序连续存在,只缺最后一层右侧若干结点。

若树中包含n个结点,对于任意一个结点m来说,有如下性质:

  • 如果m!=1,则结点m的父结点的编号为m/2;
  • 如果2*m<=n,则结点m的左子树根结点的编号为2*m;若2*m+1>n,则无左子树,也没有右子树;
  • 如果2*m+1<=n,则结点m的右子树根结点编号为2*m+1;若2*m+1>n,则无右子树。
  • 对于该完全二叉树来说,其深度为[log2n]+1。

         满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树。

3.二叉树的顺序存储

树结构的顺序存储一般采用一维结构数组来表示。

顺序存储的二叉树通常情况只考虑完全二叉树。

  • 第n个元素的左子结点是2*n+1
  • 第n个元素的右子结点是2*n+2
  • 第n个元素的父结点是(n-1)/2

(1)二叉树抽象类

package cn.kimtian.tree.arraybinarytree;

/**
 * 顺序存储的二叉树
 *
 * @author kimtian
 */
public class ArrayBinaryTree {
    /**
     * 一个存储树的数组
     */
    int[] data;

    public ArrayBinaryTree(int[] data) {
        this.data = data;
    }
}

(2)给二叉树赋值 

package cn.kimtian.tree.arraybinarytree;

/**
 * 创建一个顺序存储的二叉树
 *
 * @author kimtian
 */
public class TestArrayBinaryTree {
    public static void main(String[] args) {
        int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        ArrayBinaryTree arrayBinaryTree = new ArrayBinaryTree(a);
    }
}

4.二叉树的链式存储

(1)二叉树抽象类

package cn.kimtian.tree;

/**
 * 链式存储的二叉树
 *
 * @author kimtian
 */
public class BinaryTree {
    /**
     * 根结点
     */
    TreeNode root;

    /**
     * 设置根结点
     *
     * @param root 根结点
     */
    public void setRoot(TreeNode root) {
        this.root = root;
    }

    /**
     * 获取根结点
     *
     * @return TreeNode 根结点
     */
    public TreeNode getRoot() {
        return root;
    }
}

(2)二叉树的结点

package cn.kimtian.tree;

/**
 * 树里面的结点
 *
 * @author kimtian
 */
public class TreeNode {
    /**
     * 树里面的值,结点的权
     */
    int value;
    /**
     * 左儿子
     */
    TreeNode leftNode;
    /**
     * 右儿子
     */
    TreeNode rightNode;

    public TreeNode(int value) {
        this.value = value;
    }

    public void setLeftNode(TreeNode leftNode) {
        this.leftNode = leftNode;
    }

    public void setRightNode(TreeNode rightNode) {
        this.rightNode = rightNode;
    }
}

 (3)给二叉树赋值

package cn.kimtian.tree;

/**
 * 测试链式存储的二叉树
 *
 * @author kimtian
 */
public class TestBinaryTree {
    public static void main(String[] args) {
        //创建一棵树
        BinaryTree binaryTree = new BinaryTree();
        //创建一个根结点
        TreeNode root = new TreeNode(1);
        //将根结点赋给树
        binaryTree.setRoot(root);
        //创建一个子左结点
        TreeNode leftTwo = new TreeNode(2);
        //创建一个子右结点
        TreeNode rightTwo = new TreeNode(3);
        //给根的左结点赋值
        root.setLeftNode(leftTwo);
        //给根的右结点赋值
        root.setRightNode(rightTwo);
    }
}

猜你喜欢

转载自blog.csdn.net/third_/article/details/85707472