二叉樹的先序遍歷:
1:訪問根節點
2:訪問左子樹
3:訪問右子樹
二叉樹的中序遍歷:
1:中序遍歷左子樹
2:訪問根節點
3:中序遍歷右子樹
二叉樹的後序遍歷:
1:後序遍歷左子樹
2:後序遍歷右子樹
3:訪問根節點
使用遞歸的方式來實現二叉樹的幾種遍歷:
public class Code_01_PreInPosTraversal {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static void preOrderRecur(Node head) { //遞歸的方式 先序遍歷
if (head == null) {
return;
}
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
public static void inOrderRecur(Node head) { // 遞歸的方式 中序遍歷
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
public static void posOrderRecur(Node head) { //遞歸的方式 後序遍歷
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.print(head.value + " ");
}
這裏的return返回是此函數的結束處,相應的變量的參數也會返回到上一層的參數處,覆蓋原來的參數,繼續此函數之後未完成的函數動作,如果此函數執行完則跳出此層遞歸,繼續返回上次未完成的函數處(遞歸調用處)。
理解一下遞歸的實質:
使用非遞歸的方法:
注意return:return的時候代表這個子函數已經執行完畢了,使用再執行的是下一個棧元素
import java.util.Stack;
public class Code_01_PreInPosTraversal {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static void preOrderRecur(Node head) { //遞歸的方式 先序遍歷
if (head == null) {
return;
}
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
public static void inOrderRecur(Node head) { // 遞歸的方式 中序遍歷
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
public static void posOrderRecur(Node head) { //遞歸的方式 後序遍歷
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.print(head.value + " ");
}
public static void preOrderUnRecur(Node head) { //先序遍歷 非遞歸
System.out.print("pre-order: ");
if (head != null) {
Stack<Node> stack = new Stack<Node>();
stack.add(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.print(head.value + " ");
if (head.right != null) { //先序遍歷要先把右邊的壓入棧中
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
System.out.println();
}
public static void inOrderUnRecur(Node head) { //中序遍歷 非遞歸
System.out.print("in-order: ");
if (head != null) {
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || head != null) { //這個條件是當head在最高的節點時和head的左邊爲空時這個邊界
if (head != null) { //把左邊的節點依次壓入棧中
stack.push(head);
head = head.left;
} else {
head = stack.pop(); //左邊已經爲空了,彈出,看右邊有沒有節點
System.out.print(head.value + " ");
head = head.right;
}
}
}
System.out.println();
}
public static void posOrderUnRecur1(Node head) { //後序遍歷 非遞歸 使用兩個棧
System.out.print("pos-order: ");
if (head != null) {
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();//用來存放按後序排序好的二叉樹
s1.push(head);
while (!s1.isEmpty()) {
head = s1.pop();
s2.push(head);
if (head.left != null) {
s1.push(head.left); //放到棧S2時剛好左子樹的在右子樹的上面
}
if (head.right != null) {
s1.push(head.right);
}
}
while (!s2.isEmpty()) {
System.out.print(s2.pop().value + " ");
}
}
System.out.println();
}
public static void posOrderUnRecur2(Node h) { //使用一個棧
System.out.print("pos-order: ");
if (h != null) {
Stack<Node> stack = new Stack<Node>();
stack.push(h);
Node c = null;
while (!stack.isEmpty()) {
c = stack.peek();//取出但不銷燬,還是在原來的棧中
if (c.left != null && h != c.left && h != c.right) {
stack.push(c.left);
} else if (c.right != null && h != c.right) { //防止一個節點被壓入兩次
stack.push(c.right);
} else {
System.out.print(stack.pop().value + " ");
h = c;
}
}
}
System.out.println();
}
自己好好理解非遞歸,再自己敲一遍。