浅析二叉查找树

本文深入探讨了二叉查找树的定义、特性及其在数据搜索中的应用,详细讲解了插入、删除、查找前驱和后继、按排名找值及按值找排名的操作方法,并提供了C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是二叉查找树

所谓二叉查找树,就是严格任一左子树小于根,右子树大于根的二叉树,平均情况在 O ( l o g n ) O(log n) O(logn)内查找数据元素。在大规模数据的搜索中,显然最简易的方法是利用快速排序或者归并排序对数据进行排序,然后根据下标来查询具体位置的具体数值,期望值为 O ( n l o g n ) O(nlog n) O(nlogn),而利用二叉查找树,则可在输入时对数据进行处理,期望 O ( l o g n ) O(logn) O(logn)的时间查找位置。

插入

对于二叉查找树的插入,只需从根结点开始,不断比较当前结点与该元素的大小关系,较小向左子树递归,较大向右子树递归,直至找到插入位置。特别地,当结点数值大小与该元素相同时,只需修改该结点的 c n t cnt cnt值。

删除

对于删除,同样先查找数据所在位置,修改该结点 c n t cnt cnt值。特别地,当 c n t = = 0 cnt == 0 cnt==0时,表示二叉查找树中已无该数值。

查找

之所以有二叉查找树这种较普通二叉树更高级的数据结构,重点就是为了提高查找的效率。

1.查找前驱和后继

对于前驱和后继,其实方法等同于插入,只不过对于前驱而言,要一直查找到没有右子树为止,以确保前驱最大;同样,查找后继时要直到没有左子树为止,以保证后继最小。

2.按排名找值

此时结构体中的size值将发挥作用,它用于记录以该结点为根包括该结点在内的树的大小。此时根据排名,可以通过不断比较结点的size值,找到所要确定的值。

3.按值找排名

对于给定的数值,要确定其的位置,同样,首先通过不断递归找到该元素,然后不断将结点值之间的size值做差,最后得到元素的具体位置。

p s : ps: ps:对于二叉查找树而言,其查找效率已经大幅提高,然后对于输入为递增或递减的数据而言,其会退化成 O ( n ) O(n) O(n)的单链,关于这种情况的改进,则需要一种更高级的数据结构——二叉平衡树。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 9e2 + 16;
const int INF = 0x7fffffff;
int pos;
typedef struct BinarySearchTree
{
	int val;		//表示权值
	int rank;		//表示排名
	int size;		//表示当前结点子树大小(包括该结点)
	int cnt;		//表示当前结点的数量
	int ls, rs;		//表示左右子树
}bst;
bst tree[maxn];
void add(int cur, int v)		//实现结点的插入
{
	tree[cur].size++;
	if (tree[cur].val == v)
	{
		tree[cur].cnt++;
		return;
	}
	if (tree[cur].val > v)
	{
		if (tree[cur].ls != 0)
		{
			add(tree[cur].ls, v);
		}
		else
		{
			pos++;
			tree[pos].val = v;
			tree[pos].size = 1;
			tree[pos].cnt = 1;
			tree[cur].ls = pos;
		}
	}
	else
	{
		if (tree[cur].rs != 0)
		{
			add(tree[cur].rs, v);
		}
		else
		{
			pos++;
			tree[pos].val = v;
			tree[pos].size = 1;
			tree[pos].cnt = 1;
			tree[cur].rs = pos;
		}
	}
}
int GetPre(int cur, int val, int ans)		//实现查找前驱
{
	if (tree[cur].val >= val)
	{
		if (tree[cur].ls == 0)
		{
			return ans;
		}
		else
		{
			GetPre(tree[cur].ls, val, ans);
		}
	}
	else
	{
		if (tree[cur].rs == 0)
		{
			if (tree[cur].val < val)
			{
				return tree[cur].val;
			}
			else
			{
				return ans;
			}
		}
		if (tree[cur].cnt != 0)
		{
			return GetPre(tree[cur].rs, val, tree[cur].val);
		}
		else
		{
			return GetPre(tree[cur].rs, val, ans);
		}
	}	
}
int GetNext(int cur, int val, int ans)		//实现查找后继
{
	if (tree[cur].val <= val)
	{
		if (tree[cur].rs == 0)
		{
			return ans;
		}
		else
		{
			GetNext(tree[cur].rs, val, ans);
		}
	}
	else
	{
		if (tree[cur].ls == 0)
		{
			if (tree[cur].val > val)
			{
				return tree[cur].val;
			}
			else
			{
				return ans;
			}
		}
		if (tree[cur].cnt != 0)
		{
			return GetNext(tree[cur].ls, val, tree[cur].val);
		}
		else
		{
			return GetNext(tree[cur].ls, val, ans);
		}
	}
}
int GetValByRank(int cur, int rank)		//实现按排名找值
{
	if (cur == 0)
	{
		return INF;
	}
	if (tree[tree[cur].ls].size >= rank)
	{
		return GetValByRank(tree[cur].ls, rank);
	}
	if (tree[tree[cur].ls].size + tree[cur].cnt >= rank)
	{
		return tree[cur].val;
	}
	return GetValByRank(tree[cur].rs, rank - tree[tree[cur].ls].size - tree[cur].cnt);
}
int GetRankByVal(int cur, int val)		//实现按值找排名
{
	if (cur == 0)
	{
		return 0;
	}
	if (val == tree[cur].val)
	{
		return tree[tree[cur].ls].size + 1;
	}
	if (tree[cur].val > val)
	{
		return GetRankByVal(tree[cur].ls, val);
	}
	return GetRankByVal(tree[cur].rs, val) + tree[tree[cur].ls].size + tree[cur].cnt;
}

参考博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值