大神 地址 :http://blog.csdn.net/v_JULY_v/article/details/6015165
1.把二元查找树转变成排序的双向链表
题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ \
6 14
/ \ / \
4 8 12 16
/\
7 9
转换成双向链表
4=6=8=10=12=14=16。
上面是题目。 我尝试着 先想想思路。 要求是 不能创建任何借点 只能调整指针方向。 这是重点。刚开始想了一下。我暂时想到的思路是。因为是二元查找树。 本身就是有序的。左节点比他小。右节点比本身大。 转换的过程 就是一个有序查询的过程。
需要分2种处理:(我的约定是: 将树左节点的指针 记录 链表的前节点。 右边节点的指针 记录 链表的后一个节点。)
1。如果本身是 父节点的左节点(图中6)。 那么 本身的左节点(4) 就是他转换成链表的前一个节点。 而右节点的最小左节点(7)。 就是它转换成链表的后一个节点;
就是将它本身的 父节点 的左节点指针 指向 他的右节点。
10
/ \
8 14
/ \ / \
7 9 12 16
6
/
4
2..如果本身 是父节点的右节点。 跟上面的思路相反。就行了 右节点不变。左节点最大右节点 变 父节点的 右节点。
10
/ \
8 14
/ \ \
7 9 12
6 \
/ 16
4
这样 只要一次 顺序 排序 就可以实现了。 思路 这样 现在开始手写代码试试这思路 可不可行。 本人菜鸟 也只会java。 就用java实现;
经过一段时间的代码编写。总算实现了核心代码如下
private void convert(Node root){
if(root==null)
return;
convertLeft(root);
convertRight(root);
}
private void convertLeft(Node root){
Node leftNode =root.getPre();
if(leftNode==null)
return;
Node rightNode=leftNode.getNext();
if(rightNode!=null&&rightNode!=root){
root.setPre(rightNode);
Node childLeftNode=rightNode;
while(childLeftNode.getPre()!=null){
childLeftNode=childLeftNode.getPre();
}
childLeftNode.setPre(leftNode);
leftNode.setNext(childLeftNode);
convertLeft(root);
}else{
leftNode.setNext(root);
convertLeft(leftNode);
}
}
private void convertRight(Node root){
Node rightNode = root.getNext();
if(rightNode==null)
return;
Node leftNode=rightNode.getPre();
if(leftNode!=null&&leftNode!=root){
root.setNext(leftNode);
Node childRightNode=leftNode;
while(childRightNode.getNext()!=null){
childRightNode=childRightNode.getNext();
}
childRightNode.setNext(rightNode);
rightNode.setPre(childRightNode);
convertRight(root);
}else{
rightNode.setPre(root);
convertRight(rightNode);
}
}
运行测试了一下 貌似可以的。测试一下 超过一万个时候 直接就 java.lang.StackOverflowError。。 递归的烦恼啊。
然后思考了一下。貌似就是一个中序查询啊。不管怎么说 是完成。