算法导论 第十八章;B 树

B树是为磁盘或其他直接存取辅助存储设备而设计的一种平衡查找树。B树的”分支因子“可能很大,即每个节点可以有很多子女。这一因子由所用磁盘特性所决定,并且可以降低磁盘I/O操作次数。许多数据库系统都使用B树或B树的变形来存储信息。

B树结构形式如下:

其特点:

1)每个节点x有以下域:

a)  x.n:当前存储在节点x中的关键字

b) x.n 个key值,以非降序顺序存放,即 x.key(1) ≤ x.key(2) ≤ ... ≤ x.key(x.n)

c) x.leaf:bool型,若为叶子节点 x.leaf=TRUE,反之为FALUSE

2) 每个节点x包含x.n+1个指向其子女的指针x.c(1),x.c(2),...x.c(x.n+1)。(叶子节点无此域)

3)各关键字x.key(i)对存储在各子树中的关键字范围加以分隔:如果k(i)为存储在x.c(i)为根的子树中的关键字,则:

4) 每个叶子节点具有相同的深度,即树的高度 h

5) 每个节点包含的key数有一个上界和下界,这些界可以用一个称为B树的最小度数的固定整数 t ≥ 2 来表示:

a) 每个非根的节点必须至少有t-1个 key. 每个非根内节点至少有t个子女。如果树非空,则根节点至少包含一个key.

b) 每个节点可包含至多2t-1个key。所以一个内节点至多可能有2t个子女。如果一个节点恰好有2t-1个key,则称该点是满的。

6)如果n ≥ 1,则对任意的一棵包含n个关键字,高度为h,最小度t ≥ 2的B树T,有:

B树插入和搜索操作的完整代码如下:

#include<iostream>
#include<cstdlib>
#include<cstring>
#define Disk_Write(x)
#define Disk_Read(x)
#define t 2
#define N 2*t
using namespace std;

typedef struct BTNode{
	int n;           //the number of keys storing in the current node
	char key[N];     //N keys storing in nondecreasing order
	bool leaf;       //TRUE:left;FALSE:internal node
	BTNode *c[N+1];  //point n+1 children
	}BTNode;

typedef struct BTree{
	BTNode *root;
	}BTree;

void BTree_Print(BTNode *x)
{
	for(int i=1;i<=x->n;i++)
	{
		if(x->leaf == false)
			BTree_Print(x->c[i]);
		cout<< x->key[i]<<"  ";
	 	}
	if(x->leaf == false)
		BTree_Print(x->c[x->n+1]);
	}

void BTree_SplitChild(BTNode *x,int i)
{
	BTNode *z=new BTNode();
	BTNode *y=x->c[i];   //split y (2t-1 keys) into y (t-1 keys) and  z(t-1 keys)
	z->leaf=y->leaf;
	z->n=t-1;
	for(int j=1 ; j<=t-1 ; j++)
		z->key[j]=y->key[t+j];

	if(y->leaf==false)//if y has children ,copy its children to z
		for(int j=1; j<=t; j++)
			z->c[j]=y->c[j+t];
	y->n=t-1;

	//let z become the (i+1)th child of x
	for(int j=x->n+1; j>=i+1; j--)
		x->c[j+1]=x->c[j];
	x->c[i+1]=z;

	//insert the (t)th key of y into (i)th index of x
	for(int j=x->n; j>=i; j--)
	   x->key[j+1]=x->key[j];
	x->key[i]=y->key[t];
	x->n++;

	Disk_Write(y);
	Disk_Write(z);
	Disk_Write(x);
	}
void BTree_Insert_Nonfull(BTNode *x,char k)
{
	int i=x->n;
	if(x->leaf)
	{//x node is leaf
		while(i>=1 && k < x->key[i])  //search for the insert index
		{
			x->key[i+1]=x->key[i];
			i--;
		 	}
		//insert key
		x->key[i+1]=k;
		x->n++;
		Disk_Write(x);
		}
	else   // x node is not leaf
	{
		while(i>=1 && k < x->key[i])
			i--;
		i++;
	//Read its child,and insert the key into its child node
	Disk_Read(x->c[i]);
	//case 1: the child is full
	if(x->c[i]->n == 2*t-1)
	{
		BTree_SplitChild(x,i);
		if(k > x->key[i])
			i++;
		}
	//case 2:the child is not full
	BTree_Insert_Nonfull(x->c[i],k);
	}
}
void BTree_Insert(BTree *T,char k)
{
	BTNode *r=T->root;
	if(r->n == 2*t-1)
	{//root node is full
		//a new node s becomes the root
		BTNode *s=new BTNode();
		T->root=s;
		s->leaf=false;
		s->n=0;
		s->c[1]=r;
		//split the original root into two chilren of s
		BTree_SplitChild(s,1);
		//insert the key into the nonfull node
		BTree_Insert_Nonfull(s,k);
		}
		else//root node is not full
			BTree_Insert_Nonfull(r,k); //insert key into root node directly
	}
