二叉树的六种遍历
Node:
package com.test.node;
/**
* @author :wdl
* @date :Created in 2021-12-06 14:31
* @description:模拟二叉树节点
*/
public class Node {
private int value; //节点的值
private Node node; //此节点,数据类型为Node
private Node left; //此节点的左子节点,数据类型为Node
private Node right; //此节点的右子节点,数据类型为Node
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getNode() {
return node;
}
public void setNode(Node node) {
this.node = node;
}
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;
}
public Node(int value) {
this.value=value;
this.left=null;
this.right=null;
}
public String toString() { //自定义的toString方法,为了方便之后的输出
return this.value+" ";
}
}
java - Test:
package com.test.node;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
/**
* @author :wdl
* @date :Created in 2021-12-06 14:32
* @description:测试
*/
public class Test {
public static void main(String[] args) {
int[] ints = {0,1,2,3,4,5,6,7,8,9};
ArrayList<Node> nodes = new ArrayList<>();
create(ints,nodes);
Node node = nodes.get(0);
System.out.println("数组转二叉树");
print(node);
System.out.println("");
System.out.println("递归前序遍历");
preTraversal(node);
System.out.println("");System.out.println("");
System.out.println("递归中序遍历");
midTraversal(node);
System.out.println("");System.out.println("");
System.out.println("递归后序遍历");
postTraversal(node);
System.out.println("");System.out.println("");
System.out.println("非递归前序遍历");
preOrderTraversalbyLoop(node);
System.out.println("");System.out.println("");
System.out.println("非递归中序遍历");
inOrderTraversalbyLoop(node);
System.out.println("");System.out.println("");
System.out.println("非递归后序遍历");
postOrderTraversalbyLoop(node);
System.out.println("");System.out.println("");
System.out.println("广度优先遍历");
bfs(node);
System.out.println("");System.out.println("");
System.out.println("深度度优先遍历");
List<Integer> intArr = new ArrayList<>();
List<Integer> intArr2 = new ArrayList<>();
List<List<Integer>> intArrs = new ArrayList<>();
intArrs.add(intArr);
dfs(node,intArrs, intArr2);
System.out.println(intArrs);
}
public static void print(Node... node){
ArrayList<Node> nodes = new ArrayList<Node>();
for (Node node1 : node) {
System.out.print(node1.getValue()+" ");
Node left = node1.getLeft();
Node right = node1.getRight();
if(left != null) nodes.add(left);
if(right != null) nodes.add(right);
}
System.out.println("");
if(nodes.size()>0){
print(nodes.toArray(new Node[]{}));
}
}
/**
* 数组升华二叉树
* @param datas
* @param list
*/
public static void create(int[] datas, List<Node> list) {
//将数组里面的东西变成节点的形式
for(int i=0;i<datas.length;i++) {
Node node=new Node(datas[i]);
list.add(node);
}
//节点关联成树
for(int index=0;index<list.size()/2-1;index++) {
list.get(index).setLeft(list.get(index*2+1));
//编号为n的节点他的左子节点编号为2*n 右子节点编号为2*n+1 但是因为list从0开始编号,所以还要+1
list.get(index).setRight(list.get(index*2+2)); //与上同理
}
//单独处理最后一个父节点 ,list.size()/2-1进行设置,避免单孩子情况
int index=list.size()/2-1;
list.get(index).setLeft(list.get(index*2+1));
if(list.size()%2==1)
//如果有奇数个节点,最后一个父节点才有右子节点
list.get(index).setRight(list.get(index*2+2));
}
/**
* 递归前序遍历
* @param node
*/
public static void preTraversal(Node node){
if (node == null) //很重要,必须加上 当遇到叶子节点用来停止向下遍历
return;
System.out.print(node.getValue()+" ");
preTraversal(node.getLeft());
preTraversal(node.getRight());
}
/**
* 递归中序遍历
* @param node
*/
public static void midTraversal(Node node){
if (node == null)
return;
midTraversal(node.getLeft());
System.out.print(node.getValue()+" ");
midTraversal(node.getRight());
}
/**
* 递归后序遍历
* @param node
*/
public static void postTraversal(Node node){
if (node == null)
return;
postTraversal(node.getLeft());
postTraversal(node.getRight());
System.out.print(node.getValue()+" ");
}
/**
* 非递归前序遍历
* @param node
*/
public static void preOrderTraversalbyLoop(Node node){
Stack<Node> stack = new Stack();
Node p = node;
while(p!=null || !stack.isEmpty()){
while(p!=null){
//当p不为空时,就读取p的值,并不断更新p为其左子节点,即不断读取左子节点
System.out.print(p.getValue()+" ");
stack.push(p); //将p入栈
p = p.getLeft();
}
if(!stack.isEmpty()){
p = stack.pop();
p = p.getRight();
}
}
}
/**
* 非递归中序遍历
* @param node
*/
public static void inOrderTraversalbyLoop(Node node){
Stack<Node> stack = new Stack();
Node p = node;
while(p!=null || !stack.isEmpty()){
while(p!=null){
stack.push(p);
p = p.getLeft();
}
if(!stack.isEmpty()){
p = stack.pop();
System.out.print(p.getValue()+" ");
p = p.getRight();
}
}
}
/**
* 非递归后序遍历
* @param node
*/
public static void postOrderTraversalbyLoop(Node node){
Stack<Node> stack = new Stack<Node>();
Node p = node, prev = node;
while(p!=null || !stack.isEmpty()){
while(p!=null){
stack.push(p);
p = p.getLeft();
}
if(!stack.isEmpty()){
Node temp = stack.peek().getRight();
//只是拿出来栈顶这个值,并没有进行删除
if(temp == null||temp == prev){
//节点没有右子节点或者到达根节点【考虑到最后一种情况】
p = stack.pop();
System.out.print(p.getValue()+" ");
prev = p;
p = null;
}
else{
p = temp;
}
}
}
}
/**
* 广度优先遍历
* @param root
*/
public static void bfs(Node root){
if(root == null) return;
LinkedList<Node> queue = new LinkedList<Node>();
queue.offer(root); //首先将根节点存入队列
//当队列里有值时,每次取出队首的node打印,打印之后判断node是否有子节点,若有,则将子节点加入队列
while(queue.size() > 0){
Node node = queue.peek();
queue.poll();//取出队首元素并打印
System.out.print(node.getValue()+" ");
if(node.getLeft() != null){ //如果有左子节点,则将其存入队列
queue.offer(node.getLeft());
}
if(node.getRight() != null){ //如果有右子节点,则将其存入队列
queue.offer(node.getRight());
}
}
}
/**
* 深度优先遍历
*/
public static void dfs(Node node,List<List<Integer>> rst,List<Integer> list){
if(node == null) return;
if(node.getLeft() == null && node.getRight() == null){
list.add(node.getValue());
/* 这里将list存入rst中时,不能直接将list存入,而是通过新建一个list来实现,
* 因为如果直接用list的话,后面remove的时候也会将其最后一个存的节点删掉
* */
rst.add(new ArrayList<>(list));
list.remove(list.size()-1);
}
list.add(node.getValue());
dfs(node.getLeft(),rst,list);
dfs(node.getRight(),rst,list);
list.remove(list.size()-1);
}
}
Result:
数组转二叉树
0
1 2
3 4 5 6
7 8 9
递归前序遍历
0 1 3 7 8 4 9 2 5 6
递归中序遍历
7 3 8 1 9 4 0 5 2 6
递归后序遍历
7 8 3 9 4 1 5 6 2 0
非递归前序遍历
0 1 3 7 8 4 9 2 5 6
非递归中序遍历
7 3 8 1 9 4 0 5 2 6
非递归后序遍历
7 8 3 9 4 1 5 6 2 0
广度优先遍历
0 1 2 3 4 5 6 7 8 9
深度度优先遍历
[[], [0, 1, 3, 7], [0, 1, 3, 8], [0, 1, 4, 9], [0, 2, 5], [0, 2, 6]]