首页 > 其他 > 详细

[算法]二叉树的遍历:前序,中序与后序

时间:2014-02-12 04:39:29      阅读:364      评论:0      收藏:0      [点我收藏+]

二叉树的遍历是二叉树的众多算法的基础。主要有,前序,中序与后序。

对于以下二叉树:

bubuko.com,布布扣

前序:12354

中序:21543

后序:24531


笔者实现了三种遍历方式:

1  前序:递归版本比较简单,只需要改变push_back操作的位置即可。

vector<int> PreOrderTraverse2(TreeNode *root)
{
	vector<int> nodes;
	vector<int> temp;
	if(root == NULL) return nodes;
	nodes.push_back(root->val);
	temp = PreOrderTraverse2(root->left);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	temp = PreOrderTraverse2(root->right);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	return nodes;

}

 前序迭代版本,步骤如下:

(1)首先访问根节点root,先将root节点输出,压入堆栈,

(2)再考虑root节点的左子树,左子树也是一颗二叉树,重复(1)。

(3)某一步的左子树为空,那么该节点左子树已访问完毕,弹出栈顶,访问该节点的右子树,重复(1)即可。

很简单,只需要记住,在将节点压入堆栈时,该节点就已被访问,再访问完左孩子之后,再考虑右孩子所在的二叉树。


vector<int> PreOrderTraverse(TreeNode *root)
{
	vector<int> nodes;
	stack<TreeNode *> s;
	if(root == NULL) return nodes;
	TreeNode *temp = root;
	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);//入栈之前就访问
			nodes.push_back(temp->val);
			temp = temp->left;
		}//左子树访问完毕
		temp = s.top();
		s.pop();
		temp = temp->right;
	}
	return nodes;
}

2  中序, 递归版本:

vector<int> InOrderTraverse2(TreeNode *root)
{
	vector<int> nodes;
	vector<int> temp;
	if(root == NULL) return nodes;
	temp = InOrderTraverse2(root->left);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	nodes.push_back(root->val);
	temp = InOrderTraverse2(root->right);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	return nodes;

}

迭代版本:

(1)首先访问根节点root,压入堆栈。

(2)访问root的左子树,重复(1)即可。

(3)如果某节点左子树为空,那么该节点输出,并考察其右子树,重复(1)即可。

PS:节点入栈使不访问,遇到节点就入栈,直到栈顶左子树访问完毕,那么将栈顶弹出,考虑右子树,重复即可。

vector<int> InOrderTraverse(TreeNode *root)
{
	vector<int> nodes;
	if(root == NULL) return nodes;
	TreeNode *temp = root;
	stack<TreeNode *> s;

	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);
			temp = temp->left;
		}// 左子树完毕
		temp = s.top();
		nodes.push_back(temp->val);
		s.pop();
		temp = temp->right;
	}
	return nodes;
}

3 后序,递归版本:

vector<int> PostOrderTraverse2(TreeNode *root)
{
	vector<int> nodes;
	vector<int> temp;
	if(root == NULL) return nodes;
	temp = PostOrderTraverse2(root->left);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	temp = PostOrderTraverse2(root->right);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	nodes.push_back(root->val);
	return nodes;

}

迭代版本:步骤如下:

PS:遇到根节点root,分两种情况讨论,如果根节点的右子树还没被访问,那么根节点入栈;否则输出根节点。

vector<int> PostOrderTraverse(TreeNode *root)
{
	vector<int> nodes;
	if(root == NULL) return nodes;
	TreeNode *temp = root;
	TreeNode *pre = root; //记录前一次访问的节点
	stack<TreeNode *> s;
	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);
			temp = temp->left;
		}
		temp = s.top();
		if (temp->right == NULL || pre == temp->right)
		{
			nodes.push_back(temp->val);
			pre = temp;
			s.pop();
			temp = NULL;//保证不重复访问
		}
		else
		{
			temp = temp->right;
		}
	}
	return nodes;
}

后序遍历的递归版本比较复杂。自己在编写代码时会出现死循环,因为出现了重复访问,因此上述的temp=NULL语句很重要。


后记:上述3种算法的空间复杂度均为O(n)。

完整的代码为:

#include<iostream>
#include<vector>
#include<stack>

using namespace std;

struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x):val(x),left(NULL),right(NULL){}
};

