二叉樹1:實現二叉樹的先序、中序、後序遍歷,包括遞歸方式和非遞歸方式

二叉樹的先序遍歷:
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();
	}

自己好好理解非遞歸,再自己敲一遍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章