1. 程式人生 > >資料結構(六)——樹結構(Tree) 基礎

資料結構(六)——樹結構(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);
    }
}