LCR 155. 将二叉搜索树转化为排序的双向链表
LCR 155. 将二叉搜索树转化为排序的双向链表
参考题解
前言
什么是循环双链表?
双向链表又称双链表,是链表的一种数据结构类型,其每个数据结点包含两个指针,分别指向直接前驱和直接后继,支持从前驱或后继任意结点进行双向遍历。通常采用双向循环链表结构实现,该结构通过头尾结点互连形成闭环。
什么是二叉搜索树?
关键性质:左 < 根 < 右
二叉搜索树(BST
)又称二叉查找树或二叉排序树。
在二叉搜索树中:
-
若任意结点的左子树不空,则左子树上所有结点的值均不大于它的根结点的值。
-
若任意结点的右子树不空,则右子树上所有结点的值均不小于它的根结点的值。
-
任意结点的左、右子树也分别为二叉搜索树
中序遍历
核心思想:左根右
解法思想
首先,从题目可以知道,最终要是要将二叉搜索树转换为一个已排序的双向循环链表,而在二叉树的遍历中,中序遍历恰好可以将一个二叉搜索树转换为一个有序地数组
因此,本题可以采用中序遍历的思想
函数解析
dfs
函数 – 深度优先遍历
如果当前遍历的节点为null
,那就说明当前访问的是叶子节点,直接返回。(因为深度优先遍历函数递
下去完之后肯定是要从二叉树的最下边开始归
回来的)
递归当前的节点的左节点:dfs(cur.left)
构建双链表:
- 判断
pre
节点是否为null
,如果是,那就说明当前节点cur
是头结点 - 如果不为
null
,那就pre.right = cur
,构建pre
的后继指针 - 接着构建
cur
的前驱指针,cur.left = pre
- 构建好当前节点之后,接着构建下一个节点,
pre
就要替代cur
的位置 - 递归当前节点的右结点:
dfs(cur.right)
public void dfs(Node cur) {if(cur == null) {return;}dfs(cur.left);if(pre != null) {pre.right = cur;} else {head = cur;} cur.left = pre;pre = cur;dfs(cur.right);
}
treeToDoublyList
函数
- 如果当前节点
root
为空,直接返回root
或者null
- 转化为双链表:
dfs(root)
- 构建循环双链表:头结点
head
要指向pre
的后继指针,pre
指向head
的前驱指针 - 返回
head
关于pre
:
在构建双链表阶段,当cur
遍历完最后一个节点的时候,就会继续遍历下一个节点,但下一个节点为null
,而pre
就会替代原本cur
的位置,所以pre
就会成为链表的尾结点。
public Node treeToDoublyList(Node root) {if(root == null) return root;dfs(root); // 构建双链表head.left = pre;pre.right = head;return head;
}
完整代码展示
class Solution {Node pre, head;public Node treeToDoublyList(Node root) {if(root == null) return root;dfs(root); // 构建双链表head.left = pre;pre.right = head;return head; }public void dfs(Node cur) {if(cur == null) {return;}dfs(cur.left);if(pre != null) {pre.right = cur;} else {head = cur;} cur.left = pre;pre = cur;dfs(cur.right);}
}
end…