数据结构-----------B树
2016-07-22 22:03
435 查看
一、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)插入
三、代码实现:
一棵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; } else end--; } 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; }四、结果:
相关文章推荐
- 数据结构与算法 1 :基本概念,线性表顺序结构,线性表链式结构,单向循环链表
- SDUT2136数据结构实验之二叉树的建立与遍历
- 单链表
- 树状数组 ( 基础篇 )——敌兵布阵 ( HDU 1166 )
- SDUT2118数据结构实验之链表三:链表的逆置
- AVL树的插入与删除操作
- 数据结构-串操作应用之词索引表
- 每次弹出一个栈的最小元素
- 计算几何中的精确度
- 数据结构实验之二叉树二:遍历二叉树
- 数据结构和算法系列17 图
- PQ树小结
- 数据结构与算法JavaScript - 列表
- 数据结构和算法关系
- 1.17 k阶斐波那契序列的第m项值的函数算法
- SDUT 3343 数据结构实验之二叉树四:还原二叉树
- C++学习之路(3) 常用数据结构与STL
- SDUT 2137 数据结构实验之求二叉树后序遍历和层次遍历
- 【算法和数据结构】平衡查找树之B树
- 归并排序