1. 程式人生 > >資料結構-二叉樹基礎題目小結(遍歷,求節點數目等等)

資料結構-二叉樹基礎題目小結(遍歷,求節點數目等等)

給定一個前序序列陣列構造一個二叉樹

思路:首先序列中要有給定的非法值,也就是二叉樹中對應的空節點;對於構造一個二叉樹可以使用遞迴的思想:先構造當前節點,再構造左子樹,再右子樹,直到遇到非法值時,將NULL返回,使得上一個節點的一端連結到NULL,圖示如下:

這裡寫圖片描述

    /*  int arr[] = { 1,2,3,'#','#',4,'#','#',5,6 ,'#','#','#' };
    BinaryTree<int> tree1(arr, sizeof(arr) / sizeof(arr[0]), '#');*/

    BinaryTree(const T* arr, size_t sz, const T& invalid)
    {
        size_t index
= 0; _root = _CreatTree(arr, sz, index, invalid); } Node* _CreatTree(const T* arr, size_t sz, size_t& index, const T& invalid) { Node* node = NULL; if (arr[index] != invalid) { node = new Node(arr[index]); node->_left = _CreatTree(arr, sz, ++index
, invalid); node->_right = _CreatTree(arr, sz, ++index, invalid); } return node; }

前、中、後序遍歷遞迴寫法:

前序遍歷:先遍歷根節點,再遍歷左子樹,再遍歷右子樹;所以最先輸出根節點;
中序遍歷:先遍歷根節點左子樹,再遍歷根節點,再遍歷右子樹;
後序遍歷:先遍歷左子樹,再右子樹,最後根節點。
//前序
    void PrevOrederR()
    {
        _PrevOrederR(_root);
        cout<<
endl; } void _PrevOrderR(Node* node) { if (node == NULL) return; cout << node->_data << " "; _PrevOrderR(node->_left); _PrevOrderR(node->_right); } //中序 void MidOrderR() { _MidOrderR(_root); cout<<endl; } void _MidOrderR(Node* node) { if (node == NULL) return; _MidOrder(node->_left); cout << node->_data << " "; _MidOrder(node->_right); } //後序 void BackOrderR() { _BackOrderR(_root); cout<<endl; } void _BackOrderR(Node* node) { if (node == NULL) return; _BackOrderR(node->_left); _BackOrderR(node->_right); cout << node->_data << " "; }
輸出結果:拿一開始構造的二叉樹為例

這裡寫圖片描述

前、中、後序遍歷非遞迴寫法:

思路:將遞迴轉遞迴無非就是轉為迴圈或者使用棧來模擬遞迴的過程;前序和後序比較簡單,在後序遍歷時需要注意加判斷當前節點的右子樹是否已經遍歷過,只有當左右子樹都遍歷過後,才可輸出當前根節點。
    //遍歷非遞迴
    void PrevOrderNR()
    {
        stack<Node*> s;
        Node* cur = _root;
        while (cur || !s.empty())
        {
            while (cur != NULL)
            {
                s.push(cur);
                cout << cur->_data << " ";
                cur = cur->_left;
            }
            //到最左根節點,該回溯了
            if (!s.empty())
            {
                cur = s.top();
                s.pop();
                cur = cur->_right;
            }
        }
        cout << endl;
    }

    void MidOrderNR()
    {
        stack<Node*> s;
        Node* cur = _root;

        while (cur != NULL || !s.empty())
        {
            while (cur != NULL)
            {
                s.push(cur);
                cur = cur->_left;
            }

            //到最左節點
            if (!s.empty())
            {
                cur = s.top();
                cout << cur->_data << " ";
                s.pop();
                cur = cur->_right;
            }
        }
        cout << endl;
    }

    void BackOrderNR()
    {
        stack<Node*> s;
        Node* cur = _root;
        Node* prev = NULL;

        while (cur != NULL || !s.empty())
        {
            while (cur != NULL)
            {
                s.push(cur);
                cur = cur->_left;
            }

            Node* top = s.top();

            if (top->_right == NULL || top->_right == prev)
            {
                cout << top->_data << " ";
                s.pop();
            }
            else
            {   //說明此時右子樹還沒判斷,不可直接pop
                cur = top->_right;
            }
            prev = top;
        }
        cout << endl;
    }
輸出結果:

這裡寫圖片描述

層序遍歷:

