题目
输入一棵二叉搜索树,将该二叉搜索树转换为一个排序的双向链表。要求不能创建任何新的节点,只能调整指针的方向。例如:
10
/ \
6 14
/\ /\
4 8 12 16
需要转换为的双向链表为:4=6=8=10=12=14=16。
解法
首先定义二叉搜索树的节点结构:
BSTreeNode {
int value;
BSTreeNode left:
BSTreeNode right;
}
注意:文中涉及的代码均为伪代码。这是为了主要体现问题解决方法的思想,而隐藏其具体的实现。根据伪代码,可以使用C/C++, JAVA,Python等语言容易的实现。
问题分析:
1. 首先根据题目,我们可以发现,这里涉及的是经典的数据结构:二叉搜索树和双向链表。一般来说,对于树结构,我们首先就应该想到递归的方法,因为树本身就是递归定义的。因此,我们可以首先想到递归的思想。
2. 根据二叉搜索树的特性,我们容易知道,二叉搜索树的中序遍历结果就是有序的。因此,实现该问题的比较简单的想法可以是:首先,对二叉搜索树进行中序遍历,存储遍历种的每一个节点(顺序保存),然后根据存储的结构遍历一遍,构建有序的双向链表即可。但这种方式违法了题目要求:不能构建新的节点。虽然这个思路容易想到,但这里不满足要求。
3. 有了递归的思想,同时有了中序遍历时二叉搜索树节点有序,这两个思想。我们是否可以在中序遍历二叉搜索树的基础上,调整每个节点的left和right指针,构建双向链表呢?答案是肯定的。
思想:中序遍历二叉搜索树,调整当前遍历的节点的left指针指向其前一个节点,right指针指向后一个节点。如果是遍历中的第一个节点,则初始化双向链表的head和tail指针指向该节点,然后按照中序遍历的顺序依次构建后续的节点,最终构建出双向链表。伪代码如下:
INORDER-TREE-WALK(BSTreeNode root):
BSTreeNode head, tail; // 创建双向链表创建head和tail
if root == null
return;
if root.left != null
INORDER-TREE-WALK(root.left);
CHANGE-NODE(head, tail, root);
INORDER-TREE-WALK(root.right);
CHANGE-NODE(BSTreeNode head, BSTreeNode tail, BSTreeNode node):
if head == null
head = node;
tail = node;
else // 修改left和right指针的指向
node.left = tail;
tail.right = node;
tail = node.;
注:由于这里主要使用的伪代码表达思想,没有用具体语言实现(之后实现以后会添加),可能有细节问题,敬请指正。