因为是第一次写T树,网上的参考源码稀缺,所以程序中不免有bug,正在修正中。
我的同步博客:http://blog.youkuaiyun.com/moxiaomomo/archive/2011/06/09/6535008.aspx
主要参考资料来源于csdn博客:
http://blog.youkuaiyun.com/liuxuezong/archive/2010/12/03/6052686.aspx
http://blog.youkuaiyun.com/liuxuezong/archive/2010/12/06/6058373.aspx
我的同步博客:http://blog.youkuaiyun.com/moxiaomomo/archive/2011/06/09/6535008.aspx
view plaincopy to clipboardprint?
#pragma once
//
// by xiaomo
// 2011.06
// Ttree.h
#include<iostream>
using namespace std;
enum ENUM
{
MaxSize=64,
MinSize=MaxSize-2
};
template<typename T>
struct TtreeNode
{
int balance; //平衡因子
TtreeNode<T>* left; //左子树指针
TtreeNode<T>* right; //右子树指针
unsigned short int nItems; //当前实际元素数目
T item[MaxSize]; //节点键值数组
T data[MaxSize]; //数据数组
};
template<typename T>
class Ttree
{
public:
Ttree(void);
virtual ~Ttree(void);
void clear(); //清空树
void _erase(TtreeNode<T>* pNode); //删除pNode以及其子节点
void freeNode(TtreeNode<T>* pNode); //删除当前节点
bool isEmpty(); //判断树是否为空
void insert(const T key,const T data); //插入操作
void remove(T key);
T find(T key); //查找
virtual int keycompare(T key1,T key2); //键值的比较
void traverseTree(int order);
protected:
void preOrderTraverse(TtreeNode<T>* pNode)const; //遍历,const说明该函数不能修改类中任何非const函数
void inOrderTraverse(TtreeNode<T>* pNode)const;
void postOrderTraverse(TtreeNode<T>* pNode)const;
TtreeNode<T>* root; //当前root指针
int m_nSize; //当前已分配的节点数目
private:
TtreeNode<T>* mallocNode();
int balanceFactor(TtreeNode<T>* pNode)const;
int Depth(TtreeNode<T>* pNode)const;
bool _insert(TtreeNode<T>* &pNode,const T key,const T data); //插入操作
int _remove(TtreeNode<T>* &pNode,T key); //删除操作
//树的四种旋转情况,调整树以适应平衡环境
TtreeNode<T>* SingleRotateLeft(TtreeNode<T>* pNode); //左左
TtreeNode<T>* SingleRotateRight(TtreeNode<T>* pNode); //右右
TtreeNode<T>* DoubleRotateLeft(TtreeNode<T>* pNode); //左右
TtreeNode<T>* DoubleRotateRight(TtreeNode<T>* pNode); //右左
int balanceLeftBranch(TtreeNode<T>* &pNode); //调整左子树
int balanceRightBranch(TtreeNode<T>* &pNode); //调整右子树
};
template<typename T>
Ttree<T>::Ttree(void) //构造函数
{
root=NULL;
m_nSize=0;
}
template<typename T> //释构函数
Ttree<T>::~Ttree(void)
{
clear();
root=NULL;
m_nSize=0;
}
template<typename T>
void Ttree<T>::clear() //清空树
{
_erase(root);
}
template<typename T>
void Ttree<T>::_erase(TtreeNode<T>* pNode) //删除pnode节点及其子节点
{
if(pNode==NULL)
{
return;
}
_erase(pNode->left);
_erase(pNode->right);
freeNode(pNode);
}
template<typename T>
void Ttree<T>::freeNode(TtreeNode<T>* pNode) //删除当前节点
{
if(pNode)
{
delete pNode;
pNode=NULL;
}
}
template<typename T>
bool Ttree<T>::isEmpty() //判断是否为空
{
if(root==NULL)return true;
else return false;
}
template<typename T>
TtreeNode<T>* Ttree<T>::mallocNode() //分配空间
{
TtreeNode<T>* pNode=new TtreeNode<T>;
memset(pNode, 0, sizeof(TtreeNode<T>));
pNode->balance=0;
pNode->left=NULL;
pNode->right=NULL;
pNode->nItems=0;
m_nSize+=1;
return pNode;
}
template<typename T>
int Ttree<T>::keycompare(T key1, T key2)
{
int p=key1;
int q=key2;
return p<q?-1:(p==q?0:1);
}
template<typename T>
void Ttree<T>::traverseTree(int order)
{
switch(order)
{
case 1:
preOrderTraverse(root);
break;
case 2:
inOrderTraverse(root);
break;
case 3:
postOrderTraverse(root);
break;
}
}
template<typename T>
void Ttree<T>::preOrderTraverse(TtreeNode<T> *pNode) const //先序遍历
{
if(pNode)
{
for(int i=0;i<pNode->nItems;++i)
{
cout<<pNode->item[i]<<" ";
//cout<<pNode->data[i]<<" ";
}
cout<<endl;
preOrderTraverse(pNode->left);
preOrderTraverse(pNode->right);
}
}
template<typename T>
void Ttree<T>::inOrderTraverse(TtreeNode<T> *pNode) const //中序遍历
{
if(pNode)
{
inOrderTraverse(pNode->left);
for(int i=0;i<pNode->nItems;++i)
{
cout<<pNode->item[i]<<" ";// cout<<pNode->data[i]<<" ";
}
cout<<endl;
inOrderTraverse(pNode->right);
}
}
template<typename T>
void Ttree<T>::postOrderTraverse(TtreeNode<T> *pNode) const //后序遍历
{
if(pNode)
{
postOrderTraverse(pNode->left);
postOrderTraverse(pNode->right);
for(int i=0;i<pNode->nItems;++i)
{
cout<<pNode->item[i]<<" ";//cout<<pNode->data[i]<<" ";
}cout<<endl;
}
}
template<typename T> //平衡因子
int Ttree<T>::balanceFactor(TtreeNode<T> *pNode) const
{
return Depth(pNode->right)-Depth(pNode->left);
}
template<typename T> //求树的深度
int Ttree<T>::Depth(TtreeNode<T> *pNode) const
{
if(pNode==NULL)return 0;
int l=Depth(pNode->left);
int r=Depth(pNode->right);
return 1+(l>r?l:r);
}
template<typename T>
TtreeNode<T>* Ttree<T>::SingleRotateLeft(TtreeNode<T> *pNode) //左左情况(右旋)
{
TtreeNode<T>* pl=pNode->left;
pNode->left=pl->right;
pl->right=pNode;
//调整平衡因子
pNode->balance=balanceFactor(pNode);
pl->balance=balanceFactor(pl);
return pl;
}
template<typename T>
TtreeNode<T>* Ttree<T>::SingleRotateRight(TtreeNode<T> *pNode) //右右情况(左旋)
{
TtreeNode<T>* pr=pNode->right;
pNode->right=pr->left;
pr->left=pNode;
//调整平衡因子
pNode->balance=balanceFactor(pNode);
pr->balance=balanceFactor(pr);
return pr;
}
template<typename T>
TtreeNode<T>* Ttree<T>::DoubleRotateLeft(TtreeNode<T> *pNode) //左右情况(先左旋后右旋)
{
pNode->left=SingleRotateRight(pNode->left); //left rotation
pNode->balance=balanceFactor(pNode); //Adjust the balance factor
return SingleRotateLeft(pNode); //right rotation
}
template<typename T>
TtreeNode<T>* Ttree<T>::DoubleRotateRight(TtreeNode<T> *pNode) //右左情况(先右旋后左旋)
{
pNode->right=SingleRotateLeft(pNode->right); //right rotation
pNode->balance=balanceFactor(pNode); //Adjust the balance factor
return SingleRotateRight(pNode); //left rotation
}
template<typename T>
T Ttree<T>::find(T key) //查找节点
{
TtreeNode<T>* pNode=root;
while(pNode)
{
int n=pNode->nItems;
T keymin=pNode->item[0];
T keymax=pNode->item[n>0?n-1:0];
int ncmp1=keycompare(key,keymin);
int ncmp2=keycompare(key,keymax);
if(ncmp1>=0&&ncmp2<=0) //二分查找
{
int l=0,r=n-1;
while(l<=r)
{
int i=(l+r)>>1;
T itemkey=pNode->item[i];
int ncmp=keycompare(key,itemkey);
if(ncmp==0)
{
return pNode->data[i];
}
else if(ncmp>0) {l=i+1;}
else {r=i-1;}
}
break;
}
else if(ncmp1<0)
{
pNode=pNode->left;
}
else if(ncmp2>0)
{
pNode=pNode->right;
}
}
return -1;
}
template<typename T>
void Ttree<T>::insert(const T key,const T data) //插入节点
{
if(root==NULL)
{
root=mallocNode();
root->item[0]=key;
root->data[0]=data;
root->nItems=1;
root->left=NULL;
root->right=NULL;
}
else
{
TtreeNode<T>* pNode=root;
//根据具体情况插入节点
_insert(pNode,key,data);
if(pNode!=root)
{
root=pNode;
}
}
}
template<typename T>
bool Ttree<T>::_insert(TtreeNode<T> * &pNode,const T key,const T data)
{
int n=pNode->nItems;
T keymin=pNode->item[0];
T keymax=pNode->item[n>0?n-1:0];
//compare to the minnimum key
int nDifMin=keycompare(key,keymin);
if(nDifMin<=0) //如果key小于等于keymin
{
TtreeNode<T>* pl=pNode->left;
if((nDifMin==0||pl==NULL)&&pNode->nItems<MaxSize) //在当前节点插入新数据
{
for(int i=n;i>0;--i)
{
pNode->item[i]=pNode->item[i-1];
pNode->data[i]=pNode->data[i-1];
}
pNode->item[0]=key;
pNode->data[0]=data;
pNode->nItems+=1;
return false;
}
if(pl==NULL) //当前键值数目已经达到最大值,而且左子树为空的情况下,新建左子树并插入数据
{
pl=mallocNode();
pl->item[0]=key;
pl->data[0]=data;
pl->nItems+=1;
pNode->left=pl;
}
else //其他情况下,继续递归
{
TtreeNode<T>* plchild=pl;
bool isbfGrow=_insert(plchild,key,data);
if(plchild!=pl)
{
pNode->left=pl=plchild; //relocation
}
if(!isbfGrow) //如果左子树深度不增加,则返回false
{
return false;
}
}
//在左子树深度加1的情况下,程序才运行到此处,则需要更新balance factor
if(pNode->balance>0)
{
pNode->balance=0;
return false;
}
if(pNode->balance==0)
{
pNode->balance=-1;
return true;
}
else
{
if(pl->balance<0) //遇到左左情况,执行右旋
{
pNode=SingleRotateLeft(pNode);
}
else
{
pNode=DoubleRotateLeft(pNode); //遇到左右情况,先左旋再右旋
}
return false;
}
}
//compare to the maxmum key value
int nDifMax=keycompare(key,keymax);
if(nDifMax>=0) //如果key大于等于keymax
{
TtreeNode<T>* pr=pNode->right;
if((pr==NULL||nDifMax)&&pNode->nItems<MaxSize) //在当前节点插入数据
{
pNode->item[n]=key;
pNode->data[n]=data;
pNode->nItems+=1;
return false;
}
else if(pr==NULL) //创建新的右子树
{
pr=mallocNode();
pr->item[0]=key;
pr->data[0]=data;
pr->nItems+=1;
pNode->right=pr;
}
else
{ //继续递归查找并插入
TtreeNode<T>* prchild=pr;
bool isbfGrow=_insert(prchild,key,data);
if(prchild!=pr)
{
pNode->right=pr=prchild;
}
if(!isbfGrow)
{
return false;
}
}
//在右子树深度加1的情况下,程序才运行到此处,则需要更新balance factor
if(pNode->balance<0)
{
pNode->balance=0;
return false;
}
else if(pNode->balance==0)
{
pNode->balance=1;
return true;
}
else
{
if(pr->balance>0)
{
pNode=SingleRotateRight(pNode);
}
else
{
pNode=DoubleRotateRight(pNode);
}
return false;
}
}
//新的键值在数组的中间,用二分法查找
int l=0,r=n-1;
while(l<r)
{
int mid=(l+r)>>1;
T cur_key=pNode->item[mid];
int cmp=keycompare(key,cur_key);
if(cmp>0)
{
l=mid+1;
}
else if(cmp>0)
{
r=mid;
}
else{break;}
}
if(pNode->nItems<MaxSize) //数组长度没达到最大值
{
for(int i=n;i>r;--i)
{
pNode->item[i]=pNode->item[i-1];
pNode->data[i]=pNode->data[i-1];
}
pNode->item[r]=key;
pNode->data[r]=data;
pNode->nItems+=1;
return false;
}
else
{
T keyID,dataID;
//考虑平平衡因子的大小做出不同的选择
if(pNode->balance>=0)
{ //由于数组长度达到最大,在当前节点中插入新数据,并将数组原第一个元素插入到左子树中
keyID=pNode->item[0];
dataID=pNode->data[0];
for(int i=1;i<r;++i)
{
pNode->item[i-1]=pNode->item[i];
pNode->data[i-1]=pNode->data[i];
}
pNode->item[r-1]=key;
pNode->data[r-1]=data;
return _insert(pNode,keyID,dataID);
}
else{ //在当前节点中插入新数据,并将数组原第一个元素插入到有子树中。当前是左子树深度较大,因此往右子树添加元素
keyID=pNode->item[n-1];
dataID=pNode->data[n-1];
for(int i=n-1;i>r;--i)
{
pNode->item[i]=pNode->item[i-1];
pNode->data[i]=pNode->data[i-1];
}
pNode->item[r]=key;
pNode->data[r]=data;
return _insert(pNode,keyID,dataID);
}
}
return 0;
}
template<typename T>
int Ttree<T>::balanceLeftBranch(TtreeNode<T>* &pNode)//平衡左子树,更新节点信息
{
if(pNode->balance<0){pNode->balance=0;return 1;} //返回1表示当前调整的情况对当前节点的父节点以及祖先节点的平衡因子产生影响
else if(pNode->balance==0){pNode->balance=1;return 0;} //返回0则对父节点及祖先节点无影响
else {
TtreeNode<T>* pr=pNode->right;
if(pr->balance>=0)
{
pNode=SingleRotateRight(pNode); //右旋
//return 0;
}
else {
pNode=DoubleRotateRight(pNode); //先右旋后左旋
//return 1;
}
return 1;
}
return 0;
}
template<typename T>
int Ttree<T>::balanceRightBranch(TtreeNode<T>* &pNode)//平衡右子树,更新节点信息
{
if(pNode->balance>0){pNode->balance=0;return 1;}
else if(pNode->balance==0){pNode->balance=-1;return 0;}
else {
TtreeNode<T>* pl=pNode->left;
if(pl->balance<=0)
{
pNode=SingleRotateLeft(pNode); //左旋
}
else {
pNode=DoubleRotateLeft(pNode); //先左旋后右旋
}
return 1;
}
}
template<typename T>
void Ttree<T>::remove(T key)
{
int isOK=_remove(root,key);
if(isOK==-1){cout<<"fail to remove such data"<<endl;}
}
template<typename T>
int Ttree<T>::_remove(TtreeNode<T>* &pNode,T key) //删除操作
{
if(pNode==NULL)return -1;
int n=pNode->nItems;
T keymin=pNode->item[0];
T keymax=pNode->item[n>0?n-1:0];
int nDifMin=keycompare(key,keymin);
if(nDifMin<0) //继续搜索左子树
{
TtreeNode<T>* pl=pNode->left;
if(pl!=NULL)
{
TtreeNode<T>* plchild=pl;
int flag=_remove(plchild,key);
if(pl!=plchild)
{
pNode->left=plchild;
}
if(flag>0) //flag>0表明树的层次由于remove操作而改变,则重新调整
{
return balanceLeftBranch(pNode);
}
else return flag;
}
else return -1; //表示没有找到要删除的key
}
int nDifMax=keycompare(key,keymax);
if(nDifMax<=0) //在当前节点删除数据
{
int i=0;
for(i=0;i<n;++i)
{
if(key==pNode->item[i])break;
}
if(pNode->item[i]!=key)return -1; //表示没有找到要删除的key
if(n<=1)
{
if(pNode->left==NULL) //如果左子树为空,此种情况对于左右子树皆为空也适用
{
TtreeNode<T>* pNewNode=pNode->right;
freeNode(pNode);
pNode=pNewNode;
}
else if(pNode->right==NULL)//如果右子树为空
{
TtreeNode<T>* pNewNode=pNode->left;
freeNode(pNode);
pNode=pNewNode;
}
return 1; //树层次改变,返回1
}
else { //在当前节点内删除
if(pNode->nItems<=MinSize) //当前节点键值数目小于或等于最低限制值
{
TtreeNode<T>* plchild=pNode->left,*prchild=pNode->right;
//如果结点N中的键值数量少于最小值,则根据N的平衡因子决定从结点N的左子树中移出最大的键值或者右子树中移出最小值来填充。
if(plchild!=NULL&&pNode->balance<=0)
{
while(plchild->right!=NULL)
{
plchild=plchild->right;
}
while(i>0)
{
pNode->item[i]=pNode->item[i-1];
pNode->data[i]=pNode->data[i-1];
--i;
}
pNode->item[0]=plchild->item[plchild->nItems-1];
pNode->data[0]=plchild->data[plchild->nItems-1];
key=pNode->item[0];
TtreeNode<T>* plTmp=plchild;
int flag=_remove(plTmp,key);
if(plTmp!=plchild)
{pNode->left=plTmp;}
if(flag>0){flag=balanceLeftBranch(pNode);}
return flag;
}
else if(prchild!=NULL)
{
while(prchild->left!=NULL)
{
prchild=prchild->left;
}
while(i<n-1)
{
pNode->item[i]=pNode->item[i+1];
pNode->data[i]=pNode->data[i+1];
++i;
}
pNode->item[n-1]=plchild->item[0];
pNode->data[n-1]=plchild->data[0];
key=pNode->item[n-1];
TtreeNode<T>* prTmp=prchild;
int flag=_remove(prTmp,key);
if(prTmp!=prchild)
{pNode->right=prTmp;}
if(flag>0){flag=balanceRightBranch(pNode);}
return flag;
}
}
//当前节点键值数目大于最小限制值
int k=i;
while(k<n-1)
{
pNode->item[k]=pNode->item[k+1];
pNode->data[k]=pNode->data[k+1];
k++;
}
pNode->nItems-=1;
return 0; //树的层次不变,返回0
}
}
else{ //搜索右子树
TtreeNode<T>* pr=pNode->right;
if(pr!=NULL)
{
TtreeNode<T>* prchild=pr;
int flag=_remove(prchild,key);
if(pr!=prchild)
{pNode->right=prchild;}
if(flag>0) //树层次改变
{
return balanceRightBranch(pNode);
}
else return flag; //树层次不变
}
}
return -1;
}
主要参考资料来源于csdn博客:
http://blog.youkuaiyun.com/liuxuezong/archive/2010/12/03/6052686.aspx
http://blog.youkuaiyun.com/liuxuezong/archive/2010/12/06/6058373.aspx