搜索二叉樹的實現


定義二叉樹的節點:包含左節點,右節點和當前結點的值
    /**
     * 定義二叉搜索樹的節點
     * @param <AnyType>
     */
    private static class BinaryNode<AnyType>{
        BinaryNode(AnyType theElement){
            this(theElement, null, null);
        }
        //通過構造函數創建節點
        BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
            this.theElement = theElement;
            this.left = left;
            this.right = right;
        }

        AnyType theElement;
        BinaryNode left;
        BinaryNode right;
    }
節點之間的比較方法:通過自定義的Comparator或默認的Compare方法
    /**
     * 定義比較方法:若傳入了比較方式,則用傳入的比較方式,否則用默認方式
     * 返回為0表示 lhs = rhs
     * 返回為負數表示 lhs < rhs
     * 返回為正數表示 lhs > rhs
     * @param lhs
     * @param rhs
     * @return
     */
    private int myCompare(AnyType lhs, AnyType rhs){
        if (cmp != null){
            return cmp.compare(lhs, rhs);
        } else {
            return  ((Comparable)lhs).compareTo(rhs);
        }
    }
查找結點:比較傳入的元素與當前結點元素的值,若傳入的元素小于當前節點的元素,則繼續查找當前結點的左子樹,若大于,則繼續查找當前結點的右子樹,若等于,表示找到該節點,返回true。
    /**
     * 搜索二叉樹中是否包含某個元素節點
     * @param x
     * @param t
     * @return
     */
    private boolean contains(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return false;
        }
        //比較元素與當前結點的元素
        int compareResult = myCompare(x, t.theElement);
        //小于當前元素,則搜索左子樹
        if (compareResult < 0){
            contains(x, t.left);
        }
        //大于當前元素,則搜索右子樹
        else if (compareResult > 0){
            contains(x, t.right);
        }
        //等于情況,表示存在,直接返回
        return true;
    }
