本程序集二叉树各种操作于一体
1.递归形式的前序遍历,中序遍历,后序遍历
2.非递归形式的前序遍历,中序遍历,后序遍历
3.二叉树的建立
4.二叉树上各种操作的实现
读者可以直接根据函数头和说明直接调用或者调试,对每种操作的算法解释,在其它的博客中(点击上方链接即可),欢迎借鉴学习
函数头
//按前序遍历建立一颗带头节点的二叉树
template <typename T> BiTree<T> *createBiTree();
//递归先序遍历二叉树
template<typename T> void preOrder(BiTree<T> *bt);
//递归中序遍历二叉树
template<typename T> void inOrder(BiTree<T> *bt);
//递归后序遍历二叉树
template<typename T> void postOrder(BiTree<T> *bt);
//队列实现二叉树层序遍历
template<typename T> void levelOrder(BiTree<T> *bt);
//非递归方法中序遍历二叉树
template<typename T> void inOrderNR(BiTree<T> *bt) ;
//非递归方法前序遍历二叉树
template<typename T> void preOrderNR(BiTree<T> *bt);
//非递归方法后序递归二叉树
template<typename T> void postOrderNR(BiTree<T> *bt);
//访问根节点
template<typename T> void visit(BiTree<T> *bt);
//求二叉树bt子树深度的递归算法
template<typename T> int getDepth(BiTree<T> *bt);
//在二叉树bt中查找数据元素值为data的节点,
//查找成功,返回指向该节点的指针,失败返回空指针
template<typename T> BiTree<T> *getData( BiTree<T> *bt,T data);
//统计二叉树bt中叶子节点的个数
template<typename T> int countLeaf(BiTree<T> *bt);
//非递归方法中序遍历二叉树来计算统计二叉树叶子节点个数
template<typename T> int countLeafNR(BiTree<T> *bt) ;
//利用二叉树的性质计算二叉树bt中度为2的节点的个数
template<typename T> int countDegreeTwo(BiTree<T> *bt) ;
//非递归中序遍历二叉树,统计二叉树中度为1的节点个数
template<typename T> int countDegreeOne(BiTree<T> *bt) ;
//非递归中序遍历二叉树,统计二叉树中所有节点的个数
template<typename T> int countNode(BiTree<T> *bt) ;
//非递归中序遍历获得二叉树bt中数据的最大值
template<typename T> T getMaxVal(BiTree<T> *bt);
//非递归中序遍历获得二叉树bt中数据的最小值
template<typename T> T getMinVal(BiTree<T> *bt);
完整代码
#include<bits/stdc++.h>
using namespace std;
const char flag = '#';
//二叉树节点结构体定义
template <typename T=double>
struct BiTree{
T data;
BiTree<T> *left,//左子树
*right;//右子树
//构造函数
BiTree(){ left = right = NULL; }
BiTree(const T &theData){ data = theData;left = right = NULL;}
BiTree(const T theData,BiTree *theLeft,BiTree *theRight)
{data = theData;left=theLeft;right = theRight; }
};
//按前序遍历建立一颗带头节点的二叉树
template <typename T> BiTree<T> *createBiTree();
//递归先序遍历二叉树
template<typename T> void preOrder(BiTree<T> *bt);
//递归中序遍历二叉树
template<typename T> void inOrder(BiTree<T> *bt);
//递归后序遍历二叉树
template<typename T> void postOrder(BiTree<T> *bt);
//队列实现二叉树层序遍历
template<typename T> void levelOrder(BiTree<T> *bt);
//非递归方法中序遍历二叉树
template<typename T> void inOrderNR(BiTree<T> *bt) ;
//非递归方法前序遍历二叉树
template<typename T> void preOrderNR(BiTree<T> *bt);
//非递归方法后序递归二叉树
template<typename T> void postOrderNR(BiTree<T> *bt);
//访问根节点
template<typename T> void visit(BiTree<T> *bt);
//求二叉树bt子树深度的递归算法
template<typename T> int getDepth(BiTree<T> *bt);
//在二叉树bt中查找数据元素值为data的节点,
//查找成功,返回指向该节点的指针,失败返回空指针
template<typename T> BiTree<T> *getData( BiTree<T> *bt,T data);
//统计二叉树bt中叶子节点的个数
template<typename T> int countLeaf(BiTree<T> *bt);
//非递归方法中序遍历二叉树来计算统计二叉树叶子节点个数
template<typename T> int countLeafNR(BiTree<T> *bt) ;
//利用二叉树的性质计算二叉树bt中度为2的节点的个数
template<typename T> int countDegreeTwo(BiTree<T> *bt) ;
//非递归中序遍历二叉树,统计二叉树中度为1的节点个数
template<typename T> int countDegreeOne(BiTree<T> *bt) ;
//非递归中序遍历二叉树,统计二叉树中所有节点的个数
template<typename T> int countNode(BiTree<T> *bt) ;
//非递归中序遍历获得二叉树bt中数据的最大值
template<typename T> T getMaxVal(BiTree<T> *bt);
//非递归中序遍历获得二叉树bt中数据的最小值
template<typename T> T getMinVal(BiTree<T> *bt);
int main()
{
BiTree<char> *bt;
cout<<" 用前序遍历创建二叉树:";
bt = createBiTree<char>();
cout<<" 对遍历的测试" <<endl;
cout<<" 前序遍历结果:"; preOrder(bt);cout<<endl;
cout<<" 中序遍历结果:"; inOrder(bt);cout<<endl;
cout<<" 后序遍历结果:"; postOrder(bt); cout<<endl;
cout<<" 非递归前序遍历结果:"; preOrderNR(bt);cout<<endl;
cout<<" 非递归中序遍历结果:"; inOrderNR(bt) ;cout<<endl;
cout<<" 非递归后序遍历结果:"; postOrderNR(bt);cout<<endl;
cout<<" 层次遍历结果:"; levelOrder(bt); cout<<endl;
cout<<endl;
cout<<" 对相关操作的测试" <<endl;
cout<<" 递归方法统计二叉树叶子节点个数为:"<<countLeaf(bt)<<endl;
cout<<" 用递归求得二叉树bt子树深度为:"<<getDepth(bt)<<endl;
char x = 'G';
//cout<<" 递归查找"<<x<<" 的子树深度为:"<<getDepth(getData(bt,x))<<endl;
cout<<" 递归查找值为"<<x<<" 的节点的值为:"<<getData(bt,x)->data<<endl;
//cout<<" 非递归方法统计"<<endl;
cout<<" 该二叉树总的节点个数为:"<<countNode(bt)<<endl;
cout<<" 该二叉树叶子节点个数为:"<<countLeafNR(bt)<<endl;
cout<<" 该二叉树度为1节点个数为:"<<countDegreeOne(bt)<<endl;
cout<<" 该二叉树度为2节点个数为:"<<countDegreeTwo(bt)<<endl;
cout<<" 该二叉树中数值最大值为:"<<getMaxVal(bt)<<endl;
cout<<" 该二叉树中数值最小值为:"<<getMinVal(bt)<<endl;
}
// A B C # # D E # G # # F # # #
//zmooc A B D # # F E # # # C G # H # # I # #
//非递归中序遍历获得二叉树bt中数据的最大值
//非递归中序遍历二叉树,统计二叉树中所有节点的个数
template<typename T> int countNode(BiTree<T> *bt) {
int ans ;
stack<BiTree<T>* > s; //创建栈
BiTree<T> *p = bt; //创建临时指针p
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
//visit(s.top());//访问根结点
ans++;
p = s.top(); // p要指向此时s的栈顶元素,否则p=NULL,程序就会出错
s.pop(); //结点出栈
p = p->right; // 转向右子树
}
return ans;
}
template<typename T> T getMaxVal(BiTree<T> *bt){
T ans = bt->data;
stack<BiTree<T>* > s; //创建栈
BiTree<T> *p = bt; //创建临时指针p
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
//visit(s.top());//访问根结点
if(ans <= s.top()->data)
ans = s.top()->data;
p = s.top(); // p要指向此时s的栈顶元素,否则p=NULL,程序就会出错
s.pop(); //结点出栈
p = p->right; // 转向右子树
}
return ans;
}
//非递归中序遍历获得二叉树bt中数据的最小值
template<typename T> T getMinVal(BiTree<T> *bt){
T ans = bt->data;
stack<BiTree<T>* > s; //创建栈
BiTree<T> *p = bt; //创建临时指针p
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
//visit(s.top());//访问根结点
if(ans > s.top()->data)
ans = s.top()->data;
p = s.top(); // p要指向此时s的栈顶元素,否则p=NULL,程序就会出错
s.pop(); //结点出栈
p = p->right; // 转向右子树
}
return ans;
}
//利用二叉树的性质计算二叉树bt中度为2的节点的个数
template<typename T> int countDegreeTwo(BiTree<T> *bt) {
return countLeaf(bt) - 1;
}
//非递归方法中序遍历二叉树来计算统计二叉树叶子节点个数
template<typename T> int countLeafNR(BiTree<T> *bt)
{ int count = 0;
stack<BiTree<T>* > s; //创建栈
BiTree<T> *p = bt; //创建临时指针p
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
//visit(s.top());//访问根结点
if(s.top()->right == NULL && s.top()->left == NULL)//访问的时候检测是否为叶子节点
count++;
p = s.top(); // p要指向此时s的栈顶元素,否则p=NULL,程序就会出错
s.pop(); //结点出栈
p = p->right; // 转向右子树
}
return count;
}
//非递归——中序遍历二叉树统计二叉树中度为2的节点个数
template<typename T> int countDegreeOne(BiTree<T> *bt)
{ int count = 0;
stack<BiTree<T>* > s; //创建栈
BiTree<T> *p = bt; //创建临时指针p
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
//visit(s.top());//访问根结点
if(s.top()->right == NULL ^ s.top()->left == NULL)//访问的时候检测是否为叶子节点
count++;
p = s.top(); // p要指向此时s的栈顶元素,否则p=NULL,程序就会出错
s.pop(); //结点出栈
p = p->right; // 转向右子树
}
return count;
}
//队列实现二叉树层序遍历
template<typename T> void levelOrder(BiTree<T> *bt)
{
queue<BiTree<T> *> q; //声明队列q,类型为二叉树节点的指针
if(bt == NULL ) //如果二叉树为空,直接退出
{
return ;
}
q.push(bt);
while(!q.empty()) //队列非空时
{
visit(q.front()); //访问队首节点
if(q.front()->left != NULL)//队首结点的左孩子进队列
q.push(q.front()->left);
if(q.front()->right != NULL)//队首节点的右孩子进队
q.push(q.front()->right);
q.pop(); //队首结点出队列
}
}
//非递归方法中序遍历二叉树
template<typename T> void inOrderNR(BiTree<T> *bt)
{
stack<BiTree<T>* > s; //创建栈
BiTree<T> *p = bt; //创建临时指针p
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
visit(s.top());//访问根结点
p = s.top(); // p要指向此时s的栈顶元素,否则p=NULL,程序就会出错
s.pop(); //结点出栈
p = p->right; // 转向右子树
}
}
//非递归方法前序遍历二叉树
template<typename T> void preOrderNR(BiTree<T> *bt)
{
stack<BiTree<T>* > s;
BiTree<T> *p = bt;
while(p || !s.empty()) //指针p不为空或者s不为空,循环一直进行下去
{
while(p)
{
s.push(p);
visit(p); //访问根节点
p = p->left;
}
p = s.top();
s.pop();
p = p->right;
}
}
//非递归方法后序递归二叉树
template<typename T> void postOrderNR(BiTree<T> *bt){
stack<BiTree<T>* > s;
BiTree<T> *p = bt;
BiTree<T> *pre = nullptr; //增加一指向前一结点的指针
while(p || !s.empty())
{
while(p != NULL) /*一直向左并将沿途结点压入堆栈*/
{
s.push(p) ;
p = p->left;
}
p = s.top();
if(pre == p->right || p->right == NULL) //如果栈顶结点的右
{
visit(p);
pre = p; //pre指向上一次访问的结点
s.pop();
p = nullptr; //这里的p如果直接指向栈顶元素的有结点(即p=s.top())
//将会导致循环出不去,也就是到最后一个
}
else
{
p = p->right;
}
}
}
//按前序遍历建立一颗带头节点的二叉树
template <typename T> BiTree<T> *createBiTree()
{
T data;
cin >> data;
if(data == flag)
{
return NULL;
}
else
{
BiTree<T> *bt ;
bt = new BiTree<T>(data,createBiTree<T>(),createBiTree<T>());
return bt;
}
}
//递归先序遍历二叉树
template<typename T> void preOrder(BiTree<T> *bt)
{
if(bt == NULL) //递归调用的结束条件
return ;
visit(bt); //访问树根
preOrder(bt->left); //先序遍历递归左子树
preOrder(bt->right);// 先序遍历递归右子树
}
//递归后序遍历二叉树
template<typename T> void postOrder(BiTree<T> *bt)
{
if(bt == NULL) //递归调用的结束条件
return ;
postOrder(bt->left); //后序遍历递归左子树
postOrder(bt->right);//后序遍历递归右子树
visit(bt); //访问树根
}
//递归中序遍历二叉树
template<typename T> void inOrder(BiTree<T> *bt)
{
if(bt == NULL) //递归调用的结束条件
return ;
inOrder(bt->left); //中序遍历递归左子树
visit(bt); //访问树根
inOrder(bt->right); // 中序遍历递归右子树
}
//统计二叉树bt中叶子节点的个数
template<typename T> int countLeaf(BiTree<T> *bt){
//bt为根节点,返回值为bt的叶子节点个数
if(bt == NULL) return 0;
if(bt->left == NULL && bt->right == NULL)
return 1; //左节点为空,右节点为空,则bt为叶子节点,返回1
return countLeaf(bt->left) + countLeaf(bt->right);
}
//在二叉树bt中查找数据元素值为data的节点,
//查找成功,返回指向该节点的指针,失败返回空指针
template<typename T> BiTree<T> *getData( BiTree<T> *bt,T data)
{
BiTree<T> *p = bt; //设置一个临时指针,便于判断
if(bt!= NULL)
{
if(p->data == data) //查找成功返回
return p;
if(bt->left != NULL) //若有左子树 ,在左子树中查找
{
p = getData(bt->left,data);
if(p!= NULL) //若查找到了,返回结果
return p;
}
if(bt->right != NULL) //若有右子树,在右子树中查找
{
p = getData(bt->right,data);
if(p!=NULL) //若查找到了,返回结果
return p;
}
}
return nullptr; //查找失败,返回NULL
}
//求二叉树bt子树深度的递归算法
template<typename T> int getDepth(BiTree<T> *bt)
{
if(bt == NULL)
return 0;
int l = getDepth(bt->left);
int r = getDepth(bt->right);
return (r>l? r: l) +1;
}
//访问根节点
template<typename T> void visit(BiTree<T> *bt)
{
cout<<bt->data<<" ";
}