1. 程式人生 > >按層次生成、遍歷二叉樹

按層次生成、遍歷二叉樹

對於二叉樹一般是按深度生成和遍歷,比如使用遞迴方法進行先序遍歷、中序遍歷、後序遍歷。這次我們按層次生成和遍歷二叉樹。

這種遍歷方式關鍵在於需要使用一個佇列儲存“已處理該節點,但還沒處理它的子節點”這樣的節點。

# Python程式碼

# Definition for singly-linked list.
class BinTree(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object)
:
# 按層次建立二叉樹 def createBinTree(self, inputList): # 尚未設定子節點的節點列表 nodeList = [] if (inputList == None) or (len(inputList) == 0): return None # 取出根元素 value = inputList.pop(0) root = BinTree(value) nodeList.append(root) # 結束條件:所有值不為“#”的節點都設定了子節點,即nodeList為空
while len(nodeList) != 0: leftValue = inputList.pop(0) rightValue = inputList.pop(0) if leftValue != '#' and rightValue != '#': nodeLeft = BinTree(leftValue) nodeRight = BinTree(rightValue) # 每次取出兩個節點,加入到 “未設定子節點的節點列表”
nodeList.append(nodeLeft) nodeList.append(nodeRight) nodeList[0].left = nodeLeft nodeList[0].right = nodeRight # 為節點設定子節點後移出佇列 nodeList.pop(0) # 若值為#,不需要處理,預設情況下節點的左右節點都為None elif leftValue == '#' and rightValue != '#': nodeRight = BinTree(rightValue) nodeList.append(nodeRight) nodeList[0].right = nodeRight nodeList.pop(0) elif rightValue == '#' and leftValue != '#': nodeLeft = BinTree(leftValue) nodeList.append(nodeLeft) nodeList[0].left = nodeLeft nodeList.pop(0) else: nodeList.pop(0) return root # 按層次遍歷二叉樹 def traverseBinTree(self, root): nodeList = [] # 先將根節點加入佇列中 if root != None: nodeList.append(root) while len(nodeList) != 0: # 輸出佇列第一個節點值,並將該節點的左右子節點加入佇列 node = nodeList.pop(0) if node == None: print('#') continue print(node.val) leftNode = node.left rightNode = node.right nodeList.append(leftNode) nodeList.append(rightNode) s = Solution() root = s.createBinTree(inputList = ['A', 'B', 'C', '#', 'D', '#', 'E', 'F', '#', '#', '#', '#', '#']) s.traverseBinTree(root)



再進一步,不僅要按層次遍歷二叉樹,還要將每一層分別放在一個列表中。[ [3], [9,20], [15,7] ],實現這個要求重點在於確定何時一層遍歷完成。每層二叉樹的節點數目(含null節點)為上一層不含null節點的數目 * 2。可以採用兩個變數,記錄本層應該有多少個節點、和已經遍歷到多少個節點。二者相等時,本層節點遍歷結束。

// Java程式碼

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> resultList = new ArrayList<>();

        // 記錄待遍歷的節點,每次取出隊首元素,並將其子節點(如果有)新增到佇列中。
        // 當nodeList為空時,所有節點遍歷結束
        List<TreeNode> nodeList = new ArrayList<>();

        // 記錄二叉樹每一層的節點
        List<Integer> layerList = new ArrayList<>();

        // 本層應該有多少個節點
        int eachLineNodeNum = 1;

        // 已經遍歷到多少個節點
        int currentNodeNum = 0;

        // 本層有多少個空節點
        int nullNodeNum = 0;

        if (root != null)
            nodeList.add(root);
        while (nodeList.size() != 0) {
            TreeNode node = nodeList.remove(0);
            if (node == null) {
                nullNodeNum ++;

                currentNodeNum++;

                if (eachLineNodeNum == currentNodeNum) {

                    // 下一層的節點數應為本層非空節點數 *2
                    eachLineNodeNum = (eachLineNodeNum - nullNodeNum) * 2;
                    currentNodeNum = 0;
                    nullNodeNum = 0;
//                  System.out.println("一層結束");

                    // 將layerList複製一份。
                    // 否則由於"引用傳遞"的特點,執行layerList.clear()時也會將resultList中的結果清除
                    if (layerList.size() != 0) {
                        resultList.add(new ArrayList<Integer>(layerList));
                        layerList.clear();
                    }

                }
                continue;
            }
            layerList.add(node.val);
            currentNodeNum++;
            if (eachLineNodeNum == currentNodeNum) {
                eachLineNodeNum = (eachLineNodeNum - nullNodeNum) * 2;
                currentNodeNum = 0;
                nullNodeNum = 0;
//              System.out.println("一層結束");
                if (layerList.size() != 0) {
                    resultList.add(new ArrayList<Integer>(layerList));
                    layerList.clear();
                }
            }

            TreeNode leftNode = node.left;
            TreeNode rightNode = node.right;

            nodeList.add(leftNode);
            nodeList.add(rightNode);
        }

        Collections.reverse(resultList);
        return resultList;
    }
}

相關推薦

層次生成

對於二叉樹一般是按深度生成和遍歷,比如使用遞迴方法進行先序遍歷、中序遍歷、後序遍歷。這次我們按層次生成和遍歷二叉樹。 這種遍歷方式關鍵在於需要使用一個佇列儲存“已處理該節點,但還沒處理它的子節點”這樣的節點。 # Python程式碼 # Definit

