栈实现树的前序, 中序, 后序遍历

本文介绍了如何利用栈实现二叉树的前序、中序和后序遍历。前序遍历通过根-左-右的顺序进行,中序遍历特点是根在左右子树之间。后序遍历则需要特殊处理,通过先遍历左右子树再访问根节点,并反转顺序得到正确结果。文中提供了相应的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前序遍历:
Code1:

vector<int> preorderTraversal(TreeNode* root) { // 前序遍历.
    vector<int> retvec;
    stack<TreeNode*> stk;

    while (root != NULL || !stk.empty()) {
        while (root != NULL) {
            retvec.push_back(root->val);		// 首次碰到 root, 就将其"输出"
            stk.push(root);
            root = root->left;
        }
        root = stk.top();
        stk.pop();
        root = root->right;
    }
}

Code2
使用栈实现 DFS 应用到二叉树就是前序遍历的结果.

class Solution {	// DFS的非递归版本
public:
    vector<int> DFSTraversal(TreeNode* root) {
        vector<int> vec;
        stack<TreeNode*> stk;
        stk.push(root);

        while (!stk.empty()) {
        	root = stk.top();
        	stk.pop();

        	vec.push_back(root->val);
        	// 非二叉树, 将当前结点的孩子结点, 从右至左依次入栈.
        	if(root->right) stk.push(root->right);
        	if(root->left) stk.push(root->left);
        }

        return vec;
    }
};

中序遍历:
Code:

vector<int> inorderTraversal(TreeNode* root) {  // 中序遍历.
    vector<int> retvec;
    stack<TreeNode*> stk;

    while (root != NULL || !stk.empty()) {
        // 注意循环进行的条件.
        while (root != NULL) {
            stk.push(root);
            root = root->left;
        }
        root = stk.top();	// 取一个非空元素.
        stk.pop();
        retvec.push_back(root->val);
        root = root->right;
        // 同样的方法处理右子节点, 可能为空
    }
    return retvec;
}

注意前序遍历和中序遍历中 retvec.push_back() 出现的地方。


补充: 后序遍历
网上看到思路:

  • 前序遍历 => 根, 左, 右.
  • 后序遍历 => 左, 右, 根.
  • 仿照前序遍历方法求解出 => 根, 右, 左.
  • reverse => 得到后序遍历.

Code1:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> stk;
        vector<int> vec;
        while (root != NULL || !stk.empty()) {
            while (root != NULL) {
                vec.push_back(root->val);
                stk.push(root);
                root = root->right;
            }
            root = stk.top();
            stk.pop();
            root = root->left;
        }
        reverse(vec.begin(), vec.end());
        return vec;
    }
};

Code2:
使用其他辅助结构,记录当前结点是从 左子节点返回还是右子节点返回

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

enum status { st_left, st_right };

struct hlpNode {
	TreeNode *pa;	// 添加对应的 TreeNode 引用 
	status st;		// 标记用于区别父节点是第几次进栈,从而知道是从左子节点还是右子节点返回
	hlpNode(TreeNode *p) : pa(p), st(st_left) {}	// 默认, 即第一次为 left
};

class solution {
	public:
		vector<int> postorderTraversal(TreeNode *root) {
			vector<int> vec;
			stack<hlpNode *> stk;
			hlpNode *node;
			while (root != NULL || !stk.empty()) {
				while(root != NULL) {
					node = new hlpNode(root);
					stk.push(node);
					root = root->left;
				}
				node = stk.top();
				stk.pop();
				if(node->st == st_left) {
				// 继续处理右子节点, 并更新 st_left 为 st_right
					node->st = st_right;
					stk.push(node);
					root = node->pa->right;
				} else {
				// 左右子节点均处理完成, "输出"根结点
					vec.push_back(node->pa->val);
				}
			}
		}
};
参考博客1
参考博客2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值