二叉樹的遍歷(Java實現)
列舉了二叉樹的前序、中序、後序的遞迴和非遞迴遍歷方法,以及層次遍歷、分層輸出的層次遍歷方法。
舉例如下:
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
//構造樹結構測試用
TreeNode a = new TreeNode(1);
TreeNode b = new TreeNode(2);
TreeNode c = new TreeNode(3);
TreeNode d = new TreeNode(4);
TreeNode e = new TreeNode(5);
TreeNode f = new TreeNode(6);
TreeNode g = new TreeNode(7);
a.left = b;
a.right = c;
b.right = d;
c.left = e;
c.right = f;
f.left = g;
System.out .print("recursivePreOrder: ");
recursivePreOrder(a);
System.out.print('\n' + "recursiveInOrder: ");
recursiveInOrder(a);
System.out.print('\n' + "recursivePostOrder: ");
recursivePostOrder(a);
System.out.print('\n' + "iterativePreOrder: ");
iterativePreOrder(a);
System.out .print('\n' + "iterativePreOrder_2: ");
iterativePreOrder_2(a);
System.out.print('\n' + "iterativeInOrder: ");
iterativeInOrder(a);
System.out.print('\n' + "iterativePostOrder: ");
iterativePostOrder(a);
System.out.print('\n' + "iterativePostOrder_2: ");
iterativePostOrder_2(a);
System.out.print('\n' + "iterativePostOrder_3: ");
iterativePostOrder_3(a);
System.out.print('\n' + "iterativeLevelOrder: ");
iterativeLevelOrder(a);
System.out.print('\n' + "iterativeLevelOrder_2: " + '\n');
iterativeLevelOrder_2(a);
System.out.print('\n' + "recursiveLevelOrder: ");
recurLevelOrder(a);
System.out.print('\n' + "recursiveLevelOrderBottom: " + '\n');
List<List<Integer>> lists = recursiveLevelOrderBottom(a);
for (List<Integer> list : lists) {
for (int p : list) {
System.out.print(p + " ");
}
System.out.println();
}
}
public static void visit(TreeNode p) {
System.out.print(p.val + " ");
}
//**********遞迴的先序遍歷**********
public static void recursivePreOrder(TreeNode p) {
if (p == null) return;
visit(p);
recursivePreOrder(p.left);
recursivePreOrder(p.right);
}
//**********遞迴的中序遍歷**********
public static void recursiveInOrder(TreeNode p) {
if (p == null) return;
recursiveInOrder(p.left);
visit(p);
recursiveInOrder(p.right);
}
//**********遞迴的後序遍歷**********
public static void recursivePostOrder(TreeNode p) {
if (p == null) return;
recursivePostOrder(p.left);
recursivePostOrder(p.right);
visit(p);
}
//**********非遞迴的先序遍歷**********
//手算的思想,先變訪問邊找,找到最左下方的,然後向上再向訪問右邊的
public static void iterativePreOrder(TreeNode p) {
if (p == null) return;
Stack<TreeNode> stack = new Stack<TreeNode>();
while (!stack.empty() || p != null) {
while (p != null) {
visit(p);
stack.push(p);
p = p.left;
}
p = stack.pop();
p = p.right;
}
}
//**********非遞迴的先序遍歷**********
//棧的思想,按層次倒著進棧,利用後進先出解決順序問題
public static void iterativePreOrder_2(TreeNode p) {
if (p == null) return;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(p);
while (!stack.empty()) {
p = stack.pop();
visit(p);
if (p.right != null) stack.push(p.right);
if (p.left != null) stack.push(p.left);
}
}
//**********非遞迴的中序遍歷**********
public static void iterativeInOrder(TreeNode p) {
if (p == null) return;
Stack<TreeNode> stack = new Stack<TreeNode>();
while (!stack.empty() || p != null) {
while (p != null) {
stack.push(p);
p = p.left;
}
p = stack.pop();
visit(p);
p = p.right;
}
}
//**********非遞迴的後序遍歷**********
//注意prev的作用
public static void iterativePostOrder(TreeNode p) {
if (p == null) return;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode prev = p;
while (!stack.empty() || p != null) {
while (p != null) {
stack.push(p);
p = p.left;
}
p = stack.peek().right;
if (p == null || p == prev) {
//若棧頂節點的右節點為空或者已經visit過,則按順序應該訪問棧頂節點
p = stack.pop();
visit(p);
//prev用來標記已經visit過這個節點
prev = p;
p = null;
}
}
}
//**********非遞迴的後序遍歷**********
//和上一種方法思想類似
public static void iterativePostOrder_2(TreeNode p) {
if (p == null) return;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode prev = p;
while (p != null) {
while (p.left != null) {
stack.push(p);
p = p.left;
}
while (p != null && (p.right == null || p.right == prev)) {
visit(p);
prev = p;
if (stack.empty()) return;
p = stack.pop();
}
stack.push(p);
p = p.right;
}
}
//**********非遞迴的後序遍歷**********
//雙棧法,易於理解
public static void iterativePostOrder_3(TreeNode p) {
if (p == null) return;
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<TreeNode> result = new Stack<TreeNode>();
while (!stack.empty() || p != null) {
while (p != null) {
stack.push(p);
result.push(p);
p = p.right;
}
if (!stack.empty()) p = stack.pop().left;
}
while (!result.empty()) {
p = result.pop();
visit(p);
}
}
//**********非遞迴的層次遍歷**********
public static void iterativeLevelOrder(TreeNode p) {
if (p == null) return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(p);
while (!queue.isEmpty()) {
p = queue.poll();
if (p.left != null) queue.offer(p.left);
if (p.right != null) queue.offer(p.right);
visit(p);
}
}
//**********非遞迴的分層輸出的層次遍歷**********
public static void iterativeLevelOrder_1(TreeNode p) {
if (p == null) return;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(p);
while (!queue.isEmpty()) {
int levelNum = queue.size();
for (int i = 0; i < levelNum; i++) {
p = queue.poll();
if (p.left != null) queue.offer(p.left);
if (p.right != null) queue.offer(p.right);
visit(p);
}
System.out.println();
}
}
//**********非遞迴的分層輸出的層次遍歷**********
//維護兩個int,代表上一層和下一層的節點數量,上一層遍歷結束之後lineUp = lineDown; lineDown = 0;
public static void iterativeLevelOrder_2(TreeNode p) {
if (p == null) return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
int lineUp = 1, lineDown = 0;
queue.offer(p);
while (!queue.isEmpty()) {
p = queue.poll();
visit(p);
if (p.left != null){
queue.offer(p.left);
lineDown++;
}
if (p.right != null){
queue.offer(p.right);
lineDown++;
}
if (--lineUp == 0) {
lineUp = lineDown;
lineDown = 0;
System.out.println();
}
}
}
//**********遞迴的層次遍歷訪問**********
public static void recurLevelOrder(TreeNode root) {
if (root == null) return;
int depth = maxDepth(root);
//如果要倒序訪問只需修改此處順序
for (int i = 1; i <= depth; i++) visitNodeAtDepth(root, i);
}
//訪問特定層的節點
public static void visitNodeAtDepth(TreeNode p, int depth) {
if (p == null || depth < 1) return;
//因為要按順序訪問(列印),所以要規定必須到某一層才能visit
if (depth == 1) {
visit(p);
return;
}
//每次都要遍歷depth之上的所有層
visitNodeAtDepth(p.left, depth - 1);
visitNodeAtDepth(p.right, depth - 1);
}
//得到樹的層數
public static int maxDepth(TreeNode root) {
if (root == null) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
//**********遞迴的倒序層次遍歷並儲存結果至list**********
//LeetCode107
//之所以用LinkedList是因為有addFirst()方法,可以逆序儲存
public static List<List<Integer>> recursiveLevelOrderBottom(TreeNode root) {
LinkedList<List<Integer>> lists = new LinkedList<List<Integer>>();
addToList(lists, root, 1);
return lists;
}
//將depth層的p節點儲存至list
public static void addToList(LinkedList<List<Integer>> lists, TreeNode p, int depth) {
if (p == null) return;
if (lists.size() < depth) lists.addFirst(new LinkedList<Integer>());
//由於不用輸出只是儲存,可以使用get控制儲存在哪一層,所以不用規定層數
lists.get(lists.size() - depth).add(p.val);
addToList(lists, p.left, depth + 1);
addToList(lists, p.right, depth + 1);
}
}
執行結果:
recursivePreOrder: 1 2 4 3 5 6 7
recursiveInOrder: 2 4 1 5 3 7 6
recursivePostOrder: 4 2 5 7 6 3 1
iterativePreOrder: 1 2 4 3 5 6 7
iterativePreOrder_2: 1 2 4 3 5 6 7
iterativeInOrder: 2 4 1 5 3 7 6
iterativePostOrder: 4 2 5 7 6 3 1
iterativePostOrder_2: 4 2 5 7 6 3 1
iterativePostOrder_3: 4 2 5 7 6 3 1
iterativeLevelOrder: 1 2 3 4 5 6 7
iterativeLevelOrder_2:
1
2 3
4 5 6
7
recursiveLevelOrder: 1 2 3 4 5 6 7
recursiveLevelOrderBottom:
7
4 5 6
2 3
1
相關推薦
二叉樹遍歷(C++實現)
二叉樹3種深度優先遍歷(遞迴、非遞迴)、層次遍歷,最簡潔、最好記! #include<iostream> #include<stack> #include<queue> using namespace std; //節點定義 struct Node { c
zcmu 4931 二叉樹遍歷(資料結構)
【題目】 二叉樹遍歷 【程式碼】 #include <cstdio> #include <cstdlib> #include <cstring> #inc
二叉樹遍歷(前序)(遞迴+非遞迴)
題目 Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes’ values. For example: Given binary
二叉樹遍歷(中序)(遞迴+非遞迴)
Binary Tree Inorder Traversal(二叉樹中序遍歷) Given a binary tree, return the inorder traversal of its nodes’ values. For example: Given binary tree{
【程式設計3】二叉樹遍歷(LeetCode.102)
文章目錄 一、二叉樹的層次遍歷 1、題目描述——LeetCode.102 2、分析 3、實現 二、二叉樹(Binary Tree) 1、相關概念
二叉樹的深度(Java實現)
本題為劍指offer面試題39 牛客網測試地址:https://www.nowcoder.com/questionTerminal/435fb86331474282a3499955f0a41e8b
【演算法】二叉樹遍歷(層序)
1.問題描述: 層序遍歷二叉樹; 2.分析: 用佇列實現,首先將頭節點加入佇列;如果佇列不為空,則執行如下操作:從佇列中取出元素輸出,若該元素的子節點不為空,則將其加入佇列。 3.程式碼實現: void levelSort(TreeNode * pHead)
資料結構-二叉樹的遍歷(Java實現)
二叉樹介紹 二叉樹的概念:一棵二叉樹是節點的一個有限集合,該集合或者為空,或者由一個根節點加上兩棵左子樹和右子樹組成 二叉樹具有如下特點: 1、每個結點最多有兩棵子樹,結點的度最大為2。 2、左子樹和右子樹是有順序的,次序不能顛倒。 3、即使某結點只有
二叉樹系列--層序遍歷(java實現)
記錄兩道題目: 第一題:計算二叉樹的深度,兩行遞迴即可搞定。 public static int level(Node root) { if (root == null) return 0; return level(root.left) + 1 > l
二叉樹的遍歷(Java實現)
列舉了二叉樹的前序、中序、後序的遞迴和非遞迴遍歷方法,以及層次遍歷、分層輸出的層次遍歷方法。 舉例如下: import java.util.LinkedList; import java.util.List; import java.util.Que
二叉樹的前序遍歷,中序遍歷,後序遍歷(Java實現)
1.前序遍歷 前序遍歷(DLR,lchild,data,rchild),是二叉樹遍歷的一種,也叫做先根遍歷、先序遍歷、前序周遊,可記做根左右。前序遍歷首先訪問根結點然後遍歷左子樹,最後遍歷右子樹。前序遍歷首先訪問根結點然後遍歷左子樹,最後遍歷右子樹。在遍歷左、右子樹時,
二叉樹遍歷的python實現(前序、中序、後序)
實現二叉樹的三種遍歷方式,未完善二叉樹的生成、樹的程式遍歷等,本程式僅做記錄,程式中構造的二叉樹結構如下: # -*- coding: utf-8 -*- """ Created on Thu Sep 13 16:46:46 2018 Description:二叉樹
二叉樹遍歷(四種方式、迭代及遞迴的實現)
二叉樹的常見遍歷方式主要有前序,中序和後序,以及層次遍歷(從上到下,從左到右)四種方法。 前、中、後遍歷分別順序如下: 分別通過遞迴和迴圈的方式實現(Python): # -*- coding:utf-8 -*- class TreeNode: def __
二叉樹遍歷遞迴實現(前中後與層序遍歷)
#include <iostream> #include <bits/stdc++.h> using namespace std; const int MA=100; template<class T> struct ThrBiNode {
非遞迴實現二叉樹遍歷(前/中/後序)
//基本資料結構 template<class T> struct BinaryTreeNode { T _data; BinaryTreeNode<T>* _left;
非遞迴實現二叉樹遍歷(附c++完整程式碼)
先序、中序和後序遍歷過程:遍歷過程中經過結點的路線一樣,只是訪問各結點的時機不同。 從圖中可以看到,前序遍歷在第一次遇見元素時輸出,中序遍歷在第二次遇見元素時輸出,後序遍歷在第三次遇見元素時輸出。 非遞迴演算法實現的基本思路:使用堆疊 一、前序遍歷 1、遞迴實
數據結構之中序遍歷轉興許遍歷(JAVA實現)(二)
百度 empty 表達 pty 中序 tor opera lin sem 算法流程: 主要分為四步: 1.當前字符為數字或者字母,則直接輸出 2.當前字符為)。則在棧中匹配輸出。一直匹配到),則停止輸出(就是將)及其
二叉樹遍歷(王道)
中序 數組 har 不為 位置 mem 一行 遍歷 uil 題目描述: 二叉樹的前序、中序、後序遍歷的定義:前序遍歷:對任一子樹,先訪問跟,然後遍歷其左子樹,最後遍歷其右子樹;中序遍歷:對任一子樹,先遍歷其左子樹,然後訪問根,最後遍歷其右子樹;後序遍歷:對任一子樹,先遍歷其
二叉樹遍歷(迴圈和遞迴)
遞迴 1.前序遍歷 void preorder(BinTree *T) { if(T==NULL) return; cout << T->data; preorder(T->left); preorder(T->rig
二叉樹遍歷(前序、中序、後序) UVA 548 Tree
今天覆習前面的內容的時候看到一道題UVA 548 Tree,說的是輸入一個二叉樹中序和後序的集合,沿著二叉樹的一條邊走,問葉子為多少的這條路最短。 看到這道題,中序?後序?什麼玩意???不知道,百度!查了之後會了,就回來A了這題。 先給一個二叉樹 二叉樹前序遍歷