B树值查找操作详解(附代码讲解及代码)

B树的查找

那就开始吧!

举个栗子,我先画几张图,让大家体验一下它的查找方式。然后,开始上代码解释。好吗?


就以上面的为例,现在,我们要依次查找如下几个键值,请记牢12 8 17三个键值。那就按部就班进行。
No.1 首先要找键值为:12
在这里插入图片描述
上来,就找到了。因为12这个键值正好处于B树的临时根节点。由此可见,查找键值是从B树的根节点进行的。

No.2 接着查找8
在这里插入图片描述
看着很简单,对吧?聪明的你应该不这么觉得。那就一起分析一下上图吧

首先,红色的箭头即findNode是在tempRootNode对吧,相信你还记得B树的结构。

如果B树的结构还不知道的读者,或者之前没有了解过B树的结构,亦或者没看过其他博主写过相关B树的文章,可以在我的主页->博客分类->数据结构算法里面。进行查找哦。

那先要做什么呢?是不是先看一下当前findNode所指向的节点是否有我们想要找的键值,对的。这一找,啥也没有。该咋办呢?还有它的孩子,但此刻的findNode该怎么找呢?不会随便指个位置,就开始找吧。当然不是,这时候,会借助要查找的键值与findNode里面的键值关系对吧?发现8<12,然后就应该返回对应的孩子,继续走下去对吧?没错。此时,findNode来到了6 9的节点,继续查找键值,如果键值没有,就开始找合适的孩子进行遍历。

概括一下:

  • 在查找键值的时候,总是在B树的临时根节点进行查找;
  • 如果根节点没有要找的键值,就要遍历合适的孩子进行查找;
  • 直到找到目标键值为止,如果没有找到,就返回空

看了上面的概括,我现在有点饿了,你自己看看17是如何查找的?

ok,接下来进入B树查找的代码讲解:

这里先声明一下,一般查找到节点都是要曝光的,而且在后面的删除节点都是需要先经过查找,我B树的struct在class里面,所有,要在public属性里面准备一个指针,好用来接受这个已经查找到节点。(当然,如果结构不这么设计,就不会这样啦)。

	my_B_tree* find(const size_t& findValue)//查找的键值。
	{
		return _find(findValue, tempRootNode);//findValue 目标查找的键值;tempRootNode B树的临时根节点
	}

_find函数内容是查找目标键值的主干,该函数体中的函数,会在下面一一奉上!

if (root)
		{
			int pos = binarySearch(root->key, findValue, 0, root->degress);
			if (pos != -1)
				return root;
			else
			{
				Insert_Location location = indexSelection(root, findValue);
				switch (location)
				{
				case Insert_Location::_first:
				{
					my_B_tree* okNode = nullptr;
					okNode = _find(findValue, root->sonPt[(int)location]);
					return okNode;
				}

				case Insert_Location::_second:
				{
					my_B_tree* okNode = nullptr;
					okNode = _find(findValue, root->sonPt[(int)location]);
					return okNode;
				}
				case Insert_Location::_third:
				{

					my_B_tree* okNode = nullptr;
					okNode = _find(findValue, root->sonPt[(int)location]);
					return okNode;
				}
				}
			}
		}
		return nullptr;

先来在这里解释一下基本逻辑,相信大家不难看到,这个函数是一个递归。且听我来分析:
还是文章首部画的那张图吧,这次寻找19

在这里插入图片描述
先仔细看一下上面的图,从根节点开始找19。这个函数又是一个递归,那它就不能缺少递归的条件,否则就会函数栈boom!所以右图的意思是这样的,12的节点进入函数中,先判断该节点是否为空?如果不为空,就使用二分查找来搜索是否有19这个键值,结果:没有,那就搜索路径,然后走合适的路径进入到17。……来到了19的节点,这个时候发现二分查找搜索找到了目标键:19.返回此节点的地址。该递归函数return出函数栈,此时回到了函数之前所调用它的递归函数的位置,然后继续return,直到把这个目标所在节点返回出来。这里,我要提醒一下,一定要在最后加return nullptr;如果不加,这个函数没有找到的话,就会返回一个野指针。

binarySearch函数是一个二分查找算法,考虑到B树的多阶性,所以这里使用了效率较高的二分查找来进行查找是否在当前节点。如果是就返回index,否则返回-1.

	int midIndex;
	while (leftIndex <= rightIndex)
	{
		midIndex = ((rightIndex-leftIndex) >> 1)+leftIndex;
		if (findValue == arr[midIndex])
			return midIndex;
		if (findValue < arr[midIndex])
			rightIndex = midIndex-1;
		else if (findValue > arr[midIndex])
			leftIndex = midIndex+1;
	
	}
	return -1;

indexSelection函数作用:当目标键值不在当前节点中,就继续往下一层选择合适的孩子寻找。

		size_t i = 0;
		//分裂后,根节点关键字个数为1的情况
		for (; i < curNode->degress; ++i)
		{
			if (key <= curNode->key[i])
			{
				//如果满足条件,就根据当前的索引i值,返回指定的指针进行插入
				return (Insert_Location)i;
			}
			//否则就继续循环
		}

		return (Insert_Location)(i);

感谢各位的阅读, 如果有更好的优化,请在下方评论留言,我会认真的考虑各位的建议。B树的删除,博主还未实现,且听下回对B树删除的分析。谢谢大家!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值