现在的位置: 首页 > 综合 > 正文

四:二叉树遍历

2013年12月17日 ⁄ 综合 ⁄ 共 3707字 ⁄ 字号 评论关闭

1:递归:

//先序 
void PreOrder(BTNode *p)
{
	if( p != NULL)//注意不要忽略掉 
	{
		cout<<p->data;
		PreOrder(p->left);
		PreOrder(p->right);
	}
}
//中序 
void InOrder(BTNode *p)
{
	if( p!=NULL )//注意不要忽略掉
	{
		InOrder(p->left);
		cout<<p->data;
		InOrder(p->right);
	}
}
//后序 
void PostOrder(BTNode *p)
{
	if( p!=NULL )//注意不要忽略掉
	{
		PostOrder(p->left);
		PostOrder(p->right);
		cout<<p->data;	
	}
}

2:非递归

//非递归的先序序遍历 
void PreOrder(BTNode *root)
{
	stack<BTNode*>S;
	BTNode *p;
	if( root!=NULL )//如果二叉树不为空
	{	
		S.push(root);
		while( !S.empty())
		{ 	
			p=S.top();
			S.pop();
			
			cout<<p->data;
			if( p->right!=NULL )//先将右儿子入栈
			{
				 S.push(p->right);
			}

			if( p->left!=NULL )//将左儿子入栈
			{
				S.push(p->left);
			}
		}
	}
	cout<<endl;
}

//非递归的中序序遍历 
void InOrder(BTNode *root)
{
	stack<BTNode*>S;
	BTNode *p;
	if( root!=NULL )//如果二叉树不为空
	{	
		p=root;
		while( !S.empty() || p!=NULL )
		{ 
			while( p!=NULL )//先扫描*p的所有左节点, 并入栈
			{
		    	S.push(p);
				p=p->left;
			}
            
			//此时, 栈顶元素没有左孩子或左孩子均已访问过
			if( !S.empty() )//
			{
				p=S.top();
				S.pop();
				cout<<p->data;

				p=p->right;
			}
		}
	}
	cout<<endl;
}

//非递归的后序遍历 
void PostOrder(BTNode *root)
{
    stack<BTNode*>S;
	BTNode *p, *pre;
	int flag;//标记 
	
	if( root!=NULL ) //二叉树非空 
	{
		p=root;
		do
		{
			while( p!=NULL)//将*p的所有左节点入栈
			{
				S.push(p);
				p=p->left; 
			} 
			
			//执行到此处时,栈顶元素没有左儿子或左子树均已访问过
			pre=NULL;//pre指向栈顶元素的前一个已访问的节点 
			flag=1; //表示*b的左孩子已访问过, 或为空
			
			while( !S.empty() && flag)
			{
				p=S.top();//取出当前的栈顶元素 
				
				if( p->right==pre )//当*p的右儿子已访问过,或pre=NULL即*p的右儿子为空 
				{
					S.pop();//将p出栈 
					
					pre=p;//pre指向刚访问过的节点 
					cout<<p->data;	
				}
				else//
				{
				    p=p->right;//p指向右儿子 
					flag=0;	//表示*b的左儿子尚未访问过 
				}
			} 
		}while( !S.empty()); 
	}
	cout<<endl;
} 

3:层次遍历

//层次遍历:其实就是BFS
void LevelOrder(BTNode *p) 
{
	queue<BTNode *> Q;
	BTNode *temp=NULL;//注意 
	Q.push( p );
	while( !Q.empty() )
	{
		temp=Q.front();
		Q.pop();
		cout<<temp->data;
		if( temp->left!=NULL)
		    Q.push( temp->left);
        if( temp->right!=NULL)
		    Q.push( temp->right);
	}
	cout<<endl;
}

完整程序:

#include<iostream> 
#include<stack>
#include<queue>
using namespace std;
typedef struct Node
{
	char data;
	Node *left;
	Node *right;
}BTNode;

