题目
二叉搜索树与双向链表
一、何为二叉搜索树?
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
先贴上树的定义:
class Binary_Tree():
def __init__(self, root=None, left=None, right=None):
self.root = root
self.left = left
self.right = right
二、思路一 中序遍历递归
根据二叉搜索树的特性,如果从最小的节点排序到最大的节点,可以看出对这颗二叉树是进行了中序遍历:左->根->右
贴上剑指offer的神图~
在进行指针变换的时候可以发现,每个根节点的左节点(双线链表中的前一个节点)指向了这个节点的左子树的最右节点:
每个根节点的右节点(双向链表中的后一个节点)指向了这个节点的右子树的最左节点:
显然这里可以采用中序遍历递归的思路:
有左子树的时候遍历左子树获得左子树的最小节点和最大节点
连接左子树和根节点:将左子树的最大节点指向根节点,根节点的前一个节点指向左子树的最大节点
有右子树的时候遍历右子树获得右子树的最小节点和最大节点
连接根节点和右子树:将根节点的下一个节点指向右子树的头节点,右子树的头节点前一个节点指向根节点
需要注意的情况是:
如果一个根节点只有右子树而没有左子树,此时应该判断是否有右子树,并将根节点与右子树连接后在返回
def tree_to_link_1(tree):
def order(tree):
if not tree:
return None
# 当前根节点有左子树,递归返回左子树的最小节点和最大节点
if tree.left:
head1, last1 = tree_to_link_1(tree.left)
if head1 == last1:
last1 = head1
# 当前根节点没有左子树
else:
# 递归返回的条件:遍历到了树的最左边(左叶子节点/右叶子节点)
# 当前根节点没有左子树但是有右子树
if tree.right:
# 获取右子树的双向链表的最小节点和最大节点
head2, last2 = tree_to_link_1(tree.right)
if head2 == last2:
last2 = head2
# 处理根节点
tree.right = head2
head2.left = tree
return tree, last2
# 当前根节点没有左子树也没有右子树,叶子节点
else:
return tree, tree
# 处理根节点
last1.right = tree
tree.left = last1
# 当前根节点有右子树,递归返回右子树的最小节点和最大节点
if tree.right:
head2, last2 = tree_to_link_1(tree.right)
if head2 == last2:
last2 = head2
tree.right = head2
head2.left = tree
else:
last2 = tree
return head1, last2
head, last = order(tree)
head.left = last
last.right = head
return head
这种方式,时间复杂度为O(N),牺牲了较大的空间来存储中间变量~
三、思路一_2 中序遍历递归(节省空间的方式)
借鉴了力扣大神的题解,空间复杂度O(N), 时间复杂度O(N)
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(cur):
if not cur: return
dfs(cur.left) # 递归左子树
if self.pre: # 修改节点引用
self.pre.right, cur.left = cur, self.pre
else: # 记录头节点
self.head = cur
self.pre = cur # 保存 cur
dfs(cur.right) # 递归右子树
if not root: return
self.pre = None
dfs(root)
self.head.left, self.pre.right = self.pre, self.head
return self.head