相比祖传的递归算法,非递归算法会麻烦很多,尤其是后续遍历的非递归算法,这些算法都借助了栈的数据结构,理解上的问题这里不多讲,我在代码里都加了较多注释,大家放心看便是
头文件:
#ifndef BITREE_H
#define BITREE_H
#include<iostream>
#include<string>
#include<stack>
using namespace std;
const int SIZE = 100;
template<typename T>
struct Binode {
T data;
Binode<T>* Lchild;
Binode<T>* Rchild;
};
template<typename T>
class BiTree
{
Binode<T>* root;
Binode<T>* Create(Binode<T>* bt);
void Release(Binode<T>* bt);
void Preorder(Binode<T>* bt);
void Inorder(Binode<T>* bt);
void Postorder(Binode<T>* bt);
public:
BiTree() { root=Create(root); }
~BiTree() { Release(root); }
void PreOrder() { Preorder(root); }
void InOrder() { Inorder(root); }
void PostOrder() { Postorder(root); }
void Levelorder();
};
template<typename T>
Binode<T>* BiTree<T>::Create(Binode<T>* bt)
{
char ch;
cin >> ch;
if (ch == '#') bt = NULL;
else
{
bt = new Binode<T>;
bt->data = ch;
bt->Lchild = Create(bt->Lchild);
bt->Rchild = Create(bt->Rchild);
}
return bt;
}
template<typename T>
void BiTree<T>::Preorder(Binode<T>* bt)
{
if (bt == NULL)return;
Binode<T>* p=bt;
stack<Binode<T>> q;
while (!q.empty() || p)
{
//边遍历边打印,并将节点存入栈中,以后需要通过这些根节点进入其右子树;
while (p != NULL)
{
cout << p->data ;
q.push(*p);
p = p->Lchild;
}
//左子树遍历完成,进入右子树;
if (!q.empty())
{
p =& q.top();
q.pop();
p = p->Rchild;//进入右子树,并开始新一轮的左子树遍历;
}
}
cout << endl;
}
template<typename T>
void BiTree<T>::Inorder(Binode<T>* bt)
{
if (bt == NULL)return;//树为空直接结束;
Binode<T>* p = bt;
stack<Binode<T>> q;
//一直遍历到最左边,边遍历边将节点储存到栈中;
while (!q.empty() || p)
{
while (p != NULL)
{
q.push(*p);
p = p->Lchild;
}
//左子树遍历完成
if (!q.empty())
{
p = &q.top();
q.pop();
cout << p->data;
p = p->Rchild;//进入右子树,并开始新一轮的左子树遍历;
}
}
cout << endl;
}
template<typename T>
void BiTree<T>::Postorder(Binode<T>* bt)
{
stack<Binode<T>*>s;
Binode<T>* current=bt, * pastvisit=NULL;//current指向当前节点,pastvisit指向上一次访问的节点;
while (current)
{
s.push(current);
current = current->Lchild;
}//一直遍历到最左边,边遍历边将节点储存在栈中
while (!s.empty())
{
current = s.top();
s.pop();//左子树为空,current返回根节点,并将其出栈
if (current->Rchild == NULL || current->Rchild == pastvisit)//当current的右子树为空或其右子树已被访问时,访问current(此时左子树已访问完)
{
cout << current->data;
pastvisit = current;//更新pastvisit指针
}
else
{
s.push(current);//将current重新入栈
current = current->Rchild;//current一定有右子树且不为空,进入右子树,并开始新一轮的左子树遍历;
while (current)
{
s.push(current);
current = current->Lchild;
}
}
}
cout << endl;
}
template<typename T>
void BiTree<T>::Release(Binode<T>* bt)
{
if (bt != NULL)
{
Release(bt->Lchild);
Release(bt->Rchild);
delete bt;
}
}
template<typename T>
void BiTree<T>::Levelorder()
{
int front, rear;
front = -1; rear = -1;
Binode<T>* q;
Binode<T>* Q[SIZE] = { 0 };
if (root == NULL)return;
Q[++rear] = root;
while (front != rear)
{
q = Q[++front];
cout << q->data;
if (q->Lchild != NULL)Q[++rear] = q->Lchild;
if (q->Rchild != NULL)Q[++rear] = q->Rchild;
}
}
#endif
源文件
#include"Bitree.h"
int main()
{
BiTree<char>root;
root.InOrder();
cout << endl;
root.PreOrder();
cout << endl;
root.PostOrder();
cout << endl;
root.Levelorder();
}