树的先序,中序,后序的非递归写法

  • 先序遍历:根-左-右
//入站要先右节点在左节点
class Solution {
public:
	void preorderTraversal(TreeNode* root) {
		if (!root) return;
		stack<TreeNode*> st; st.push(root);
		while (!st.empty())
		{//直接弹出,所以根节点和当前左右孩子不会同时在栈中,因此“根”总是在前面。
			TreeNode* p = st.top(); st.pop();
			cout << p->val << endl;

			if (p->right) st.push(p->right);
			if (p->left) st.push(p->left);
		}
	}
};
  • 后序遍历:左右根;使用两个栈,第一个栈元素出栈到第二个栈。因此第二个栈:根-右-左即可,第一个栈:根-左-右,由于栈先入后出所以要先左子树后右子树。
class Solution {
public:
	void postorderTraversal(TreeNode* root) {
		if (!root) return;
		stack<TreeNode*> st1, st2;
		st.push(root);
		while(!st1.empty())
		{
			TreeNode* top = st1.top();
			st2.push(top); st1.pop();
			if(top->left) st1.push(top->left);
			if(top->right) st1.push(top->right);
		}
		//第二个栈中,根节点和当前左右孩子会同时在栈中,所以一起遵循逆序。
		while(!st2.empty())
		{	
			cout << st2.top()->val << endl;
			st2.pop();
		}
};
//方法二:使用一个栈.使用两个额外的节点分别记录当前节点(根节点)和上次访问的节点,对任意子树,
//左节点未访问,先访问左节点;如果上次访问左节点而没访问右节点:访问右节点;否则才访问当前节点。
class Solution {
public:
	void postorderTraversal(TreeNode* root) {
		if(!root) return;
		TreeNode* last = NULL;
		stack<TreeNode*> st; st.push(root);
		while(!st.empty())
		{
			TreeNode* cur = st.top();
			if(cur->left && cur->left != last && cur->right != last)
				st.push(cur->left);
			else if(cur->right && cur->right != last)
				st.push(cur->right);
			else{
				cout << cur->val;
				st.pop();
			}
			last = cur;
		}
	}
}

中序借助一个辅助节点

//先顺着左子树下去并把根节点加入栈中,直到左节点为空,从栈中拿出一个节点访问值,并沿右子树循环。
class Solution {
public:
	void Traversal(TreeNode* root) {
		if (!root) return;
		stack<TreeNode*> st; 
		TreeNode* p = root;
		while (!st.empty() || p)
		{
			if (p)
			{//push_back写在这里就是先序。
				st.push(p);
				p = p->left;
			}
			else {
				p = st.top(); st.pop();
				cout << p->val <<endl;
				p = p->right;
			}
		}
	}
};
  • 深度优先搜索(递归或非递归形式的先序、中序、后续)空间复杂度都是树的高度,即栈空间大小;时间复杂度是 O ( n ) O(n) O(n),其中n是节点数。
  • 官渡优先搜索(层次遍历)空间复杂度是每层节点数的最大值,即队列大小;时间复杂度是 O ( n ) O(n) O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值