二叉树的非递归遍历 (leetcode-重点掌握不使用栈的非递归)

利用数据结构-栈,队列, 加上相应思路等完成。

2019-06-09 补充 二叉树 不使用栈 进行 先序/中序 非递归遍历(摘自leetcode上某个大神)视频讲解:https://www.youtube.com/watch?v=wGXB9OWhPTg,即Morris 遍历

leetcode题目地址

leetcode练习,隔段时间敲几次代码

144 . Binary Tree Preorder Traversal
https://leetcode.com/problems/binary-tree-preorder-traversal/

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

94 . Binary Tree Inorder Traversal
https://leetcode.com/problems/binary-tree-inorder-traversal/

https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

145 . Binary Tree Postorder Traversal
https://leetcode.com/problems/binary-tree-postorder-traversal/

https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

非递归先/前序(根-左-右)

非递归,使用栈

利用栈,根节点先pop, 然后先push right节点,再push left节点,pop则是先左再右

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        if(root == null){
            return ans;
        }
        Stack<TreeNode> sta = new Stack();
        sta.push(root);
        while(!sta.isEmpty()){
            TreeNode node = sta.pop();
            ans.add(node.val);
            if(node.right != null){
                sta.push(node.right);
            }
            if(node.left != null){
                sta.push(node.left);
            }
        }
        return ans;
    }
}

非递归,不使用栈

主要是链接前序节点到根,每个根访问两次:一次打印并建立链接,一次是取消链接转向右子树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> preOrderList = new ArrayList<>(512);
        TreeNode current = root;
        while(current != null) {
            // 左子树是null, 则 打印该节点,转向该节点的右子树
            if (current.left == null) {
                preOrderList.add(current.val);
                current = current.right; // 靠right 设置current
            }else {
                // find the predecessor(该节点的左子树 的 最右节点,不能等于该节点)
                TreeNode predecessor = current.left;
                while(predecessor.right != current && predecessor.right != null) {
                    predecessor = predecessor.right;
                }
                // 该节点第一次遍历 建立 predecessor.right = 自己
                if(predecessor.right == null) {
                    preOrderList.add(current.val);
                    predecessor.right = current;
                    current = current.left;
                }else { // 该节点第二次被访问到, predecessor.right不是null,是自己了,并消除这种link
                    predecessor.right = null;
                    current = current.right;
                }
            }
        }
        return preOrderList;
    }
}

非递归中序(左-根-右)

非递归,使用栈

每次取栈顶,而栈的顺序是 从根到最左,取出该节点打印并出栈
如果取出的节点没有右子树
则cur = cur->right;为null,下一次取出其父节点
如果右子树不为空
则 cur = cur->right;后下一次会往栈中添加右子树,但是根是在这之前入栈的

即操作确保了一定是 左 根 右 的顺序

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        if(root == null){
            return ans;
        }
        Stack<TreeNode> sta = new Stack<>();

        TreeNode cur = root;
        while(!sta.isEmpty() || cur != null){
            if(cur != null){ // 不断的左,直到左节点为空
                sta.push(cur);
                cur = cur.left;
            }else{
                TreeNode node = sta.pop();
                ans.add(node.val);
                
                if(node.right == null){
                    // do nothing; 即继续弹出栈中元素
                }else{
                    // 左子树为空,根打印了,那么转向右子树
                    cur = node.right;
                }
            }
        }
        return ans;
    }
}

非递归,不使用栈

主要是链接前序节点到根,每个根访问两次:第一次建立链接,另一次是取消链接 并打印,即后打印根,然后在转向右子树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList(16);
        if(root == null){
            return ans;
        }
        TreeNode cur = root;
        while(cur != null){
            if(cur.left == null){
                ans.add(cur.val);
                cur = cur.right; // 右子树建立遍历关联
            }else{
                // 不断的找到最右节点
                TreeNode pre = cur.left;
                while(pre.right != null && pre.right != cur){
                    pre = pre.right;
                }
                if(pre.right == null){ // 第一次访问
                    pre.right = cur;
                    cur = cur.left;
                }else{	// 第二次访问
                    ans.add(cur.val);
                    pre.right = null;
                    cur = cur.right;
                }
            }
        }
        return ans;
    }
}

非递归后序(左-右-根)

非递归,使用栈

需要记录是否右子树访问完成,然后再访问根(对比下中序非递归使用栈)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        if(root == null){
            return ans;
        }
        TreeNode preVisit = null;
        TreeNode cur = root;
        Stack<TreeNode> sta = new Stack();
        while(!sta.isEmpty() || cur != null){
            if(cur != null){
                sta.push(cur);
                cur = cur.left;
            }else{
                TreeNode node = sta.peek();

                if(node.right == null || node.right == preVisit){
                    sta.pop();
                    ans.add(node.val);
                    preVisit = node;
                }else{
                    cur = node.right;
                }
            }
        }
        return ans;
    }
}

非递归,不使用栈

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

     public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> preOrderList = new ArrayList<>(512);
        TreeNode current = root;
        while(current != null) {
            if (current.left == null) {
                current = current.right;
            }else {
                TreeNode predecessor = current.left;
                while(predecessor.right != current && predecessor.right != null) {
                    predecessor = predecessor.right;
                }
                if(predecessor.right == null) {
                    predecessor.right = current;
                    current = current.left;
                }else {
                    // 先消除链接
                    predecessor.right = null;
                    //  current.left 右子树靠right链接起来了,需要逆序全部访问到
                    addPath(preOrderList, current.left);
                    current = current.right;// 继续转向右子树,如果为空则退出
                }
            }
        }
        // 前面操作确保了,左子树先全部完成了,然后右子树的左子树也全部完成了,且右子树的右节点为null
        // 那么只需要再来一次逆序访问即可
        addPath(preOrderList, root);
        return preOrderList;
    }
    
    public void addPath(List<Integer> res, TreeNode node) {
        // 添加元素
        int count = 0;
        while (node != null) {
            ++count;
            res.add(node.val);
            node = node.right;
        }
        // 逆序
        int left = res.size() - count;
        int right = res.size() - 1;
        while (left < right) {
            int temp = res.get(left);
            res.set(left, res.get(right));
            res.set(right, temp);
            left++;
            right--;
        }
    }

}

