樹:整體理解

二叉查找樹

二叉查找樹出現的目的是使查詢的速率整體能夠維持在O(logn)上,而又不像鏈表那樣查詢一定需要O(logN)的時間復雜度,和數組那樣在增刪上會引起整個數組進行重構導致的效率問題.

二叉查找樹的特點

  • 二叉查找樹的的左子節點一定比當前節點小,右子節點一定比當前節點大.
  • 二叉查找樹不允許存在相同的值.

這樣在理想的情況下,二叉查找樹的查詢效率就在O(logN)上了.
二叉查找樹的實現

package Tree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * Created by Hammy on 2018/3/3.
 */
public class BST<T extends Comparable> implements BinarySearchTree<T>
{
    public TreeNode<T> root;

    public BST(){
        this.root = null;
    }

    public BST(T data){
        root = new TreeNode<T>(data,null,null);
    }
    @Override
    public boolean isEmpty() {
        return size()==0;
    }

    @Override
    public int size() {
        if(root==null)
            return 0;

        return size(root);
    }

    private int size(TreeNode<T> node){
        if(node==null)
            return 0;

        return size(node.left) + 1 + size(node.right);
    }

    @Override
    public int height() {
        if(root==null){
            return 0;
        }

        return height(root);
    }

    private int height(TreeNode<T> node){
        if(node==null)
            return 0;

        int left = height(node.left);
        int right = height(node.right);

        return (left>right)?(left+1):(right+1);
    }

    @Override
    public String preOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        TreeNode<T> tempNode = root;
        while(tempNode!=null||!stack.isEmpty()){
            if(tempNode!=null){
                stringBuffer.append(tempNode.data+",");
                stack.push(tempNode);
                tempNode=tempNode.left;
            }else{
                tempNode=stack.pop();
                tempNode=tempNode.right;
            }
        }
        return stringBuffer.toString();
    }

    @Override
    public String inOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        TreeNode<T> tempNode = root;
        while(tempNode!=null||!stack.isEmpty()){
            while(tempNode!=null){
                stack.push(tempNode);
                tempNode=tempNode.left;
            }
            if(!stack.isEmpty()){
                tempNode=stack.pop();
                stringBuffer.append(tempNode.data+",");
                tempNode=tempNode.right;
            }
        }

        return stringBuffer.toString();
    }

    @Override
    public String postOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        TreeNode<T> curNode = root;
        TreeNode<T> preNode = root;
        while(curNode!=null||!stack.isEmpty()){
            while(curNode!=null){
                stack.push(curNode);
                curNode=curNode.left;
            }
            if(!stack.isEmpty()){
                TreeNode<T> tempNode = stack.peek().right;
                if(tempNode==null||tempNode==preNode){
                    curNode=stack.pop();
                    stringBuffer.append(curNode.data+",");
                    preNode=curNode;
                    curNode=null;
                }else{
                    curNode=tempNode;
                }
            }
        }

        return stringBuffer.toString();
    }

    @Override
    public String levelOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Queue<TreeNode<T>> queue = new LinkedList<TreeNode<T>>();

        TreeNode<T> tempNode = root;
        while(tempNode!=null){
            stringBuffer.append(tempNode.data+",");
            if(tempNode.left!=null)
                queue.add(tempNode.left);
            if(tempNode.right!=null)
                queue.add(tempNode.right);

            tempNode=queue.poll();
        }

        return stringBuffer.toString();
    }

    @Override
    public void insert(T data) throws Exception {
        if(data==null)
            throw new Exception("data can't be null");

        root=insert(root,data);
    }

    private TreeNode<T> insert(TreeNode<T> node,T data){
        if(node==null){
            node=new TreeNode<T>(data,null,null);
        }else{
            int compareResult=data.compareTo(node.data);
            if(compareResult<0)
                node.left=insert(node.left,data);
            if(compareResult>0)
                node.right=insert(node.right,data);

        }
        return node;
    }

    @Override
    public T remove(T data) throws Exception {
        if(data==null)
            throw new Exception("data can't be null");

        return remove(root,data).data;
    }

    private TreeNode<T> remove(TreeNode<T> node,T data) throws Exception{
        if(node==null)
            return null;

        int compareResult=data.compareTo(node.data);
        if(compareResult>0){
            node.right=remove(node.right,data);
            return node;
        }
        if(compareResult<0){
            node.left=remove(node.left,data);
            return node;
        }
        //如果要刪除節點的左子樹為空
        if(node.left==null){
            TreeNode<T> rightNode = node.right;
            node.right=null;

            return rightNode;
        }
        if(node.right==null){
            TreeNode<T> leftNode = node.left;
            node.left=null;

            return leftNode;
        }
        //左右子樹都不為空
        TreeNode<T> successorNode = new TreeNode<T>(findMin(node.right).data,null,null);
        successorNode.left=node.left;
        successorNode.right=remove(node.right,data);
        //將原節點set null
        node.left=null;
        node.right=null;
        if(root.data==data)
            root=successorNode;

        return successorNode;
    }

    @Override
    public T findMax() throws Exception {
        if(root==null)
            throw new Exception("data can't be null");

        return findMax(root).data;
    }

    private TreeNode<T> findMax(TreeNode<T> node){
        TreeNode<T> tempNode = node;
        while(tempNode.right!=null){
            tempNode=tempNode.right;
        }

        return tempNode;
    }

    @Override
    public T findMin() throws Exception {
        if(root==null)
            throw new Exception("data can't be null");

        return findMin(root).data;
    }

    private TreeNode<T> findMin(TreeNode<T> node) throws Exception{
        TreeNode<T> tempNode = node;
        while(tempNode.left!=null)
            tempNode=tempNode.left;

        return tempNode;
    }

    @Override
    public boolean contain(T data) throws Exception {
        if(data==null)
            throw new Exception("data can't be null");

        return contain(root,data);
    }

    private boolean contain(TreeNode<T> node,T data){
        if(node==null)
            return false;

        int compareResult=data.compareTo(node.data);
        if(compareResult>0)
            return contain(node.right,data);
        if(compareResult<0)
            return contain(node.left,data);

        return true;
    }
}

