目录
前言
个人认为二叉树的核心是递归,绝大部分的操作,都可以使用递归来实现。
主要操作
结构体和类定义
template <class T>
struct BinTreeNode{
T data;
BinTreeNode *leftChild,*rightChild;
BinTreeNode():leftChild(NULL),rightChild(NULL){}
BinTreeNode(T x,BinTreeNode<T> *l=NULL,BinTreeNode<T> *r=NULL)
:data(x),leftChild(l),rightChild(r){}
};
//类定义
//对象: 结点的有限集合, 二叉树是有序树
template <class T>
class BinaryTree {
public:
//构造函数
BinaryTree ():root(NULL){}
BinaryTree(T value):RefValue(value),root(NULL){}
BinaryTree(BinaryTree<T>& s);
~BinaryTree(){destroy(root);}
BinaryTree (BinTreeNode<T> *lch,BinTreeNode<T> *rch, T item);
//构造函数, 以item为根, lch和rch为左、右子
//树构造一棵二叉树
//BinTreeNode<T> *createpretree(int l,int i,string &a);
void CreatTree(BinTreeNode<T> *& root);
//高度、深度、判空、取结点
int Height (BinTreeNode<T> * root);//求树深度或高度{return Height(root);}
int Size (BinTreeNode<T> * root);//求树中结点个数{return Size(root);}
bool IsEmpty (){return (root==NULL)?true:false;}; //判二叉树空否?
bool Find (T& item,BinTreeNode<T> * root); //判断item是否在树中
BinTreeNode<T> *getData(T& item,BinTreeNode<T> * root); //取得结点数据
//求结点
BinTreeNode<T> *Parent (BinTreeNode <T> *subTree,BinTreeNode<T> *t);
//求结点 t 的双亲{return (root==NULL||root==t)?NULL:Parent(root,t);}
BinTreeNode<T> *LeftChild (BinTreeNode<T> *t)//求结点 t 的左子女
{return (t!=NULL)?t->leftChild:NULL;}
BinTreeNode<T> *RightChild (BinTreeNode<T> *t)//求结点 t 的右子女
{return (t!=NULL)?t->rightChild:NULL;}
//遍历
BinTreeNode<T> *getRoot (){return root;} //取根
BinTreeNode<T> *CopyTree( BinTreeNode<T> *orignode);
void preOrder ( BinTreeNode<T> *root);//前序遍历
void inOrder ( BinTreeNode<T> * root);//中序遍历
void postOrder ( BinTreeNode<T> * root);//后序遍历
void levelOrder (BinTreeNode<T> * root);//层次序遍历
protected:
BinTreeNode<T> * root;
T RefValue;
void destroy (BinTreeNode<T> * subTree);
};
一、二叉树建立
前序遍历建立二叉树
空传入
template <class T>
void BinaryTree<T>::CreatTree(BinTreeNode<T> *& root)
{ T item;
cin>>item;
if(item!=RefValue)
{ root=new BinTreeNode<T>(item);
if(root ==NULL)
{ cerr<<"分配结点失败!\n"; exit(1); }
CreatTree(root->leftChild);
CreatTree(root->rightChild);
}
else root=NULL;
}
传引用
template <class T>
BinTreeNode<T> * BinaryTree<T>::createpretree(int l,int i,string &a)
{//l为数组a的长度,i为数组下标
BinTreeNode<T> *root;
if(l==0||a[i]=='#'||i==l)root=NULL;
else
{
root=new BinTreeNode<T>(a[i++]);
root->leftChild=createpretree(l,i,a);
root->rightChild=createpretree(l,++i,a);
}
return root;
}
二、遍历
2.1前序遍历
template <class T>
void BinaryTree<T>::preOrder(BinTreeNode<T> * root)
{
if (root != NULL)
{
cout<<root->data<<" "; //先序访问根结点
preOrder(root->leftChild); //遍历左子树
preOrder(root->rightChild); //先序遍历右子树
}
}
2.2中序遍历
template <class T>
void BinaryTree<T>::inOrder(BinTreeNode<T> * root)
{
if (root != NULL)
{
inOrder(root->leftChild); //中序遍历左子树
cout<<root->data<<" "; //访问根结点
inOrder(root->rightChild); //中序遍历右子树
}
}
2.3后序遍历
template <class T>
void BinaryTree<T>::postOrder(BinTreeNode<T> * root)
{
if (root != NULL)
{
postOrder(root->leftChild); //后序遍历左子树
postOrder(root->rightChild); //遍历右子树
cout<<root->data<<" "; //后序访问根结点
}
}
2.4层次遍历
template <class T>
void BinaryTree<T>::levelOrder(BinTreeNode<T> *root)
{ if (root == NULL) return;
queue<BinTreeNode<T> * > Q;
BinTreeNode<T> *p;
Q.push(root); //根结点入队列
while (!Q.empty())
{
p=Q.front();
cout<<(Q.front())->data<<" "; //输出出队结点的数据
Q.pop(); //队头结点出队
if (p->leftChild != NULL) //若出队结点有左孩子
{ Q.push(p->leftChild);} //左孩子入队列p=p->leftChild;
if (p->rightChild != NULL)
{Q.push(p->rightChild);
}
}
}
有一种方法是使用自定义的队列,思路大致和上面相同,但在此不写怎么麻烦的方法了。
三、求结点
3.1求父结点
template <class T>
BinTreeNode<T> *BinaryTree<T>::
Parent (BinTreeNode <T> *subTree,BinTreeNode <T> *t)
{
if (subTree == NULL) return NULL;
if (subTree->leftChild == t ||subTree->rightChild == t)
return subTree; //找到, 返回父结点地址
BinTreeNode <T> *p;
if ((p = Parent (subTree->leftChild, t)) != NULL)
return p; //递归在左子树中搜索
else return Parent (subTree->rightChild, t);
//递归在右子树中搜索
}
3.2求左子结点、右子结点
//定义在类中
BinTreeNode<T> *LeftChild (BinTreeNode<T> *t)
{return (t!=NULL)?t->leftChild:NULL;}//求结点 t 的左子女
BinTreeNode<T> *RightChild (BinTreeNode<T> *t)
{return (t!=NULL)?t->rightChild:NULL;} //求结点 t 的右子女
四、求高度、深度、判空等
4.1高度
template <class T>
int BinaryTree<T>::Height(BinTreeNode<T> * root)
{
if (root == NULL) return 0;
else
{
int i = Height(root->leftChild);
int j = Height(root->rightChild);
return (i < j) ? j+1 : i+1;
}
}
4.2结点个数
template <class T>
int BinaryTree<T>::Size(BinTreeNode<T> * root)
{
if (root == NULL) return 0; //空树
else
return 1+Size(root->leftChild)+Size(root->rightChild);
}
4.3判空
//在类中
bool IsEmpty (){return (root==NULL)?true:false;};
4.4结点是否存在
template<class T>
bool BinaryTree<T>::Find (T& item,BinTreeNode<T> * root)
{
if(this->getData(item,root)==NULL)return false;
else return true;
}
4.5结点数据
template<class T>
BinTreeNode<T> *BinaryTree<T>::getData(T& item,BinTreeNode<T> * root)
{
if(root==NULL)return NULL;
if(root->data==item)return root;
return getData(item,root->leftChild)!=NULL?getData(item,root->leftChild):getData(item,root->rightChild);
}
4.6销毁二叉树
template<class T>
void BinaryTree<T>::destroy (BinTreeNode<T>* subTree) {
//私有函数: 后序遍历删除根为subTree的子树;
if (subTree != NULL) {
destroy (subTree->leftChild); //删除左子树
destroy (subTree->rightChild); //删除右子树
delete subTree; //删除根结点
}
}
五、主函数
int main()
{
char ch;
cout<<"输入结束标志:";
cin>>ch;
BinaryTree<char> t(ch);
BinTreeNode<char>* head=t.getRoot();
t.CreatTree(head);
return 0;
}
六、总代码
#include<bits/stdc++.h>
using namespace std;
template <class T>
struct BinTreeNode{
T data;
BinTreeNode *leftChild,*rightChild;
BinTreeNode():leftChild(NULL),rightChild(NULL){}
BinTreeNode(T x,BinTreeNode<T> *l=NULL,BinTreeNode<T> *r=NULL)
:data(x),leftChild(l),rightChild(r){}
};
//类定义
//对象: 结点的有限集合, 二叉树是有序树
template <class T>
class BinaryTree {
public:
BinaryTree ():root(NULL){} //构造函数
BinaryTree(T value):RefValue(value),root(NULL){}
BinaryTree(BinaryTree<T>& s);
~BinaryTree(){destroy(root);}
BinaryTree (BinTreeNode<T> *lch,BinTreeNode<T> *rch, T item);
//构造函数, 以item为根, lch和rch为左、右子
//树构造一棵二叉树
//BinTreeNode<T> *createpretree(int l,int i,string &a);
void CreatTree(BinTreeNode<T> *& root);
int Height (BinTreeNode<T> * root);//求树深度或高度{return Height(root);}
int Size (BinTreeNode<T> * root);//求树中结点个数{return Size(root);}
bool IsEmpty (){return (root==NULL)?true:false;}; //判二叉树空否?
BinTreeNode<T> *Parent (BinTreeNode <T> *subTree,BinTreeNode<T> *t);
//求结点 t 的双亲{return (root==NULL||root==t)?NULL:Parent(root,t);}
BinTreeNode<T> *LeftChild (BinTreeNode<T> *t)
{return (t!=NULL)?t->leftChild:NULL;}//求结点 t 的左子女
BinTreeNode<T> *RightChild (BinTreeNode<T> *t)
{return (t!=NULL)?t->rightChild:NULL;} //求结点 t 的右子女
//bool Insert (const T& item); //在树中插入新元素
//bool Remove (T item); //在树中删除元素
bool Find (T& item,BinTreeNode<T> * root); //判断item是否在树中
BinTreeNode<T> *getData(T& item,BinTreeNode<T> * root); //取得结点数据
BinTreeNode<T> *getRoot (){return root;} //取根
BinTreeNode<T> *CopyTree( BinTreeNode<T> *orignode);
void preOrder ( BinTreeNode<T> *root);//前序遍历
void inOrder ( BinTreeNode<T> * root);//中序遍历
void postOrder ( BinTreeNode<T> * root);//后序遍历
void levelOrder (BinTreeNode<T> * root);//层次序遍历
protected:
BinTreeNode<T> * root;
T RefValue;
void destroy (BinTreeNode<T> * subTree);
};
//template <class T>
//BinaryTree::BinaryTree()
/*
//建立二叉树
template <class T>
BinTreeNode<T> * BinaryTree<T>::createpretree(int l,int i,string &a)
{
BinTreeNode<T> *root;
if(l==0||a[i]=='#'||i==l)root=NULL;
else
{
root=new BinTreeNode<T>(a[i++]);
root->leftChild=createpretree(l,i,a);
root->rightChild=createpretree(l,++i,a);
}
return root;
}*/
//先序遍历创建一棵二叉树
template <class T>
void BinaryTree<T>::CreatTree(BinTreeNode<T> *& root)
{ T item;
cin>>item;
if(item!=RefValue)
{ root=new BinTreeNode<T>(item);
if(root ==NULL)
{ cerr<<"分配结点失败!\n"; exit(1); }
CreatTree(root->leftChild);
CreatTree(root->rightChild);
}
else root=NULL;
}
//遍历
//先序遍历
template <class T>
void BinaryTree<T>::preOrder(BinTreeNode<T> * root)
{
if (root != NULL)
{ cout<<root->data<<" "; //先序访问根结点
preOrder(root->leftChild); //遍历左子树
preOrder(root->rightChild); //先序遍历右子树
}
}
//中序遍历
template <class T>
void BinaryTree<T>::inOrder(BinTreeNode<T> * root)
{
if (root != NULL)
{
inOrder(root->leftChild); //中序遍历左子树
cout<<root->data<<" "; //访问根结点
inOrder(root->rightChild); //中序遍历右子树
}
}
//后序遍历
template <class T>
void BinaryTree<T>::postOrder(BinTreeNode<T> * root)
{
if (root != NULL)
{
postOrder(root->leftChild); //后序遍历左子树
postOrder(root->rightChild); //遍历右子树
cout<<root->data<<" "; //后序访问根结点
}
}
//层次遍历
template <class T>
void BinaryTree<T>::levelOrder(BinTreeNode<T> *root)
{ if (root == NULL) return;
queue<BinTreeNode<T> * > Q;
BinTreeNode<T> *p;
Q.push(root); //根结点入队列
while (!Q.empty())
{
p=Q.front();
cout<<(Q.front())->data<<" "; //输出出队结点的数据
Q.pop(); //队头结点出队
if (p->leftChild != NULL) //若出队结点有左孩子
{ Q.push(p->leftChild);} //左孩子入队列p=p->leftChild;
if (p->rightChild != NULL)
{Q.push(p->rightChild);
}
}
}
//结点个数
template <class T>
int BinaryTree<T>::Size(BinTreeNode<T> * root)
{
if (root == NULL) return 0; //空树
else
return 1+Size(root->leftChild)+Size(root->rightChild);
}
//空树高度为0
template <class T>
int BinaryTree<T>::Height(BinTreeNode<T> * root)
{
if (root == NULL) return 0;
else
{
int i = Height(root->leftChild);
int j = Height(root->rightChild);
return (i < j) ? j+1 : i+1;
}
}
//二叉树复制
template <class T>
BinTreeNode<T> * BinaryTree<T>::CopyTree( BinTreeNode<T> *orignode)
{
if(orignode==NULL) return NULL;
BinTreeNode<T> *temp=new BinTreeNode<T>;
temp->data=orignode->data;
temp->leftChild=CopyTree(orignode->leftChild);
temp->rightChild=CopyTree(orignode->rightChild);
return temp;
}
//寻找双亲结点
template <class T>
BinTreeNode<T> *BinaryTree<T>::
Parent (BinTreeNode <T> *subTree,BinTreeNode <T> *t)
{
if (subTree == NULL) return NULL;
if (subTree->leftChild == t ||subTree->rightChild == t)
return subTree; //找到, 返回父结点地址
BinTreeNode <T> *p;
if ((p = Parent (subTree->leftChild, t)) != NULL)
return p; //递归在左子树中搜索
else return Parent (subTree->rightChild, t);
//递归在右子树中搜索
}
//查找结点数据
template<class T>
BinTreeNode<T> *BinaryTree<T>::getData(T& item,BinTreeNode<T> * root)
{
if(root==NULL)return NULL;
if(root->data==item)return root;
return getData(item,root->leftChild)!=NULL?getData(item,root->leftChild):getData(item,root->rightChild);
}
//查找结点是否在树中
template<class T>
bool BinaryTree<T>::Find (T& item,BinTreeNode<T> * root)
{
if(this->getData(item,root)==NULL)return false;
else return true;
}
//销毁二叉树
template<class T>
void BinaryTree<T>::destroy (BinTreeNode<T>* subTree) {
//私有函数: 后序遍历删除根为subTree的子树;
if (subTree != NULL) {
destroy (subTree->leftChild); //删除左子树
destroy (subTree->rightChild); //删除右子树
delete subTree; //删除根结点
}
}
//BinTreeNode<char> *root;
int main()
{
char ch;
cout<<"输入结束标志:";
cin>>ch;
BinaryTree<char> t(ch);
// cout<<"输入遍历序列:";
// string a;
// cin>>a;
// int l=a.length();
// int i=0;
BinTreeNode<char>* head=t.getRoot();
t.CreatTree(head);
return 0;
}
七、总结
点个赞再走吧~~