第一部分:二叉树结点的定义
二叉树结点有三个属性:数据域、左结点、右结点。构造方法写三个参数,这样创建结点的时候代码更简洁,且要从叶子结点开始创建(从底往上创建)。注:如果只写一个赋值参数的构造器,那么创建节点的顺序就无所谓了,但是创建二叉树时要多写几行代码。
package binaryTree.bean;
/*
* 二叉树的结点
*/
public class Node {
private int data;
private Node left;
private Node right;
public Node(int data,Node left,Node right){
this.data = data;
this.left = left;
this.right = right;
}
public int getData(){
return data;
}
public void setData(int data){
this.data = data;
}
public Node getLeft(){
return left;
}
public void setLeft(Node left){
this.left = left;
}
public Node getRight(){
return right;
}
public void setRight(Node right){
this.right = right;
}
}
第二部分:全部代码
该二叉树(你可以任意画一个)有五个结点,为了方便描述,赋值分别为1、2、3、4、5。前中后序遍历递归与非递归完整代码如下:
package binaryTree;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/* 二叉树
* @1
* / \
* @2 @3
* / \
* @4 @5
*/
/*
* 递归与非递归
* 先序遍历 preOrderTraverse 1 2 4 5 3
* 中序遍历 inOrderTraverse 4 2 5 1 3
* 后序遍历 postOrderTraverse 4 5 2 3 1
* 层序遍历 levelOrderTraverse 1 2 3 4 5
*/
/*
* 栈 stack类 入栈push(),出栈pop()
* 队列 Queue接口 LinkedList为实现类 入队offer(),出队poll()
*/
import binaryTree.bean.Node;
public class BinaryTree {
public static void main(String[] args) {
//结点一的左右结点为结点二、结点三
//结点二的左右结点为结点四、五
//结点三、四、五的左右结点均为空
//由于Node的构造方法为三个参数,故要从叶子结点开始设置
Node node4 = new Node(4, null, null);
Node node5 = new Node(5, null, null);
Node node2 = new Node(2, node4, node5);
Node node3 = new Node(3, null, null);
Node node1 = new Node(1, node2, node3);
//preOrderTraverse1(node1);
//inOrderTraverse1(node1);
//postOrderTraverse1(node1);
//preOrderTraverse2(node1);
//inOrderTraverse2(node1);
//postOrderTraverse2(node1);
levelOrderTraverse(node1);
}
//先序遍历(递归法)
private static void preOrderTraverse1(Node head){
if(head == null)
return;
//根左右
System.out.print(head.getData()+" ");
preOrderTraverse1(head.getLeft());
preOrderTraverse1(head.getRight());
}
//后序遍历(递归法)
private static void postOrderTraverse1(Node head){
if(head == null)
return;
//左右根
postOrderTraverse1(head.getLeft());
postOrderTraverse1(head.getRight());
System.out.print(head.getData()+" ");
}
//中序遍历(递归法)
private static void inOrderTraverse1(Node head){
if(head == null)
return;
//左根右
inOrderTraverse1(head.getLeft());
System.out.print(head.getData()+" ");
inOrderTraverse1(head.getRight());
}
/*
* 先序遍历(非递归法)
* 1.申请一个栈记为stack.
* 2.然后将头结点head压入stack中
* 3.每次从stack中弹出栈顶结点,记为cur,然后打印cur结点的值.如果cur右孩子不为空的话,
* 先将cur的右孩子先压入stack中再将cur的左孩子压入stack。
* 然后从stack中弹出栈顶结点并记为cur,打印cur结点的值,如果cur右孩子不为空的话,先将
* cur的右孩子先压入stack中,再将cur的左孩子压入stack.然后重复以上步骤(若某个结点没有
* 孩子,则栈继续弹出),直到stack为空,全部过程结束。
*/
private static void preOrderTraverse2(Node head){
Stack<Node> stack = new Stack<>();
stack.push(head);
while(!stack.isEmpty()){
Node current = stack.pop();
System.out.print(current.getData()+" ");
if(current.getRight()!=null){
stack.push(current.getRight());
}
if(current.getLeft()!=null){
stack.push(current.getLeft());
}
}
}
/*
* 中序遍历(非递归法)
* 1.申请一个新的栈记为stack,申请变量cur,初始时令cur等于头结点。
* 2.进入while(current!=null||!stack.isEmpty())循环,
* 然后判断当current!=null时, 把cur结点压入栈中,然后令cur=cur.getLeft,然后重复while循环
* 如果cur为空,则从stack中弹出一个结点记为node,
* 打印node的值,并让cur=node.right,然后继续重复while循环
*/
private static void inOrderTraverse2(Node head){
Stack<Node> stack = new Stack<>();
Node current = head;
while(current!=null||!stack.isEmpty()){
if(current!=null){
stack.push(current);
current = current.getLeft();
}else{
Node node = stack.pop();
System.out.print(node.getData()+" ");
current = node.getRight();
}
}
}
/*
* 后序遍历(非递归方法一:使用两个栈)
* 1.申请两个栈记为s1、s2.将头结点压入s1中,然后弹出并放入s2中
* 2.将 从s1弹出并放入s2中的结点 记为cur,然后先把cur的左孩子压入s1中,再把cur的
* 右孩子压入s1中.(若弹出的结点cur没有左右孩子,则继续从s1弹出结点并放入s2中)
* 3.循环步骤2,直到s1为空,过程停止。
* 4.从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序。
*/
private static void postOrderTraverse2(Node head){
Stack<Node> stack1 = new Stack<>();
Stack<Node> stack2 = new Stack<>();
stack1.push(head);
while(!stack1.isEmpty()){
Node current = stack1.pop();
stack2.push(current);
if(current.getLeft()!=null){
stack1.push(current.getLeft());
}
if(current.getRight()!=null){
stack1.push(current.getRight());
}
}
while(!stack2.isEmpty()){
Node node = stack2.pop();
System.out.print(node.getData()+" ");
}
}
/*
* 层序遍历
* 每一层都是从左到右的遍历输出,借助于队列实现。offer()为入队,poll()为出队
* 1.先将根节点入队
* 2.将队首节点赋为cur,然后出队并打印,
* 如果当前结点cur的左结点不为空则将左结点入队,然后若右结点不为空则将右结点入队。
* 3.重复步骤2直到队空
*/
private static void levelOrderTraverse(Node head){
Queue<Node> queue = new LinkedList<>();
queue.offer(head);
while(!queue.isEmpty()){
Node current = queue.poll();
System.out.print(current.getData()+" ");
if(current.getLeft()!=null){
queue.offer(current.getLeft());
}
if(current.getRight()!=null){
queue.offer(current.getRight());
}
}
}
}
注:前中后序遍历,不管是递归方法还是非递归方法,遍历整棵树的时间复杂度都是O(N),N为二叉树的结点数。
每一种方法我都运行成功,都有详细的注释,有问题的话欢迎在评论区提问,一起学习进步!
2755

被折叠的 条评论
为什么被折叠?



