前面的2-3树实现分析已经分析了2-3树的遍历(traverse),检索(retrieve),插入(insert)和删除(delete)的算法,经过三天的努力,我在分析的基础上采用回溯的方式实现了2-3树,由于还在初级阶段,肯定会出现不少的问题,请多赐教。但经过测试,运行还算正确。下面是代码实现:
2-3树的异常处理类
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// two_three_tree_exception.h
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef TWO_THREE_TREE_EXCEPTION_H_
#define TWO_THREE_TREE_EXCEPTION_H_
#include<stdexcept>
#include<string>
class TTTException :public std::logic_error
{
public:
TTTException(const std::string &message="")
:std::logic_error(message.c_str())
{}
};
#endif
2-3树的item类,每个节点的数据的存储在这里,包含了一个关键字keyword和相关的值 tel。
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// two_three_tree_item.h
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef TWO_THREE_TREE_ITEM_H_
#define TWO_THREE_TREE_ITEM_H_
#include<string>
typedef std::string KeyType;
class ItemType
{
public:
ItemType(){}
ItemType(const KeyType &_key,const std::string &_tel)
:keyword(_key),tel(_tel)
{}
//get key word keyword;
const KeyType & getKey()const
{
return keyword;
}
//set value tel;
void setTel(const std::string &_tel)
{
tel=_tel;
}
//get value tel;
std::string getTel()const
{
return tel;
}
private:
KeyType keyword;
std::string tel;
};
#endif
2-3树的节点类,实现树的完整连接,其中包含两个item,三个孩子:左孩子,中孩子,右孩子
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// two_three_tree_node.h
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef TWO_THREE_TREE_NODE_H_
#define TWO_THREE_TREE_NODE_H_
#include"two_three_tree_item.h"
class Node
{
private:
Node(ItemType &_item,Node *_leftPtr,Node*_middlePtr)
:fItem(_item),LeftPtr(_leftPtr)
,MiddlePtr(_middlePtr),RightPtr(NULL)
{Nitems=1;}
//当节点中的item项数为1时,调用此函数重新整合节点
void reSet(ItemType &_item,Node *_leftPtr,
Node*_middlePtr)
{
Node *tempL=_leftPtr,*tempM=_middlePtr;
fItem=_item;
LeftPtr=tempL;
MiddlePtr=tempM;
RightPtr=NULL;
setNumb(1);
}
//当节点中的item项数为2时,调用此函数重新整合节点
void reSet( ItemType &_fitem,ItemType &_litem,Node *_leftPtr,Node *_middlePtr,Node *_rightPtr)
{
ItemType tempfi=_fitem,templi=_litem;
Node *tempL=_leftPtr,*tempM=_middlePtr,*tempR=_rightPtr;
LeftPtr=tempL;
MiddlePtr=tempM;
RightPtr=tempR;
fItem=tempfi;
lItem=templi;
setNumb(2);
}
//设置节点中item的数目
void setNumb(int n)
{
Nitems=n;
}
//清空当前节点中的孩子和item(items)
void clear()
{
LeftPtr=MiddlePtr=RightPtr=NULL;
setNumb(0);
}
ItemType fItem,lItem;
Node *LeftPtr,*MiddlePtr,*RightPtr;
int Nitems;
friend class ttTree;
};
#endif
2-3树实现的头文件
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// two_three_tree.h
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef TWO_THREE_TREE_H_
#define TWO_THREE_TREE_H_
#include"two_three_tree_exception.h"
#include"two_three_tree_node.h"
typedef void (*FuncT)(ItemType &_item);
class ttTree
{
public:
//默认构造函数
ttTree();
//复制构造函数
ttTree(ttTree &_tree);
//析构函数
virtual ~ttTree();
virtual bool empty()const;
//检索
virtual void retrieve(const KeyType &_keyword,ItemType &_item)throw(TTTException);
//遍历
virtual void traverse(FuncT visit);
//插入
virtual void insert(const ItemType & newitem)
throw(TTTException);
//删除
virtual void remove(const KeyType &keyword)
throw(TTTException);
//赋值操作符重载
virtual ttTree &operator=(ttTree &oldtree)throw(TTTException);
protected:
bool insertTree(Node *&treePtr,Node *&tempPtr,ItemType &tempItem)throw(TTTException);
bool removeTree(Node *&treePtr,Node *&tempPtr,const KeyType &_key)
throw(TTTException);
void retrieveTree(Node * &treePtr,const KeyType &_key,ItemType &_item)throw(TTTException);
void traverseTree(Node *&treePtr,FuncT visit);
//复制构造函数
void copyTree(Node *&newtree, Node* &oldtree)throw(TTTException);
void destroy(Node *&treePtr);
//在插入的情况下,当当前的item数大于2时,调用此函数维护2-3的原有属性
bool insertMaintain(Node *&treePtr,Node *&tempPtr,ItemType &tempItem,char ch)throw(TTTException);
//在删除的情况下,当当前的item数小于1时,调用此函数维护2-3的原有属性
bool removeMaintain(Node *&treePtr,Node *&tempPtr,char ch);
//寻找当前节点treeptr中项目的中序后继,
int processLeft(Node *&treePtr,Node*&tempPtr,ItemType &replace);
//当前的节点treePtr中item数目为2时返回true,否侧返回false
bool twoItem(Node *&treePtr)const;
//当前的节点treePtr中的item数目为1时返回true,否则返回false
bool oneItem(Node *&treePtr)const;
//判断当前节点treePtr是否为根节点,如是则返回true,否则返回false
bool isRoot(Node *&treePtr)const;
//判断当前节点treePtr是否为叶节点,若是则返回true,否则返回false
bool isLeaf(Node *&treePtr)const;
//判断当前节点treePtr中是否存在与关键字_key相等的项
//若存在则返回true,否则返回false
bool equal(Node*&treePtr,const KeyType & _key)const;
//按项中关键字的大小重新排序first,middle,last,使其满足
//first.getkey()<=middle.getKey()<=last.getkey()
void sort(ItemType &first,ItemType &middle,ItemType &last);
private:
Node *root;
};
#endif
2-3树的现实文件