二叉树的遍历分为深度优先遍历、广度优先遍历。深度优先分为前序遍历、中序遍历、后序遍历,每种方法又分为递归和非递归;广度优先只有一种。
一、深度优先遍历
1.前序遍历
- 递归实现:
public void preTree(treeNode T) {
if(T==null)
return;
System.out.print(T.data+" ");
preTree(T.lchild);
preTree(T.rchild);
}
其中的参数treeNode T是已建立好的根结点root,后面也是。
- 非递归实现:
public void nonRecursivePreTree() {
if(root==null) return;
Stack<treeNode> p=new Stack<treeNode>();
p.push(root);
while(!p.isEmpty()) {
treeNode t=p.pop();
System.out.print(t.data+" ");
if(t.rchild!=null)
p.push(t.rchild);
if(t.lchild!=null)
p.push(t.lchild);
}
}
大概思路:准备一个栈p,先将根结点压入栈,然后进入循环——判空、栈顶元素出栈、输出该元素、该元素右孩子入栈、左孩子入栈(注意先右后左),直至栈空。
2.中序遍历
- 递归实现:
public void inTree(treeNode T) {
if(T==null)
return;
inTree(T.lchild);
System.out.print(T.data+" ");
inTree(T.rchild);
}
- 非递归实现:
public void nonRecursiveInTree() {
if(root==null) return;
treeNode n=root;
Stack<treeNode> p=new Stack<treeNode>();
while(!p.isEmpty()||n!=null) {
while(n!=null) {
p.push(n);
n=n.lchild;
}
System.out.print(p.peek().data+" ");
n=p.pop().rchild;
}
}
大概思路:准备一个栈p、一个临时结点n,将根结点root赋予n,进入循环——判断栈空或n是否为null,然后一直向左找孩子,找到一个左孩子就直接入栈,直到左孩子为null,不入栈,此时n=null,然后输出此时的栈顶元素值、出栈、让n等于该元素的右孩子。
3.后序遍历
- 递归实现:
public void postTree(treeNode T) {
if(T==null)
return;
postTree(T.lchild);
postTree(T.rchild);
System.out.print(T.data+" ");
}
- 非递归实现:
public void nonRecursivePostTree() {
if(root==null)return;
Stack<treeNode> n1=new Stack<treeNode>();
Stack<treeNode> n2=new Stack<treeNode>();
n1.push(root);
while(!n1.isEmpty()) {
treeNode t=n1.pop();
n2.push(t);
if(t.lchild!=null)
n1.push(t.lchild);
if(t.rchild!=null) {
n1.push(t.rchild);
}
}
while(!n2.isEmpty()) {
System.out.print(n2.pop().data+" ");
}
}
大概思路:准备两个栈,将root压入第一个栈,进入循环——第一个栈判空,出栈栈顶元素,将其压入第二个栈中,然后将该元素的左孩子、右孩子压入第一个栈中(注意先左后右),直至第一个栈空,然后按序输出第二个栈即可。
二、广度优先遍历
public void BFS() {
if(root==null)return;
Queue<treeNode> n=new LinkedList<treeNode>();
n.offer(root);
while(!n.isEmpty()) {
treeNode t=n.poll();
System.out.print(t.data+" ");
if(t.lchild!=null)
n.offer(t.lchild);
if(t.rchild!=null)
n.offer(t.rchild);
}
}
大概思路:准备一个队列,先让根结点root入队,进入循环——判空、队首元素出队、输出该元素、该元素左孩子、右孩子入队(注意先左后右),直至队空。
广度优先遍历形式较为单一,并不像深度优先遍历那样复杂,但都有不可小视的作用。