二叉树的实现、广度优先遍历和递归、非递归的深度优先遍历,思路在注释中:
package 二叉树;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<E> {
public static class TreeNode<E>{
TreeNode<E> leftChild;
TreeNode<E> rightChild;
E value;
public TreeNode(E value, TreeNode<E> leftChild, TreeNode<E> rightChild){
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
TreeNode<E> root;
public BinaryTree(TreeNode<E> root){
this.root = root;
}
public void breadFirstTravel(){
Queue<TreeNode<E>> queue = new LinkedList<TreeNode<E>>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode<E> currentNode = queue.poll();
System.out.print(currentNode.value+" ");
if(currentNode.leftChild!=null)
queue.add(currentNode.leftChild);
if(currentNode.rightChild!=null)
queue.add(currentNode.rightChild);
}
System.out.println();
}
public void preRootTravalWithRecursion(){
preRootTravalWithRecursion(root);
System.out.println();
}
private void preRootTravalWithRecursion(TreeNode<E> node){
if(node!=null){
System.out.print(node.value+" ");
preRootTravalWithRecursion(node.leftChild);
preRootTravalWithRecursion(node.rightChild);
}
}
public void inRootTravalWithRecursion(){
inRootTravalWithRecursion(root);
System.out.println();
}
private void inRootTravalWithRecursion(TreeNode<E> node){
if(node!=null){
inRootTravalWithRecursion(node.leftChild);
System.out.print(node.value+" ");
inRootTravalWithRecursion(node.rightChild);
}
}
public void postRootTravalWithRecursion(){
postRootTravalWithRecursion(root);
System.out.println();
}
private void postRootTravalWithRecursion(TreeNode<E> node){
if(node!=null){
postRootTravalWithRecursion(node.leftChild);
postRootTravalWithRecursion(node.rightChild);
System.out.print(node.value+" ");
}
}
//单栈实现非递归先序遍历 访问节点 右子树入栈 左子树入栈
public void preRootTravelWithoutRecursion(){
Deque<TreeNode<E>> deque = new LinkedList<TreeNode<E>>();
TreeNode<E> temp ;
if(root!=null){
deque.addLast(root);
while(!deque.isEmpty()){
//访问节点
temp = deque.removeLast();
System.out.print(temp.value+" ");
//右子树入栈
if(temp.rightChild!=null)
deque.addLast(temp.rightChild);
//左子树入栈
if(temp.leftChild!=null)
deque.addLast(temp.leftChild);
}
System.out.println();
}
}
//单栈非递归实现二叉树的中序遍历
public void inRootTravelWithoutRecursion(){
Deque<TreeNode<E>> deque = new LinkedList<TreeNode<E>>();
TreeNode<E> temp = root;
while(temp!=null||!deque.isEmpty()){
//当前节点所有左侧子节点压入栈
while(temp!=null){
deque.addLast(temp);
temp = temp.leftChild;
}
//访问当前结点 转向右子树
if(!deque.isEmpty()){
temp = deque.removeLast();
System.out.print(temp.value+" ");
//转向右子树
temp = temp.rightChild;
}
}
System.out.println();
}
//非递归单栈后序遍历
public void postRootTravelWithoutRecursion(){
Deque<TreeNode<E>> deque = new LinkedList<TreeNode<E>>();
TreeNode<E> pointer = root;
TreeNode<E> preNode = null;//存放上一个被访问过的元素
while(pointer!=null){
for(;pointer.leftChild!=null;pointer = pointer.leftChild){//将所有有左子树的结点压入栈中
deque.addLast(pointer);
}
while(pointer!=null && (pointer.rightChild==null||preNode==pointer.rightChild)){//右子树被访问过了或者右子树为空
System.out.print(pointer.value+" ");
preNode = pointer;//把pointer置为上一个访问节点
if(deque.isEmpty())
{
return;
}
pointer = deque.removeLast();
}
deque.addLast(pointer);
pointer = pointer.rightChild;
}
System.out.println();
}
}
对于广度优先遍历,借助队列来实现,从根开始,将根入队列,然后如果左孩子不为空,左孩子入队列,右孩子不为空,右孩子入队列。然后出对列,继续访问,直到队列空。
对于递归实现的深度优先遍历,每当要访问一个结点,便对这个结点的左孩子右孩子进行递归深度优先遍历,先序、中序、后序只不过是对该节点访问、对左孩子递归、对右孩子递归的顺序问题而已。
对于非递归的先序遍历,借助栈来实现。从根开始,访问根结点,将其右子树入栈,然后左子树入栈。弹栈重复上述步骤,直到栈空。
对于非递归的中序遍历,借助栈来实现。对于访问一个结点,将其所有左节点入栈。然后弹栈,访问当前节点,转向栈内结点的右子树,如果这些右子树有左子树,继续入栈这些左结点。重复以上,直到栈空并且当前访问结点为空。
对于非递归的后序遍历,借助栈来实现。将所有有左子树的结点压入栈中,当前结点为最后一个没有左子树的结点,如果当前结点没有右子树或者右子树被访问过,则访问当前结点,将当前结点置为上一次访问的结点,否则当前结点入栈,转向右子树。