插入節點:若當前結點為空,則將新節點放置此處,否則判斷傳入的值與當前節點的值,若傳入的值小于當前結點的值則繼續搜索當前結點的左子樹,若大于,則繼續搜索當前結點的右子樹。
    /**
     * 實現插入操作
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
        //當前節點為空,則將該節點在此處
        if (t == null){
            return new BinaryNode<AnyType>(x, null, null);
        }
        //進行比較
        int compareResult = myCompare(x, t.theElement);
        //元素小于當前結點元素,則加入到左子樹
        if (compareResult < 0){
            t.left = insert(x, t.left);
        } else if (compareResult > 0){
            t.right = insert(x, t.right);
        } else {
            //do nothing
        }
        return t;
    }
刪除某個節點:先根據給定的值找到要刪除的節點,若沒有找到該節點,則不會進行刪除操作。

a. 刪除的節點為葉子節點,即沒有孩子,則直接刪除即可,不會破壞樹的結構。

Paste_Image.png

b. 若節點中只包含左子樹,或只包含右子樹,則直接刪除該節點,并將其左子樹或右子樹設置為父節點的左子樹或右子樹即可。

Paste_Image.png

c. 當刪除的節點中包含左右子樹時,一般的策略是用其右子樹的最小數據代替要刪除的節點,并遞歸刪除該節點。因為右子樹的最小節點是不可能有左子樹的,因此第二次刪除較為容易。

Paste_Image.png

如上圖,我們要刪除的節點是5,則找到該節點,然后找到節點值為5的右子樹的最小節點,即節點值為6的節點--->將節點值為6的節點代替要刪除的節點5---->然后遞歸刪除原本的節點6

    /**
     * 實現移除某個節點
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return t;
        }
        //比較大小
        int compareResult = myCompare(x, t.theElement);
        //元素小于當前結點元素,則搜索左子樹
        if (compareResult < 0){
            t.left = remove(x, t.left);
        }
        //元素大于當前結點元素,則搜索右子樹
        else if (compareResult > 0){
            t.right = remove(x, t.right);
        }
        //相等,表示找到對應的節點,如果該節點存在左右孩子
        else if (t.left != null && t.right != null){
            //搜索到右子樹的最小節點,并替代當前結點
            t.theElement = (AnyType) findMin(t.right).theElement;
            //并遞歸刪除右子樹的最小節點
            t.right = remove(t.theElement, t.right);
        }
        //否則,將不為空的孩子節點替代掉當前結點
        else {
            t = (t.left != null) ? t.left : t.right;
        }
        return t;
    }
查找最大的節點:不斷向右邊搜索節點,直到該節點不存在右邊子節點。
查找最小的節點:不斷向左邊搜索節點,直到該節點不存在左邊子節點。
    /**
     *  實現獲取二叉樹中最小的節點
     *  遞歸查找左子樹,直到當前結點的左節點為空,則返回當前節點
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.left == null){
            return t;
        }
        return findMin(t.left);
    }

    /**
     * 實現獲取二叉樹中最大的節點
     * 遞歸查找右子樹,直到當前節點的右節點為空,返回當前節點
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.right == null){
            return t;
        }
        return findMax(t.right);
    }

實現三種遍歷樹的方式:
/**
     * 前序遍歷
     * 訪問順序為:根節點->左節點->右節點
     * @param node
     */
    public void preOrder(BinaryNode<AnyType> node){
        if (node != null){
            System.out.print(node.right + " ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    /**
     * 中序遍歷
     * 訪問順序為:左節點->根節點->右節點
     * @param node
     */
    public void inOrder(BinaryNode<AnyType> node){
        if (node != null){
            inOrder(node.left);
            System.out.print(node.theElement + " ");
            inOrder(node.right);
        }
    }

    /**
     * 后序遍歷
     * 訪問順序為:左節點->右節點->根節點
     * @param node
     */
    public void postOrder(BinaryNode<AnyType> node){
        if (node != null){
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.theElement + " ");
        }
    }
完整代碼:
package BinaryTree;

import org.omg.CORBA.Any;

import java.nio.BufferUnderflowException;
import java.util.Comparator;

/**
 * Created by Administrator on 2017/3/7/007.
 * 實現搜索二叉樹的基本操作
 */
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {

    /**
     * 定義二叉搜索樹的節點
     * @param <AnyType>
     */
    private static class BinaryNode<AnyType>{
        BinaryNode(AnyType theElement){
            this(theElement, null, null);
        }
        //通過構造函數創建節點
        BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
            this.theElement = theElement;
            this.left = left;
            this.right = right;
        }

        AnyType theElement;
        BinaryNode left;
        BinaryNode right;
    }

    /**
     * 定義二叉樹的根節點
     */
    private BinaryNode<AnyType> root;

    /**
     * 定義比較方式
     */
    private Comparator<? super AnyType> cmp;

    public BinarySearchTree(){
        this(null);
    }

    /**
     * 構造函數,傳入比較方式
     * @param c
     */
    public BinarySearchTree(Comparator<? super AnyType> c){
        root = null;
        cmp = c;
    }

    /**
     * 定義比較方法:若傳入了比較方式,則用傳入的比較方式,否則用默認的方法
     * @param lhs
     * @param rhs
     * @return
     */
    private int myCompare(AnyType lhs, AnyType rhs){
        if (cmp != null){
            return cmp.compare(lhs, rhs);
        } else {
            return  ((Comparable)lhs).compareTo(rhs);
        }

    }

    /**
     * 使二叉樹變為空
     */
    public void makeEmpty(){
        root = null;
    }

    /**
     * 檢查二叉樹是否為空
     * @return
     */
    public boolean isEmpty(){
        return root == null;
    }

    /**
     * 檢查二叉樹中是否包含某個元素
     * @param x
     * @return
     */
    public boolean contains(AnyType x){
        return contains(x, root);
    }

    /**
     * 搜索查找二叉樹中最小的元素
     * @return
     */
    public AnyType findMin(){
        if (isEmpty()) throw new BufferUnderflowException();
        return findMin(root).theElement;
    }

    /**
     * 搜索查找二叉樹中最大的元素
     * @return
     */
    public AnyType findMax(){
        if (isEmpty()) throw new BufferUnderflowException();
        return findMax(root).theElement;
    }

    /**
     * 插入元素
     * @param x
     */
    public void insert(AnyType x){
        root = insert(x, root);
    }

    /**
     * 刪除元素
     * @param x
     */
    public void remove(AnyType x){
        root = remove(x, root);
    }


    /**
     * 搜索二叉樹中是否包含某個元素節點
     * @param x
     * @param t
     * @return
     */
    private boolean contains(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return false;
        }
        //比較元素與當前結點的元素
        int compareResult = myCompare(x, t.theElement);
        //小于當前元素,則搜索左子樹
        if (compareResult < 0){
            contains(x, t.left);
        }
        //大于當前元素,則搜索右子樹
        else if (compareResult > 0){
            contains(x, t.right);
        }
        //等于情況,表示存在,直接返回
        return true;
    }

    /**
     *  實現獲取二叉樹中最小的節點
     *  遞歸查找左子樹,直到當前結點的左節點為空,則返回當前節點
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.left == null){
            return t;
        }
        return findMin(t.left);
    }

    /**
     * 實現獲取二叉樹中最大的節點
     * 遞歸查找右子樹,直到當前節點的右節點為空,返回當前節點
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.right == null){
            return t;
        }
        return findMax(t.right);
    }

    /**
     * 實現插入操作
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
        //當前節點為空,則將該節點在此處
        if (t == null){
            return new BinaryNode<AnyType>(x, null, null);
        }
        //進行比較
        int compareResult = myCompare(x, t.theElement);
        //元素小于當前結點元素,則加入到左子樹
        if (compareResult < 0){
            t.left = insert(x, t.left);
        } else if (compareResult > 0){
            t.right = insert(x, t.right);
        } else {
            //do nothing
        }
        return t;
    }

    /**
     * 實現移除某個節點
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return t;
        }
        //比較大小
        int compareResult = myCompare(x, t.theElement);
        //元素小于當前結點元素,則搜索左子樹
        if (compareResult < 0){
            t.left = remove(x, t.left);
        }
        //元素大于當前結點元素,則搜索右子樹
        else if (compareResult > 0){
            t.right = remove(x, t.right);
        }
        //相等,表示找到對應的節點,如果該節點存在左右孩子
        else if (t.left != null && t.right != null){
            //搜索到右子樹的最小節點,并替代當前結點
            t.theElement = (AnyType) findMin(t.right).theElement;
            //并遞歸刪除右子樹的最小節點
            t.right = remove(t.theElement, t.right);
        }
        //否則,將不為空的孩子節點替代掉當前結點
        else {
            t = (t.left != null) ? t.left : t.right;
        }
        return t;
    }

    /**
     * 前序遍歷
     * 訪問順序為:根節點->左節點->右節點
     * @param node
     */
    public void preOrder(BinaryNode<AnyType> node){
        if (node != null){
            System.out.print(node.right + " ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    /**
     * 中序遍歷
     * 訪問順序為:左節點->根節點->右節點
     * @param node
     */
    public void inOrder(BinaryNode<AnyType> node){
        if (node != null){
            inOrder(node.left);
            System.out.print(node.theElement + " ");
            inOrder(node.right);
        }
    }

    /**
     * 后序遍歷
     * 訪問順序為:左節點->右節點->根節點
     * @param node
     */
    public void postOrder(BinaryNode<AnyType> node){
        if (node != null){
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.theElement + " ");
        }
    }

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,384評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內容

  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結點至多有m個孩子。 除根結點和葉子結點外,其它每個結點至少有m...
    文檔隨手記閱讀 13,285評論 0 25
  • 數據結構與算法--從平衡二叉樹(AVL)到紅黑樹 上節學習了二叉查找樹。算法的性能取決于樹的形狀,而樹的形狀取決于...
    sunhaiyu閱讀 7,674評論 4 32
  • 數據結構和算法--二叉樹的實現 幾種二叉樹 1、二叉樹 和普通的樹相比,二叉樹有如下特點: 每個結點最多只有兩棵子...
    sunhaiyu閱讀 6,498評論 0 14
  • 四、樹與二叉樹 1. 二叉樹的順序存儲結構 二叉樹的順序存儲就是用數組存儲二叉樹。二叉樹的每個結點在順序存儲中都有...
    MinoyJet閱讀 1,567評論 0 7
  • 特里莎修女說:“人們經常是不講道理的、沒有邏輯的和以自我為中心的,不管怎樣,你要原諒他們。即使你是友善的,人們可能...
    petitsh閱讀 346評論 0 1