leetcode 144、leetcode 94、leetcode 145 二叉树的前序遍历迭代实现 等

二叉树的迭代遍历

前序遍历

假如你出生在皇室,你们家有皇位继承,需要排继承顺序,江山总得有人继承。当前:包括皇帝在内,总共有7个人,可以继承皇位。

突然敌人来犯,7个人谁都可能会死,所有人投票决定按照【前序遍历】的顺序继承皇位。

定义:左孩子——皇子(孙) 右孩子——公主

首先是儿子2继承,儿子2死后是孙子4,孙子4死后是孙女5。

很不幸,儿子2这一支死完了,轮到了公主3这一支,公主3上位。

又很不幸,公主3 go die,王爷6上位,6死了,郡主7上位。

image-20240611230549801

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) 
    {
        vector<int> res;
        if (root == nullptr) 
        {
            return res;
        }

        stack<TreeNode*> stk;
        TreeNode* node = root;
        while (!stk.empty() || node != nullptr) 
        {
            while (node != nullptr)
            {
                res.emplace_back(node->val);
                stk.emplace(node);
                node = node->left;
            }
            node = stk.top();
            stk.pop();
            node = node->right;
        }
        return res;
    }
};
//代码怎么写,当前结点为空 并且栈也为空
 while (node != nullptr || !stk.empty()) 
 {
      while(node! = nullptr)		// 寻找最左的孩子  也就是嫡皇子
      {
          result.insert(node->val);	//打印当前元素  继承皇位
          stk.push(node);			//记录当前元素 相当于族谱一样的
          node = node ->left;
      }
     
      //最左的孩子 没有儿子  相当于嫡皇子没有儿子   那就翻记录【stack】看看有没有公主  同样以后还是要
      																			//找左孩子
      node = stk.top();
      stk.pop();
      node= node->right;
 }
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();                       // 根
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return result;
    }
};

//作者:代码随想录
//链接:https://leetcode.cn/problems/binary-tree-postorder-traversal/solutions/367420/bang-ni-dui-er-cha-shu-bu-zai-mi-mang-che-di-chi-t/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

中序遍历

中序遍历是什么? 左根右

较前序遍历,有什么不同? 先处理左子树,再处理当前结点,最后处理右结点。

为什么需要栈? 给定的参数,肯定是从根结点开始, 程序遍历原始参数是 根左, 想要达到左根的结果,使用栈比较方便。

依旧一路向左? 因为我们人在遍历二叉树的时候 ,很自然的就是找最左的

有右孩子

[1,2,4,5,3,6,7]

遍历到2时,2是个根,左根右【4,2,5】 有右孩子5,切到5上,以5为根继续【左根右】

最终结果:【[4,2,5,1,6,3,7]】

image-20240611230549801

没有右孩子

遍历到2时,[1,2,5,3,6,7] 左根右【4,2,null】

image-20240612010501800

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> result;
        stack<TreeNode*> sta;
        TreeNode* cur = root;

        if(root == nullptr)
            return result;

        while(cur!= nullptr || !sta.empty())
        {
            while (cur!= nullptr)
            {
                sta.push(cur);
                cur = cur->left;
            }
            
            cur = sta.top();
            sta.pop();
            result.push_back(cur->val);    //打印元素  移到这里? 为什么是这里, 因为下一步要切到  cur->right 上。
            cur = cur->right;

        }
        return result;
     }
};

后序遍历

注意到,所有的子树,最后一个结点就是子树的根结点。

  1. 先将根结点入栈,输出到结果数组中
  2. 左子树头入栈,右子树头入栈,
  3. 弹出栈顶元素,输出到结果数组中,
  4. 第2步和 第3步 循环 直至所有的结果输出【辅助栈为空】
/**
 * 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) 
   {
    	vector<int> result; // 存储后序遍历结果
    	stack<TreeNode*> stk; // 辅助栈

    	// 如果根节点为空,则直接返回空结果
    	if (root == nullptr) return result;

    	// 将根节点入栈
    	stk.push(root);

    	// 当栈不为空时进行遍历
    	while (!stk.empty()) 
        {
        	TreeNode* curr = stk.top(); // 取出栈顶节点
        	stk.pop();

        	// 将当前节点值插入到结果的头部,实现倒序
        	result.insert(result.begin(), curr->val);

        	// 如果当前节点的左子树不为空,则将左子树入栈
        	if (curr->left) stk.push(curr->left);
        	// 如果当前节点的右子树不为空,则将右子树入栈
        	if (curr->right) stk.push(curr->right);
    	}

    	return result;
	}
};

另一种想法

能不能尽量统一写法? 就记住前(后)序遍历,在前(后)序遍历的基础上调整;

前序遍历:根左右

后序遍历: 左右根

所有人,接触到这个问题时,很自然会想过,前序遍历 逆序是不是后续遍历? 答案是肯定的 不是。

前序逆序: 右左根

与预期 左右根差一点。调整下前序遍历,左右的处理顺序就可以有后序遍历的逆序~

//前序遍历
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();                       // 根
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return result;
    }
};
//后序遍历
//上面的没有什么不同   
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
            if (node->right) st.push(node->right); // 空节点不入栈
        }
        reverse(result.begin(), result.end()); // 将结果反转之后就是左右根的顺序了
        return result;
    }
};

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值