二叉树的三种遍历 循环实现 - C++实现

三种遍历:先序、中序、后序

先序循环遍历:

// 先序遍历
void preOrderIterator(TreeNode *root){
	if (root)
	{
		stack<TreeNode*> s;
		while(root || !s.empty()){	// 只要root不为空
			// 一路压栈
			while(root){	// r非空
				cout << root->_data << " ";
				s.push(root);
				root = root->_left;	// 将r取为r的左节点
			}
			// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
			root = s.top();
			s.pop();
			root = root->_right;
		}
	}
}

中序循环遍历:

// 中序遍历
void midOrderIterator(TreeNode *root){
	if (root)
	{
		stack<TreeNode*> s;
		while(root || !s.empty()){	// 只要root不为空
			// 一路压栈
			while(root){	// r非空
				s.push(root);
				root = root->_left;	// 将r取为r的左节点
			}
			// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
			root = s.top();
			s.pop();
			cout << root->_data << " ";
			root = root->_right;
		}
	}
}

后序循环遍历:比较麻烦,使用cur记录当前的节点,使用pre记录上一个被输出的节点

如果满足当前节点没有子节点 或者 上一个输出的节点 |是当前节点的子节点| 即当前节点的子节点| 已经被访问过了,就可以输出当前节点

void postOrderIterator(TreeNode *root){
	if (root)
	{
		stack<TreeNode*> s;
		TreeNode* cur;	// 当前节点
		TreeNode* pre = NULL; // 上一次访问的节点
		s.push(root);
		while(!s.empty()){
			cur = s.top();s.pop();	// 先取出栈顶的节点,得到节点的值
			s.push(cur);	// 再把节点放回去

			// 如果当前节点没有子节点 或者 子节点都已经被访问过了
			if ((cur->_left==NULL && cur->_right==NULL) || (pre!=NULL && (pre==cur->_left || pre==cur->_right)))
			{
				cout << cur->_data << " ";
				s.pop();
				pre = cur;
			}else{
				if (cur->_right != NULL) s.push(cur->_right);
				if (cur->_left != NULL) s.push(cur->_left);
			}

		}
		
	}
}

完整代码:

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

// 树的三种遍历的循环实现
// 用到了栈,也可以用前面自己写的数据结构
typedef struct _TreeNode
{
	int _data;
	struct _TreeNode* _left;
	struct _TreeNode* _right;
}TreeNode;


// 先序遍历
void preOrderIterator(TreeNode *root){
	if (root)
	{
		stack<TreeNode*> s;
		while(root || !s.empty()){	// 只要root不为空
			// 一路压栈
			while(root){	// r非空
				cout << root->_data << " ";
				s.push(root);
				root = root->_left;	// 将r取为r的左节点
			}
			// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
			root = s.top();
			s.pop();
			root = root->_right;
		}
	}
}

// 中序遍历
void midOrderIterator(TreeNode *root){
	if (root)
	{
		stack<TreeNode*> s;
		while(root || !s.empty()){	// 只要root不为空
			// 一路压栈
			while(root){	// r非空
				s.push(root);
				root = root->_left;	// 将r取为r的左节点
			}
			// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
			root = s.top();
			s.pop();
			cout << root->_data << " ";
			root = root->_right;
		}
	}
}

// 后序遍历
void postOrderIterator(TreeNode *root){
	if (root)
	{
		stack<TreeNode*> s;
		TreeNode* cur;	// 当前节点
		TreeNode* pre = NULL; // 上一次访问的节点
		s.push(root);
		while(!s.empty()){
			cur = s.top();s.pop();	// 先取出栈顶的节点,得到节点的值
			s.push(cur);	// 再把节点放回去

			// 如果当前节点没有子节点 或者 子节点都已经被访问过了
			if ((cur->_left==NULL && cur->_right==NULL) || (pre!=NULL && (pre==cur->_left || pre==cur->_right)))
			{
				cout << cur->_data << " ";
				s.pop();
				pre = cur;
			}else{
				if (cur->_right != NULL) s.push(cur->_right);
				if (cur->_left != NULL) s.push(cur->_left);
			}

		}
		
	}
}


int main(int argc, char const *argv[])
{
	TreeNode a, b, c, d, e, f;
	// 创建一个指向根节点的指针
	TreeNode* root  = &a;
	a._data = 1;
	b._data = 2;
	c._data = 3;
	d._data	= 4;
	e._data = 5;
	f._data = 6;
	a._left = &b;
	a._right = &c;
	b._left = &d;
	b._right = &e;
	c._left = NULL;
	c._right = &f;
	d._left = d._right = NULL;
	e._left = e._right = NULL;
	f._left = f._right = NULL;

	preOrderIterator(root);
	cout << endl;
	midOrderIterator(root);
	cout << endl;
	postOrderIterator(root);
	cout << endl;

	return 0;
}

输出:

1 2 4 5 3 6
4 2 5 1 3 6
4 5 2 6 3 1

发布了145 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43826242/article/details/101020811