數據結構 - 二叉搜索樹(Binary Search Tree)

接上章: 二叉樹簡介

本章主要介紹二叉搜索樹的性質以及二叉搜索樹節點的增加和刪除操作。

?二叉搜索樹是二叉樹的一種,是應用非常廣泛的一種二叉樹,英文簡稱為 BST ,又被稱為:二叉查找樹、二叉排序樹 。

一、【二叉搜索樹】性質:

二叉搜索樹性質:
?任意一個節點的值都大于其左子樹所有節點的值 ;
?任意一個節點的值都小于其右子樹所有節點的值 ;
?它的左右子樹也是一棵二叉搜索樹
? 二叉搜索樹可以大大提高搜索數據的效率
? 二叉搜索樹存儲的元素必須具備可比較性,比如 int、double 等;
?如果是自定義類型,需要指定比較方式 ,不允許為 null


001.png
二、【二叉搜索樹】節點的增加和刪除。

?1.二叉搜索樹節點的添加
節點的添加分三步走策略:
1.1 找到父節點 parent
1.2 創建新節點 node
1.3 parent.left == node 或者parent.right = node
注意:遇到相等的元素,建議覆蓋舊值

如添加1、11。如下圖所示:

002.JPG

二叉搜索樹【添加】節點核心偽代碼:

public void add(E element) {
        elementNotNullCheck(element);
        
        // 添加第一個節點
        if (root == null) {
            root = new Node<>(element, null);
            size++;
            return;
        }
        
        // 添加的不是第一個節點
        // 找到父節點
        Node<E> parent = root;
        Node<E> node = root;
        int cmp = 0;
        while (node != null) {
            cmp = compare(element, node.element);
            //記錄父節點
            parent = node;
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) {
                node = node.left;
            } else { // 相等
                node.element = element;
                return;
            }
        }

        // 看看插入到父節點的哪個位置
        Node<E> newNode = new Node<>(element, parent);
        if (cmp > 0) {
            parent.right = newNode;
        } else {
            parent.left = newNode;
        }
    }

?2.二叉搜索樹節點的刪除
相對于二叉搜索樹節點的添加,這里二叉搜索樹的刪除就相對比較麻煩一點,分為節點為三種情況,分別是葉子節點的刪除度為1節點的刪除度為2節點的刪除

?2.二叉搜索樹節點的刪除

?2.1 葉子節點的刪除
? 直接刪除
? node == node.parent.left
? node.parent.left = null

? node == node.parent.right
? node.parent.right = null

? node.parent == null
? root = null

003.jpg
?2.2 度為1節點的刪除

? 用 子節點【替代】原節點的位置
?child 是 node.left 或者 child 是 node.right
?用 child 替代 node 的位置

?如果node 是左子節點
?child.parent = node.parent
?node.parent.left = child
?如果node 是右子節點
?child.parent = node.parent
?node.parent.right = child
?如果node 是根節點
?root = child
?child.parent = null

003-2.jpg

?2.3 度為2節點的刪除

? 先用前驅或者后繼節點的值覆蓋原節點的值
? 然后刪除相應的前驅或者后繼節點
如果一個節點的度為 2,那么,它的前驅、后繼節點的度只可能是 1 和 0

003-3.jpg

二叉搜索樹【刪除】節點核心偽代碼:

private void remove(Node<E> node) {
        if (node == null) return;
        // 度為2的節點
        if (node.hasTwoChildren()) { 
            // 找到后繼節點
            Node<E> s = successor(node);
            // 用后繼節點的值覆蓋度為2的節點的值
            node.element = s.element;
            // 刪除后繼節點
            node = s;
        }
        
        // 刪除node節點(node的度必然是1或者0)
        Node<E> replacement = node.left != null ? node.left : node.right;
        // node是度為1的節點
        if (replacement != null) { 
            // 更改parent
            replacement.parent = node.parent;
            // 更改parent的left、right的指向
            if (node.parent == null) { // node是度為1的節點并且是根節點
                root = replacement;
            } else if (node == node.parent.left) {
                node.parent.left = replacement;
            } else { // node == node.parent.right
                node.parent.right = replacement;
            }
        } else if (node.parent == null) { // node是葉子節點并且是根節點
            root = null;
        } else { // node是葉子節點,但不是根節點
            if (node == node.parent.left) {
                node.parent.left = null;
            } else { // node == node.parent.right
                node.parent.right = null;
            }
        }
    }

這里記錄下二叉搜索樹的性質以及二叉搜索樹節點的添加和刪除,便于以后查閱學習。

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