資料結構-二叉樹基礎題目小結(遍歷,求節點數目等等)
給定一個前序序列陣列構造一個二叉樹
思路:首先序列中要有給定的非法值,也就是二叉樹中對應的空節點;對於構造一個二叉樹可以使用遞迴的思想:先構造當前節點,再構造左子樹,再右子樹,直到遇到非法值時,將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