使用二叉树非递归遍历的一些题目

230. Kth Smallest Element in a BST

题目地址
https://leetcode.com/problems/kth-smallest-element-in-a-bst/

ac代码如下;

/**
 * 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:
	int kthSmallest(TreeNode* root, int k) {
		
		if (root == NULL)
			return 0;

		stack<TreeNode*> sta;
		sta.push(root);
		TreeNode* pLeft = root->left;

		int outTh = 1;

		while (!sta.empty() || pLeft != NULL)
		{
			while (pLeft != NULL)
			{
				sta.push(pLeft);
				pLeft = pLeft->left;
			}

			TreeNode* top = sta.top();
			sta.pop();

			if (outTh == k)
			{
				return top->val;
			}
			outTh++;
			//cout << top->val;

			if (top->right != NULL) 
				pLeft = top->right;
		}

		return 0;
	}
};

114. Flatten Binary Tree to Linked List

题目地址
https://leetcode.com/problems/flatten-binary-tree-to-linked-list/
题目描述
Given a binary tree, flatten it to a linked list in-place.

For example,
Given

     1
    / \
   2   5
  / \   \
 3   4   6

The flattened tree should look like:

  1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

采用非递归,使用堆栈的先序遍历

ac代码如下:

/**
 * 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:
	
	void flatten(TreeNode* root) {
		if (root == NULL)
			return;

		stack<TreeNode*> sta;
		sta.push(root);

		TreeNode* lastNode = NULL;
		while (!sta.empty())
		{
			TreeNode* top = sta.top();
			sta.pop();
			
			if (top->right != NULL)
				sta.push(top->right);

			if (top->left != NULL)
				sta.push(top->left);

			if (lastNode != NULL){
				lastNode->left = NULL;
				lastNode->right = top;
			}
			lastNode = top;
		}
		return;
	}
};

采用递归

/**
 * 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:

	void dfs(TreeNode* root)
	{
		if (root == NULL)
			return;
		else if (root->left == NULL && root->right == NULL)
			return;
		else if (root->left != NULL && root->right == NULL){
			TreeNode* rootL = root->left;
			dfs(rootL);
			root->left = NULL;
			root->right = rootL;
			return;
		}
		else if (root->left == NULL && root->right != NULL)
		{
			TreeNode* rootR = root->right;
			dfs(rootR);
			root->right = rootR;
			return ;
		}
		else{
			TreeNode* rootL = root->left;
			TreeNode* rootR = root->right;

			dfs(rootL);
			dfs(rootR);

			root->right = rootL;
			root->left = NULL;

			TreeNode* pre = NULL;
			TreeNode* t = rootL;
			while (t != NULL){
				pre = t;
				t = t->right;
			}
			pre->right = rootR;
		}
	}

	void flatten(TreeNode* root) {
		if (root == NULL)
			return;

		dfs(root);

		return;
	}
};

采用非递归,不使用栈

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public void flatten(TreeNode root) {
        if(root == null){
            return;
        }
        TreeNode cur = root;
        while(cur != null){
            if(cur.left == null){
                cur = cur.right;
            }else{
                TreeNode preNode = cur.left;
                while(preNode.right != null){
                    preNode = preNode.right;
                }
                // cur.right变成preNode的右子树
                TreeNode curRight = cur.right;
                cur.right = null;
                preNode.right = curRight;

                // 左子树变右子树,顺便就把cur.left设置成right了
                TreeNode curLeft = cur.left;
                cur.left = null;
                cur.right = curLeft;

                cur = cur.right;
            }
        }
    }
}

面试题 17.12. BiNode

https://leetcode-cn.com/problems/binode-lcci/

非递归使用栈

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode convertBiNode(TreeNode root) {
        if(root == null){
            return null;
        }
        Stack<TreeNode> sta = new Stack<>();

        TreeNode dummy = new TreeNode(-1);
        TreeNode tail = dummy;

        TreeNode cur = root;
        while(!sta.isEmpty() || cur != null){
            if(cur != null){
                sta.push(cur);
                cur = cur.left;
            }else{
                TreeNode node = sta.pop();

                if(node.right != null){
                    cur = node.right;
                }

                tail.right = node;
                tail = node;
                tail.left = null;
            }
        }

        TreeNode res = dummy.right;
        dummy.right = null;
        return res;
    }
}

非递归,不使用栈

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode convertBiNode(TreeNode root) {
        if(root == null){
            return null;
        }

        TreeNode dummy = new TreeNode(-1);
        TreeNode tail = dummy;

        TreeNode cur = root;
        while(cur != null){
            if(cur.left == null){
                TreeNode node = cur;
                cur = cur.right;
                
                tail.right = node;
                tail = node;
                tail.left = null;
            }else{
                TreeNode pre = cur.left;
                while(pre.right != null && pre.right != cur){
                    pre = pre.right;
                }
                // 第一次访问
                if(pre.right == null){
                    pre.right = cur;
                    cur = cur.left;
                }else{
                    pre.right = null;

                    TreeNode node = cur;
                    //  转向右子树
                    cur = cur.right;

                    tail.right = node;
                    tail = node;
                    tail.left = null;
                }
            }
        }

        TreeNode res = dummy.right;
        dummy.right = null;
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值