###思路
比如如下图中的二叉搜索树,则输出转换之后的排序双向链表为:
在二叉树中,每个结点都有两个指向子节点的指针。在双向链表中,每个结点也有两个指针,他们分别指向前一个结点和后一个结点。由于这两种结点的结构相似,同时二叉搜索树也是一种排序的数据结构,因此在理论上有可能实现二叉搜索树和排序的双向链表的转换。在搜索二叉树中,左子结点的值总是小于父节点的值,右子节点的值总是大于父节点的值。因此我们在转换称排序的双向链表时,原先指向的左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子节点的指针调整为俩表为指向后一个结点的指针。接下来我们考虑如何转化。
由于要求转换之后的链表是排好序的,我们可疑中序遍历树中的每一个结点,这是因为中序遍历算法的特点是按照从小到达的顺序遍历二叉树的每一个结点。当遍历到根节点的时候,我们把树堪称三部分:值为10的结点,根节点为6的左子树、根节点为14的右子树。根据排序链表的定义,值为10的结点将和它的左子树的最大的一个结点(即值为8的结点)链接起来,同时它还将和右子树最小的结点(即值为12的结点)链接起来,如图:
按照中序遍历的顺序,当我们遍历转换到根节点(值为10的结点)时,它的左子树已经转换成一个排序的链表了,并且处在链表中的最后一个结点是当前值的最大的结点。我们把值为8的结点根节点链接起来,此时链表中的最后一个结点是10了。接着我们去遍历转换右子树,并把根节点和右子树最小的结点链接起来。至于怎么去转换它的左子树和右子树,由于遍历和转换过程是一样的,我们自然的想到了递归。
###AC代码
package com.zhumq.leetcode;
public class TreeNodetoLinkedList {
//定义树节点
public class TreeNode
{
int val;
TreeNode left = null;
TreeNode right = null;
TreeNode(int val)
{
this.val = val;
}
}
public TreeNode convert(TreeNode pRoot)
{
if(pRoot == null)
return null;
//用于记录双向链表尾结点
TreeNode pLastNodeInList = null;
//转换节点
convertNode(pRoot, pLastNodeInList);
//pLastNodeInList指向双向链表的尾结点,我们需要重新返回头结点
TreeNode pHead = pLastNodeInList ;
while(pLastNodeInList != null && pLastNodeInList.left != null)
pHead = pHead.left;
//返回头节点
return pHead;
}
//递归转换的函数
public void convertNode(TreeNode pNode, TreeNode pLastNodeInList)
{
if(pNode == null)
return ;
TreeNode pCurrent = pNode;
//递归处理左子树
if(pCurrent.left != null)
convertNode(pNode.left, pLastNodeInList);
//处理当前节点
//将当前节点的左指针指向已经转换好的链表的最后一个位置
pCurrent.left = pLastNodeInList;
//将已经转换好的链表的最后一个节点的右指针指向当前节点
if(pLastNodeInList != null)
pLastNodeInList.right = pCurrent;
//更新已经转换好的链表的最后一个节点
pLastNodeInList = pCurrent;
//递归处理右子树
if(pCurrent.right != null)
convertNode(pNode.right, pLastNodeInList);
}
}