二叉树的遍历


前序遍历非递归:

每次都是走树的左子树,直到左子树为空,然后从递归的最深处返回到父节点,访问右节点。因此,这里需要一个方法来对节点序列来回溯。将访问途中遇到的节点都记录下来。

vector<char> preOrder1(TreeNode *root)
{
	stack<TreeNode *> s;
	vector<char> result;
	TreeNode *p = root;

	while(p!=NULL || !s.empty())
	{
		while(p!=NULL)
		{
			result.push_back(p->data);
			s.push(p);//先序,先访问再入栈
			p = p->left;//依此访问左子树
		}

		if(!s.empty())
		{
			p = s.top();//回溯到父节点
			s.pop();
			p = p->right;
		}		
	}

	return result;
}

中序遍历非递归:

和前序遍历的区别是,前序是先访问后入栈,这里是先入栈后访问。

vector<char> midOrder1(TreeNode *root)
{
	stack<TreeNode *> s;
	vector<char> result;
	TreeNode *p = root;
	while(p != NULL || !s.empty())
	{
		while(p!=NULL)
		{
			s.push(p);
			p = p->left;
		}

		if(!s.empty())
		{
			p = s.top();
			s.pop();
			result.push_back(p->data);
			p = p->right;
		}
	}
	return result;
}

后续遍历非递归:

用栈来模拟递归的实现。三个节点都要入栈,顺序是root->right->left。入栈后,根节点和左右节点分不清楚,所以需要引进一个标志位bPushed,表示该节点左右子树都入栈了。

vector<char> postOrder1(TreeNode *root)
{
	vector<char> result;
	stack<TreeNode *> s;
	if(root)
	{
		s.push(root);
		root->bPushed = false;
	}
	while(!s.empty())
	{
		TreeNode *p = s.top();
		s.pop();

		if(p->bPushed)
		{
			result.push_back(p->data);
		}
		else
		{
			p->bPushed = true;
			s.push(p);

			if(p->right != NULL)
			{
				p->right->bPushed = false;
				s.push(p->right);
			}

			if(p->left != NULL)
			{
				p->left->bPushed = false;
				s.push(p->left);
			}			
		}
	}

	return result;
}


二叉树遍历(递归和非递归方法)

下面的code实现了很多种遍历的方法,不仅仅是上面的。

参考了:http://blog.csdn.net/chencheng126/article/details/44020269

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

struct TreeNode
{
	char data;
	TreeNode *left;
	TreeNode *right;
	bool bPushed;//表示该节点的左右子树都入栈了
};

//前序遍历
//1.递归
void preOrder(TreeNode *root,vector<char> &result)
{
	if(root)
	{
		result.push_back(root->data);
		preOrder(root->left,result);
		preOrder(root->right,result);
	}
}

//栈1。
//思路一:仔细分析一下递归程序,可以发现每次都是走树的左子树,直到左子树为空,然后从递归的最深处返回到父节点,访问右节点。因此,这里需要一个方法来对节点序列来回溯。将访问途中遇到的节点都记录下来。因为节点出现的次序和恢复的顺序是相反的,因此要用到栈。
vector<char> preOrder1(TreeNode *root)
{
	stack<TreeNode *> s;
	vector<char> result;
	TreeNode *p = root;

	while(p!=NULL || !s.empty())
	{
		while(p!=NULL)
		{
			result.push_back(p->data);
			s.push(p);//先序,先访问再入栈
			p = p->left;//依此访问左子树
		}

		if(!s.empty())
		{
			p = s.top();//回溯到父节点
			s.pop();
			p = p->right;
		}		
	}

	return result;
}

//栈2
//思路二;用栈来模拟递归的实现。将root压栈,然后弹出,压右子树,然后压左子树。
vector<char> preOrder2(TreeNode *root)
{
	vector<char> result;
	stack<TreeNode *> s;
	if(root)
	{			
		s.push(root);

		while(!s.empty())
		{
			TreeNode *p = s.top();
			s.pop();
			result.push_back(p->data);//访问root节点,不需要入栈

			if(p->right)
				s.push(p->right);
			if(p->left)
				s.push(p->left);		
		}
	}
	return result;
}

