《原神攻略》高配四風速切隊玩法講解
阿新 • • 發佈:2021-08-03
一、遞迴方式遍歷
遞迴方法完成二叉樹的遍歷,每一個節點都能回去3次(雖然某一次回去的時候什麼也沒幹)
在遞迴序的基礎上,選擇列印的時機不同可演變出前序、中序、後續三種遍歷方式
前序-列印遞迴遍歷時第1次出現的數字(頭左右):1,2,4,5,3,6,7
中序-列印遞迴遍歷時第2次出現的數字(左頭右):4,2,5,1,6,3,7
後續-列印遞迴遍歷時第3次出現的數字(左右頭):4,5,2,6,7,3,1
public static void preOrderRecur(Node head) { if (head == null) { return前序遞迴遍歷; } System.out.print(head.value + " "); //此位置為前序遞迴 preOrderRecur(head.left); //System.out.print(head.value + " "); //此位置為中序遞迴 preOrderRecur(head.right); //System.out.print(head.value + " "); //此位置為後序遞迴 }
二、非遞迴方式遍歷
1、前序遍歷
先把頭節點放入棧中
1)每次在棧中彈出一個節點,記為cur
2)列印(處理)cur
3)如有cur有左右孩子(沒有孩子就不操作,繼續步驟1),先把cur右孩子壓棧,再把cur左孩子壓棧
4)迴圈以上三步操作
//前序非遞迴 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()) { //只要棧不是空的,迴圈3個步驟 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(); }
2、後續遍歷
由前序遍歷進行改進而來:
準備兩棧(多一個收集棧),先把頭節點放入正常棧中
1)每次在正常棧中彈出一個節點,記為cur
2)把cur放入一個收集棧中
3)如有cur有左右孩子(沒有孩子就不操作,繼續步驟1),先把cur左孩子壓入正常棧,再把cur右孩子壓正常棧
迴圈以上三步操作
4)再把收集棧中的元素依次彈出就是後續遍歷結果
//後序非遞迴 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()) { //迴圈1/2/3 head = s1.pop(); //1、每次彈出一個元素 s2.push(head); //2、彈出之後不列印,而是放入收集棧中 if (head.left != null) { s1.push(head.left); //3、先壓左節點 } if (head.right != null) { s1.push(head.right); //3、再壓右節點 } } while (!s2.isEmpty()) { System.out.print(s2.pop().value + " "); //4、最後把收集棧中的元素彈出進行列印 } } }後續非遞迴遍歷
3、中序遍歷
1)把當前節點的所有左節點壓棧
2)依次彈出節點的過程中,列印
3)每彈出一個節點,把目標移到彈出節點的右節點上面
迴圈以上三個操作
//中序非遞迴 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) { if (head != null) { //1、把當前節點所有的左節點壓棧 stack.push(head); head = head.left; } else { //所有左節點壓棧之後 head = stack.pop(); //2、彈出一個節點,列印 System.out.print(head.value + " "); head = head.right; //3、然後移動到彈出節點的右節點上面,迴圈以上步驟 } } } }中序非遞迴遍歷
為什麼進行以上三步操作就能實現前中後的中序遍歷?
整體程式碼
package Algorithms; /** * @author : zhang * @version : 1.0 * @date : Create in 2021/8/11 * @description : */ import java.util.Stack; public class 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()) { //只要棧不是空的,迴圈3個步驟 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) { if (head != null) { //1、把當前節點所有的左節點壓棧 stack.push(head); head = head.left; } else { //所有左節點壓棧之後 head = stack.pop(); //2、彈出一個節點,列印 System.out.print(head.value + " "); head = head.right; //3、然後移動到彈出節點的右節點上面,迴圈以上步驟 } } } } //後序非遞迴 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()) { //迴圈1/2/3 head = s1.pop(); //1、每次彈出一個元素 s2.push(head); //2、彈出之後不列印,而是放入收集棧中 if (head.left != null) { s1.push(head.left); //3、先壓左節點 } if (head.right != null) { s1.push(head.right); //3、再壓右節點 } } while (!s2.isEmpty()) { System.out.print(s2.pop().value + " "); //4、最後把收集棧中的元素彈出進行列印 } } 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(); } public static void main(String[] args) { Node head = new Node(1); head.left = new Node(2); head.right = new Node(3); head.left.left = new Node(4); head.left.right = new Node(5); head.right.left = new Node(6); head.right.right = new Node(7); // recursive System.out.println("==============recursive=============="); System.out.print("pre-order: "); preOrderRecur(head); System.out.println(); System.out.print("in-order: "); inOrderRecur(head); System.out.println(); System.out.print("pos-order: "); posOrderRecur(head); System.out.println(); // unrecursive System.out.println("============unrecursive============="); preOrderUnRecur(head); inOrderUnRecur(head); posOrderUnRecur1(head); posOrderUnRecur2(head); } } /** * ==============recursive============== * pre-order: 1 2 4 5 3 6 7 * in-order: 4 2 5 1 6 3 7 * pos-order: 4 5 2 6 7 3 1 * ============unrecursive============= * pre-order: 1 2 4 5 3 6 7 * in-order: 4 2 5 1 6 3 7 * pos-order: 4 5 2 6 7 3 1 * pos-order: 4 5 2 6 7 3 1 */