二叉搜索樹(Binary Search Tree,BST)

来源:https://www.cnblogs.com/dupengpeng/archive/2023/09/12/17694918.html
-Advertisement-
Play Games

二叉搜索樹(Binary Search Tree,BST) 二叉搜索樹(Binary Search Tree),也稱二叉查找樹或二叉排序樹,是一種特殊的二叉樹,它滿足以下性質 對於二叉搜索樹的每個節點 左子樹中的所有節點的值都小於該節點的值 右子樹中的所有節點的值都大於(或等於)該節點的值 對於二叉 ...


二叉搜索樹(Binary Search Tree,BST)

二叉搜索樹(Binary Search Tree),也稱二叉查找樹或二叉排序樹,是一種特殊的二叉樹,它滿足以下性質

  1. 對於二叉搜索樹的每個節點
    • 左子樹中的所有節點的值都小於該節點的值
    • 右子樹中的所有節點的值都大於(或等於)該節點的值
  2. 對於二叉搜索樹的任意節點,其左子樹和右子樹也是二叉搜索樹。

由於這種特性,二叉搜索樹可以支持高效地進行查找、插入和刪除操作。對於查找操作,可以通過比較目標值與當前節點的值來決定向左子樹還是右子樹進行搜索。對於插入操作,可以按照比較結果找到合適的位置並插入新節點。對於刪除操作,則需要按照一定規則來處理不同情況下的節點刪除

插入節點

在二叉搜索樹中插入一個新節點的步驟如下:

  1. 如果樹為空,將新節點作為根節點。
  2. 如果樹不為空,從根節點開始遍歷樹。
  3. 比較要插入的值與當前節點的值。
    • 如果要插入的值小於當前節點的值,向左子樹方向繼續遍歷。
    • 如果要插入的值大於當前節點的值,向右子樹方向繼續遍歷。
    • 如果要插入的值等於當前節點的值,根據具體需求決定是替換當前節點的值還是忽略該值。
  4. 當遇到空節點時,表示找到了合適的位置插入新節點。
  5. 創建一個新節點,並將其插入到空節點的位置。
  6. 完成插入操作。

示例代碼:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}


class BinarySearchTree {
    private TreeNode root;

    public BinarySearchTree() {
        root = null;
    }

    // 插入節點
    public void insert(int val) {
        root = insertNode(root, val);
    }

    private TreeNode insertNode(TreeNode root, int val) {
        // 如果當前節點為空,說明找到了應該插入的位置,創建新節點並返回
        if (root == null) {
            return new TreeNode(val);
        }

        // 如果插入的值小於當前節點的值,向左子樹插入
        if (val < root.val) {
            root.left = insertNode(root.left, val);
        } else if (val > root.val) {
            // 如果插入的值大於當前節點的值,向右子樹插入
            root.right = insertNode(root.right, val);
        }

        return root;
    }
}

搜索節點(查找)

在二叉搜索樹中搜索一個特定值的步驟如下:

  1. 從根節點開始,將要搜索的值與當前節點的值進行比較。
  2. 如果要搜索的值等於當前節點的值,返回true,表示找到了目標值。
  3. 如果要搜索的值小於當前節點的值,則向左子樹方向繼續搜索。
  4. 如果要搜索的值大於當前節點的值,則向右子樹方向繼續搜索。
  5. 如果遇到空節點,則表示未找到目標值,返回false。
  6. 重覆步驟2至步驟5,直到找到目標值或搜索完整個樹。
    下麵是使用上述步驟實現搜索方法的示例代碼:
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    // 搜索節點
    public boolean search(int val) {
        return searchNode(root, val);
    }

    private boolean searchNode(TreeNode root, int val) {
        // 當前節點為空,未找到目標值
        if (root == null) {
            return false;
        }

        // 目標值與當前節點的值相等,找到目標值
        if (val == root.val) {
            return true;
        } else if (val < root.val) {
            // 目標值小於當前節點的值,在左子樹中繼續搜索
            return searchNode(root.left, val);
        } else {
            // 目標值大於當前節點的值,在右子樹中繼續搜索
            return searchNode(root.right, val);
        }
    }
}

刪除節點

