二叉树生成与非递归遍历
先贴上代码
#include<iostream>
#include<stdlib.h>
#include<stack>
using namespace std;
struct Bnode{
char data;
struct Bnode *left;
struct Bnode *right;
}Node;
enum Type{
FRONT,
MIDDLE,
BACK,
N_FRONT,
N_MIDDLE,
N_BACK
};
void create(Bnode** T); //create Btree
void FrontTraversal(Bnode* T); //递归遍历
void MidTraversal(Bnode* T);
void BackTraversal(Bnode* T);
void NFrontTraversal(Bnode* T); //非递归遍历;
void NMidTraversal(Bnode* T);
void NBackTraversal(Bnode* T);
//把六种遍历结合;
void Traversal(Bnode* T,Type type);
int main(){
struct Bnode* root;
create(&root);
Traversal(root,FRONT);
Traversal(root,MIDDLE);
Traversal(root,BACK);
Traversal(root,N_FRONT);
Traversal(root,N_MIDDLE);
Traversal(root,N_BACK);
return 0;
}
void create(struct Bnode** T){
char temp;
cin>>temp;
if(temp=='#'){
*T = NULL;
}
else{
*T=new Bnode;
(*T)->data = temp;
create(&(*T)->left);
create(&(*T)->right);
}
}
void FrontTraversal(Bnode* T){
if(T == NULL)
return;
else{
cout<<T->data<<" ";
FrontTraversal(T->left);
FrontTraversal(T->right);
}
}
void MidTraversal(Bnode* T){
if(T == NULL)
return;
else{
MidTraversal(T->left);
cout<<T->data<<" ";
MidTraversal(T->right);
}
}
void BackTraversal(Bnode* T){
if(T == NULL)
return;
else{
BackTraversal(T->left);
BackTraversal(T->right);
cout<<T->data<<" ";
}
}
void NFrontTraversal(Bnode* root){
stack<Bnode *> s;
while(root != NULL || !s.empty()){
if(root!=NULL){
s.push(root);
cout<<root->data<<" ";
root = root->left;
}
else{
root = s.top();
s.pop();
root = root->right;
}
}
}
void NMidTraversal(Bnode* root){
stack<Bnode *> s;
while(root != NULL || !s.empty()){
if(root!=NULL){
s.push(root);
root = root->left;
}
else{
root = s.top();
cout<<root->data<<" ";
s.pop();
root = root->right;
}
}
}
void NBackTraversal(Bnode* root){
stack<Bnode* >s,output;
Bnode* head;
s.push(root);
while(!s.empty()){ //主要思想是模仿递归;
head = s.top();
output.push(head);
s.pop();
if(head->left!=NULL)
s.push(head->left);
if(head->right!=NULL)
s.push(head->right);
}
while(!output.empty()){
cout<<output.top()->data<<" ";
output.pop();
}
}
void Traversal(Bnode* T,Type type){
switch (type)
{
case FRONT:
cout<<"递归前序遍历"<<endl;
FrontTraversal(T);
cout<<endl;
break;
case MIDDLE:
cout<<"递归中序遍历"<<endl;
MidTraversal(T);
cout<<endl;
break;
case BACK:
cout<<"递归后续遍历"<<endl;
BackTraversal(T);
cout<<endl;
break;
case N_FRONT:
cout<<"非递归前序遍历"<<endl;
NFrontTraversal(T);
cout<<endl;
break;
case N_MIDDLE:
cout<<"非递归中序遍历"<<endl;
NMidTraversal(T);
cout<<endl;
break;
case N_BACK:
cout<<"非递归后续遍历"<<endl;
NBackTraversal(T);
cout<<endl;
break;
}
}
//
void LevelTraversal(Bnode* root){
queue<Bnode*> s;
Bnode* temp = root;
s.push(root);
while(!s.empty()){
temp = s.top();
s.pop();
cout<<temp->data;
if(temp->left!=NULL){
s.push(temp->left);
}
if(temp->right!=NULL){
s.push(temp->right);
}
}
}
前序与中序遍历如果真的懂二叉树的遍历都应该可以写出其非递归遍历,主要是模拟了其递归的运作方式;
其中前序遍历主要思路就是不断的遍历左子树,并不断把当前节点压入到栈中,(主要用于记忆)当有遇到空节点,就需要弹出栈顶,也就是最后一个压入到栈中的记忆点,只要理解二叉树的递归遍历很好写前序与中序遍历。
其中最难想的是非递归的后续遍历,后续遍历在做具体的操作的时候,一种写法是需要一个flag做标记当且仅当左右子树全空的时候才出栈,但是还有一种思路就是既然后续遍历的是左右中的顺序,那我可以用两个栈模拟也就是一个栈做临时用以右左中的顺序压入,然后就可以以左右中的顺序弹出栈。