先上代码,看不懂请看后面的图解就一定能懂了
创建Node类 :
package Tree1; public class Node { //节点值 int data; Node leftChild; //左孩子 Node rightChild ; //右孩子 //初始化,无参构造器 public Node() { data = 0; leftChild = rightChild = null; } //初始化,一参构造函数 public Node(int value) { this.data = value; leftChild = rightChild = null; } }
方法实现类:
package Tree1; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; public class Tree { /** * 非递归实现树先序,中序,后序递归(栈) */ public static void main(String[] args) { Node node4 = new Node(4); Node node1 = new Node(1); Node node2 = new Node(2); Node node3 = new Node(3); Node node5 = new Node(5); Node node6 = new Node(6); Node node7 = new Node(7); node4.leftChild = node2; node4.rightChild = node6; node2.leftChild = node1; node2.rightChild = node3; node6.leftChild = node5; node6.rightChild = node7; System.out.println("=====先序遍历====="); preOrder(node4); System.out.println("\n=====中序遍历====="); midOrder(node4); System.out.println("\n=====后序遍历====="); latOrder(node4); System.out.println("\n=====层序遍历====="); floOrder(node4); } /** * 先序遍历 * 1.先将根节点入栈 * 2.访问根节点 * 3.如果根节点存在右孩子,则将右孩子入栈 * 4.如果根节点存在左孩子,则将左孩子入栈(注意:一定是右孩子先入栈,然后左孩子入栈) * 5.重复2-4 * @param root */ //传入根节点 public static void preOrder(Node root){ if (root==null){ System.out.println("空树"); } //创建栈 Stack<Node> stack = new Stack<>(); //进栈 stack.push(root); //判断是否栈是否为空 while(!stack.isEmpty()){ //栈顶元素节点赋给temp Node temp = stack.pop(); //输出节点 System.out.printf(temp.data+" "); //判断左孩子是否为空 if (temp.rightChild!=null){ //不为空就进栈 stack.push(temp.rightChild); } 判断右孩子是否为空 if (temp.leftChild!=null){ //不为空就进栈 stack.push(temp.leftChild); } } } /** * 中序遍历 * 1.先将根节点入栈 * 2.将当前节点的所有左孩子入栈,直到左孩子为空 * 3.访问栈顶元素,如果栈顶元素存在右孩子,则继续第2步 * 4.重复第2、3步,直到栈为空并且所有的节点都被访问 * @param root */ public static void midOrder(Node root){ if (root==null){ System.out.println("空树"); } Node temp = root; Stack<Node> stack = new Stack<>(); while(temp!=null || !stack.isEmpty()){ while(temp!=null){ stack.push(temp); temp = temp.leftChild; } temp = stack.pop(); System.out.printf(temp.data+" "); if(temp.rightChild!=null){ temp = temp.rightChild; }else { temp = null; } } } /** * 后续遍历 * 1.根节点入栈 * 2.将根节点的左子树入栈,直到最左,没有左孩子为止 * 3.得到栈顶元素的值,先不访问,判断栈顶元素是否存在右孩子,如果存在并且没有被访问, * 则将右孩子入栈,否则, * 就访问栈顶元素 * @param root */ public static void latOrder(Node root){ if (root==null){ System.out.println("空树"); } Node temp = root; Node pre = null; Stack<Node> stack = new Stack<>(); while(temp!=null || !stack.isEmpty()){ while(temp!=null){ stack.push(temp); temp = temp.leftChild; } if(!stack.isEmpty()){ temp = stack.peek(); if(temp != null){ if(temp.rightChild == null || temp.rightChild == pre){ temp = stack.pop(); System.out.printf(temp.data+" "); pre = temp; temp = null; }else { temp = temp.rightChild; } } } } } /** * 层序遍历 * @param root */ public static void floOrder(Node root){ if (root==null){ System.out.println("空树"); } Queue<Node> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()){ Node temp = queue.poll(); System.out.printf(temp.data+" "); if (temp.leftChild!=null){ queue.offer(temp.leftChild); } if (temp.rightChild!=null){ queue.offer(temp.rightChild); } } } }
非递归实现前序遍历
前序遍历的顺序:根---左---右
对于非递归实现二叉树的前序遍历得借助栈这一数据结构,具体做法如下:
1. 创建一个栈,并将二叉树的根节点保存在栈中
2. 当栈不为空的时候,将栈顶元素取出遍历
3. 如果根结点有右子树,将右子树的根节点保存在栈中
4. 再遍历根的左子树,而左子树遍历的顺序也是先遍历根,看是否有右子树,再继续遍历左子树,按照这个顺序进行循环
5. 最后当栈取到空的时候返回
非递归实现中续遍历
中序遍历的顺序:左---根---右
实现非递归遍历借助栈这一数据结构,具体做法如下:
1. 依次将根与左子树的根节点入栈
2. 取出栈顶元素遍历
3. 访问栈顶元素的右子树
4. 栈顶元素右子树也是二叉树,所以将上述操作进行循环
非递归实现后续遍历
后续遍历顺序:左---右---根
实现非递归后续遍历也得借助栈这一数据结构,具体做法如下:
1. 第一步与中序遍历的操作相同,依次将左子树的根节点保存在栈中
2. 获取栈顶元素,如果该结点的右子树为空,则遍历该结点,否则遍历该结点的右子树
3. 右子树又是一颗二叉树,继续循环上述操作
注意:用pre标记每一次遍历的元素,这里每一次获取栈顶元素,当获取栈顶元素的右为空时或者等于标记的结点时,此时都遍历该元素,这样做目的是防止循环,导致栈溢出。