您的位置:首页 > 其它

二叉树前序,中序,后序的遍历【递归(借用栈实现)和非递归】

2017-07-25 00:36 423 查看
#include<iostream>
#include<cassert>
#include<stack>
using namespace std;
template<class T>
struct TreeNode
{
T data;
TreeNode<T>* left;
TreeNode<T>* right;
TreeNode(const T& x)
:data(x)
,left(NULL)
,right(NULL)
{}
};
template<class T>
class BinaryTree
{
typedef TreeNode<T> Node;
public:
BinaryTree(const T* arr,int sz,const T& invalib)//1.构造函数---前序构造二叉树
{
assert(arr);
int index=0;
_root=CreatTree(arr,sz,invalib,index);
}
~BinaryTree()//2.析构函数
{
Destroy(_root);//销毁一颗二叉树
_root=NULL;
}
void PreOrder()//6.前序遍历打印(递归)
{
_PreOrder(_root);
}
void InOrder()//7.中序遍历打印(递归)
{
_InOrder(_root);
}
void EndOrder()//8.后序遍历打印(递归)
{
_EndOrder(_root);
}
void PreOrderNO()//10.前序遍历打印(非递归)
{
_PreOrder(_root);
}
void InOrderNO()//11.中序遍历打印(非递归)
{
_InOrderNO(_root);
}
void EndOrderNO()//12.后序遍历打印(非递归)
{
_EndOrderNO(_root);
}
protected:
Node* CreatTree(const T* arr,int sz,const T& invalib,int& index)//前序构造二叉树
{
assert(arr);
Node* root=NULL;
while (index<sz&&arr[index]!=invalib)
{
root=new Node(arr[index]);
root->left=CreatTree(arr,sz,invalib,++index);//此处index必须前置++
root->right=CreatTree(arr,sz,invalib,++index);//此处index必须前置++
}
return root;
}
void Destroy(Node* root)//销毁一颗二叉树
{
//1.树为空,直接返回,无结点销毁
if (root==NULL)
{
return ;
}
//2.树只有一个结点,则销毁该节点
if (root->left==NULL&&root->right==NULL)
{
delete root;
root=NULL;
return;
}
//3.树的结点大于一个,则先销毁左子树,后销毁右子树
Destroy(root->left);
Destroy(root->right);
delete root;
root=NULL;
}

----------

void _PreOrder(Node* root)//前序遍历打印(递归):根->左->右
{
//1.根结点为空,二叉树为空,直接返回---递归返回条件
if (root==NULL)
{
return ;
}

//2.根结点不为空,先打印根结点,在打印左子树,后打印右子树
cout<<root->data<<" ";
_PreOrder(root->left);
_PreOrder(root->right);
}

----------

void _InOrder(Node* root)//中序遍历打印(递归):左->根->右
{
//1.根结为空,二叉树没有结点---递归返回条件
if (root==NULL)
{
return ;
}
//2.根结点不为空,二叉树有节点
_InOrder(root->left);
cout<<root->data<<" ";
_InOrder(root->right);
}

----------

void _EndOrder(Node* root)//后序遍历打印(递归):左->右->根
{
//1.根结点为空,二叉树没有结点---递归返回条件
if (root==NULL)
{
return ;
}
//2.根结点不为空,二叉树有节点
_EndOrder(root->left);
_EndOrder(root->right);
cout<<root->data<<" ";
}

----------

void _PreOrderNO(Node* root)//前序遍历打印(非递归)---用栈实现(根左右)
{
stack<Node*>  s;
Node* cur=root;
while (cur||!s.empty())
{
while (cur)
{
s.push(cur);
cout<<cur->data<<" ";
cur=cur->left;
}
//top从栈中取出来,表示以这个结点为根结点的树的左子树已经访问完了,
//剩余右子树还没有访问,循环子问题访问右树
Node* top=s.top();
s.pop();
//子问题的方式访问右树
cur=top->right;
}
}

----------

void _InOrderNO(Node* root)//中序遍历打印(非递归)---用栈实现(左根右)
{
stack<Node*> s;
Node* cur=root;
while (cur||!s.empty())
{
while (cur)
{
s.push(cur);
cur=cur->left;
}
Node* top=s.top();
cout<<top->data<<" ";
//表示左子树和根结点已经访问完了,剩下右子树没有访问,循环子问题访问右树
s.pop();
//循环子问题访问右树
cur=top->right;
}
}

----------

void _EndOrderNO(Node* root)//后序遍历打印(非递归)---用栈实现(左右根)
{
stack<Node*>  s;
Node* cur=root;
Node* prev=NULL;//记录已经访问过的结点
while (cur||!s.empty())
{
while (cur)
{
s.push(cur);
cur=cur->left;
}
Node* top=s.top();
//如果该根结点的右子树已经访问过了或者右子树为空,那么直接访问该根结点,
//然后更新prev,从栈中pop掉该节点
if (prev==top->right||top->right==NULL)
{
cout<<top->data<<" ";
s.pop();
prev=top;
}
如果该根结点的右子树没有访问过了或者右子树为不为空
循环更新cur,循环子问题访问右子树
else
{
cur=top->right;
}

}
}
protected:
Node* _root;
};

int main()
{
int arr[]={1,2,3,'#','#',4,'#','#',5,6,'#','#','#'};
int sz=sizeof(arr)/sizeof(arr[0]);
BinaryTree<int>  bt(arr,sz,'#');

cout<<"前序打印【递归】";
bt.PreOrder();
cout<<endl;

cout<<"中序打印【递归】";
bt.InOrder();
cout<<endl;

cout<<"后序打印【递归】";
bt.EndOrder();
cout<<endl;

cout<<"前序打印【非递归】";
bt.PreOrderNO();
cout<<endl;

cout<<"中序打印【非递归】";
bt.InOrderNO();
cout<<endl;

cout<<"后序打印【非递归】";
bt.EndOrderNO();
cout<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉树 递归 遍历
相关文章推荐