二叉树的遍历主要是前序、中序和后序遍历(还有层序遍历,参见:层序遍历)
(一)递归形式
这三种遍历访问顺序分别为:
前序:根->左子树->右子树
中序:左子树->根->右子树
后序:左子树->右子树->根
递归的形式来写非常简单,伪代码如下:
//前序遍历
void PreOrder(TreeNode *root)
{
if (root == NULL)
return;
Visit root->val;
PreOrder(root->left);
PreOrder(root->right);
}
//中序遍历
void InOrder(TreeNode *root)
{
if (root == NULL)
return;
InOrder(root->left);
Visit root->val;
InOrder(root->right);
}
//后序遍历
void PostOrder(TreeNode *root)
{
if (root == NULL)
return;
PostOrder(root->left);
PostOrder(root->right);
Visit root->val;
}
(二)非递归形式
非递归形式主要利用栈来实现各种顺序遍历时节点的访问顺序。
2.1非递归先序遍历
1.对于节点P,只要左子树不为空,就一直向左访问,并将访问的节点压栈。
2.当左子树为空时,另P指向栈顶元素的右节点并弹栈,执行步骤1。
void PreOrderNonRescursion(TreeNode *root)//伪代码
{
NodeType *p=root;
stack<NodeType*>s;
while(NULL!=p || !s.empty())
{
while(NULL!=p)
{
s.push(p);
visit p->val;
p=p->left;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->right;
}
}
}
2.2非递归中序遍历
与先序遍历类似。
1.对于节点P,只要左子树不为空,就一直向左压栈(但不访问)
2.当左子树为空时,访问栈顶元素,并另P指向栈顶元素的右子树,弹栈,执行步骤1。
template <typename T>
void InOrderNonRescursion(TreeNode*root)//伪代码
{
NodeType *p=root;
stack<NodeType*>s;
while(NULL!=p || !s.empty())
{
while(NULL!=p)
{
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top();
visit p->val
s.pop();
p=p->right;
}
}
}
2.3非递归后序遍历
这个就相对复杂了。要保证在访问当前节点Cur之前,
1.要么Cur不存在左右孩子,即左右子树为NULL。
2.要么Cur的左右孩子已经被访问过了,Pre节点不为NULL且为Cur节点的左右孩子之一。
否则,如果不满足上述条件,说明当前Cur节点的左右孩子还没有被访问,那么为了保证先左子树在右子树的访问顺序,我们要先将右子树压栈,再将左子树压栈(如果不为空的话。)
结合上述条件有:
void Tree<T>::PostOrderNonRescursion(NodeType*root)//伪代码
{
NodeType *pre=NULL;
//NodeType *cur=root;
NodeType *cur;
stack<NodeType*>s;
s.push(root);
while( !s.empty())
{
cur=s.top();
if( ((cur->left==NULL)&&(cur->right==NULL))|| //左右子树为空
(pre!=NULL&&(pre==cur->left||pre==cur->right)) )//或者左右子树已被访问
{
//visit cur
s.pop();
pre=cur;
}
else
{
if(cur->right!=NULL)
s.push(cur->right);
if(cur->left !=NULL)
s.push(cur->left);
}
}
}
(三)二叉树的封装
假期无聊。想了想,就把上述三种遍历递归和非递归形式用模板封装了下。
3.1数据结构
//TreeNode.h
#ifndef __TREENODE_H__
#define __TREENODE_H__
#include "Tree.h"
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
template <typename T> class Tree;
template <typename T>
class TreeNode
{
friend class Tree<T>;
private:
T val;
public:
TreeNode<T>*left;
TreeNode<T>*right;
TreeNode():val(0),left(NULL),right(NULL){}
TreeNode(T x):val(x),left(NULL),right(NULL){}
};
#endif
3.2二叉树的封装
#ifndef __TREE_H__
#define __TREE_H__
#include "TreeNode.h"
using namespace std;
template <typename T> class TreeNode;
template <typename T>
class Tree
{
typedef TreeNode<T> NodeType;
private:
NodeType *root;
void PreOrder_(NodeType *,vector<T>&);
void InOrder_(NodeType *,vector<T>&);
void PostOrder_(NodeType *,vector<T>&);
void PreOrderNonRescursion_(NodeType *,vector<T>&);
void InOrderNonRescursion_(NodeType *,vector<T>&);
void PostOrderNonRescursion_(NodeType *,vector<T>&);
void DestroyAllNode_(NodeType *);
public:
Tree(NodeType * r){root=r;}
~Tree();
void PreOrder(vector<T>&);
void InOrder(vector<T>&);
void PostOrder(vector<T>&);
void PreOrderNonRescursion(vector<T>&);
void InOrderNonRescursion(vector<T>&);
void PostOrderNonRescursion(vector<T>&);
};
//constructor and destructor//
template <typename T>
void Tree<T>::DestroyAllNode_(NodeType*root)
{
if(root==NULL)
return ;
DestroyAllNode_(root->left);
DestroyAllNode_(root->right);
delete root;
root=NULL;
return ;
}
template <typename T>
Tree<T>::~Tree()
{
DestroyAllNode_(root);
}
/PreOrder Traversal//
template <typename T>
void Tree<T>::PreOrder_(NodeType*root,vector<T>&res)
{
if(root==NULL)
{
return;
}
res.push_back(root->val);
PreOrder_(root->left,res);
PreOrder_(root->right,res);
}
template <typename T>
void Tree<T>::PreOrder(vector<T>&res)
{
PreOrder_(root,res);
}
template <typename T>
void Tree<T>::PreOrderNonRescursion_(NodeType*root,vector<T>&res)
{
NodeType *p=root;
stack<NodeType*>s;
while(NULL!=p || !s.empty())
{
while(NULL!=p)
{
s.push(p);
res.push_back(p->val);
p=p->left;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->right;
}
}
}
template <typename T>
void Tree<T>::PreOrderNonRescursion(vector<T>&res)
{
PreOrderNonRescursion_(root,res);
}
//InOrder Traversal///
template <typename T>
void Tree<T>::InOrder_(NodeType*root,vector<T>&res)
{
if(root==NULL)
{
return;
}
InOrder_(root->left,res);
res.push_back(root->val);
InOrder_(root->right,res);
}
template <typename T>
void Tree<T>::InOrder(vector<T>&res)
{
InOrder_(root,res);
}
template <typename T>
void Tree<T>::InOrderNonRescursion_(NodeType*root,vector<T>&res)
{
NodeType *p=root;
stack<NodeType*>s;
while(NULL!=p || !s.empty())
{
while(NULL!=p)
{
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top();
res.push_back(p->val);
s.pop();
p=p->right;
}
}
}
template <typename T>
void Tree<T>::InOrderNonRescursion(vector<T>&res)
{
InOrderNonRescursion_(root,res);
}
/PostOrder Traversal
template <typename T>
void Tree<T>::PostOrder_(NodeType*root,vector<T>&res)
{
if(root==NULL)
{
return;
}
PostOrder_(root->left,res);
PostOrder_(root->right,res);
res.push_back(root->val);
}
template <typename T>
void Tree<T>::PostOrder(vector<T>&res)
{
PostOrder_(root,res);
}
template <typename T>
void Tree<T>::PostOrderNonRescursion_(NodeType*root,vector<T>&res)
{
NodeType *pre=NULL;
//NodeType *cur=root;
NodeType *cur;
stack<NodeType*>s;
s.push(root);
while( !s.empty())
{
cur=s.top();
if( ((cur->left==NULL)&&(cur->right==NULL))||
(pre!=NULL&&(pre==cur->left||pre==cur->right)) )
{
res.push_back(cur->val);
s.pop();
pre=cur;
}
else
{
if(cur->right!=NULL)
s.push(cur->right);
if(cur->left !=NULL)
s.push(cur->left);
}
}
}
template <typename T>
void Tree<T>::PostOrderNonRescursion(vector<T>&res)
{
PostOrderNonRescursion_(root,res);
}
#endif
3.3测试
//main.cpp
#include "Tree.h"
int main()
{
TreeNode<int> *root=new TreeNode<int>(0);
root->left=new TreeNode<int>(1);
root->right=new TreeNode<int>(2);
Tree<int> t(root);
vector<int>res;
t.PreOrder(res);
for(int i=0;i<res.size();i++)
{
cout << res[i];
cout <<endl;
}
res.clear();
t.PreOrderNonRescursion(res);
for(int i=0;i<res.size();i++)
{
cout << res[i];
cout <<endl;
}
res.clear();
t.InOrder(res);
for(int i=0;i<res.size();i++)
{
cout << res[i];
cout <<endl;
}
res.clear();
t.InOrderNonRescursion(res);
for(int i=0;i<res.size();i++)
{
cout << res[i];
cout <<endl;
}
res.clear();
t.PostOrder(res);
for(int i=0;i<res.size();i++)
{
cout << res[i];
cout <<endl;
}
res.clear();
t.PostOrderNonRescursion(res);
for(int i=0;i<res.size();i++)
{
cout << res[i];
cout <<endl;
}
return 0;
}
(四)参考
1.http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html