题目:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
分析:
树本身为二叉搜索树,具有一定的排序规律,要调整成为排序双向链表,需要知道,原本树的根节点右指针指向的元素比根节点大,左指针需要调整指向比根节点小的元素。且整棵树中,最小的节点是最左的节点,最大的节点是最右的节点。二叉树左右节点调整可以采用递归思路。
递归处理左子树,左边是有序的双链表了,将根连到链表的尾端,再递归处理右子树。因此,每次需要记录排序双链表中最右的节点,以便连接后续节点。
实现:
public class Solution {
public TreeNode Convert(TreeNode root) {
// 用于保存处理过程中的双向链表的尾结点
TreeNode[] lastNode = new TreeNode[1];
convertNode(root, lastNode);
// 找到双向链表的头结点
TreeNode head = lastNode[0];
while (head != null && head.left != null) {
head = head.left;
}
return head;
}
public void convertNode(TreeNode node, TreeNode[] lastNode) {
// 结点不为空
if (node != null) {
// 如果有左子树就先处理左子树
if (node.left != null) {
convertNode(node.left, lastNode);
}
// 将当前结点的前驱指向已经处理好的双向链表(由当前结点的左子树构成)的尾结点
node.left = lastNode[0];
// 如果左子树转换成的双向链表不为空,设置尾结点的后继
if (lastNode[0] != null) {
lastNode[0].right = node;
}
// 记录当前结点为尾结点
lastNode[0] = node;
// 处理右子树
if (node.right != null) {
convertNode(node.right, lastNode);
}
}
}
}
其中,结点定义如下:
<span style="font-family:Microsoft YaHei;font-size:14px;">public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}</span>