BTNode *BTree_Search(BTNode *x,char k,int &i)
{//return pair(y,i)consisting of a node y and an index i such that y.keyi=k
	 i=1;
	while(i <= x->n && k > x->key[i])
		i++;
	if(i <= x->n && k == x->key[i])
		return x;
	else if(x->leaf)
	{
		i=0;
		return NULL;
		}
	else
	{
		Disk_Read(x->c[i]);
		return BTree_Search(x->c[i],k,i);
	 	}
	}

void BTree_Create(BTree *T,string ch)
{
	//first,create an empty root node
	BTNode *x=new BTNode();
	x->leaf=true;
	x->n=0;

	Disk_Write(x);
	T->root=x;

	//second,add new keys into T by calling Insert method
	for(int i=0;i<ch.length();i++)
		BTree_Insert(T,ch[i]);
	}

void BTree_PrintDetail(BTNode *x)
{

	cout<<"The root is:";
	for(int i=1;i<=x->n;i++)
		cout<<x->key[i]<<"  ";
	cout<<endl;

	cout<<"The root's child is:"<<endl;
	for(int j=1;j<=x->n+1;j++)
	  {
		BTNode *child=x->c[j];
		for(int i=1;i<=child->n;i++)
			cout<<child->key[i]<<"   ";
		cout<<endl;
		}

	for(int i=1;i<=x->n+1;i++)
	{
		cout<<"The "<<i<<" child"<<endl;
		BTNode *child0=x->c[i];
		int m=child0->n+1;
		for(int j=1;j<=m;j++)
	 	{
			BTNode *c1=child0->c[j];
			for(int jj=1;jj<=c1->n;jj++)
				cout<<c1->key[jj]<<"  ";
			cout<<endl;
			}
		}
}

int main()
{
	//string test_ch={'F','S','Q','K','C','L','H','T','V','W','M','R','N','P','A','B','X','Y','D','Z','E'};
	string test_ch="FSQKCLHTVWMRNPABXYDZE";
	cout<<"/*----------------------------Create B-tree---------------------------*/"<<endl;
	BTree *T=new BTree();
	BTree_Create(T,test_ch);
	cout<<"After creating ,the B-tree(its degree is "<<t<<"):"<<endl;
	BTree_Print(T->root);
	cout<<endl;
	cout<<"The detail B-tree is:"<<endl;
	BTree_PrintDetail(T->root);
	cout<<"/*--------------------------------------------------------------------*/"<<endl;

	cout<<"/*---------------------------Insert B-tree----------------------------*/"<<endl;
	char ich;
	cout<<"Please input the inserting char:";
	cin>>ich;
	BTree_Insert(T,ich);
	cout<<"After inserting ,the B-tree:"<<endl;
	BTree_Print(T->root);
	cout<<endl;

	cout<<"The detail of B-tree is:"<<endl;
	BTree_PrintDetail(T->root);
	cout<<"/*---------------------------------------------------------------------*/"<<endl;

	cout<<"/*--------------------------Search B-tree------------------------------*/"<<endl;
	char sch;
	BTNode *sNode=NULL;
	int index;
	cout<<"Please input the searching char:";
	cin>>sch;
	sNode=BTree_Search(T->root,sch,index);
	if(sNode==NULL)
		cout<<"The key doesn't exist in the B-tree."<<endl;
	else
	{
		cout<<"The key in the Node:";
		for(int i=1;i<=sNode->n;i++)
			cout<<sNode->key[i]<<"  ";
		cout<<endl;
		cout<<"The index of the key in the node is:"<<index<<endl;
		}
	cout<<"/*---------------------------------------------------------------------*/"<<endl;

	return 0;
	}

运行结果:

【注:若有错误,请指正~~~】

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-04 12:40:48

算法导论 第十八章;B 树的相关文章

算法导论第十二章__二叉搜索数

package I第12章__二叉搜索树; //普通二叉树 public class BinaryTree<T> { // -----------------------数据结构--------------------------------- private int height = 0; private Node<T> rootNode; class Node<T> { T t; int key; Node left; Node right; public Node

