B树操作详解

B树是一颗多路的平衡搜索树,其规定树根至少有两个孩子,每个内部节点有两个或以上的孩子。用来衡量B树规模的一个指标是“最小度数”t,其表示B树所有内部节点的孩子数为t~2t个。

B树的一个结点有两个存储域,分别是关键字和孩子结点,关键字用于划分孩子节点,一个关键字的左右两侧各有一个孩子。类似于二叉搜索树,一个关键字x的左孩子的关键字值都比x小,右孩子的关键字值都比x大。因此,一个结点的关键字的个数是t-1~2t-1个。

下图是一个简单的B树,该树的最小度数t是2。

B树有以下性质:

性质1. 根结点至少有两个子女;
性质2. 每个非根节点所包含的关键字个数 j 满足:t-1 <= j <= 2t-1;
性质3. 除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1;
性质4. 所有的叶子结点都位于同一层。
下面给出实际编程时B树以及B树结点的数据结构定义。
typedef struct LinkKey
{
	int key;
	struct LinkKey *next;
} LinkKey;

typedef struct LinkNode
{
	void *node;
	struct LinkNode *next;
} LinkNode;

typedef struct BNode
{
	int n;	// 孩子个数,so key个数为n-1
	bool leaf;
	LinkKey *key;
	LinkNode *children;
	struct BNode *parent;
} BNode;

typedef struct BTree
{
	BNode *root;
	int t;	// B树的最小度数
} Btree;
考虑到B树结点中多关键字和多结点的遍历,删除以及插入操作以及其数目的不确定性,为了降低时间和空间复杂度,我们不使用数组对这些数据进行组织,取而代之的是单链表。上述定义中的LinkKey和LinkNode就是存储一个结点的关键字和孩子结点指针的链表数据结构。一个结点的关键字以非递减的顺序存储,结点指针的存储顺序与关键字顺序对应。BNode的leaf属性记录该结点是否为叶子结点(true/false)。

1. B树的插入

B树的插入操作需要先根据要插入的关键字k值找到正确的插入位置,该过程与二叉搜索树的插入类似。从树根出发,遍历当前结点的关键字链表,找到一个前面的关键字比k小,后面的关键字比k大的位置,然后再取出这个位置的孩子指针,继续遍历该孩子结点的关键字。如此往复,直到当前结点为叶子结点时,找到合适的位置将关键字k插入叶子结点的关键字链表中即可。

1.1 单链表操作

该过程主要涉及到的是对单链表的操作,这里不做详细讨论,只给出后续程序中使用到的方法的定义。

/**
* 以下是链表的操作
*/
LinkKey *initLinkKey()
{
	LinkKey *head = (LinkKey *)malloc(sizeof(LinkKey));
	head->key = INT_MIN;
	head->next = NULL;
	return head;
}

void destroyLinkKey(LinkKey *link)
{
	while (link != NULL)
	{
		LinkKey *next = link->next;
		free(link);
		link = next;
	}
}

int getKey(LinkKey *link, int which)
{
	int i = -1;
	while (i < which && link->next != NULL)
	{
		link = link->next;
		i++;
	}
	if (i == -1)		return INT_MIN;
	return link->key;
}

void insertLinkKey(LinkKey *link, int key)
{
	while (link->next != NULL)
	{
		if (key <= link->next->key)
		{
			break;
		}
		link = link->next;
	}
	LinkKey *node = (LinkKey *)malloc(sizeof(LinkKey));
	node->key = key;
	node->next = link->next;
	link->next = node;
}

bool deleteLinkKey(LinkKey *link, int key)
{
	while (link->next != NULL && key > l
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值