本人之前看过好多次树的非递归遍历,但是总是不久就忘记了,于是又重新的好好的理解了一下.说一下我的个人理解.
树的各种遍历其实就是自己创建一种逻辑结构,里面可能包括某种数据结构,逻辑判断.
我们就是需要让树结构在里面走一圈,出来的就是我们需要的顺序
而我把这个走一圈分为三个阶段:1.准备 2.存 3.取
准备:我们初始化我们需要的条件,比如说用到了什么容器,数据结构,以及初始化条件,以怎么样的一个条件取执行存取操作
存 :把数据放入容器中
取 :从容器中取出数据
然而存和取之间确定好他们之间的工作关系,谁先执行或者说怎么个交替工作流程.
上代码!
1.先序遍历
先序遍历:根左右
准备: 1.把根节点加入栈中,弹出就输出
加: 2.对节点先判断右,再判断左,有就加(因为栈后进先出,所以先加右后加左)
取: 3.弹出并输出元素,重复对子树进行判断.(根据之前放入的顺序,所以弹出的顺序就是先遍历左子树)
public static void pre(Node head) {
System.out.print("先序遍历:");
Stack<Node> stack = new Stack();
stack.add(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.print(head.value);
if (head.right != null) {
stack.add(head.right);
}
if (head.left != null) {
stack.add(head.left);
}
}
}
2.中序遍历
中序遍历:左根右
准备: 1.新建栈,首先拿到根节点
加: 2.把树的左边全部加入栈中,直至加入空节点
取: 3.若节点为空,弹出栈节点,直接输出,再去遍历右子树
public static void mid(Node head) {
System.out.print("中序遍历:");
Stack<Node> s = new Stack();
while (!s.empty() || head != null) {
if (head != null) {
s.push(head);
head = head.left;
} else {
head = s.pop();
System.out.print(head.value);
head = head.right;
}
}
}
3.后序遍历
后序遍历:左右根
先序是根左右,我们先实现根右左,然后过一遍栈就实现了左右根
public static void last(Node head) {
System.out.print("后序遍历:");
Stack<Node> s = new Stack();
Stack<Node> ss = new Stack();
s.add(head);
while (!s.empty()) {
head = s.pop();
ss.add(head);
if (head.left != null) {
s.add(head.left);
}
if (head.right != null) {
s.add(head.right);
}
}
while (!ss.empty()) {
System.out.print(ss.pop().value);
}
}
4.层序遍历
层序遍历:一层一层遍历
准备 1.新建队列,把根节点加入队列中
加 2.判断,有左加左,有右加右(队列先进先出)
取 3.每次加完需要操作元素,弹出栈(因为之前放入的顺序,所以遍历的顺序树先左子树,而且只遍历一层,就回去遍历上层的右子树)
public static void ceng(Node head) {
System.out.print("层序遍历:");
Queue<Node> q = new ArrayDeque<>();
q.add(head);
while (!q.isEmpty()) {
head = ((ArrayDeque<Node>) q).pop();
System.out.print(head.value);
if (head.left != null) {
q.add(head.left);
}
if (head.right != null) {
q.add(head.right);
}
}
}
最后是执行效果:
public static void main(String[] args) {
Node node7 = new Node(7);
Node node6 = new Node(6);
Node node5 = new Node(5);
Node node4 = new Node(4);
Node node3 = new Node(3,node6,node7);
Node node2 = new Node(2,node4,node5);
Node node1 = new Node(1,node2,node3);
/*
1
/ \
2 3
/ \ / \
4 5 6 7
*/
pre(node1);
//1 2 4 5 3 6 7
System.out.println();
mid(node1);
//4 2 5 1 6 3 7
System.out.println();
last(node1);
//4 5 2 6 7 3 1
System.out.println();
ceng(node1);
//1 2 3 4 5 6 7
}
千万要理解,不要背!
千万要理解,不要背!
千万要理解,不要背!
如果理解不了可以自己在纸上画,模拟压栈出栈等操作,再走上两个测试用例,理解就好记了.