一想到二叉搜索树,你的第一反应就应该是“中序遍历”。
显而易见,二叉搜索树的直观印象就是左<根<右。中序遍历的顺序是啥?左根右。所以当你遍历完二叉树之后,就会发现,你完成了排序。
在遍历二叉搜索树之前我们需要先重温下如果去遍历一个普通的树。
最简单的方法就是
public void printPre(TreeNode node) {
if (node == null) return;
System.out.println(node.val);//word
printPre2(node.left); //AA
printPre2(node.right); //BB
}
上面是先序遍历,如果想要中序遍历,只需要将word放进AA和BB之间就可以了,如果要后序排序,就放到BB后面。
如果你说我要的不是这种,题设方法让我返回一个List,你也不需要再重新写个方法调用,你可能需要下面这种:
public List<TreeNode> getListTree(TreeNode node) {
List<TreeNode> list = new ArrayList<>();
if (node == null)
return list;
list.add(node);
list.addAll(getListTree(node.left));
list.addAll(getListTree(node.right));
return list;
}
同样你可以调整 list.add(node);的位置来改变你的遍历顺序。
假如你的面试官觉得递归不好,浪费资源太多,需要你去用迭代。其实你会发现迭代方法来遍历树,前序和中序是更加简单的。
首先你需要一个Stack去临时存储下节点,然后直接写出俩个while限定条件(无论是中序还是先序都是通用的)
- while (node != null || !stack.isEmpty())
- while(node != null)
最后请尽情写上你的代码。
public void printPre(TreeNode node) {
Stack<TreeNode> stack = new Stack<>();
while (node != null || !stack.isEmpty()) {
while(node != null) {
stack.push(node);
System.out.println(node.val);
node = node.left;
}
node = stack.pop();
node = node.right;
}
}
再贴上中序遍历迭代的代码
public void printMid(TreeNode node) {
Stack<TreeNode> stack = new Stack<>();
if (node == null) return;
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
System.out.println(node.val);
node = node.right;
}
}
!!是不是发现代码相似度99%,没错,只是读取节点语句 System.out.println(node.val);的顺序改变了。
先序遍历是什么?边存边读,我存进stack一个,我就读一个。
中序遍历是什么?边取边读,我取出stack一个,我就读一个。
扯了这么多,让我们回到二叉搜索树。
题目来了,请注意:
给定一棵二叉搜索树,请找出其中的第k小的结点。
怎么解决??先不管,我先中序遍历想一想,好像就解决了。中序遍历加上索引自增就是解决问题的方法。
怎么遍历?显而易见,使用迭代。
代码:
import java.util.Stack;
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
Stack<TreeNode> stack=new Stack<>();
int count=0;
while(pRoot!=null || !stack.isEmpty()){
while(pRoot!=null){
stack.push(pRoot);
pRoot=pRoot.left;
}
pRoot=stack.pop();
count++;
if(count==k){
return pRoot;
}
pRoot=pRoot.right;
}
return null;
}
}