二叉树展开为链表(很详细)
描述
给定一个二叉树,原地将它展开为链表。
例如,给定二叉树
1
/ \
2 5
/ \ \
3 4 6
将其展开为:
1
\
2
\
3
\
4
\
5
\
6
解析
变形的后续遍历
直觉是先序遍历,但是节点会丢失,可以使用后续遍历。
我们依次遍历 6 5 4 3 2 1,然后每遍历一个节点就将当前节点的右指针更新为上一个节点。
遍历到 5,把 5 的右指针指向 6。6 <- 5 4 3 2 1。
遍历到 4,把 4 的右指针指向 5。6 <- 5 <- 4 3 2 1。
直接思路
将左子树插入到右子树的地方
将原来的右子树接到左子树的最右边节点
考虑新的右子树的根节点,一直重复上边的过程,直到新的右子树为 null
代码
直接思路
public void flatten(TreeNode root) { while (root != null) { //左子树为 null,直接考虑下一个节点 if (root.left == null) { root = root.right; } else { // 找左子树最右边的节点 TreeNode pre = root.left; while (pre.right != null) { pre = pre.right; } //将原来的右子树接到左子树的最右边节点 pre.right = root.right; // 将左子树插入到右子树的地方 root.right = root.left; root.left = null; // 考虑下一个节点 root = root.right; } } }
变形的后续遍历
private TreeNode pre = null; public void flatten(TreeNode root) { if (root == null) return; flatten(root.right); flatten(root.left); root.right = pre; root.left = null; pre = root; }
利用一个全局变量 pre
,更新当前根节点的右指针为 pre
,左指针为 null
。相应的左孩子也要置为 null
,同样的也不用担心左孩子丢失,因为是后序遍历,左孩子已经遍历过了。