二叉树展开为链表C++

给你二叉树的根结点 root ,请你将它展开为一个单链表:

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。
二叉树展开为链表C++_第1张图片

迭代法,创建了一个哨兵节点(先序遍历),用了栈,空间复杂度为O(n)

class Solution {
public:
    void flatten(TreeNode* root) {
        if(root==nullptr) return;
        TreeNode* dummy = new TreeNode();
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            st.pop();
            // 栈先进后出,所以左子节点先出栈
            if(node->right) st.push(node->right);
            if(node->left) st.push(node->left);
            // 清空当前节点的左右子节点
            node->left = nullptr;
            node->right = nullptr;
            // 将当前节点加入新的链表
            dummy->right = node;
            dummy = node;
        }
    }
};

迭代法,原地创建,没有创建新节点,并且空间复杂度为O(1)

class Solution {
public:
    void flatten(TreeNode* root) {
        if(root==nullptr) return ;
        TreeNode* cur = root;
        while(cur){
            // 若当前节点的左子树存在,则检查左子树
            if(cur->left){
                // 找到左子树的“前驱节点”,即当前节点左子树的最右节点
                TreeNode* pre = cur->left;
                while(pre->right){
                    pre=pre->right;
                }
                // 找到前驱节点后,将当前节点的右子树,挪到前驱节点的右子树中
                pre->right = cur->right;
                // 将当前节点的左子树,改到右子树中去,并置空左子树
                cur->right = cur->left;
                cur->left = nullptr;
            }
            // 若左子树不存在或左子树已变为右子树,则查看的下一个节点为右子树
            cur = cur->right;
        }
    }
};

思路:

  1. 找到左子树的最右节点(前驱节点)
  2. 将当前节点的右子树接到前驱节点的右边
  3. 将左子树移到右边,并置空左指针
    1
   / \
  2   5
 / \   \
3   4   6
  • 当前节点 1,左子树存在
    – 找到左子树最右节点 (4)
    – 将 1 的右子树 (5->6) 接到 4 的右边
    – 将左子树移到右边
    1
    \
     2
    / \
    3  4  
         \
          5
           \
            6

以此类推

你可能感兴趣的:(二叉树展开为链表C++)