C#二叉搜索樹(shù)算法實(shí)現(xiàn)步驟和實(shí)例代碼
二叉搜索樹(shù)算法實(shí)現(xiàn)原理
二叉搜索樹(shù)(Binary Search Tree,簡(jiǎn)稱(chēng)BST)是一種節(jié)點(diǎn)有序排列的二叉樹(shù)數(shù)據(jù)結(jié)構(gòu)。它具有以下性質(zhì):
- 每個(gè)節(jié)點(diǎn)最多有兩個(gè)子節(jié)點(diǎn)。
- 對(duì)于每個(gè)節(jié)點(diǎn),其左子樹(shù)的所有節(jié)點(diǎn)值都小于該節(jié)點(diǎn)值,其右子樹(shù)的所有節(jié)點(diǎn)值都大于該節(jié)點(diǎn)值。
實(shí)現(xiàn)基本步驟和代碼示例
步驟
- 定義節(jié)點(diǎn)類(lèi):包含節(jié)點(diǎn)值、左子節(jié)點(diǎn)和右子節(jié)點(diǎn)。
- 插入節(jié)點(diǎn):遞歸或迭代地將新值插入到樹(shù)中合適的位置。
- 搜索節(jié)點(diǎn):根據(jù)節(jié)點(diǎn)值在樹(shù)中查找特定值。
- 刪除節(jié)點(diǎn):從樹(shù)中刪除特定值的節(jié)點(diǎn),并維護(hù)樹(shù)的結(jié)構(gòu)。
- 遍歷樹(shù):包括前序遍歷、中序遍歷、后序遍歷和層次遍歷等。
完整代碼示例
namespace HelloDotNetGuide.常見(jiàn)算法 { public class 二叉搜索樹(shù)算法 { public static void BinarySearchTreeRun() { var bst = new BinarySearchTree(); // 插入一些值到樹(shù)中 bst.Insert(50); bst.Insert(30); bst.Insert(20); bst.Insert(40); bst.Insert(70); bst.Insert(60); bst.Insert(80); bst.Insert(750); Console.WriteLine("中序遍歷(打印有序數(shù)組):"); bst.InorderTraversal(); Console.WriteLine("\n"); // 查找某些值 Console.WriteLine("Search for 40: " + bst.Search(40)); // 輸出: True Console.WriteLine("Search for 25: " + bst.Search(25)); // 輸出: False Console.WriteLine("\n"); // 刪除某個(gè)值 bst.Delete(50); Console.WriteLine("刪除50后:"); bst.InorderTraversal(); } } /// <summary> /// 定義二叉搜索樹(shù)的節(jié)點(diǎn)結(jié)構(gòu) /// </summary> public class TreeNode { public int Value; public TreeNode Left; public TreeNode Right; public TreeNode(int value) { Value = value; Left = null; Right = null; } } /// <summary> /// 定義二叉搜索樹(shù)類(lèi) /// </summary> public class BinarySearchTree { private TreeNode root; public BinarySearchTree() { root = null; } #region 插入節(jié)點(diǎn) /// <summary> /// 插入新值到二叉搜索樹(shù)中 /// </summary> /// <param name="value">value</param> public void Insert(int value) { if (root == null) { root = new TreeNode(value); } else { InsertRec(root, value); } } private void InsertRec(TreeNode node, int value) { if (value < node.Value) { if (node.Left == null) { node.Left = new TreeNode(value); } else { InsertRec(node.Left, value); } } else if (value > node.Value) { if (node.Right == null) { node.Right = new TreeNode(value); } else { InsertRec(node.Right, value); } } else { //值已經(jīng)存在于樹(shù)中,不再插入 return; } } #endregion #region 查找節(jié)點(diǎn) /// <summary> /// 查找某個(gè)值是否存在于二叉搜索樹(shù)中 /// </summary> /// <param name="value">value</param> /// <returns></returns> public bool Search(int value) { return SearchRec(root, value); } private bool SearchRec(TreeNode node, int value) { // 如果當(dāng)前節(jié)點(diǎn)為空,表示未找到目標(biāo)值 if (node == null) { return false; } // 如果找到目標(biāo)值,返回true if (node.Value == value) { return true; } // 遞歸查找左子樹(shù)或右子樹(shù) if (value < node.Value) { return SearchRec(node.Left, value); } else { return SearchRec(node.Right, value); } } #endregion #region 中序遍歷 /// <summary> /// 中序遍歷(打印有序數(shù)組) /// </summary> public void InorderTraversal() { InorderTraversalRec(root); } private void InorderTraversalRec(TreeNode root) { if (root != null) { InorderTraversalRec(root.Left); Console.WriteLine(root.Value); InorderTraversalRec(root.Right); } } #endregion #region 刪除節(jié)點(diǎn) /// <summary> /// 刪除某個(gè)值 /// </summary> /// <param name="val">val</param> public void Delete(int val) { root = DeleteNode(root, val); } private TreeNode DeleteNode(TreeNode node, int val) { if (node == null) { return null; } if (val < node.Value) { node.Left = DeleteNode(node.Left, val); } else if (val > node.Value) { node.Right = DeleteNode(node.Right, val); } else { // 節(jié)點(diǎn)有兩個(gè)子節(jié)點(diǎn) if (node.Left != null && node.Right != null) { // 使用右子樹(shù)中的最小節(jié)點(diǎn)替換當(dāng)前節(jié)點(diǎn) TreeNode minNode = FindMin(node.Right); node.Value = minNode.Value; node.Right = DeleteNode(node.Right, minNode.Value); } // 節(jié)點(diǎn)有一個(gè)子節(jié)點(diǎn)或沒(méi)有子節(jié)點(diǎn) else { TreeNode? temp = node.Left != null ? node.Left : node.Right; node = temp; } } return node; } /// <summary> /// 找到樹(shù)中的最小節(jié)點(diǎn) /// </summary> /// <param name="node"></param> /// <returns></returns> private TreeNode FindMin(TreeNode node) { while (node.Left != null) { node = node.Left; } return node; } #endregion } }
輸出結(jié)果:
數(shù)組與搜索樹(shù)的效率對(duì)比
二叉搜索樹(shù)的各項(xiàng)操作的時(shí)間復(fù)雜度都是對(duì)數(shù)階,具有穩(wěn)定且高效的性能。只有在高頻添加、低頻查找刪除數(shù)據(jù)的場(chǎng)景下,數(shù)組比二叉搜索樹(shù)的效率更高。
二叉搜索樹(shù)常見(jiàn)應(yīng)用
- 用作系統(tǒng)中的多級(jí)索引,實(shí)現(xiàn)高效的查找、插入、刪除操作。
- 作為某些搜索算法的底層數(shù)據(jù)結(jié)構(gòu)。
- 用于存儲(chǔ)數(shù)據(jù)流,以保持其有序狀態(tài)。
C#數(shù)據(jù)結(jié)構(gòu)與算法實(shí)戰(zhàn)入門(mén)指南
參考文章
- https://www.hello-algo.com/chapter_tree/binary_search_tree
- https://www.hello-algo.com/chapter_tree/binary_tree_traversal
到此這篇關(guān)于C#二叉搜索樹(shù)算法的文章就介紹到這了,更多相關(guān)C#二叉搜索樹(shù)算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解MongoDB for C#基礎(chǔ)入門(mén)
本篇文章主要介紹了MongoDB for C#基礎(chǔ)入門(mén),具體介紹了c#中關(guān)于對(duì)MongoDB的連接,插入,查詢(xún)等,有需要的可以了解一下。2016-12-12Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)效果的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)的效果,文中的實(shí)現(xiàn)步驟講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2022-12-12C#使用DateTime.Now靜態(tài)屬性動(dòng)態(tài)獲得系統(tǒng)當(dāng)前日期和時(shí)間
本文主要介紹了C#使用DateTime.Now靜態(tài)屬性動(dòng)態(tài)獲得系統(tǒng)當(dāng)前日期和時(shí)間,DateTime結(jié)構(gòu)的Now靜態(tài)屬性只是得到一個(gè)系統(tǒng)時(shí)間對(duì)象,該時(shí)間對(duì)象不會(huì)隨著系統(tǒng)時(shí)間的變化而變化,如果要?jiǎng)討B(tài)顯示系統(tǒng)時(shí)間,可以使用計(jì)時(shí)器間隔地獲取系統(tǒng)時(shí)間對(duì)象并顯示,感興趣的可以了解一下2024-01-01簡(jiǎn)介Winform中創(chuàng)建用戶(hù)控件
用戶(hù)控件可以讓開(kāi)發(fā)人員對(duì)VS控件進(jìn)行組裝。下面我們來(lái)創(chuàng)建一個(gè)按鈕的用戶(hù)控件我們可以給它添加屬性,并且添加相應(yīng)鼠標(biāo)移入、移出事件。2013-03-03