二叉树遍历的非递归形式,主要是依靠 栈 来实现的:
对于二叉树的先序遍历,先将根结点压入栈中,然后将树中所有的左子树压入栈中同时访问其值,对于最后一个左子树压入栈中后,它的左子树为NULL ;访问它的右子树,并从栈中将其退出,再以它的右子树为根结点的形式进行访问,当栈中元素第一次全部清空之后,若根结点的右子树不为空,继续进行进栈操作,直到栈再次为空且右子树为NULL时结束;
#include<iostream>
#include<stdio.h>
#include<stack>
#include<string.h>
#include<stdlib.h>
using namespace std ;
struct Node {
int data ;
Node *left ;
Node *right ;
};
Node* newnode() {
Node *root = new Node ;
root->left = NULL ;
root->right = NULL ;
return root ;
};
int main() {
Node *root = newnode() ;
char s[100] ;
while(cin >> s ) {
Node *t = root ;
if(strcmp(s,"()") == 0 )
break ;
int data ;
sscanf(&s[1],"%d",&data);
char *s1 = (strchr(s,',')+1) ;
int len = strlen(s1) ;
for(int i = 0 ; i < len ; i++) {
if(s1[i] == 'L') {
if((t->left) == NULL)
t->left = newnode() ;
t = t -> left ;
}
else if(s1[i] == 'R') {
if((t->right) == NULL)
t->right = newnode() ;
t = t -> right ;
}
}
t -> data = data ;
}
stack<Node*> ss ;
Node *r = root ;
while((!ss.empty())||r!=NULL) {
while(r != NULL) {
cout << r->data << " ";
ss.push(r);
r = r->left ;
}
r = ss.top() ;
r = r->right ;
ss.pop();
}
cout << endl ;
return 0 ;
}
二叉树中序遍历非递归实现:
只需要在上面代码的基础上,把cout << r->data << " "; 移动到r = r -> right 前面即可;
二叉树后序遍历的非递归实现:
后序遍历与先序、中序遍历要复杂一些,因为,后序遍历要保证左孩子、右孩子都被访问并且,左孩子在右孩子先前访问,控制条件就比较难找了,所以需要引入一个标志量,当同一个结点被两次出栈,则输出这个结点的值:
#include<iostream>
#include<stdio.h>
#include<stack>
#include<string.h>
#include<stdlib.h>
using namespace std ;
struct Node {
int data ;
int visit ;
Node *left ;
Node *right ;
};
Node* newnode() {
Node *root = new Node ;
root->left = NULL ;
root->right = NULL ;
root->visit = 0 ;
return root ;
};
int main() {
Node *root = newnode() ;
char s[100] ;
while(cin >> s ) {
Node *t = root ;
if(strcmp(s,"()") == 0 )
break ;
int data ;
sscanf(&s[1],"%d",&data);
char *s1 = (strchr(s,',')+1) ;
int len = strlen(s1) ;
for(int i = 0 ; i < len ; i++) {
if(s1[i] == 'L') {
if((t->left) == NULL)
t->left = newnode() ;
t = t -> left ;
}
else if(s1[i] == 'R') {
if((t->right) == NULL)
t->right = newnode() ;
t = t -> right ;
}
}
t -> data = data ;
}
stack<Node*> ss ;
Node *r = root ;
while((!ss.empty())||r!=NULL) {
while(r != NULL) {
ss.push(r) ;
r= r->left ;
}
r = ss.top() ;
ss.pop();
if( r->visit == 0 ) { //第一次出栈,再给压进去,访问其右结点
r->visit = 1 ;
ss.push(r) ;
r = r->right ;
}
else if( r->visit == 1 ) {
cout << r->data << " " ;
r = NULL ; // r 赋值为 NULL,当再次循环时,直接向右边进行遍历!
}
}
cout << endl ;
return 0 ;
}
另外一种二叉树后序遍历的非递归算法思想:
若想输出这个结点的值,这个结点应该满足下面两个条件之一:
1、这个结点没有孩子结点,即为叶子结点,则直接输出这个值;
2、这个结点的左孩子和右孩子都被访问过,则直接输出这个值 ;
如果这个结点既不是叶子结点,左孩子或右孩子也没被访问,则需要先将其右孩子结点压入栈中,然后将左孩子结点压入栈中,这样就保证了左孩子在右孩子前被访问。
#include<iostream>
#include<stdio.h>
#include<stack>
#include<string.h>
#include<stdlib.h>
using namespace std ;
struct Node {
int data ;
int visit ;
Node *left ;
Node *right ;
};
Node* newnode() {
Node *root = new Node ;
root->left = NULL ;
root->right = NULL ;
root->visit = 0 ;
return root ;
};
int main() {
Node *root = newnode() ;
char s[100] ;
while(cin >> s ) {
Node *t = root ;
if(strcmp(s,"()") == 0 )
break ;
int data ;
sscanf(&s[1],"%d",&data);
char *s1 = (strchr(s,',')+1) ;
int len = strlen(s1) ;
for(int i = 0 ; i < len ; i++) {
if(s1[i] == 'L') {
if((t->left) == NULL)
t->left = newnode() ;
t = t -> left ;
}
else if(s1[i] == 'R') {
if((t->right) == NULL)
t->right = newnode() ;
t = t -> right ;
}
}
t -> data = data ;
}
stack< Node* > ss ;
Node *pre = NULL ;
Node *r = root ;
ss.push(root) ;
while(!ss.empty()) {
r = ss.top();
if((r->left == NULL && r->right == NULL)||(r->left == pre||r->right == pre)&&pre !=NULL) {
cout << r->data << " " ;
ss.pop();
pre = r ;
}
else {
if(r->right != NULL)
ss.push(r->right) ;
if(r->left != NULL)
ss.push(r->left) ;
}
}
cout << endl ;
return 0 ;
}