void CreateBTree(  BTNode *&root, char str[])//参数:传入根节点的指针,二叉树的括号表示 
{
	int j=0, flag=0;
	stack<BTNode *> S;
	BTNode *p=NULL, *temp=NULL; 
	while( str[j]!='\0')
	{
		switch( str[j] )
		{
			case '(':flag=1;S.push(p);break;//若遇到左括号,则把前面刚刚创建的那个节点入栈 
			case ',':flag=2;break;//若遇到逗号,说明其后创建的节点为右孩子节点, flag=2
			case ')':S.pop();break;//若遇到右括号,说明栈顶结点的左右孩子处理完毕, 栈顶结点出栈
			
			default://遇到元素
			p=new Node;//创建新节点
			p->data=str[j]; p->left=p->right=NULL;//为新建节点赋值:且此时栈顶结点是p的父节点 
			
			if( root==NULL ) //如果根节点为空
			{
			    root=p;
			}
			else 
			{
				temp=S.top();
		    	switch( flag )
			   {
			    	case 1:temp->left=p;break;//flag=1说明p为栈顶元素左儿子
				    case 2:temp->right=p;break;//p为栈顶元素右儿子
			   }
			}	 
		}
		
		j++;
	}
}
//非递归的先序序遍历 
void PreOrder(BTNode *root)
{
	stack<BTNode*>S;
	BTNode *p;
	if( root!=NULL )//如果二叉树不为空
	{	
		S.push(root);
		while( !S.empty())
		{ 	
			p=S.top();
			S.pop();
			
			cout<<p->data;
			if( p->right!=NULL )//先将右儿子入栈
			{
				 S.push(p->right);
			}

			if( p->left!=NULL )//将左儿子入栈
			{
				S.push(p->left);
			}
		}
	}
	cout<<endl;
}
//非递归的中序序遍历 
void InOrder(BTNode *root)
{
	stack<BTNode*>S;
	BTNode *p;
	if( root!=NULL )//如果二叉树不为空
	{	
		p=root;
		while( !S.empty() || p!=NULL )
		{ 
			while( p!=NULL )//先扫描*p的所有左节点, 并入栈
			{
		    	S.push(p);
				p=p->left;
			}
            
			//此时, 栈顶元素没有左孩子或左孩子均已访问过
			if( !S.empty() )//
			{
				p=S.top();
				S.pop();
				cout<<p->data;

				p=p->right;
			}
		}
	}
	cout<<endl;
}
//非递归的后序遍历 
void PostOrder(BTNode *root)
{
    stack<BTNode*>S;
	BTNode *p, *pre;
	int flag;//标记 
	
	if( root!=NULL ) //二叉树非空 
	{
		p=root;
		do
		{
			while( p!=NULL)//将*p的所有左节点入栈
			{
				S.push(p);
				p=p->left; 
			} 
			
			//执行到此处时,栈顶元素没有左儿子或左子树均已访问过
			pre=NULL;//pre指向栈顶元素的前一个已访问的节点 
			flag=1; //表示*b的左孩子已访问过, 或为空
			
			while( !S.empty() && flag)
			{
				p=S.top();//取出当前的栈顶元素 
				
				if( p->right==pre )//当*p的右儿子已访问过,或pre=NULL即*p的右儿子为空 
				{
					S.pop();//将p出栈 
					
					pre=p;//pre指向刚访问过的节点 
					cout<<p->data;	
				}
				else//
				{
				    p=p->right;//p指向右儿子 
					flag=0;	//表示*b的左儿子尚未访问过 
				}
			} 
		}while( !S.empty()); 
	}
	cout<<endl;
} 

//层次遍历:其实就是BFS
void LevelOrder(BTNode *p) 
{
	queue<BTNode *> Q;
	BTNode *temp=NULL;//注意 
	Q.push( p );
	while( !Q.empty() )
	{
		temp=Q.front();
		Q.pop();
		cout<<temp->data;
		if( temp->left!=NULL)
		    Q.push( temp->left);
        if( temp->right!=NULL)
		    Q.push( temp->right);
	}
	cout<<endl;
}
 
int main()
{
	char str[100];
	BTNode *root=NULL;//注意一定要对指针赋初值,否则会出现各种诡异的错误
	cout<<"输入二叉树的括号表示:"; 
	cin>>str;
	CreateBTree(root, str);
	cout<<"先序遍历结果为:"; 
	PreOrder(root);
	cout<<"中序遍历结果为:";
	InOrder(root);
	cout<<"后序遍历结果为:";
	PostOrder(root);
	cout<<"层次遍历结果为:";
	LevelOrder(root);
	
}

抱歉!评论已关闭.