思路:利用佇列先進先出的特性完成
    void LevelOrder()
    {
        queue<Node*> q;
        Node* node = _root;
        if (node != NULL)
            q.push(node);

        while (!q.empty())
        {
            Node* cur = q.front();
            cout << cur->_data << " ";
            q.pop();
            if (cur->_left != NULL)
                q.push(cur -> _left);
            if (cur->_right != NULL)
                q.push(cur->_right);
        }
        cout << endl;
    }

//輸出結果:1 2 5 3 4 6

求節點數目:

思路一:利用子問題的思想:左子樹節點個數加右子樹節點個數加自己的一個,如果當前節點為NULL,則返回0;

    int SizeByChildQue()
    {
        return _SizeByChildQue(_root);
    }

    int _SizeByChildQue(Node* node)
    {
        if (node == NULL)
            return 0;
        return _SizeByChildQue(node->_left) + _SizeByChildQue(node->_right) + 1;
    }
思路二:利用遍歷的思想:給定一個引數,遍歷所有節點,只要不為NULL,節點個數加1
    int SizeByTrav()
    {
        size_t size = 0;
        _SizeByTrav(_root, size);
        return size;
    }

    void _SizeByTrav(Node* node, size_t& size)
    {
        if (node == NULL)
            return;

        size++;
        _SizeByTrav(node->_left, size);
        _SizeByTrav(node->_right,size);
    }

求葉子節點數目:如同求節點數目,只不過在統計數目時需要判斷是否左右都為NULL,所以也可分為兩種寫法:

思路一:子問題:左子樹葉子節點個數加右子樹葉子節點個數,同時還要注意如果只有一個節點。
    int LeafSizeByChildQue()
    {
        return _LeafSizeByChildQue(_root);
    }

    int _LeafSizeByChildQue(Node* node)
    {
        if (node == NULL)
            return 0;

        //進行判斷,只有當左右都為空時才算做一個葉子節點
        if (node->_left == NULL && node->_right == NULL)
        {
            return 1;
        }
        return _LeafSizeByChildQue(node->_left) + _LeafSizeByChildQue(node->_right);
    }
思路二:遍歷思想,只有噹噹前節點為葉子節點時,才對計數+1;切記size要傳引用,否則回到第一個棧幀時size仍為0!
    int LeafSizeByTrav()
    {
        size_t size = 0;
        _LeafSizeByTrav(_root, size);
        return size;
    }

    void _LeafSizeByTrav(Node* node, size_t& size)
    {
        if (node == NULL)
            return;

        if (node->_left == NULL && node->_right == NULL)
            size++;

        _LeafSizeByTrav(node->_left, size);
        _LeafSizeByTrav(node->_right, size);
    }

二叉樹的高度:

思路:需要注意的是,高度是最長的那條路;劃分為子問題為:該節點的高度等於左子樹和右子樹高度中大的那個再加上1。
    size_t Height()
    {
        return _Height(_root);
    }

    size_t _Height(Node* node)
    {
        if (node == NULL)
            return 0;

        size_t lHeight = _Height(node->_left);
        size_t rHeight = _Height(node->_right);
        //注意返回時要加上當前的高度1
        return lHeight > rHeight ? lHeight + 1 : rHeight + 1;
    }

相關推薦

資料結構-基礎題目小結節點數目等等

給定一個前序序列陣列構造一個二叉樹 思路:首先序列中要有給定的非法值,也就是二叉樹中對應的空節點;對於構造一個二叉樹可以使用遞迴的思想:先構造當前節點,再構造左子樹,再右子樹,直到遇到非法值時

資料結構——的結點插入與

BTree.h: #ifndef _BTREE_H_ #define _BTREE_H_ //二叉樹的結點資料型別 typedef struct _btreeNode {     int data;     struct _btreeN

利用棧結構實現的非遞迴深度、葉子節點數、兩個結點的最近公共祖先及結點的最大距離

原文地址:http://blog.csdn.net/forbes_zhong/article/details/51227747 利用棧實現二叉樹的非遞迴遍歷,並求二叉樹的深度、葉子節點數、兩個節點的最近公共祖先以及二叉樹結點的最大距離,部分參考《劍指offer》這本書

郝斌資料結構入門--P70- 已知兩種序列原始

郝斌資料結構入門--P70-樹 已知兩種遍歷序列求原始二叉樹   已知先序、中序、後序任何一種序列,不能夠找到原始二叉樹。 經過研究發現,已知一棵樹的兩種序列,可以把二叉樹求出來。 也經過研究發現,已知先序和後序,無法還原出原始的二叉樹。 最終表明,通過  先

