1. 程式人生 > >二叉查詢樹中節點的包含,插入,刪除操作

二叉查詢樹中節點的包含,插入,刪除操作

二叉查詢樹

最近在看大話資料結構,遇到二叉查詢樹,原理上聽起來比較簡單,但是要實際寫程式碼實現的時候感覺還是有點困難。

1. 二叉查詢樹的定義:

        一棵空數,或者是具有如下性質的二叉樹:

        ①若左子樹不空,則左子樹上所有節點的值均小於它根節點上的值。

        ②若右子樹不空,則右子樹上所有節點的值均小於它根節點上的值。

        ③它的左右子樹也分別為二叉查詢樹。

        特別注意:二叉查詢樹一定要滿足左子樹上的值全部比根節點小,右子樹上的值全部比根節點大。

2.二叉查詢樹的包含:

        判斷某個節點是否在二叉查詢樹上,原理實現應該是很容易,將目標值與根節點比較,大於根節點的值,則以根節點的右節點遞迴,小於根節點的值,則以根節點的左節點遞迴。相等的時候,則返回正確值。

程式碼實現:

public boolean contains(TreeNode t, int key){
        if(t == null){
            return false; 
        }
        if(t.val < key){
            return contains(t.right, key);
        }if(t.val > key){
            return contains(t.left, key);
        }else{
            return true;
        }
    }

3.二叉查詢樹的最大,最小值:

        二叉查詢樹的最大最小值應該是比較容易實現的,根據定義,最左端的葉子節點上的值即為最小值,最右端的葉子節點上的值即為最大值。(最小值將right改為left即可)

程式碼實現:

非遞迴實現:

public TreeNode findMax(TreeNode t){
        if(t == null){
            return null;
        }
        while(t.right != null){
            t = t.right;
        }
        return t;
    }

遞迴實現:

public TreeNode findMax(TreeNode t){
        if(t == null){
            return null;
        }
        if(t.right == null){
            return t;
        }
        return findMax(t.right);
    }

4.二叉查詢樹的插入:

可以想象,插入一個節點,即是在某個節點上面多加一條分支,但是如果樹中某個節點的值與其相等的話,則不做任何操作。

public TreeNode insert(TreeNode t, int key){
        if(t == null){
            return new TreeNode(key);
        }
        if(t.val < key){
            t.right = insert(t.right, key);
        }if(t.val > key){
            t.left = insert(t.left, key);
        }else{};

        return t;
    }

5.二叉查詢樹的刪除:

刪除是二叉查詢樹中最為複雜的一個操作,可以分成三種情況來考慮:

①若是葉子節點的話,只需要將其賦值為空即可;

②若僅包含左節點或者右節點,則將其左節點或者右節點的值賦給其本身,將左右節點賦值為空;

③若既包含左節點,也包含右節點,則可以通過中序遍歷將其前驅(或後繼)節點的值賦給其本身,將前驅(後繼)

    節點刪除。

程式碼實現:

實現一:

public TreeNode remove(TreeNode t, int key){
        if(t == null){
            return null;
        }
        if(t.val == key){
            if(t.left != null && t.right == null){
                t = t.left;
            }else if(t.right != null && t.left == null){
                t = t.right;
            }else if(t.right != null && t.left != null){
                t.val = findMax(t.left).val;
                remove(t.left, t.val);
            }else{
                t = null;
            }
        }else if(t.val < key){
            t.right = remove(t.right, key);
        }else {
            t.left = remove(t.left, key);
        }
        return t;
    }

實現二:

public TreeNode remove1(TreeNode t, int key){
        if(t == null){
            return t;
        }
        if(t.val < key){
            t.right = remove1(t.right, key);
        }else if(t.val > key){
            t.left = remove1(t.left, key);
        }else if(t.left != null && t.right != null){
            t.val = findMin(t.right).val;
            t.right = remove1(t.right, t.val);
        }else{
            t = (t.left != null) ? t.left : t.right;
        }
        return t;
    }

實現二中findMin方法為前面二叉查詢樹的最小值的方法。

實現一和二的區別在於若左右節點均不為空的時候,一個使用的是前驅,一個使用的是後繼來代替。