题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
1.思路:目标是将二叉搜索树变成有序的双向链表,可以这么做:
第一步:首先将二叉搜索树按中序遍历,然后存入ArrayList中
第二步:将arraylist中前后节点用指针串起来,left指针指向前一个,right指针指向后一个,首元素的left为null,尾元素的right为null
如果将二叉搜索树的每个节点看成一个个小珠子,那么第一步就是将这些小珠子按顺序放入槽中,第二步就是用线将这些珠子串起来
2.二叉搜索树的中序遍历得到的结果刚好是从小到大排序的
3.再理一下非递归中序遍历的思路:
list中保存的是最后的便利结果
1)首先是沿着根节点向左走,一直左走,直到左孩子为空(不一定为叶子,因为有可能最后一个双亲节点没有左孩子,只有右孩子),这时候栈里的就是根节点到左孩子为空的路径
(地点2),然后就应该出栈对吧(地点3),出栈就意味着遍历过了,以后不再访问了,那么就加入list中(地点4),然后到达地点5,这时候就有两种情况了:
第一种:如果地点4中已经遍历的是叶子节点,那么就意味着下一个遍历节点应该是它的父亲节点,那么,就不应该走地点2那个循环,如果再走2那个循环,这样不就
死循环了吗,所以我们将tmp置为null
第二种:如果地点4出现的是双亲节点,此时左子树和自己本身已经遍历过了,那么如果有右子树,就应该开始遍历右子树,将tmp置为tmp.right
2)关于开始的时候while(!stack.empty()||(tmp!=null))这个里面为什么这么写呢,这些可以不用刻意去记,你想啊,开始stack为空,那么想要进循环那么就要加一个tmp不为空。
importjava.util.*;
publicclassSolution {
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree==null)returnpRootOfTree;
if(pRootOfTree.left==null&& pRootOfTree.right==null)returnpRootOfTree;
ArrayList<TreeNode>list1=newArrayList<TreeNode>();// 用来装搜索二叉树的中序遍历
Stack<TreeNode>stack=newStack<TreeNode>();// 栈,非递归中序遍历需要栈的辅助
TreeNode root=pRootOfTree;
// 非递归中序遍历
TreeNode tmp=root;
while(!stack.empty()||(tmp!=null)) {//地点1
while(tmp!=null) {
stack.push(tmp);
tmp=tmp.left;
}//地点2
tmp=stack.pop();//地点3
list1.add(tmp);//地点4
if(tmp.right!=null) {//地点5,如果是有右子树,那么就遍历右子树
tmp=tmp.right;
}
elsetmp=null;
}
// 然后将这些节点按顺序串起来
inti;
for(i=0;i<list1.size()-1;i++) {// 因为后面一次循环是取相邻两个节点出来,所以范围是i<list1.size()-1
if(i==0)list1.get(i).left=null;
list1.get(i).right=list1.get(i+1);
list1.get(i+1).left=list1.get(i);
}
list1.get(i).right=null;
returnlist1.get(0);
}
}