一道題目--後序+中序確定

image 題目 忘記 分享 一輪 除了 .com 二叉樹 哪裏 這樣的題目比較少, 但是據說計算機裏就是使用後序遍歷的..(忘記哪裏說的了), 多做幾次. 後序: KBFDCAE, 中序:BKEFACD ---------------------------

知道其他兩種方式另一種

已知先序和中序 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; *

已知 兩種序列 第三種序列

已知 前序和中序遍歷 求後序遍歷序列 struct node *creat(char *a, char *b, int n) { struct node *ptr; char

相關演算法——建立、深度和廣度

二叉樹相關的演算法,遍歷使用了遞迴和迭代兩種演算法,可作為結果對比。 理解起來不難,直接上程式碼,有空再補下注釋說明原理。 package com.junyang.algodemo.Tree; import java.util.LinkedList; im

淺談資料結構-

二叉樹是樹的特殊一種,具有如下特點:1、每個結點最多有兩顆子樹,結點的度最大為2。2、左子樹和右子樹是有順序的,次序不能顛倒。3、即使某結點只有一個子樹,也要區分左右子樹。 一、特殊的二叉樹及特點   1、斜樹 所有的結點都只有左子樹(左斜樹),或者只有右子樹(右斜樹)。這就是斜樹,應用較少

資料結構——程式碼

 二叉樹 C++ 環境codeblocks17 通過 /* 二叉樹 使用了自定義的 棧 和 佇列 @CGQ 2018/10/29 */ #include <iostream> #include <stdio.h> #include <stdlib.h&

資料結構 《c++版》

二叉樹節點BinNode模板類 #define BinNodePosi(T) BinNode<T> * //節點位置 #define stature(p) ((p) ? (p)->height : -1) //節點高度(與“空樹高度為-1”的約定相統一) typedef enu

----資料結構:的三種,利用遞迴演算法。

二叉樹----資料結構:二叉樹的三種遍歷,利用遞迴演算法。     魯迅:總之歲月漫長,然而值得等待。   #define CHAR /* 字元型 */  /* #define INT /* 整型(二者選一) */  #

C語言資料結構-、哈夫曼、佇列小練習

原始碼地址 GitHub:https://github.com/GYT0313/C-DataStructure 1. 二叉樹 要求: 掌握二叉樹的二叉連結串列的建立方法; 掌握二叉樹的3種遍歷遞迴演算法; 掌握二叉樹的3種遍歷的非遞迴演算法。 程式

資料結構實驗之五:層序 SDUT 3344

#include <bits/stdc++.h> using namespace std; struct node { char data; struct node *lc, *rc; }; char s[505]; int num; struct node *cre

Python資料結構——排序

二叉排序樹的過程主要是:二叉樹的構建和遍歷。 當樹構建好後,對樹進行中序遍歷(左中右),即可得到,對資料從小到大排序的結果。 如果對樹進行“右中左遍歷”,則可以得到,對資料從大到小排序的結果 # -*- coding:utf-8 -*- # file: pySort.py #

Python資料結構——先根中根後根

先序遍歷:根左右 中序遍歷:左根右 後序遍歷:左右根 # -*- coding:utf-8 -*- # file: TreeTraversal.py # class BTree: # 二叉樹節點 def __init__(self, value):

資料結構-

這篇博文主要是研究二叉樹遍歷的遞迴與非遞迴演算法,有興趣的小夥伴可以瞭解下! 二叉樹的遞迴遍歷(深度優先遍歷) 先來張圖,看看各結點遍歷時的情況: 二叉樹深度優先遍歷總結(分別為第一次,第二次,第三次進入某個結點): 先序遍歷:先訪問根結點,然後先序遍歷左子樹,最後先序遍歷右子樹;根->

資料結構——的四種方式

首先來說一下哪四種遍歷方式:前中後、層序遍歷,四種遍歷方式詳解,注意這篇部落格用的是STL,但是遍歷思想與遞迴基本一致,體會那種思想即可。 前中後序的遞迴區別主要在於輸出的語句究竟該寫在哪裡,這個主要看節點是在什麼位置輸出,如果第一個輸出就在最前面,如果第二個輸出,就在左節點後面。。。以此類

資料結構——交換左右

二叉樹交換左右子樹 #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct Node{ //二叉樹的鏈式儲存結點 char data; stru

資料結構——的結點的層次

二叉樹結點的層次 #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct Node{ //二叉樹的鏈式儲存結點 char data; int d