搜尋
首頁Javajava教程Java二元搜尋樹實例分析

    概念

    二元搜尋樹又稱二元排序樹,它或是一棵空樹,或是具有以下性質的二元樹:
    1、若它的左子樹不為空,則左子樹上所有節點的值都小於根結點的值。
    2、若它的右子樹不為空,則右子樹上所有節點的值都大於根結點的值。
    3、它的左右子樹也分別為二元搜尋樹
    Java二元搜尋樹實例分析

    # 直接實踐

    準備工作:定義一個樹節點的類,和二元搜尋樹的類別。

    Java二元搜尋樹實例分析

    搜尋二元樹的尋找功能

    假設我們已經建構好了一個這樣的二元樹,如下圖

    Java二元搜尋樹實例分析

    我們要思考的第一個問題是如何找出某個值是否在該二元樹中?

    Java二元搜尋樹實例分析

    #根據上述的邏輯,我們來把搜尋的方法進行完善。

    Java二元搜尋樹實例分析

    搜尋二元樹的插入操作

    Java二元搜尋樹實例分析

    #根據上述邏輯,我們來寫一個插入節點的程式碼。

    Java二元搜尋樹實例分析

    搜尋二元樹刪除節點的操作- 難度

    Java二元搜尋樹實例分析

    再來分析:curDummy 和parentDummy 是怎麼找到「替罪羊」的。

    Java二元搜尋樹實例分析

    總程式- 模擬實作二元搜尋樹

    class TreeNode{
        public int val;
        public TreeNode left;
        public TreeNode right;
        public TreeNode(int val){
            this.val = val;
        }
    }
    
    
    public class BinarySearchTree {
        TreeNode root;
    
        //在二叉树中 寻找指定 val 值的节点
        // 找到了,返回其节点地址;没找到返回 null
        public TreeNode search(int key){
            TreeNode cur = this.root;
            while(cur != null){
                if(cur.val == key){
                    return cur;
                }else if(cur.val < key){
                    cur = cur.right;
                }else{
                    cur = cur.left;
                }
            }
            return null;
        }
        // 插入操作
        public boolean insert(int key){
            if(this.root == null){
                this.root = new TreeNode(key);
                return true;
            }
            TreeNode cur = this.root;
            TreeNode parent = null;
            while(cur!=null){
                if(key > cur.val){
                    parent  = cur;
                    cur = cur.right;
                }else if(cur.val == key){
                    return false;
                }else{
                    parent  = cur;
                    cur = cur.left;
                }
            }
            TreeNode node = new TreeNode(key);
            if(parent .val > key){
                parent.left = node;
            }else{
                parent.right = node;
            }
            return true;
        }
        // 删除操作
        public void remove(int key){
            TreeNode cur = root;
            TreeNode parent = null;
            // 寻找 删除节点位置。
            while(cur!=null){
                if(cur.val == key){
                    removeNode(cur,parent);// 真正删除节点的代码
                    break;
                }else if(cur.val < key){
                    parent = cur;
                    cur = cur.right;
                }else{
                    parent = cur;
                    cur = cur.left;
                }
            }
        }
        // 辅助删除方法:真正删除节点的代码
        private void removeNode(TreeNode cur,TreeNode parent){
            // 情况一
            if(cur.left == null){
                if(cur == this.root){
                    this.root = this.root.right;
                }else if( cur == parent.left){
                    parent.left = cur.right;
                }else{
                    parent.right = cur.right;
                }
                // 情况二
            }else if(cur.right == null){
                if(cur == this.root){
                    this.root = root.left;
                }else if(cur == parent.left){
                    parent.left = cur.left;
                }else{
                    parent.right = cur.left;
                }
                // 情况三
            }else{
                // 第二种方法:在删除节点的右子树中寻找最小值,
                TreeNode parentDummy = cur;
                TreeNode curDummy = cur.right;
                while(curDummy.left != null){
                    parentDummy = curDummy;
                    curDummy = curDummy.left;
                }
                // 此时 curDummy 指向的 cur 右子树
                cur.val = curDummy.val;
                if(parentDummy.left != curDummy){
                    parentDummy.right = curDummy.right;
                }else{
                    parentDummy.left = curDummy.right;
                }
    
            }
        }
       // 中序遍历
        public void inorder(TreeNode root){
            if(root == null){
                return;
            }
            inorder(root.left);
            System.out.print(root.val+" ");
            inorder(root.right);
        }
    
        public static void main(String[] args) {
            int[] array = {10,8,19,3,9,4,7};
            BinarySearchTree binarySearchTree = new BinarySearchTree();
            for (int i = 0; i < array.length; i++) {
                binarySearchTree.insert(array[i]);
            }
            binarySearchTree.inorder(binarySearchTree.root);
            System.out.println();// 换行
            System.out.print("插入重复的数据 9:" + binarySearchTree.insert(9));
            System.out.println();// 换行
            System.out.print("插入不重复的数据 1:" + binarySearchTree.insert(1));
            System.out.println();// 换行
            binarySearchTree.inorder(binarySearchTree.root);
            System.out.println();// 换行
            binarySearchTree.remove(19);
            System.out.print("删除元素 19 :");
            binarySearchTree.inorder(binarySearchTree.root);
            System.out.println();// 换行
            System.out.print("查找不存在的数据50 :");
            System.out.println(binarySearchTree.search(50));
            System.out.print("查找存在的数据 7:");
            System.out.println(binarySearchTree.search(7));
        }
    }

    Java二元搜尋樹實例分析

    效能分析

      插入和刪除操作都必須先查找,查找效率代表了二叉搜尋樹中各個操作的效能。

      對有n個結點的二元搜尋樹,若每個元素查找的機率相等,則二叉搜尋樹平均查找長度是結點在二叉搜尋樹的深度的函數,即結點越深,則比較次數越多。

      但對於同一個關鍵碼集合,如果各關鍵碼插入的次序不同,可能得到不同結構的二元搜尋樹:
    Java二元搜尋樹實例分析

    如果我們能保證二元搜尋樹的左右子樹高度差不超過1。盡量滿足高度平衡條件。
    這就變成 AVL 樹了(高度平衡的二元搜尋樹)。而AVL樹,也有缺點:需要一個頻繁的旋轉。浪費很多效率。
    至此 紅黑樹就誕生了,避免更多的旋轉。

    和java 類別集的關係

    TreeMap 和TreeSet 即java 中利用搜尋樹實現的Map 和Set;實際上用的是紅黑樹,而紅黑樹是一棵近似平衡的二元搜尋樹,即在二元搜尋樹的基礎之上顏色以及紅黑樹性質驗證,關於紅黑樹的內容,等博主學了,會寫博客的。

    以上是Java二元搜尋樹實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述
    本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
    如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

    本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

    如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

    本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

    如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

    本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

    如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

    本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

    Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

    Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

    See all articles

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳圖形設置
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您聽不到任何人,如何修復音頻
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    WWE 2K25:如何解鎖Myrise中的所有內容
    1 個月前By尊渡假赌尊渡假赌尊渡假赌

    熱工具

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    Atom編輯器mac版下載

    Atom編輯器mac版下載

    最受歡迎的的開源編輯器

    VSCode Windows 64位元 下載

    VSCode Windows 64位元 下載

    微軟推出的免費、功能強大的一款IDE編輯器

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    DVWA

    DVWA

    Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中