浅谈算法和数据结构: 十 平衡查找树之B树

转载自 http://www.cnblogs.com/yangecnu/p/3632027.html 浅谈算法和数据结构: 十 平衡查找树之B树 前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥

算法第十八章 B树

一.高级数据结构 本章以后到第21章(并查集)隶属于高级数据结构的内容.前面还留了两章:贪心算法和摊还分析,打算后面再来补充.之前的章节讨论的支持动态数据集上的操作,如查找.插入.删除等都是基于简单的线性表.链表和树等结构,本章以后的部分在原来更高的层次上来讨论这些操作,更高的层次意味着更复杂的结构,但更低的时间复杂度(包括摊还时间). B树是为磁盘存储还专门设计的平衡查找树.因为磁盘操作的速度要远远慢于内存,所以度量B树的性能,不仅要考虑动态集合操作消耗了多少计算时间,还要考虑这些操作执行了多

算法导论第十五章动态规划

概述: 1.动态规划是通过组合子问题的解而解决原问题的. 2.动态规划适用于子问题不是独立的情况,也就是各子问题的包含公共的子子问题. 3.动态规划对每个子问题只求解一次,将其结果保存在一张表中. 4.动态规划的设计步骤:a.描述最优解的结构b.递归定义最优解的值c.按自底向上的方式计算最优觖的值d.由计算出的结构构造一个最优解 15.1钢条切割 钢条切割问题:给定定长的钢条和价格表,求切割方案,使得收益最大.如果n英寸的钢条的价格足够大,则不需要切割. 代码如下: //朴素递归求解钢条切割收益

算法导论第十二章 二叉搜索树

一.二叉搜索树概览 二叉搜索树(又名二叉查找树.二叉排序树)是一种可提供良好搜寻效率的树形结构,支持动态集合操作,所谓动态集合操作,就是Search.Maximum.Minimum.Insert.Delete等操作,二叉搜索树可以保证这些操作在对数时间内完成.当然,在最坏情况下,即所有节点形成一种链式树结构,则需要O(n)时间.这就说明,针对这些动态集合操作,二叉搜索树还有改进的空间,即确保最坏情况下所有操作在对数时间内完成.这样的改进结构有AVL(Adelson-Velskii-Landis)

算法导论第十九章 斐波那契堆

<算法导论>第二版中在讨论斐波那契堆之前还讨论了二项堆,但是第三版中已经把这块的内容放到思考题中,究极原因我想大概是二项堆只是个引子,目的是为了引出斐波那契堆,便于理解,而且许多经典的算法实现都是基于斐波那契堆,譬如计算最小生成树问题和寻找单源最短路径问题等,此时再把二项堆单独作为一章来讲显然没有必要.类似的堆结构还有很多,如左倾堆,斜堆,二项堆等,下次我打算开一篇博客来记录下它们的异同点. 一.摊还分析(第十七章) 这些高级的数据结构的性能分析一般是基于一个技术——摊还分析,可以理解成一种时

算法导论 第十四章:区间树

区间树是一种对动态集合进行维护的红黑树,具体设计如下: step1:基础数据结构 我们选择的基础数据结构式红黑树,其中每个节点x包含一个区间域x.int,x的关键字为区间的低端点 x.int.low. step2:附加信息 每个节点x除了区间信息外,还包含一个值x.max,即以x为根的的子树中所有区间的断点的最大值 step3:对信息维护 必须验证对含有n个节点的区间树的插入和删除都能在O(lgn)时间内完成,给定区间x.int 和 x.max 则有:x.max = max(x.int.high

转 浅谈算法和数据结构: 十 平衡查找树之B树

前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为"在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树.与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作.B-tree算法减少定位记录时所经历的中间过程,从而

算法导论 第二十二章:图的搜索

图有两种标准的表示方法,即邻接矩阵和邻接表(通常邻接矩阵用于稠密图,邻接表用于稀疏图).如下: 对于图的搜索有两种方法:深度优先搜索 & 广度优先搜索. 广度优先搜索(Breadth-first search) 广度优先搜索是将已发现和未发现顶点之间的边界沿其广度方向向外扩展.亦即算法首先会发现和s距离为k的所有点,然后才会发现和s距离为k+1的其他顶点. 伪代码: EG: 运行时间:O(V+E). 深度优先遍历(Depth-first search) 在深度优先搜索中,对于最新发现的顶点,如果