二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
二叉搜索树可分为根节点、左子树和右子树,在把左、右子树转换成排序的双向链表后再和根节点链接起来,整棵搜索二叉树就转换成了排序的双向链表。因此这个过程可以分为两个阶段:
- 将左、右子树转换为双向排序链表
- 将左、右子树的转换链表和其对应的根节点链接
整个过程通过可以递归进行。
中序遍历法:从上图转换后得到得双向链表可以看出,链表中元素得排列就是二叉树中序遍历后得结果。因此,当得到中序遍历后的结果,我们只需要做的是从第一个节点( i = 1 i = 1 i=1)开始,将第 i + 1 i + 1 i+1个结点作为第 i i i个结点的left,将第i个结点作为第 i + 1 i+1 i+1个结点的right,不断操作直到最后 i i i。
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root: return
flag = False
self.r = []
head, cur = None, None
def helper(root):
if not root: return
helper(root.left)
self.r.append(root.val)
helper(root.right)
helper(root)
for i in self.r:
node = Node(i)
if flag == False:
head = node
flag = True
cur = node
else:
cur.right = node
node.left = cur
cur = node
cur.right, head.left = head, cur
return head
但上述的方法是先使用中序遍历获取树中节点的值,然后再构建双向循环链表,这样做分为了两步完成,而且还使用了额外的存储空间。如果想要实现就地转换,可以借助上面方法的思想完成,代码如下:
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root: return
self.flag = False
self.head, self.pre = None, None
def helper(root):
if not root: return
# 左
helper(root.left)
# 根
if not self.flag:
# 如果是链表的第一个节点
self.head = root
self.flag = True
else:
self.pre.right = root
root.left = self.pre
self.pre = root
# 右
helper(root.right)
helper(root)
self.head.left = self.pre
self.pre.right = self.head
return self.head