二叉树中的遍历方法有三种,前序遍历,中序遍历,后序遍历
结点结构
template<typename T>
struct BinaryNode
{
T elem;
BinaryNode *left;
BinaryNode *right;
BinaryNode(T d, BinaryNode *l=NULL, BinaryNode *r=NULL):elem(d), left(l),right(r){}
};
1、递归算法
递归算法比较简单,毕竟二叉树是按照递归的方法定义的
前序遍历递归算法
template<typename T>
void preOrder_recursive(BinaryNode<T>* root)
{
if(!root)
{
visit(root);
preOrder_recursive(root->lchild);
preOrder_recursive(root->rchild);
}
}
中序遍历递归算法
template<typename T>
void inorder_recursive(BinaryNode<T>* root)
{
if(!root)
{
inorder_recursive(root->left);
visit(root);
inorder_recursive(root->right);
}
else
return;
}
后序遍历递归算法
template<typename T>
void preOrder_recursive(BinaryNode<T>* root)
{
if(!root)
{
visit(root);
preOrder_recursive(root->lchild);
preOrder_recursive(root->rchild);
}
}
2、非递归算法比较麻烦
都要利用栈结构来解决问题
前序遍历非递归算法
//前序遍历先访问根结点,再访问孩子结点
/*用栈储存根结点,首先一直往左访问,直至NULL时,从栈中取栈顶元素,开始访问右方结点*/
template<typename T>
void preOrder(BinaryNode<T>* root)
{
stack<BinaryNode*> bn;
BinaryNode* p=root;
while(p!=NULL||!bn.empty())
{
while(p!=NULL)
{
visit(p);
bn.push(p);
p=p->lchild;
}
if(!bn.empty())
{
p=bn.top();
bn.pop();
p=p->rchild;
}
}
}
中序遍历非递归算法
template<typename T>
void inorder(BinaryNode<T>*root)
{
stack<BinaryNode*> bn;
BinaryNode* p=root;
while(p!=NULL||!bn.empty())
{
while(p!=NULL)
{
bn.push(p);
p=p->lchild;
}
if(!bn.empty())
{
p=bn.top();
bn.pop();
visit(p);
p=p->rchild;
}
}
}
后序遍历非递归算法(挺难弄的)
两种方法
(1)法1
template<typename T>
typedef struct BinaryNodewithTag
{
BinaryNode<T>* bn;
bool tag;
}BTag;
template<typename T>
void postOrder1(BinaryNode<T>* root)
{
stack<Btag<T>*> s;
BinaryNode<T>* p=root;
BTag<T>* temp;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
temp = new BTag();
temp->bn=p;
temp->tag=true;
s.push(temp);
p=p->lchild;
}
if(!s.empty())
{
temp=s.top();
s.pop();
if(temp->tag)//第一次访问
{
temp->tag=false;
s.push(temp);
p=temp->bn->rchild;//访问右孩子
}
else//第二次访问
{
visit(temp->bn);
p=NULL;
delete temp;
}
}
}
}
(2)法2
template<typename T>
void postOrder2(BinaryNode<T>* root)
{
stack<BinaryNode*> bn;
BinaryNode *cur;
BinaryNode *pre=NULL;//上一个被访问的结点
bn.push(root);
while(!bn.empty())
{
cur=bn.top();
if((cur->rchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{//如果没有左右孩子或则左右孩子已被访问
visit(cur);
bn.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
{
bn.push(cur->rchild);
}
else(cur->lchild!=NULL)
{
bn.push(cur->lchild);
}
}
}
}