vector<int> InOrderTraverse2(TreeNode *root)
{
	vector<int> nodes;
	vector<int> temp;
	if(root == NULL) return nodes;
	temp = InOrderTraverse2(root->left);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	nodes.push_back(root->val);
	temp = InOrderTraverse2(root->right);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	return nodes;

}

vector<int> PreOrderTraverse2(TreeNode *root)
{
	vector<int> nodes;
	vector<int> temp;
	if(root == NULL) return nodes;
	nodes.push_back(root->val);
	temp = PreOrderTraverse2(root->left);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	temp = PreOrderTraverse2(root->right);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	return nodes;

}


vector<int> PostOrderTraverse2(TreeNode *root)
{
	vector<int> nodes;
	vector<int> temp;
	if(root == NULL) return nodes;
	temp = PostOrderTraverse2(root->left);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	temp = PostOrderTraverse2(root->right);
	for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i)
		nodes.push_back(temp[i]);
	nodes.push_back(root->val);
	return nodes;

}

vector<int> PreOrderTraverse(TreeNode *root)
{
	vector<int> nodes;
	stack<TreeNode *> s;
	if(root == NULL) return nodes;
	TreeNode *temp = root;
	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);//入栈之前就访问
			nodes.push_back(temp->val);
			temp = temp->left;
		}
		temp = s.top();
		s.pop();
		temp = temp->right;
	}
	return nodes;
}

vector<int> InOrderTraverse(TreeNode *root)
{
	vector<int> nodes;
	if(root == NULL) return nodes;
	TreeNode *temp = root;
	stack<TreeNode *> s;

	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);
			temp = temp->left;
		}
		temp = s.top();
		nodes.push_back(temp->val);
		s.pop();
		temp = temp->right;
	}
	return nodes;
}

vector<int> PostOrderTraverse(TreeNode *root)
{
	vector<int> nodes;
	if(root == NULL) return nodes;
	TreeNode *temp = root;
	TreeNode *pre = root; //记录前一次访问的节点
	stack<TreeNode *> s;
	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);
			temp = temp->left;
		}
		temp = s.top();
		if (temp->right == NULL || pre == temp->right)
		{
			nodes.push_back(temp->val);
			pre = temp;
			s.pop();
			temp = NULL;//保证不重复访问
		}
		else
		{
			temp = temp->right;
		}
	}
	return nodes;
}



int main()
{
	vector<int> nodes;
	TreeNode *root = new TreeNode(1);
	TreeNode *node2 = new TreeNode(2);
	TreeNode *node3 = new TreeNode(3);
	TreeNode *node4 = new TreeNode(4);
	TreeNode *node5 = new TreeNode(5);
	root->left = node2;
	root->right = node3;
	node5->right = node4;
	node3->left = node5;
	
	cout << "InOrder recursively..." << endl;
	nodes = InOrderTraverse2(root);
	for(vector<int>::size_type i = 0; i != nodes.size(); i++)
		cout << nodes[i] << " ";
	cout << endl;
	cout << "InOrder iterativelly..." << endl;
	nodes = InOrderTraverse(root);
	for(vector<int>::size_type i = 0; i != nodes.size(); i++)
		cout << nodes[i] << " ";
	cout << endl;
	cout << "PreOrder recursively..." << endl;
	nodes = PreOrderTraverse2(root);
	for(vector<int>::size_type i = 0; i != nodes.size(); i++)
		cout << nodes[i] << " ";
	cout << endl;
	cout << "PreOrder iterativelly..." << endl;
	nodes = PreOrderTraverse(root);
	for(vector<int>::size_type i = 0; i != nodes.size(); i++)
		cout << nodes[i] << " ";
	cout << endl;
	cout << "PostOrder recursively..." << endl;
	nodes = PostOrderTraverse2(root);
	for(vector<int>::size_type i = 0; i != nodes.size(); i++)
		cout << nodes[i] << " ";
	cout << endl;
	cout << "PostOrder iterativelly..." << endl;
	nodes = PostOrderTraverse(root);
	for(vector<int>::size_type i = 0; i != nodes.size(); i++)
		cout << nodes[i] << " ";
	cout << endl;
}


[算法]二叉树的遍历:前序,中序与后序

原文:http://blog.csdn.net/xuqingict/article/details/19089727

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!