数据结构
二叉树节点的数据结构其实很简单,就是包含一个值,一个左孩子指针和一个右孩子指针。
class TreeNode{
Object value;
TreeNode leftChild;
TreeNode rightChild;
public TreeNode(Object value){
this.value=value;
}
}
创建
根据二叉树的存储的数据结构的特性,我们可以很方便的用递归实现二叉树的创建。比如我们通过先序(根左右)创建二叉树。
public static TreeNode create(){
TreeNode root=null;
@SuppressWarnings("resource")
Scanner input=new Scanner (System.in);
Object value=input.next();
if(value.equals("#"))
return null;
root=new TreeNode(value);
root.leftChild=create();
root.rightChild=create();
return root;
}
同理很方便通过递归实现二叉树的先序,中序和后序遍历
//先序遍历
public static void preOrder(TreeNode root){
if(root!=null){
System.out.print(root.value+" ");
preOrder(root.leftChild);
preOrder(root.rightChild);
}
}
//中序遍历
public static void inOrder(TreeNode root){
if(root!=null){
inOrder(root.leftChild);
System.out.print(root.value+" ");
inOrder(root.rightChild);
}
}
//后序遍历
public static void postOrder(TreeNode root){
if(root!=null){
postOrder(root.leftChild);
postOrder(root.rightChild);
System.out.print(root.value+" ");
}
}
下面我们主要来看一下二叉树的非递归遍历的实现。主要是通过栈实现。
先序遍历
- 访问根节点,根节点入栈并进入左子树,进而访问左子树的根节点并入栈,继而在继续访问左子树的根节点,如此循环,直到根节点为空
- 如果栈不为空,则退栈顶节点,并进入右子树
public static void preOrderByNotRecursion(TreeNode root){
Stack<TreeNode> stack=new Stack<>();
while(root!=null||!stack.isEmpty()){
while(root!=null){
System.out.print(root.value+" ");
stack.push(root);
root=root.leftChild;
}
if(!stack.isEmpty()){
root=stack.pop();
root=root.rightChild;
}
}
}
中序遍历
- 根节点入栈,进入其左子树,进而进入左子树的根节点入栈,如此循环往复直至根节点为空
- 如果栈不为空,则从栈顶退出到上一层的节点,访问出栈节点,并进入右子树
public static void inOrderByNotRecursion(TreeNode root){
Stack<TreeNode> stack=new Stack<>();
while(root!=null||!stack.isEmpty()){
if(root!=null){
stack.push(root);
root=root.leftChild;
}else{
root=(TreeNode) stack.pop();
System.out.print(root.value+" ");
root=root.rightChild;
}
}
}
后序遍历
- 访问根节点,进入其左子树,继而继续进入左子树的根节点,如此循环直至根节点为空
- 如果栈不为空,判断栈顶的节点的右子树是否为空,右子树是否刚才访问过,是,则退栈,访问退栈节点,用临时变量temp保存访问过的右子树,并该节点其置为空
public static void postOrderByNotRecursion(TreeNode root){
Stack<TreeNode> stack=new Stack<>();
TreeNode temp=null;
while(root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.leftChild;
}
if(!stack.isEmpty()){
root=(TreeNode) stack.peek();
if(root.rightChild==null||root.rightChild==temp){
root=stack.pop();
System.out.print(root.value+" ");
temp=root;
root=null;
}else{
root=root.rightChild;
}
}
}
}
通过比较二叉树的三个非递归遍历的实现,三者的条件都是在栈不为空或者节点不为空的条件下进行的。
层次遍历
二叉树的层次遍历是通过队列实现的。访问根节点并入队列。当队列不为空时,队列头结点出队列,并访问出队列的节点。如果它的左孩子不为空,将左孩子入队列,若果它的右孩子不为空,将它的右孩子入队列。
public static void levelOrder(TreeNode root){
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
root=queue.poll();
System.out.print(root.value+" ");
if(root.leftChild!=null){
queue.add(root.leftChild);
}
if(root.rightChild!=null){
queue.add(root.rightChild);
}
}
}