输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。
二分查找树的中序遍历即为升序排列,问题就在于如何在遍历的时候更改指针的指向。一种简单的方法时,遍历二分查找树,讲遍历的结果放在一个数组中,之后再把该数组转化为双链表。如果题目要求只能使用O(1)内存,则只能在遍历的同时构建双链表,即进行指针的替换用递归的方法来解决,假定每个递归调用都会返回构建好的双链表,可把问题分解为左右两个子树。由于左右子树都已经是有序的,当前节点作为中间的一个节点,把左右子树得到的链表连接起来即可。
/**
*@Title: TreeToList.java
*@Package binarytree
*@Description: TODO
*@author peidong
*@date 2017-4-25 上午8:20:28
*@version V1.0
*/
packagebinarytree;
/**
* @ClassName: TreeToList
* @Description: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
* 要求不能创建任何新的结点,只调整指针的指向。
* @date 2017-4-25 上午8:20:28
*
*/
publicclass TreeToList {
/**
*
* @ClassName: ListNode
* @Description: 构建二叉树结点,同时也是双链表结点
* @date 2017-4-25 上午8:32:34
*
*/
public static class ListNode{
public int data;
public ListNode left;
public ListNode right;
public ListNode(int data){
this.data = data;
left = null;
right = null;
}
}
/**
*
* @Title: append
* @Description: 合并两个链表
* @param @param a
* @param @param b
* @param @return
* @return ListNode
* @throws
*/
public static ListNode append(ListNode a,ListNode b){
//边界条件判断
if(a == null){
return b;
}
if(b == null){
return a;
}
//获得两个链表的最后一个元素
ListNode aLast = a.left;
ListNode bLast = b.left;
//连接两个链表
aLast.right = b;
b.left = aLast;
bLast.right = a;
a.left = bLast;
return a;
}
public static ListNodetreeToList(ListNode root){
//边界判断
if (root == null) {
return null;
}
// 递归子树,此处要弄清楚,为什么递归在前而转换在后
ListNode aList =treeToList(root.left); // 左子树
ListNode bList =treeToList(root.right); // 右子树
// 将根节点转换为循环链表
root.left = root;
root.right = root;
//合并并排序,合并之后左子树为头结点,右子树为尾结点
aList = append(aList, root); //合并左子树与父结点
aList = append(aList, bList); //合并左子树与右子树
//返回头结点
return aList;
}
/**
*
* @Title: treeInsert
* @Description: 递归构建二叉平衡树
* @param @param root
* @param @param data
* @return void
* @throws
*/
public static void treeInsert(ListNoderoot, int data){
if(data <= root.data){
if(root.left != null){ //如果存在左子树
treeInsert(root.left,data); //左子树递归调用
}else {
root.left = newListNode(data); //不存在则构建左子树
}
}else{
if(root.right != null){
treeInsert(root.right,data); //如果存在右子树,则右子树递归
}else{
root.right = newListNode(data); //不存在则构建右子树
}
}
}
/**
*
* @Title: printBinaryTree
* @Description: 中序遍历二叉平衡树
* @param @param root
* @return void
* @throws
*/
public static voidprintBinaryTree(ListNode root){
//边界条件
if(root == null){
return;
}
//递归左子树
printBinaryTree(root.left);
//输出节点数据
System.out.print(Integer.toString(root.data)+"");
//输出右子树
printBinaryTree(root.right);
}
public static void printList(ListNodehead){
ListNode cur = head;
while(cur != null){
System.out.print(Integer.toString(cur.data)+"");
cur = cur.right;
if(cur == head){
break;
}
}
System.out.println();
}
/**
*@Title: main
*@Description: 测试用例
*@param @param args
*@return void
*@throws
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//构建根节点
ListNode root = new ListNode(6);
//插入数据构成二叉平衡树
treeInsert(root, 7);
treeInsert(root, 3);
treeInsert(root, 9);
treeInsert(root, 1);
treeInsert(root, 2);
treeInsert(root, 10);
treeInsert(root, 8);
treeInsert(root, 4);
treeInsert(root, 5);
//输出二叉树
System.out.println("二叉平衡树:");
printBinaryTree(root);
//换行
System.out.println();
//输出循环双向链表
System.out.println("循环链表:");
//将二叉树转换成循环链表
ListNode head =treeToList(root);
//输出循环链表
printList(head);
}
}