在二叉搜索樹中刪除一個節點的步驟如下:

  1. 從根節點開始,找到要刪除的節點。
  2. 如果要刪除的值等於當前節點的值,根據下麵不同的情況進行處理:
    a. 若該節點為葉節點(沒有子節點),直接刪除該節點。
    b. 若該節點只有一個子節點,將其子節點替代該節點的位置。
    c. 若該節點有兩個子節點,找到右子樹中最小的節點(或左子樹中最大的節點),將該節點的值替代要刪除的節點的值,然後遞歸刪除該最小節點(或最大節點)。
  3. 如果要刪除的值小於當前節點的值,則向左子樹方向繼續搜索。
  4. 如果要刪除的值大於當前節點的值,則向右子樹方向繼續搜索。
  5. 當遇到空節點時,表示未找到要刪除的節點。
  6. 完成刪除操作。
    下麵是使用上述步驟實現刪除方法的示例代碼:
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    private TreeNode deleteNode(TreeNode root, int val) {
        // 當前節點為空,未找到要刪除的節點
        if (root == null) {
            return null;
        }

        // 如果要刪除的值小於當前節點的值,在左子樹中繼續搜索
        if (val < root.val) {
            root.left = deleteNode(root.left, val);
        } else if (val > root.val) {
            // 如果要刪除的值大於當前節點的值,在右子樹中繼續搜索
            root.right = deleteNode(root.right, val);
        } else {
            // 找到要刪除的節點
            // 情況1: 當節點沒有子節點時,直接返回 null
            if (root.left == null && root.right == null) {
                return null;
            }
            // 情況2: 當節點只有一個子節點時,返回子節點作為當前節點的替代
            if (root.left == null) {
                return root.right;
            } else if (root.right == null) {
                return root.left;
            }
            // 情況3: 當節點有兩個子節點時,找到右子樹中最小的節點,
            //       用該節點的值替代當前節點的值,並刪除右子樹中最小的節點
            TreeNode successor = findMin(root.right);
            root.val = successor.val;
            root.right = deleteNode(root.right, successor.val);
        }

        return root;
    }

    private TreeNode findMin(TreeNode node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在今天的移動互聯網時代,手機已經成為了人們不可或缺的重要工具,而手機的聯網狀態也是我們經常需要關註的一個問題。我們需要保證手機網路處於正常的連接狀態,但是有時候,由於種種原因,手機的網路可能會斷開,這時我們需要及時發現,併進行相應的處理措施。而利用Api介面實現手機網路連接斷開的監聽,便是一種較為高 ...
  • 遞歸函數和其他拓展 課前練習 請實現一個裝飾器,把'函數的返回值'+100然後'返回' def ount(fun): def werrod(*ardes,**warrrts): res=fun(*ardes,**warrrts) return res+100 return werrod @ount ...
  • ArrayList/MySQL數據集合寫入Excel 1.文章概述: 寫入 Excel 文件通常需要使用一些庫或工具,而"EasyExcel"通常是指的阿裡巴巴開源的EasyExcel庫。這個庫可以讓我們在Java中簡便地進行Excel文件的讀寫操作。 2.導入配置: <dependency> <g ...
  • 相信很多後端開發。對於前端知識是比較零碎的,所以很多時候寫表單這樣的工作,一般就是複製黏貼,然後改改欄位。對於HTML格式,一直覺得比較雜亂,不夠簡潔。 最近TJ發現了一個有趣的小工具:Create HTML Form。 看看上面它的Slogan,是不是很有意思?居然可以通過Markdown來編寫H ...
  • 如果你的 Python 程式採集到的數據在保存成 CSV 格式的文件時出現了亂碼,那麼可嘗試以下解決方法: 1. 在打開 CSV 文件時指定編碼方式 你可以使用 Python 中的 open() 函數打開 CSV 文件,併在 open() 函數中指定文件編碼方式為 CSV 文件原始編碼方式。如果 C ...
  • 在可執行文件PE文件結構中,通常我們需要用到地址轉換相關知識,PE文件針對地址的規範有三種,其中就包括了`VA`,`RVA`,`FOA`三種,這三種該地址之間的靈活轉換也是非常有用的,本節將介紹這些地址範圍如何通過編程的方式實現轉換。VA(Virtual Address,虛擬地址):它是在進程的虛擬... ...
  • 簡介 說明 本文介紹 Java 內部類持有外部類導致記憶體泄露的原因以及其解決方案。 為什麼內部類持有外部類會導致記憶體泄露 非靜態內部類會持有外部類,如果有地方引用了這個非靜態內部類,會導致外部類也被引用,垃圾回收時無法回收這個外部類(即使外部類已經沒有其他地方在使用了)。 解決方案 不要讓其他的地方 ...
  • 平衡二叉樹(Balanced Binary Tree) 平衡二叉樹是一種特殊的二叉搜索樹,它具有以下特點: 每個節點的左子樹和右子樹的高度差不超過1。 所有的子樹也都是平衡二叉樹。 通過保持平衡性,平衡二叉樹可以在最壞情況下仍然具有較好的性能,保證查找、插入和刪除操作的時間複雜度為O(log n)。 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...