二叉查找樹會引發的問題,如果當前數據幾乎是一個順序或者逆序的前提下,二叉查找樹就把一個偏向一邊甚至退化為鏈表.這樣就完全喪失了它存在的意義.

AVL樹

AVL樹是理想的平衡二叉樹,它保證左子節點和右子節點的深度最多相差1,但每次插入和刪除二叉樹整體都會進行旋轉.但它整體的查詢的效率維持在了O(logN)

B樹

B樹這種數據結構的特點就是深度低,這樣做的目的是減少訪問外存的次數.
B樹的節點設計為一個【k,v】對,這樣就可以根據k的規則就尋找想找的value值.
特點:

  • 一顆m階的b-tree最多有m個孩子
  • 除了根節點和葉子節點外,每個節點至少有Ceil(m/2)個孩子
    -所有葉子節點都在同一層.
    -關鍵字的個數n滿足:ceil(m/2)-1<=n<=m-1
  • ki(i=1,…n)為關鍵字,且關鍵字升序排序。
  • Pi(i=1,…n)為指向子樹根節點的指針。P(i-1)指向的子樹的所有節點關鍵字均小于ki,但都大于k(i-1)

B+樹

B+樹存在的目的是為了降低b樹的深度.特點如下:

  • 非葉子節點只存儲鍵值信息。
  • 所有葉子節點之間都有一個鏈指針。
  • 數據記錄都存放在葉子節點中。

引用:https://www.cnblogs.com/vianzhang/p/7922426.html

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結點至多有m個孩子。 除根結點和葉子結點外,其它每個結點至少有m...
    文檔隨手記閱讀 13,294評論 0 25
  • 目錄 0.樹0.1 一般樹的定義0.2 二叉樹的定義 1.查找樹ADT 2.查找樹的實現2.1 二叉查找樹2.2 ...
    王偵閱讀 7,314評論 0 3
  • B樹 1.前言: 動態查找樹主要有:二叉查找樹(Binary Search Tree),平衡二叉查找樹(Balan...
    鐵甲依然在_978f閱讀 1,459評論 0 4
  • 第八章 憂患 在長清韓宅已經住了一月余,決明的身體雖然緩慢但十分穩健的恢復著,再休養著時日就完全好了。她傷的全是皮...
    文婭君閱讀 174評論 0 0