C++二叉树类实现

来源:互联网 发布:网络被限制不能玩游戏 编辑:程序博客网 时间:2024/06/06 01:56
//2015年3月21日21:41:13
//定义泛型的二叉树类
#include<iostream>
using namespace std;


//定义节点类
template<class T> class BTree;
template<class T> class BSTree;
template<class T> class BTreeNode
{
friend class BTree<T>;
friend class BSTree<T>;
T data;
BTreeNode<T> * lchild,*rchild;
public:
BTreeNode():lchild(NULL),rchild(NULL){};
BTreeNode(T d,BTreeNode<T> * l = NULL,BTreeNode<T> * r = NULL)
:data(d),lchild(l),rchild(r){};
T getdata(){return data;};
BTreeNode<T> * getleft(){return lchild;};
BTreeNode<T> * getright(){return rchild;};
};
//定义二叉树类:设置了两个同名的函数;一个是递归函数,静态,不涉及当前对象
//另一个是实例函数;涉及当前对象,通过调用递归函数想外界提供服务;实现对当前对象的操作
template<class T> class BTree
{
T * a;//数组储存数据
int n;//节点个数
BTreeNode<T> * build0(int i);//创建i个节点二叉树函数
protected:
BTreeNode<T> * root;//根节点
public:
BTree(BTreeNode<T> * p =NULL){copybt(root,p);};//设置根节点的构造函数
BTree(T a[],int n);//赋值数组的构造函数
void build(T a[],int n);//构建二叉树函数
int num();//求节点数的函数
static int num(BTreeNode<T> * p);//静态求节点数的函数
int dep();//求深度的函数
static int dep(BTreeNode<T> * p);//静态求深度的函数
bool equal(BTree & bt);//判断两个树是否相等
static bool equal(BTreeNode<T> * p,BTreeNode<T> * q);//静态判断两个树是否相等
void copybt(BTree & bt);//复制树函数
static void copybt(BTreeNode<T> * &p,BTreeNode<T> * q);//静态复制树函数
void visit(BTreeNode<T> * p);//判断
void preorder(void visit(BTreeNode<T> *p));//先序遍历
static void preorder(BTreeNode<T> * p,void visit(BTreeNode<T> * p));//先序遍历静态方法
void inorder(void visit(BTreeNode<T> * p));//中序遍历
static  void inorder(BTreeNode<T> * p,void visit(BTreeNode<T> * p));//中序遍历静态方法
void inorder1(void visit(BTreeNode<T> * p));//中序遍历非递归实现
void posorder(void visit(BTreeNode<T> * p));//后序遍历
static  void posorder(BTreeNode<T> * p,void visit(BTreeNode<T> * p));//后序遍历静态方法
void destroy();//销毁方法;释放内存
static void destroy(BTreeNode<T> * p);//静态释放内存
void setRoot(BTreeNode<T> * p);
static void prnt(BTreeNode<T> * p,int l);
void prnt(){prnt(root,1);};
};
//传入数组存储的二叉树构造函数
template<class T> BTree<T>::BTree(T a[],int n)
{
this->a = a;//指向第一个节点
this->n = n;//确定节点个数
root = build0(1);//调用函数
}
//定义创建函数
template<class T> BTreeNode<T> * BTree<T>::build0(int i)
{
BTreeNode<T> * p;
int r,l;
T t = NULL;//编译器不兼容;不然可以直接判断a[i-1]!=""
if(i<=n&&(a[i-1]!=t))
{
p = new BTreeNode<T>;
p->data = a[i-1];//储存相应的数据
l = 2*i;r = 2*i+1;//左子树对应的元素在数组中的位置;分段的.
p->lchild = build0(l);//先创建左子树
p->rchild = build0(r);//再递归创建右子树
return p;
}
else
return (NULL);//停止的条件
}
//定义确定节点个数函数
template<typename T> int BTree<T>::num()
{
return num(root);//调用静态方法求二叉树节点个数
}
//定义静态方法;求二叉树节点个数
template<class T> int BTree<T>::num(BTreeNode<T> * p)
{
if(NULL == p)//节点尾;返回0
return 0;
return num(p->lchild)+num(p->rchild)+1;//+1表示加上头节点
}
//定义求深度函数
template<class T> int BTree<T>::dep()
{
return dep(root)//调用静态方法求二叉树的深度
}
//定义静态求二叉树深度函数
template<class T> int BTree<T>::dep(BTreeNode<T> * p)
{
int max;
if(NULL == p)//空节点度为0
return 0;
else
{
max = dep(p->lchild);
if(dep(p->rchild)>max)//求左子树和右子树中最长
max = dep(p->rchild);
return max+1;
}
}
//定义判断相等函数静态方法
template<class T> bool BTree<T>::equal(BTreeNode<T> * p,BTreeNode<T> * q)
{
bool b;
if(p == NULL && q==NULL) 
b = true;
else if(p == NULL || q == NULL)
b = false;
else
b = (p->data == q->data)&&equal(p->lchild,q->lchild)&&equal(p->rchild,q->rchild);
//递归确定数据是否相等再确定左右子树是否相等
return b;
}
//定义判断二叉树是否相等函数
template<class T> bool BTree<T>::equal(BTree<T> & bt)
{
return equal(root,bt.root);//调用静态方法
}
//定义销毁函数;释放内存
template<class T> void BTree<T>::destroy()
{
destroy(root);//调用静态方法释放内存
}
//定义静态方法释放内存
template<class T> void BTree<T>::destroy(BTreeNode<T> * p)
{
if(NULL != p)
{
destroy(p->lchild);//递归释放左子树
destroy(p->rchild);//递归释放右子树
cout<<p->data<<" ";//这句话是为了调试代码
delete p;
}
}
//二叉树的复制
template<class T> void BTree<T>::copybt(BTree<T> & bt)
{
destroy(root);//先释放原来的二叉树
copybt(root,bt.root);
}
//定义定义复制函数静态方法
template<class T> void BTree<T>::copybt(BTreeNode<T> * &p,BTreeNode<T> * q)
{
if(q == NULL)
p = NULL;
else
{
p = new BTreeNode<T>();
p->data = q->data;//先存储数据再建立左右子树
copybt(p->lchild,q->lchild);
copybt(p->rchild,q->rchild);
}
}
//二叉树的遍历//递归函数
template<class T> void BTree<T>::visit(BTreeNode<T> * p)
{
cout<<p->data<<" ";//便于查看元素;一般不在类中定义;在类外定义;再传入函数指针做具体的显示任务
}
//中序遍历函数
template<class T> void BTree<T>::inorder(void visit(BTreeNode<T> * p))
{
inorder(root,visit);
cout<<endl;
}
//中序遍历函数静态方法
template<class T> void BTree<T>::inorder(BTreeNode<T> * p,void visit(BTreeNode<T> * p))
{
if(NULL!=p)
{
inorder(p->lchild,visit);
visit(p);//遍历左子树再输出中间节点的数据;然后遍历右子树
inorder(p->rchild,visit);
}
}
//二叉树遍历//非递归函数//不太理解;到时候注意复习!!!!!!!!!
template<class T> void BTree<T>::inorder1(void visit(BTreeNode<T> * p))
{
BTreeNode<T> * stack[10],* p;
int top = 0;
s = "";
stack[top] = root;
while(top>=0)
{
while(NULL!=stack[top])
{
p = stack[top]->lchild;
stack[++top] = p;
}
top--;
if(top>=0)
{
p = stack[top];
visit(p);
stack[top] = p->rchild;
}
}
cout<<endl;
}
//定义重置函数;其实可以通过重载'='运算符来实现.
template<class T> void BTree<T>::setRoot(BTreeNode<T> * p)
{
destroy(root);
copybt(root,p);
cout<<endl<<"重置成功"<<endl;//测试程序功能
}
//定义显示树函数
template<class T> void BTree<T>::prnt(BTreeNode<T> * p,int l)
{
if(NULL != p)
{
prnt(p->rchild,l+1);
for(int i = 0;i<6*(l-1);i++)
cout<<" ";
cout<<"..."<<p->data<<endl;
prnt(p->lchild,l+1);
}
}


//测试代码
void func1(BTreeNode<char> * p)//外部定义的测试函数;做具体的显示功能
{cout<<p->getdata()<<" ";}
//尝试失败
char * changeNULL(char * p,int n)
{
for(int i = 0;i<n;i++)
if(p[i] == ' ')
p[i] = NULL;
return p;
}
int main(void)
{
char * str = "-*cab";
BTree<char> bt(str,5);
bt.inorder(func1);
char * str2 = "abcd\0f";//空格用\0代替;不然会得不到预期的效果
//str2 = changeNULL(str2,6);//错误
BTree<char> bt2(str2,6);
bt2.prnt();
BTreeNode<char> * p1 = new BTreeNode<char>('x',NULL,NULL);
BTreeNode<char> * p2 = new BTreeNode<char>('y',NULL,NULL);
BTreeNode<char> * p3 = new BTreeNode<char>('z',p1,p2);
bt2.setRoot(p3);
bt2.prnt();
return 0;
}
0 0
原创粉丝点击