層次順序建立和

第一篇部落格,獻給了資料結構--二叉樹。 最近在學資料結構,總結一下二叉樹的按層次建立的方法,希望對此時的你有所幫助~ 有錯誤的地方,還望大神指出,或者有其他更好的方法,歡迎留言~ /*利用順序佇列,層次建立二叉樹*/ #include <iostream> using name

C++資料結構--層次

class node {    public:       T val; //節點值 node<T>* left; //左節點  node<T>* right; //右節點 node():val(T()),left(nullptr),right(nullptr){} node(T v,

層次演算法

問題:按層次遍歷二叉樹 在網上看了一些按層次遍歷二叉樹的演算法,這裡修改了一下通過佇列來按層次遍歷二叉樹的演算法 -------------------------------------------

JAVA層級

blog otn 二叉 all this java algorithm set com /** * @author cj 2017年7月14日下午1:14:31 */ package com.yuanye.algorithm; import java.util.Li

leet code Binary Tree Level Order Traversal II 層次

leet code 題目:https://leetcode.com/problems/binary-tree-level-order-traversal-ii/ 層次遍歷二叉樹: 思路:使用佇列層次遍歷二叉樹, 考點: 1.使用佇列,先彈出佇列對頭,把隊頭元素的左節點和右節點加入佇列

水平 程式碼中包含前序中序後序和水平四種

水平遍歷二叉樹要求一層一層從上往下從左往右遍歷,例如: 上面二叉樹的遍歷順序為:2、4、5、1、3 思路:利用佇列先進先出的性質 1、將根節點放入佇列 2、while迴圈佇列,只要佇列不為空,就取出第一個節點。獲取資料 3、將第二步取出的節點的左子節點和右子節點

java:前序,中序,後序深度,求葉子節點個數,層次

import java.util.ArrayDeque; import java.util.Queue; public class CreateTree { /** * @param args */ public static void main(Stri

層次和採用棧的方式

//中序遍歷非遞迴 @Override public void inOrderByStack() { System.out.println("中序遍歷非遞迴操作"); //建立棧 Deque<Node> stack=new LinkedList&

並列印換行

package com.zyl.algorithm; import java.util.LinkedList; public class PrintBinaryTreeByFloor { publ

JAVA 先序中序後序層序,遞迴非遞迴

定義一個二叉樹 package com.niuke.binaryTree; public class binaryTree { int data; binaryTree left; binaryTree right; public binaryTree(int

【劍指offer】從上往下列印層次【python】

題目描述 從上往下打印出二叉樹的每個節點,同層節點從左至右列印。 採用佇列的思想,出佇列則列印,然後左節點右節點分別入佇列 注意如果需要兩個不同的列表,一定不能用list = result = []這樣

(6)----

1、二叉樹定義 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t

第六章 及推導結果(前序中序和後續)

二叉樹遍歷方法 下面幾種演算法是利用遞迴的方法實現的 - 前序遍歷:先列印輸出,再先序遍歷左子樹,最後先序遍歷右子樹 - 中序遍歷:中序遍歷左子樹,再列印,最後中序遍歷右子樹 - 後序遍歷:先後序遍歷左子樹,再後序遍歷右子樹,最後列印輸出 - 總結:前

資料結構 BFS層次【C語言版本】

//案例輸入(其中的“#”表示空,並且輸入過程中不要加回車) 輸入序列ABC##DE#G##F### 輸入序列ABD##E##CF#G### 輸入序列ABD###C## #include <stdio.h> //測試OK,可以執行 #include <s

層次以及第K層

層次遍歷的時候用到了,STL中的佇列。 void LevelOrder(BtNode *ptr) { queue<BtNode*> que; que.push(ptr); while (!que.empty()) {

已知一個先序序列輸入的字元序列,如abc,,de,g,,f,,,(其中逗號表示空節點)。請建立中序和後序方式,最後求出葉子節點個數和深度。

這是一個標準的模板題 記下了就完事了! Input   輸入一個長度小於50個字元的字串。 Output 輸出共有4行: 第1行輸出中序遍歷序列; 第2行輸出後序遍歷序列; 第3行輸出葉子節點個數; 第4行輸出二叉樹深度。 Sample Input abc,,

[C/C++] 先序建立| 先序中序後序| 求深度節點數葉節點數 演算法實現

/* * BinTree.h */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #defi

的學習——(遞迴構建遞迴非遞迴前序中序後序根據前序序列中序序列構建

前言 最近兩個星期一直都在斷斷續續的學習二叉樹的資料結構,昨晚突然有點融匯貫通的感覺,這裡記錄一下吧 題目要求 給定前序序列,abc##de#g##f###,構建二叉樹,並且用遞迴和非遞迴兩種方法去做前序,中序和後序遍歷 二叉樹的資料結構 #define STACKSI

層次-三種不同的方法

給定一棵二叉樹,要求進行分層遍歷,每層的節點值單獨列印一行,下圖給出事例結構: 對此二叉樹遍歷的結果應該是: 1, 2 , 3 4, 5, 6 7, 8 第一種方法,就是利用遞迴的方法,按層進行列印,我們把根節點當做第0層,之後層次依次增加,如果我們想列印第二層怎麼辦呢,