數據結構之二叉樹詳解[1]

在前面我們介紹了堆和二叉樹的基本概念后,本篇文章將帶領大家深入學習鏈式二叉樹。

1.預備知識

2.二叉樹結點的創建

3.二叉樹的遍歷?

3.1前序遍歷

3.2中序遍歷

3.3?后序遍歷

4.統計二叉樹的結點個數

5.二叉樹葉子結點的個數

?6.二叉樹第k層的結點個數

?7.總結


1.預備知識

由于二叉樹的性質,我們在實現二叉樹及其相關功能時會經常使用到遞歸的操作。

所以我們首先介紹一下遞歸算法。

在百度百科中,對于遞歸算法的定義是:某個函數直接或者間接地調用自身,這樣原問題的求解就轉換為了許多性質相同但是規模更小的子問題。

很多同學或許對這句話無法理解,沒有關系。

在這里我們僅僅將其當作一個工具,在編寫代碼時,我們只需搞清楚繁雜的遞歸調用中的一次調用即可,不需要去深究他調用的過程。在文章后續的代碼實現中,大家可以深刻體會到這句話的意思。

2.二叉樹結點的創建

?既然是鏈式二叉樹,對學習過鏈表的大家就很簡單了。直接上代碼

typedef char BTDataType;typedef struct BTreeNode//每一個結點的結構
{BTreeNode* left;//指向左樹BTreeNode* right; //指向右樹BTDataType data;//結點的值
}BTNode;BTNode* BuyNode(BTDataType x)//為新結點開辟空間
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));newnode->data = x;newnode->left = newnode->right = NULL;return newnode;
}

3.二叉樹的遍歷?

二叉樹的遍歷有四種:前序遍歷、中序遍歷、后序遍歷、層序遍歷。

今天我們在這里講解前三種遍歷,層序遍歷請看下回分解。

3.1前序遍歷

前序遍歷就是先遍歷根結點,在遍歷左子樹,最后遍歷右子樹。

理解了概念我們直接上代碼。

