二叉树的遍历

二叉树的遍历包括先序遍历,中序遍历,后序遍历,层次遍历等等。本文对此进行整理。

二叉树结构定义如下:

//Definition for binary tree
struct TreeNode {
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  };
 

1. 先序遍历

先序遍历就是先访问根节点,然后再先序遍历左子树,最后先序遍历右子树。先序遍历也就是深度优先搜索(DFS)。

先序遍历递归实现:

vector<int> preorderTraversal(TreeNode *root)
{
	vector<int> vals;
	preorderTraversal(root, vals);
	return vals;
}
void preorderTraversal(TreeNode *root, vector<int> &vals)
{
	if(root == NULL) return;
	vals.push_back(root->val);
	preorderTraversal(root->left, vals);
	preorderTraversal(root->right, vals);
}

先序遍历非递归实现:

vector<int> preorderTraversal(TreeNode * root)
{
	vector<int> vals;
	stack<TreeNode*> s;
	TreeNode * p = root;
	while(!s.empty() || p)
	{
		if(p == NULL)
		{
			while(!s.empty() && (p == s.top()->right || s.top()->right == NULL)) 
			{	// 右子树已访问,出栈
				p = s.top();
				s.pop();
			}
			if(s.empty()) break;
			// 左子树已访问,右子树尚未访问,访问右子树
			p = s.top()->right;
		}
		else
		{
			vals.push_back(p->val);
			s.push(p);
			p = p->left;
		}
	}
	return vals;
}

2. 中序遍历

中序遍历就是先中序遍历左子树,然后访问根节点,最后中序遍历右子树。

中序遍历递归实现:

vector<int> inorderTraversal(TreeNode *root) 
{
	vector<int> vals;
	inorderTraversal(root, vals);
	return vals;
}
void inorderTraversal(TreeNode *root, vector<int> &vals)
{
	if(root == NULL) return;
	inorderTraversal(root->left, vals);
	vals.push_back(root->val);
	inorderTraversal(root->right, vals);
}
中序遍历非递归实现:

vector<int> inorderTraversal(TreeNode *root) {
	vector<int> vals;
	stack<TreeNode *> s;
	TreeNode *p = root;
	while(!s.empty() || p)
	{
		while(p)
		{
			s.push(p);
			p = p->left;
		}
		p = s.top();
		s.pop();
		vals.push_back(p->val);
		p = p->right;
	}
	return vals;
}
3. 后序遍历

后序遍历就是先后序遍历左子树,再后序遍历右子树,最后访问根节点。

后序遍历递归实现:

vector<int> postorderTraversal(TreeNode* root)
{
	vector<int> vals;
	postorderTraversal(root, vals);
	return vals;
}
void postorderTraversal(TreeNode *root, vector<int> &vals)
{
	if(root == NULL)
		return;
	postorderTraversal(root->left, vals);
	postorderTraversal(root->right, vals);
	vals.push_back(root->val);
}

后序遍历非递归实现:

vector<int> postorderTraversal(TreeNode* root)
{
	vector<int> vals;
	stack<TreeNode*> s;
	TreeNode * pre = NULL;
	TreeNode * p = root;
	while(!s.empty() || p)
	{
		while(p)
		{
			s.push(p);
			p = p->left;
		}
		pre = NULL;
		while(!s.empty() && pre == s.top()->right)
		{
			pre = s.top();
			vals.push_back(s.top()->val);
			s.pop();
		}
		if(s.empty()) break;
		p = s.top()->right;
	}
	return vals;
}
4. 层次遍历

层次遍历就是先遍历第一层节点,然后遍历第二层节点,。。。也就是广度优先搜索(BFS)。

队列实现:

vector<int> levelOrderTraversal(TreeNode *root) 
{
	vector<int> vals;
	if(root == NULL) 
		return vals;
	queue<TreeNode*> q;
	q.push(root);
	while(!q.empty())
	{
		TreeNode * p = q.front();
		q.pop();
		vals.push_back(p->val);
		if(p->left)
			q.push(p->left);
		if(p->right)
			q.push(p->right);
	}
	return vals;
}
层次遍历递归实现:

vector<int> levelOrderTraversal(TreeNode *root) 
{
	vector<int> vals;
	height = getTreeHeight(root);
	for(int level = 1; level <= height; level++)
		levelOrderTraversal(root, level, vals);
	return vals;
}
int getTreeHeight(TreeNode * root)
{
	if(root == NULL) return 0;
	int heightLeft = getTreeHeight(root->left);
	int heightRight = getTreeHeight(root->right);
	return max(heightLeft, heightRight)+1;
}
void levelOrderTraversal(TreeNdoe *root, int level, vector<int> &vals)
{
	if(root == NULL) return;
	if(level == 1)
	{
		vals.push_back(root->val);
		return;
	}
	levelOrderTraversal(root->left, level-1, vals);
	levelOrderTraversal(root->right, level-1, vals);
}
注意,此实现时间复杂度仍然为O(n).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值