//中序遍历
//1.递归
void midOrder(TreeNode* root,vector<char> &result)
{
	if(root)
	{
		midOrder(root->left,result);
		result.push_back(root->data);
		midOrder(root->right,result);
	}
}

//栈实现方式。先序的第一种方法,是先访问再入栈,这里是先入栈,再访问。
vector<char> midOrder1(TreeNode *root)
{
	stack<TreeNode *> s;
	vector<char> result;
	TreeNode *p = root;
	while(p != NULL || !s.empty())
	{
		while(p!=NULL)
		{
			s.push(p);
			p = p->left;
		}

		if(!s.empty())
		{
			p = s.top();
			s.pop();
			result.push_back(p->data);
			p = p->right;
		}
	}
	return result;
}

//用栈来模拟递归的实现。这个和preOrder2不同之处在于,preOrder的左右节点压栈之后,root节点就不用管了。而midOrder和postOrder在左右节点压栈后,root节点还是要访问,因此三个节点都要入栈。对于midOrder来说,压栈的顺序是right->root->left。但是入栈以后,根节点和左右子树节点区分不清楚,这就需要引进一个标志位,表示该节点的左右子树入栈了。
vector<char> midOrder2(TreeNode *root)
{
	stack<TreeNode *> s;
	vector<char> result;
	if(root)
	{
		s.push(root);
		root->bPushed = false;
	}

	while(!s.empty())
	{
		TreeNode *p = s.top();
		s.pop();

		if(p->bPushed)
		{
			result.push_back(p->data);
		}
		else
		{
			if(p->right != NULL)
			{
				p->right->bPushed = false;
				s.push(p->right);
			}

			p->bPushed = true;
			s.push(p);

			if(p->left != NULL)
			{
				p->left->bPushed = false;
				s.push(p->left);
			}
		}
	}

	return result;
}

//后序遍历
//递归
void postOrder(TreeNode *root,vector<char> &result)
{
	if(root)
	{
		if(root->left)
			postOrder(root->left,result);
		if(root->right)
			postOrder(root->right,result);
		result.push_back(root->data);
	}
}

//栈实现。模拟递归的实现,和midOrder2类似,不同之处是入栈的顺序变了,root->right->left.
vector<char> postOrder1(TreeNode *root)
{
	vector<char> result;
	stack<TreeNode *> s;
	if(root)
	{
		s.push(root);
		root->bPushed = false;
	}
	while(!s.empty())
	{
		TreeNode *p = s.top();
		s.pop();

		if(p->bPushed)
		{
			result.push_back(p->data);
		}
		else
		{
			p->bPushed = true;
			s.push(p);

			if(p->right != NULL)
			{
				p->right->bPushed = false;
				s.push(p->right);
			}

			if(p->left != NULL)
			{
				p->left->bPushed = false;
				s.push(p->left);
			}			
		}
	}

	return result;
}

//根据前序和中序来创建二叉树
void makeBinaryTree1(TreeNode **root,char *preOrder,char *midOrder,int length)
{
	if(length == 0)
	{
		(*root) = NULL;
		return;
	}

	(*root) = new TreeNode;
	(*root)->data = *preOrder;

	char *rootplace = strchr(midOrder,(*root)->data);
	if(rootplace == NULL)
	{
		printf("Wrong sample!");
	}

	int leftTreeLength = strlen(midOrder) - strlen(rootplace);
	int rightTreeLength = length - leftTreeLength -1;

	makeBinaryTree1(&(*root)->left,preOrder+1,midOrder,leftTreeLength);
	makeBinaryTree1(&(*root)->right,preOrder+leftTreeLength+1,rootplace+1,rightTreeLength);
}

void main()
{
	char pre[] = "abdeijcfg";
	char mid[] = "dbiejafcg";
	TreeNode* r;
	makeBinaryTree1(&r,pre,mid,strlen(pre));

	vector<char> result;
	//preOrder(r,result);
	//result = preOrder2(r);
	//midOrder(r,result);
	//result = midOrder2(r);
	//postOrder(r,result);
	result = postOrder1(r);
	for(unsigned int i=0;i < result.size();i++)
	{
		cout<<result[i]<<endl;
	}

	return;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值