题目

输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向,比如输入下图中左边的二叉搜索树,则输出转换之后的排序双向链表

思路

在二叉树中,每个结点都有两个指向子结点的指针。在双向链表中,每个结点也有两个指针,它们分别指向前一个结点和后一个结点。故链表和二叉搜索树的结构是相似的。在二叉搜索树中,左子结点的值总是小于父结点的值,右子结点的值总是大于父结点的值。因此在转换成排序双向链表时,原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针调整为链表中指向后一个结点的指针。

要求转换之后是有序的,我们知道二叉搜索树的中序遍历结果也是有序的。当中序遍历到根结点的时候,我们把二叉搜索树看成3部分:值为10的结点,根结点为6的左子树,根结点为14的右子树。根据排序链表的定义,值为10的结点将和它的左子树的最大一个结点值为8的结点链接起来,同时它还将和右子树中最小的结点值为12的结点链接起来。如下图:

按照中序递归遍历中,当我们遍历转换到根结点时,它的左子树已经转换成了一个排序的链表,并且此时链表尾部的值为左子树中值最大的结点的值(8)。我们将它(8)和根结点(10)链接起来,此时根结点(10)变成了链表尾部,接着去遍历右子树,我们知道中序遍历根结点(10)后的一个结点此时为右子树值最小的结点(12),我们将它和根结点链接起来。左右子树再用这样的办法,即递归即可解决问题。

代码

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
   public TreeNode Convert(TreeNode pRootOfTree) {
       if(pRootOfTree == null || (pRootOfTree.left == null && pRootOfTree.right == null))
           return pRootOfTree;
       ArrayList<TreeNode> nodeList = new ArrayList<>();
       BuildArrayList(pRootOfTree,nodeList);//这个函数执行后,数组中每个元素按照大小前后排序
       for(int i=0;i<nodeList.size();i++)
       {
           if(i == 0)
           {//数组的第一个节点处理,只有右子树指向下一个节点
               nodeList.get(0).right = nodeList.get(1);
           }
           else if(i == nodeList.size()-1)
           {//数组的最后一个节点,只有左子树指向前一个节点
               nodeList.get(i).left = nodeList.get(i-1);
           }
           else{//数组中的中间节点,左子树指向上一个节点,右子树指向数组的下一个节点
               nodeList.get(i).left = nodeList.get(i-1);
               nodeList.get(i).right = nodeList.get(i+1);
           }
       }
       return nodeList.get(0);
   }
   public void BuildArrayList(TreeNode root,ArrayList<TreeNode> nodeList)
   {//二叉搜索的中序遍历,并把每个节点存入数组中
       if(root == null)
           return;
       if(root.left != null)//左子树
           BuildArrayList(root.left,nodeList);
       if(root != null)//根节点
           nodeList.add(root);
       if(root.right != null)//右子树
           BuildArrayList(root.right,nodeList);
   }
}