void PreOrder(BTNode* root)//前序 根 左子樹 右子樹
{if (root == NULL){printf("NULL");return;}else {printf("%c", root->data);//打印根節點PreOrder(root->left);//遞歸遍歷左子樹PreOrder(root->right);//遞歸遍歷右子樹}
}

這里我們就使用到了遞歸。該如何理解呢。

我們只關注一次調用,既然遍歷左樹,

那么我們就讓根去找,即?PreOrder(root->left)。

遍歷右樹,即PreOrder(root->right)。

中間是如何進行調用的細節我們不需要深究,我們只需要知道這個遞歸的寫法。剩下的交給計算機。如果大家仍沒理解,可以畫個對照代碼畫一個草圖。

?

3.2中序遍歷

中序遍歷:先遍歷左子樹,在找根,最后遍歷右子樹。

代碼如下

void InOrder(BTNode* root)
{if (root == NULL){printf("NULL");return;}else {InOrder(root->left);//遍歷左樹printf("%c", root->data);//找根InOrder(root->right);//遍歷右樹}
}

這里的遞歸我們仍然按一樣的方法進行理解,只看一層調用。大家可以看圖理解。?

3.3?后序遍歷

后序遍歷:先遍歷左子樹,再遍歷右子樹,最后找根。

void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL");return;}else {PostOrder(root->left);//遍歷左樹PostOrder(root->right);//遍歷右樹printf("%c", root->data);//找根}
}

后序的圖大家就自己畫畫吧。?

4.統計二叉樹的結點個數

?如何統計二叉樹的結點個數呢。

思路很簡單,沒遍歷一個非空結點,個數加一。我們看下面代碼。

void TreeSize(BTNode* root)
{if (root == NULL)return;int count = 0;count++;//既然不為空,那么一定就有一個結點的存在TreeSize(root->left);TreeSize(root->right);
}

如果大家覺得這個代碼對的話,那就掉入陷阱了!

在遞歸調用中,count存在于棧幀之中,并且遞歸的每一次調用都會開辟新的一塊棧幀,這樣的話我們的count就無法進行值的保存而達到連續的效果。所以這里我們不能這樣進行實現。

下面我們介紹正確的寫法。

void TreeSize(BTNode* root,int*p)//p為指向節點個數的指針
{if (root == NULL)return;++(*p);//結點個數++,既然不為空,那么一定有一個根結點,所以先++TreeSize(root->left, p);//遍歷左子樹的結點TreeSize(root->right, p);//遍歷右子樹的結點
}

我們在這里運用定義了一個外部指針變量,用來記錄結點的個數,傳入的是記錄結點個數變量的地址。這樣就可以避免?原來出現的問題了。

?其實這里還有個更加簡單的方法,直接用root來記錄結點個數。

int TreeSize(BTNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

5.二叉樹葉子結點的個數

?既然可以得到結點總數,那葉子結點是不是也可以得到呢。我們先上代碼再解釋。

int BTreeLeafSize(BTNode* root)
{if (root == NULL)return 0;if (root->left == NULL && root->right == NULL) //葉子結點的特點{return 1;}return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);//找葉子結點
}

既然要找葉子結點首先我們要知道葉子結點的性質:左右子樹均為空。

所以我們在遞歸的時候需要加入葉子結點的判斷條件,如果是葉子結點就要返回。

當然在進行遞歸前要判斷根節點是否存在或者根結點是否有值,我們將其劃分為代碼中的一中情況。

?6.二叉樹第k層的結點個數

我們該如何求任意一層的結點個數呢。

我們將求第k層的結點個數轉化為求第k-1層結點的左右子樹個樹是不是就和我們求葉子結點個數大同小異了呢!

int BTreeLayerSize(BTNode* root,int k)
{if (root == NULL)return 0;if (k == 1)return 1;return BTreeLayerSize(root->left, k - 1) + BTreeLayerSize(root->right, k - 1);
}

我們加入需要的層數k,我們從根結點往下找第k層,如果要使其找到k層,就要使k=1。我們畫圖理解?。

我們假設要求第三層的結點個數,k=3。根結點為第一層,與其匹配的k=3,所以到找到第三層,就要使k--,簡而言之,我們要找到的那一層匹配的k=1。這里可能有點繞,大家可以試著自己畫圖理解?。

?7.總結

?二叉樹的內容到這里并沒有結束,后序的內容需要用到隊列的知識,所以我會在穿插隊列的實現后繼續為大家講解二叉樹的相關知識!敬請期待!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12269.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12269.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12269.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鴻蒙ArkUI開發:常用布局【相對布局】

相對布局(RelativeContainer) 相對布局可以讓子元素指定兄弟元素或父容器作為錨點,基于錨點做位置布局必須為RelativeContainer及其子元素設置ID,用于指定錨點信息。未設置ID的子元素不會顯示RelativeContainer ID為“__containe…

增程SUV價格即將崩盤?買車一定要再等等!

文 | AUTO芯球 作者 | 雷歌? 真是“離譜”啊,車圈真是逗比歡樂多, 我這兩天看一個博主連續40多小時開車直播,充電口、油箱蓋全部封死,全程視頻直播沒斷過, 就為了測試這兩天剛上市的星際元ET續航有多遠。 另一個…

Docker 創建網絡

問題: 1.需要將多個容器添加到同一個網絡. 2.docker-compose.yaml 如果不指定,默認會重新創建一個網卡. 創建網卡 docker network create -d bridge mynet ##-d 指定模式(默認橋接)查看自定義網絡信息 docker inspect mynet…

NSSCTF Web方向的例題和相關知識點(二)

[SWPUCTF 2021 新生賽]Do_you_know_http 解題: 點擊打開環境,是 提示說請使用wLLm瀏覽器訪問 我們可以更改瀏覽器信息,在burp重放器中發包后發現是302重定向,但是提示說success成功,說明 我們修改是成功的&#xff…

HTML特殊字符

特殊字符 有特殊含義的字符成為字符實體 對于有特殊含義的字符,需要通過轉移字符來表示 <span> <br><a href"http://www.atguigu.com">我 愛 前端</a> <br>&amp;amp; 效果

Element-UI 快速入門指南

文章目錄 一、安裝 Element-UI1.1 使用 npm 安裝1.2 使用 yarn 安裝 二、引入 Element-UI三、使用 Element-UI 組件3.1 按鈕組件3.2 輸入框組件3.3 表單組件3.4 表格組件3.5 彈框組件 四、自定義主題4.1 安裝主題工具4.2 初始化變量文件4.3 編譯主題 五、總結 &#x1f389;歡迎…

刷題之最長連續序列

哈希表 class Solution { public:int longestConsecutive(vector<int>& nums) {//set記錄并且去重nums中的數unordered_set<int>set;for(int i0;i<nums.size();i){set.insert(nums[i]);}int result0;//遍歷所有數for(auto iset.begin();i!set.end();i){//如…

服務的war包已經丟在tomcat中但是還是沒法訪問,如何排查?

問題出現的現象是我已經將 XWiki 的 WAR 包放置在 Tomcat 的 webapps目錄下但仍然無法訪問&#xff0c;反思之后可以從下面以下幾個方面來診斷和解決問題&#xff1a; 1. 確認 Tomcat 正在運行 首先&#xff0c;確保 Tomcat 服務正在正常運行。可以使用以下命令檢查 Tomcat 的…

鑒源論壇·觀通丨軌交軟件測試技術詳述

作者 | 劉艷青 上海控安安全測評部測試經理 版塊 | 鑒源論壇 觀通 社群 | 添加微信號“TICPShanghai”加入“上海控安51fusa安全社區” 01 集成測試技術要求 1.1 總體要求 對軟件集成測試進行靜態測試應先于動態測試&#xff1b; 集成過程是動態進行的&#xff0c;在測…

圖紙加密軟件是如何實現共享服務器圖紙防泄密?Cad圖紙防泄密廣州廠家

現在企業網絡數據安全的問題已經在社會的發展過程中引起了關注&#xff0c;尤其對研發制造類企業而言&#xff0c;企業設計圖紙的防泄密問題是這些企業在日后工作管理中的重中之重。在當今的互聯網發展形勢下&#xff0c;廣州的制造類設計企業為不讓單位圖紙泄露&#xff0c;也…

CVHub | CVPR 2024 | 英偉達發布新一代視覺基礎模型: AM-RADIO = CLIP + DINOv2 + SAM

本文來源公眾號“CVHub”&#xff0c;僅用于學術分享&#xff0c;侵權刪&#xff0c;干貨滿滿。 原文鏈接&#xff1a;CVPR 2024 | 英偉達發布新一代視覺基礎模型: AM-RADIO CLIP DINOv2 SAM 標題&#xff1a;《AM-RADIO: Agglomerative Vision Foundation Model Reduce Al…

vscode 之 output 輸出中文亂碼,終端輸出中文正常

# 1. 背景 因為沒錢買正版的軟件&#xff0c;所以轉戰 vscode 編譯器。 在編譯 python 文件時&#xff0c;發現直接右鍵 runner code&#xff0c;輸出中文亂碼。 但是在 teiminal 終端 執行py test.py 時&#xff0c;輸出正常&#xff0c;中文正常。 output 輸出中文樣式(中文…

java相等忽略音調

來自百度,親測可用 java相等忽略音調 在Java中&#xff0c;如果你想比較兩個字符串而忽略它們的音調符號&#xff0c;你可以使用java.text.Collator類來進行區域敏感的字符串比較。Collator類提供了根據特定區域的規則進行字符串比較的能力&#xff0c;可以設置忽略音調的選項…

Go微服務: Prometheus性能監控與Grafana平臺的搭建

Prometheus 概述 promethues 是一套開源的監控&報警&時間序列數據庫的組合基本原理是通過http協議周期性抓取被監控組件的狀態適合Docker、Kubernetes環境的監控系統 Promethues 整體架構 一、抓取數據的兩種方式 1 &#xff09;Short-lived jobs 短暫的任務 不會提…

RedisTemplate操作Redis詳解之連接Redis及自定義序列化

連接到Redis 使用Redis和Spring時的首要任務之一是通過IoC容器連接到Redis。為此&#xff0c;需要java連接器&#xff08;或綁定&#xff09;。無論選擇哪種庫&#xff0c;你都只需要使用一組Spring Data Redis API&#xff08;在所有連接器中行為一致&#xff09;&#xff1a;…

面對.halo勒索病毒,如何有效防范與應對?

導言&#xff1a; 隨著網絡技術的不斷發展&#xff0c;網絡安全問題也日益凸顯。其中&#xff0c;勒索病毒作為一種極具破壞性的網絡攻擊手段&#xff0c;近年來在全球范圍內頻發。其中&#xff0c;.halo勒索病毒作為勒索病毒家族中的一員&#xff0c;其危害性和傳播性不容忽視…

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 論文閱讀

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 論文閱讀 Abstract1 Introduction2 Related Work3 Proposed Approach4 Experiments5 Conclusion 文章信息&#xff1a; 原文鏈接&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/4…

Flutter 中的 Spacer 小部件:全面指南

Flutter 中的 Spacer 小部件&#xff1a;全面指南 在Flutter布局系統中&#xff0c;Spacer是一個Flex組件&#xff0c;用于占據可用空間&#xff0c;從而推動其他Widget到布局的開始或結束位置。Spacer通常與Row、Column或Flex一起使用&#xff0c;以實現靈活的布局設計。本文…

二叉樹專題(有關二叉樹的相關學習)

二叉樹 1.數概念及結構 1.1樹的結構 樹是一種非線性的數據結構&#xff0c;它是由n&#xff08;n>0&#xff09;個有限結點組成一個具有層次關系的集合。把它叫做樹是因 為它看起來像一棵倒掛的樹&#xff0c;也就是說它是根朝上&#xff0c;而葉朝下的。 有一個特殊的結…

ollama離線部署llama3(window系統)

首先介紹下ollama是什么&#xff1f;Ollama是一個開源的大型語言模型服務工具&#xff0c;旨在為用戶提供本地化的運行環境&#xff0c;滿足個性化的需求。具體來說&#xff0c;Ollama是一個功能強大的開源框架&#xff0c;可以簡化在Docker容器中部署和管理大型語言模型&a…