剑指–二叉搜索树与双向链表
1,题目:
2,思路:
方法一:中序遍历(递归版本):
- 1.序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点;
- 2.双向链表: 在构建相邻节点(设前驱节点 pre ,当前节点 cur )关系时,不仅应 pre.right=cur ,也应 cur.left=pre 。
- 3.循环链表: 设链表头节点 head 和尾节点 tail ,则应构建 head.left=tail 和 tail.right=head 。
算法流程:
dfs(cur): 递归法中序遍历;
- 1.终止条件: 当节点 cur 为空,代表越过叶节点,直接返回;
- 2.递归左子树,即 dfs(cur.left) ;
- 3.构建链表:
- 4.当 pre 为空时: 代表正在访问链表头节点,记为 head 。
- 5.当 pre不为空时: 修改双向节点引用,即 pre.right=cur , cur.left=pre ;
- 6.保存 cur : 更新 pre=cur ,即节点 cur 是后继节点的 pre;
- 7.递归右子树,即 dfs(cur.left) ;
treeToDoublyList(root):
- 1.特例处理: 若节点 root 为空,则直接返回;
- 2.初始化: 空节点 pre ;
- 3.转化为双向链表: 调用 dfs(root) ;
- 4.构建循环链表: 中序遍历完成后,head 指向头节点, pre 指向尾节点,因此修改 head 和 pre 的双向节点引用即可。
- 5.返回值: 返回链表的头节点 head 即可。
下面是对应的图解:
方法二:非递归(迭代):
-
将树的左子树依次存入stack
-
每次pop出一个Node将其右子树的左子树也依次存入stack
-
然后做连接操作
3,代码:
方法一:中序遍历(递归版本):
class Solution {
/*
思路:
1.序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点;
2.双向链表: 在构建相邻节点(设前驱节点 pre ,当前节点 cur )关系时,不仅应 pre.right=cur ,也应 cur.left=pre 。
3.循环链表: 设链表头节点 head 和尾节点 tail ,则应构建 head.left=tail 和 tail.right=head 。
算法流程:
dfs(cur): 递归法中序遍历;
1.终止条件: 当节点 cur 为空,代表越过叶节点,直接返回;
2.递归左子树,即 dfs(cur.left) ;
3.构建链表:
4.当 pre 为空时: 代表正在访问链表头节点,记为 head 。
5.当 pre不为空时: 修改双向节点引用,即 pre.right=cur , cur.left=pre ;
6.保存 cur : 更新 pre=cur ,即节点 cur 是后继节点的 pre;
7.递归右子树,即 dfs(cur.left) ;
treeToDoublyList(root):
1.特例处理: 若节点 root 为空,则直接返回;
2.初始化: 空节点 pre ;
3.转化为双向链表: 调用 dfs(root) ;
4.构建循环链表: 中序遍历完成后,head 指向头节点, pre 指向尾节点,因此修改 head 和 pre 的双向节点引用即可。
5.返回值: 返回链表的头节点 head 即可。
*/
Node pre, head;
public Node treeToDoublyList(Node root) {
if(root == null) return null;
dfs(root);
head.left = pre;
pre.right = head;
return head;
}
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);
}
}
方法二:非递归(迭代):
class Solution {
public Node treeToDoublyList(Node root) {
/*
将树的左子树依次存入stack
每次pop出一个Node将其右子树的左子树也依次存入stack
然后做连接操作
*/
if(root==null)
return null;
Node cur = root;
Node before = null;
Node after;
Node head=null;
Stack<Node> stack = new Stack<>();
while (cur != null) {
stack.add(cur);
head=cur;
cur = cur.left;
}
while (!stack.isEmpty()) {
cur = stack.pop();
Node temp = cur.right;
while (temp != null) {
stack.push(temp);
temp = temp.left;
}
if(stack.isEmpty())
after=head;
else
after = stack.peek();
cur.left = before;
cur.right = after;
before = cur;
}
head.left=before;
return head;
}
}