数据结构-----------B树

来源:互联网 发布:ubuntu创建用户和目录 编辑:程序博客网 时间:2024/05/10 18:56

一、B 树(平衡的多叉树)

  一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树,它的性质为:

1、根节点至少有两个孩子

2、每个非根节点有[⌈M/2⌉,M]个孩子;⌈M/2⌉向上取整

3、每个非根节点有[⌈M/2⌉-1,M-1]个关键字,并且以升序排列

4、key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间‘

5、所有的叶子节点都在同一层。

二、基本操作

(1)查找

(2)中序遍历

(3)插入

三、代码实现:

#pragma once#include<iostream>#include<utility>using namespace std;template<class K,int M>struct BTreeNode{BTreeNode():_parent(NULL),_size(0){for(int i=0;i<M+1;i++){_subs[i]=NULL;}}K _keys[M];BTreeNode<K,M>* _subs[M+1];BTreeNode<K,M>* _parent;size_t _size;};template<class K,int M>class BTree{public:typedef BTreeNode<K,M> Node;BTree():_root(NULL){}Node* Find(K key)  //查找key存在位置{if(_root==NULL){return NULL;}Node* cur=_root;Node* parent=NULL;    int end=cur->_size-1;while(cur){parent=cur;if(key>cur->_keys[end]){cur=cur->_subs[end+1];if(cur)end=cur->_size-1;}else if(key<cur->_keys[end]){if(end==0){cur=cur->_subs[end];if(cur)end=cur->_size-1;}elseend--;}else{return cur;}}return parent;}bool Insert(K key){if(_root==NULL){_root=new Node;_root->_keys[_root->_size]=key;_root->_size++;return true;}Node* cur=Find(key);while(1){  int end=cur->_size-1;    for(size_t i=0;i<end+1;i++) //判断该节点是否存在该关键字(判断返回的是parent还是cur){if(cur->_keys[i]==key){return false;}}while(end>=0&&end<cur->_size)  //插入关键字{ if(cur->_keys[end]>key)  {cur->_keys[end+1]=cur->_keys[end];       }  else {cur->_keys[end+1]=key;cur->_size++;break; } end--; if(end==-1) { cur->_keys[end+1]=key;cur->_size++;break; }  }end=cur->_size-1;Node* parent=cur->_parent;int div=M/2;Node* tmp;if(cur->_size>=M)  //分裂{int index=0;tmp=new Node;for(int i=div+1;i<cur->_size;i++)  //从M/2处分裂,创建一个新的节点,把M/2后的关键字拷贝到tmp中{tmp->_keys[index++]=cur->_keys[i];tmp->_size++;}index=0;for(int i=div+1;i<cur->_size+1;i++)  //从M/2处分裂,把M/2后的孩子拷贝到tmp中{tmp->_subs[index++]=cur->_subs[i];}if(parent!=NULL) //分裂的该节点不为根节点{int i=parent->_size;if(i==M-1)   //如果分裂的该节点是parent->_subs[M-1],则不需拷贝前面的parent->_subs[i],直接把创建的tmp节点链在parent->_subs[i]后面{parent->_subs[i+1]=tmp;}else  //如果分裂的该节点是parent->_subs[i],i<M-1,则需拷贝前面的parent->_subs[i],依次把parent的孩子指针向后移动,空出合适位置,链起tmp{while(parent->_subs[i]!=cur){parent->_subs[i+1]=parent->_subs[i];i--;}parent->_subs[i+1]=tmp;}   tmp->_parent=parent;}else   //分裂的该节点为根节点{ Node* root=new Node; root->_keys[0]=cur->_keys[div]; root->_subs[0]=cur; root->_subs[1]=tmp; cur->_parent=root; tmp->_parent=root; _root=root; _root->_size++;}}else{return true;}cur->_size=cur->_size-tmp->_size-1;   //把cur->_keys[M/2]插入上层,进行循环int new_key=cur->_keys[div];cur=cur->_parent;key=new_key;}}    void InOrder(){_InOrder(_root);}private:void _InOrder(Node* root){if(root==NULL){return;}int i=0;for(;i<root->_size;i++){_InOrder(root->_subs[i]);cout<<root->_keys[i]<<"->";}_InOrder(root->_subs[i]);}private:Node* _root;};
#include "BTree.h"int main(){BTree<int,3> b1;BTree<int,4> b2;BTree<int,5> b3;int a[]={53,75,139,49,145,36,101,36,24,56};for(int i=0;i<sizeof(a)/sizeof(a[0]);i++){b1.Insert(a[i]);}for(int i=0;i<sizeof(a)/sizeof(a[0]);i++){b2.Insert(a[i]);}for(int i=0;i<sizeof(a)/sizeof(a[0]);i++){b3.Insert(a[i]);}cout<<"三叉:";b1.InOrder();cout<<endl;cout<<"四叉:";b2.InOrder();cout<<endl;cout<<"五叉:";b3.InOrder();cout<<endl;system("pause");return 0;}
四、结果:



0 0
原创粉丝点击