二叉树的定义以及性质在之前的博客里已经说过了,今天来用C++实现二叉树。提供先序遍历、中序遍历、后序遍历的递归和非递归的两种实现方式,也提供了层次遍历的用队列实现方式。详细的看代码学习吧,关键注释都有加上了。
————————————————————2017.4.4补充————————————————————
今天补充了反转二叉树的实现,提供递归和非递归两个版本。
————————————————————————————————————————————————
//
// Created by huxijie on 17-3-20.
// 二叉树
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
//二叉树结点类
template <typename T>
struct BTNode{
T elemet;
BTNode<T>* lChild,*rChild;
BTNode() {
lChild = rChild = NULL;
}
BTNode(const T& x,BTNode<T>* l, BTNode<T> *r) {
elemet = x;
lChild = l;
rChild = r;
}
};
//二叉树类
template <typename T>
class BinaryTree{
private:
BTNode<T>* root;
void Clear(BTNode<T>* t);
void PreOrder(void (*Visit)(T &x),BTNode<T> *r);
void InOrder(void (*Visit)(T &x),BTNode<T> *r);
void PostOrder(void (*Visit)(T &x),BTNode<T> *r);
void LayerOrder(void (*Visit)(T &x), BTNode<T> *r);
int Size(BTNode<T>* r);
BTNode<T>* Copy(BTNode<T> *r);
BTNode<T>* InvertTree(BTNode<T> *root);
public:
BinaryTree();
~BinaryTree();
bool IsEmpty() const;
void Clear(); //移去所有结点,成为空二叉树
bool Root(T& x) const; //若二叉树非空,则x为根的值,并返回true
//构造一棵二叉树,根的值为x,以left和right为左右子树
void MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right);
void PreOrder(void (*Visit)(T &x)); //先序遍历
void InOrder(void (*Visit)(T &x)); //中序遍历
void PostOrder(void (*Visit)(T &x)); //后序遍历
void LayerOrder(void (*Visit)(T &x)); //层次遍历
int Size(); //结点个数
BTNode<T>* Copy(); //二叉树的复制
void InvertTree(); //反转二叉树
};
template <typename T>
BinaryTree<T>::BinaryTree() {
root = NULL;
}
template <typename T>
BinaryTree<T>::~BinaryTree() {
Clear();
}
template <typename T>
bool BinaryTree<T>::IsEmpty() const {
if (root == NULL) {
return true;
} else {
return false;
}
}
//递归实现清空二叉树
template <typename T>
void BinaryTree<T>::Clear(BTNode<T> *t) {
if (!t) {
return;
} else {
Clear(t->lChild);
Clear(t->rChild);
delete (t);
t = NULL;
}
}
template <typename T>
void BinaryTree<T>::Clear() {
Clear(root);
}
template <typename T>
bool BinaryTree<T>::Root(T &x) const {
if (IsEmpty()) {
return false;
}else {
x = root->elemet;
return true;
}
}
template <typename T>
void BinaryTree<T>::MakeTree(const T &x, BinaryTree<T> &left, BinaryTree<T> &right) {
if (root || &left == &right) { //若root不空则返回,若左右子树相同则返回,不构造树
return;
}
root = new BTNode<T>(x, left.root, right.root);
left.root = NULL;
right.root = NULL;
}
//访问元素的函数,作为参数传入遍历函数中
template <typename T>
void Visit(T &x) {
cout << x << " ";
}
递归实现先序遍历
//template <typename T>
//void BinaryTree<T>::PreOrder(void (*Visit)(T &x),BTNode<T> *r) {
// if (r) {
// Visit(r->elemet);
// PreOrder(Visit, r->lChild);
// PreOrder(Visit, r->rChild);
// }
//}
//非递归实现先序遍历
template <typename T>
void BinaryTree<T>::PreOrder(void (*Visit)(T &x),BTNode<T> *r) {
if (r == NULL) {
return;
}
BTNode<T>* p = r;
stack<BTNode<T> *> mystack;
while (p != NULL || !mystack.empty()) {
//边遍历边打印,并存入栈中,以后需要通过这些结点进入右子树
while (p != NULL) {
Visit(p->elemet);
mystack.push(p);
p = p->lChild;
}
//当p为空时,说明根和左子树已经遍历完了,需要进入右子树了
if (!mystack.empty()) {
p = mystack.top();
mystack.pop();
p = p->rChild;
}
}
}
template <typename T>
void BinaryTree<T>::PreOrder(void (*Visit)(T &)) {
PreOrder(Visit, root);
}
递归实现中序遍历
//template <typename T>
//void BinaryTree<T>::InOrder(void (*Visit)(T &), BTNode<T> *r) {
// if (r) {
// InOrder(Visit, r->lChild);
// Visit(r->elemet);
// InOrder(Visit, r->rChild);
// }
//}
//非递归实现中序遍历
template <typename T>
void BinaryTree<T>::InOrder(void (*Visit)(T &), BTNode<T> *r) {
if (r == NULL) {
return;
}
BTNode<T> *p = r;
stack<BTNode<T>*> mystack;
while (p != NULL || !mystack.empty()) {
//一直遍历到最后一棵左子树,边遍历边保存根结点到栈中
while (p != NULL) {
mystack.push(p);
p = p->lChild;
}
//当p为空时,说明已经到达最后一棵左子树了,这时需要出栈了
if (!mystack.empty()) {
p = mystack.top();
mystack.pop();
Visit(p->elemet);
//进入右子树,开始新的一轮左子树遍历
p = p->rChild;
}
}
}
template <typename T>
void BinaryTree<T>::InOrder(void (*Visit)(T &)) {
InOrder(Visit, root);
}
递归实现后序遍历
//template <typename T>
//void BinaryTree<T>::PostOrder(void (*Visit)(T &), BTNode<T> *r) {
// if (r) {
// PostOrder(Visit, r->lChild);
// PostOrder(Visit, r->rChild);
// Visit(r->elemet);
// }
//}
//非递归实现后序遍历
template <typename T>
void BinaryTree<T>::PostOrder(void (*Visit)(T &), BTNode<T> *r) {
if (r == NULL) {
return;
}
stack<BTNode<T>*> mystack;
BTNode<T>* pCur = r; //当前访问结点
BTNode<T>* pLast = NULL; //上次访问结点
//一直遍历到最后一棵左子树,边遍历边保存根结点到栈中
while (pCur != NULL) {
mystack.push(pCur);
pCur = pCur->lChild;
}
//已经遍历到最后一棵左子树了,接下来从栈中取结点
while (!mystack.empty()) {
pCur = mystack.top();
mystack.pop();
//一个根结点被访问的前提是:无右子树或者右子树已被访问过
if (pCur->rChild == NULL || pCur->rChild == pLast) {
Visit(pCur->elemet);
//修改最近被访问的结点
pLast = pCur;
} else { //先进入右子树
mystack.push(pCur); //根结点重新入栈
pCur = pCur->rChild; //进入右子树
while (pCur != NULL) { //开始在右子树中一直遍历到最后一棵左子树
mystack.push(pCur);
pCur = pCur->lChild;
}
}
}
}
template <typename T>
void BinaryTree<T>::PostOrder(void (*Visit)(T &)) {
PostOrder(Visit, root);
}
//用队列实现层次遍历
template <typename T>
void BinaryTree<T>::LayerOrder(void (*Visit)(T &x),BTNode<T> *r) {
if (!r) {
return;
}
queue<BTNode<T>*> myqueue;
BTNode<T> *p = r;
while (p != NULL || !myqueue.empty()) {
if (p != NULL) {
Visit(p->elemet);
myqueue.push(p->lChild);
myqueue.push(p->rChild);
}
p = myqueue.front();
myqueue.pop();
}
}
template <typename T>
void BinaryTree<T>::LayerOrder(void (*Visit)(T &)) {
LayerOrder(Visit, root);
}
//递归实现求结点总数
template <typename T>
int BinaryTree<T>::Size(BTNode<T> *r) {
if (!r) {
return 0;
} else {
return Size(r->lChild) + Size(r->rChild) + 1;
}
}
template <typename T>
int BinaryTree<T>::Size() {
return Size(root);
}
//递归实现复制二叉树
template <typename T>
BTNode<T>* BinaryTree<T>::Copy(BTNode<T> *r) {
if (!this) {
return NULL;
} else {
BTNode<T> *p = new BTNode<T>(r->elemet);
p->lChild = Copy(r->lChild);
p->rChild = Copy(r->rChild);
return p;
}
}
template <typename T>
BTNode<T>* BinaryTree<T>::Copy() {
return Copy(root);
}
递归实现反转二叉树
//template <typename T>
//BTNode<T>* BinaryTree<T>::InvertTree(BTNode<T> *root) {
// if (NULL == root) {
// return NULL;
// }
//
// root->lChild = InvertTree(root->lChild); //对左子树进行反转
// root->rChild = InvertTree(root->rChild); //对右子树进行反转
//
// //将左右子树的根结点进行交换
// BTNode<T> *tmp = root->lChild;
// root->lChild = root->rChild;
// root->rChild = tmp;
//}
//非递归实现反转二叉树
template <typename T>
BTNode<T>* BinaryTree<T>::InvertTree(BTNode<T> *root) {
if (NULL == root) {
return NULL;
}
queue<BTNode<T>*> myqueue;
myqueue.push(root); //先将根结点入队
BTNode<T> *tmp = NULL;
BTNode<T> *tmpLeft = NULL;
while (!myqueue.empty()) {
tmp = myqueue.front();
myqueue.pop();
tmpLeft = tmp->lChild; //交换左右孩子
tmp->lChild = tmp->rChild;
tmp->rChild = tmpLeft;
if (tmp->lChild != NULL) { //交换后左孩子入队
myqueue.push(tmp->lChild);
}
if (tmp->rChild != NULL) { //交换后右孩子入队
myqueue.push(tmp->rChild);
}
}
}
//反转二叉树
template <typename T>
void BinaryTree<T>::InvertTree() {
InvertTree(root);
}
最后的测试用例如下,构造的二叉树结构(左图)以及反转后的二叉树(右图)是:
int main() {
BinaryTree<char> a, b, x, y, z; //都是空二叉树
char e;
x.MakeTree('A', a, b);
y.MakeTree('B', a, b);
z.MakeTree('C', x, y);
x.MakeTree('D', a, b);
y.MakeTree('E', x, b);
x.MakeTree('F', y, z);
cout<<"先序遍历:";
x.PreOrder(Visit);
cout<<endl;
cout<<"中序遍历:";
x.InOrder(Visit);
cout<<endl;
cout<<"后序遍历:";
x.PostOrder(Visit);
cout<<endl;
cout<<"层次遍历:";
x.LayerOrder(Visit);
cout<<endl;
cout<<"结点个数:";
cout << x.Size()<<endl;
cout<<"反转二叉树......"<<endl;
x.InvertTree();
cout<<"先序遍历:";
x.PreOrder(Visit);
cout<<endl;
cout<<"中序遍历:";
x.InOrder(Visit);
cout<<endl;
cout<<"后序遍历:";
x.PostOrder(Visit);
cout<<endl;
cout<<"层次遍历:";
x.LayerOrder(Visit);
cout<<endl;
return 0;
}
运行结果是:
先序遍历:F E D C A B
中序遍历:D E F A C B
后序遍历:D E A B C F
层次遍历:F E C D A B
结点个数:6
反转二叉树......
先序遍历:F C B A E D
中序遍历:B C A F E D
后序遍历:B A C D E F
层次遍历:F C E B A D
Process finished with exit code 0