C#二叉搜索树算法

二叉搜索树算法实现原理

二叉搜索树(Binary Search Tree,简称BST)是一种节点有序排列的二叉树数据结构。它具有以下性质:

  • 每个节点最多有两个子节点。
  • 对于每个节点,其左子树的所有节点值都小于该节点值,其右子树的所有节点值都大于该节点值。

实现基本步骤和代码示例

步骤

  • 定义节点类:包含节点值、左子节点和右子节点。
  • 插入节点:递归或迭代地将新值插入到树中合适的位置。
  • 搜索节点:根据节点值在树中查找特定值。
  • 删除节点:从树中删除特定值的节点,并维护树的结构。
  • 遍历树:包括前序遍历、中序遍历、后序遍历和层次遍历等。

完整代码示例

namespace HelloDotNetGuide.常见算法
{
	public class 二叉搜索树算法
	{
		public static void BinarySearchTreeRun()
		{
			var bst = new BinarySearchTree();

			// 插入一些值到树中
			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("中序遍历(打印有序数组):");
			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");

			// 删除某个值
			bst.Delete(50);
			Console.WriteLine("删除50后:");
			bst.InorderTraversal();
		}
	}

	/// <summary>
	/// 定义二叉搜索树的节点结构
	/// </summary>
	public class TreeNode
	{
		public int Value;
		public TreeNode Left;
		public TreeNode Right;

		public TreeNode(int value)
		{
			Value = value;
			Left = null;
			Right = null;
		}
	}

	/// <summary>
	/// 定义二叉搜索树类
	/// </summary>
	public class BinarySearchTree
	{
		private TreeNode root;

		public BinarySearchTree()
		{
			root = null;
		}

		#region 插入节点

		/// <summary>
		/// 插入新值到二叉搜索树中
		/// </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
			{
				//值已经存在于树中,不再插入
				return;
			}
		}

		#endregion

		#region 查找节点

		/// <summary>
		/// 查找某个值是否存在于二叉搜索树中
		/// </summary>
		/// <param name="value">value</param>
		/// <returns></returns>
		public bool Search(int value)
		{
			return SearchRec(root, value);
		}

		private bool SearchRec(TreeNode node, int value)
		{
			// 如果当前节点为空,表示未找到目标值
			if (node == null)
			{
				return false;
			}

			// 如果找到目标值,返回true
			if (node.Value == value)
			{
				return true;
			}

			// 递归查找左子树或右子树
			if (value < node.Value)
			{
				return SearchRec(node.Left, value);
			}
			else
			{
				return SearchRec(node.Right, value);
			}
		}

		#endregion

		#region 中序遍历

		/// <summary>
		/// 中序遍历(打印有序数组)
		/// </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 删除节点

		/// <summary>
		/// 删除某个值
		/// </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
			{
				// 节点有两个子节点
				if (node.Left != null && node.Right != null)
				{
					// 使用右子树中的最小节点替换当前节点
					TreeNode minNode = FindMin(node.Right);
					node.Value = minNode.Value;
					node.Right = DeleteNode(node.Right, minNode.Value);
				}
				// 节点有一个子节点或没有子节点
				else
				{
					TreeNode? temp = node.Left != null ? node.Left : node.Right;
					node = temp;
				}
			}

			return node;
		}

		/// <summary>
		/// 找到树中的最小节点
		/// </summary>
		/// <param name="node"></param>
		/// <returns></returns>
		private TreeNode FindMin(TreeNode node)
		{
			while (node.Left != null)
			{
				node = node.Left;
			}
			return node;
		}

		#endregion
	}
}

输出结果:

image

数组与搜索树的效率对比

二叉搜索树的各项操作的时间复杂度都是对数阶,具有稳定且高效的性能。只有在高频添加、低频查找删除数据的场景下,数组比二叉搜索树的效率更高。

image

二叉搜索树常见应用

  • 用作系统中的多级索引,实现高效的查找、插入、删除操作。
  • 作为某些搜索算法的底层数据结构。
  • 用于存储数据流,以保持其有序状态。
posted @ 2024-12-14 11:31  似梦亦非梦  阅读(15)  评论(0编辑  收藏  举报