二叉树先序、中序、后续遍历(非递归实现)

二叉树遍历的非递归形式,主要是依靠 栈 来实现的:

对于二叉树的先序遍历,先将根结点压入栈中,然后将树中所有的左子树压入栈中同时访问其值,对于最后一个左子树压入栈中后,它的左子树为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 ;
}


	




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值