完整代码见git仓库:https://github.com/wangshen2016/Algorithm
树结构如下:
static class Node{
public int value;
public Node lchild = null;
public Node rchild = null;
public Node(int value) {
this.value = value;
}
public Node(int value, Node lchild, Node rchild) {
this.value = value;
this.lchild = lchild;
this.rchild = rchild;
}
}
1. 先序遍历
出栈顺序:头左右
- 准备一个栈
- 先压头节点
- 弹栈打印
- 如果有右孩子,压入右孩子
- 如果有左孩子,压入左孩子
递归
public static void pre(Node head) {
if (head == null) {
return;
}
System.out.print(head.value + " ");
pre(head.lchild);
pre(head.rchild);
}
非递归
public static void pre2(Node head) {
if (head == null) {
return;
}
Deque<Node> stack = new ArrayDeque<>();
stack.push(head);
while (!stack.isEmpty()) {
Node pop = stack.pop();
System.out.print(pop.value + " ");
if (pop.rchild != null) {
stack.push(pop.rchild);
}
if (pop.lchild != null) {
stack.push(pop.lchild);
}
}
}
2. 后序遍历
方案一:使用两个栈
出栈顺序:头右左,然后倒过来就是后序遍历
- 准备一个栈
- 先压头节点
- 弹栈并压入另一个栈
- 如果有左孩子,压入左孩子
- 如果有右孩子,压入右孩子
- 最后依次弹出第二个栈并打印
方案二:使用一个栈
使用两个指针h,c。h记录上一次打印的节点,c记录栈顶元素
- 头节点入栈
- c记录栈顶元素
- if:如果c有左孩子且上一次打印的节点不是c的左右孩子,那么c的左孩子入栈,继续2;
else if:如果c有右孩子,且上一次打印的不是c的右孩子,那么c的右孩子入栈,继续2;
else:弹出栈顶元素并打印,h记录打印的元素
递归
public static void post(Node head) {
if (head == null) {
return;
}
post(head.lchild);
post(head.rchild);
System.out.print(head.value + " ");
}
非递归方案一
public static void post2(Node head) {
if (head == null) {
return;
}
Deque<Node> stack = new ArrayDeque<>();
Deque<Node> stack2 = new ArrayDeque<>();
stack.push(head);
while (!stack.isEmpty()) {
Node pop = stack.pop();
stack2.push(pop);
if (pop.lchild != null) {
stack.push(pop.lchild);
}
if (pop.rchild != null) {
stack.push(pop.rchild);
}
}
while (!stack2.isEmpty()) {
System.out.print(stack2.pop().value + " ");
}
}
非递归方案2
public static void post3(Node h) {
if (h == null) {
return;
}
Deque<Node> stack = new ArrayDeque<>();
Node c = null;
stack.push(h);
while (!stack.isEmpty()) {
c = stack.peek();
if (c.lchild != null && h != c.lchild && h != c.rchild) {
stack.push(c.lchild);
} else if (c.rchild != null && h != c.rchild) {
stack.push(c.rchild);
} else {
Node pop = stack.pop();
System.out.print(pop.value + " ");
h = pop;
}
}
}
3. 中序遍历
- 准备一个栈
- 将整条左子树依次入栈
- 如果左孩子为空,弹栈打印,并将当前节点指向其右孩子,继续到第2步执行
递归
public static void in(Node head) {
if (head == null) {
return;
}
in(head.lchild);
System.out.print(head.value + " ");
in(head.rchild);
}
非递归
public static void in2(Node head) {
if (head != null) {
Deque<Node> stack = new ArrayDeque<>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.lchild;
} else {
head = stack.pop();
System.out.print(head.value + " ");
head = head.rchild;
}
}
}
}
4. 测试代码
public static void main(String[] args) {
Node n1 = new Node(8);
Node n2 = new Node(5);
Node n3 = new Node(4);
Node n4 = new Node(2);
Node n5 = new Node(3);
Node n6 = new Node(1);
Node n7 = new Node(6);
Node n8 = new Node(9);
Node n9 = new Node(7);
Node n10 = new Node(0);
n1.lchild = n2;
n1.rchild = n3;
n2.lchild = n4;
n2.rchild = n5;
n3.rchild = n7;
n5.lchild = n6;
n7.lchild = n8;
n8.lchild = n9;
n8.rchild = n10;
pre(n1);
System.out.println();
pre2(n1);
System.out.println();
in(n1);
System.out.println();
in2(n1);
System.out.println();
post(n1);
System.out.println();
post2(n1);
System.out.println();
post3(n1);
}