數據結構手撕--【二叉樹】

?

目錄

定義結構體:

初始化:

手動創建一個二叉樹:

前序遍歷:

中序遍歷:

后序遍歷

?二叉樹節點個數:

葉子節點個數:

二叉樹第k層節點個數:

二叉樹的高度:

?查找值為x的節點:

二叉樹的層序遍歷:

判斷二叉樹是否為完全二叉樹:

銷毀二叉樹:


二叉樹增刪查改沒有具體意義。我們主要實現搜索二叉樹

特殊的二叉樹---完全二叉樹(堆) 適合數組結構表示? (堆結構下節更新)

對于普通二叉樹我們采用 鏈式結構

定義結構體:

一個結構體就是一個樹節點

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//鏈式二叉樹//定義結構體 --- 一個結構體就是一個樹節點
typedef char BTDataType;
typedef struct BinaryTreeNode
{BinaryTreeNode* left;  //指向節點的指針 類型為節點類型BinaryTreeNode* right;BTDataType data;
}BTNode;

初始化:

? 鏈式結構 開辟空間創建新節點

BTNode BuyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));newnode->left = NULL;newnode->right = NULL;newnode->data = x;return newnode;
}

手動創建一個二叉樹:

BTNode* CreatBinaryTree()
{BTNode* nodeA = BuyNode('A');BTNode* nodeB = BuyNode('B');BTNode* nodeC = BuyNode('C');BTNode* nodeD = BuyNode('D');BTNode* nodeE = BuyNode('E');BTNode* nodeF = BuyNode('F');nodeA->left = nodeB;nodeA->right = nodeC;nodeB->left = nodeD;nodeC->left = nodeE;nodeC->right = nodeF;return nodeA;
}

前序遍歷:

---? 根左右? ?打印放在最前面 再左、右遞歸

void PerOrder(BTNode* root)
{if (root == NULL){return NULL;}printf("%c", root->data);PerOrder(root->left);PerOrder(root->right);
}

畫圖理解遞歸過程:?

中序遍歷:

---? 左根右? 打印放在中間 先左遞歸 打印 再右遞歸

void MidOrder(BTNode* root)
{if (root == NULL){return NULL;}MidOrder(root->left);printf("%c", root->data);MidOrder(root->right);
}

?

后序遍歷

-- 左右根

void PostOrder(BTNode* root)
{if (root == NULL){return NULL;}PostOrder(root->left);PostOrder(root->right);printf("%c", root->data);
}

?二叉樹節點個數:

為空返回0,不為空去遞歸左右子樹,+1是遞歸完左右返回之后+1的,即就會算此時的root節點的數量。(下圖有具體的遞歸過程)左+右+根(1)

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

葉子節點個數:

到葉子返回1(不再向下遞歸),返回 左+右? ? ?不算根的個數

int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left && root->right == NULL) //在遞歸的過程中 走到葉子就會返回1 最后左+右即可{return 1;}return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

二叉樹第k層節點個數:

往下走一層k都會減一,假如要求第五層,走到第五層k=1,把1返回即可

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

?

二叉樹的高度:

當這棵樹為空樹時,二叉樹的高度應該是0,所以當數為空我們返回0,然而當樹不等于空時,我們可以以大事化小,小事化了的思想,將當前樹的高度轉換成左右子樹兩個中的最大高度再加上一,然后左右子樹中最大高度的樹的高度又可以轉換成我們剛剛的思想,就這樣不斷遞歸下去直接我們遇見空節點.

nt BinaryTreeDepth(BTNode* root)
{//為空 返回0//遞歸左樹 遇到左右都為空的節點 返回1 再遞歸右樹 左右都為空 返回1,//左右比較 返回大的+1if (root == NULL){return NULL;}NTNode* left = BinaryTreeDepth(root->left);NTNode* right = BinaryTreeDepth(root->right);return left > right ? left + 1 : right + 1;
}

?查找值為x的節點:

只要找到了就不會返回空,只要返回的不是空就是找到了。左子樹找到了就不會再去右子樹找

BTNode* BinaryTreeFind(BTNode* root, BTNodeType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* left = BinaryTreeFind(root->left);if (left != NULL){return left;}BTNode* right = BinaryTreeFind(root->right);if (left != NULL){return right;}return NULL;
}

二叉樹的層序遍歷

借助隊列

  1. 先將根入隊列
  2. 當前節點出隊列后,將次此節點的左右孩子入隊列
  3. 一直這樣循環往復直到隊列為空,說明最后一層已經沒有節點了,遍歷結束
void BinaryTreeLevelOrder(BTNode* root)
{if (root == NULL){return NULL;}Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);printf("%c", front->data);if (front->left != NULL){QueuePush(&q, front->left);}if (front->right != NULL){QueuePush(&q, front->right);}}printf("\n");QueueDestroy(&q);
}

判斷二叉樹是否為完全二叉樹:

完全二叉樹和非完全二叉樹的區別:前者一旦有空后面就都是空,而后者一旦有空后面還會出現非空。

第二個while循環是遇到空時候,看后面是否全為空,如果是就是完全二叉樹

QueueEmpty(&q)判斷隊列是否為空,看的是front是否為空

bool BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front == NULL){break;}else{QueuePush(&q, front->left);QueuePush(&q, front->right);}}//遇到空了while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front){QueueDestory(&q);return false;}}QueueDestory(&q);return true;
}

銷毀二叉樹:

void BinaryTreeDestory(BTNode* root)
{if (root == NULL){return;}BinaryTreeDestory(root->left);BinaryTreeDestory(root->right);free(root);
}

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

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

相關文章

2025 Java 開發避坑指南:如何避免踩依賴管理的坑?

在 Java 開發的世界里&#xff0c;依賴管理就像是一座看不見的橋梁&#xff0c;連接著項目所需的各種第三方庫和框架。然而&#xff0c;這座橋梁并非總是穩固&#xff0c;稍有不慎就可能掉入 “依賴地獄”&#xff0c;導致項目編譯失敗、運行異常。2025 年&#xff0c;隨著開源…

用node打開一個網頁

前言 使用node打開網頁&#xff0c;要求跨平臺 方案 使用子進程來用命令行打開網頁鏈接就可以了&#xff0c;需要注意的是Mac系統使用的是open命令&#xff0c;Windows系統使用的是start命令&#xff0c;Linux等系統使用xdg-open命令。針對不同的操作系統使用不同的命令。 封…

使用功能包組織C++節點的具體教程

在 ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;使用功能包&#xff08;package&#xff09;來組織 C 節點是一種常見且有效的方式&#xff0c;它能讓代碼結構更清晰、便于管理和復用。 1. 環境準備 確保已經安裝了 ROS&#xff0c;這里以 ROS 2 Humble…

二項式分布html實驗

二項式分布html實驗 本文將帶你一步步搭建一個純前端的二項分布 Monte-Carlo 模擬器。 只要一個 HTML 文件&#xff0c;打開就能運行&#xff1a; 動態輸入試驗次數 n、成功概率 p 與重復次數 m點擊按鈕立刻得到「模擬頻數 vs 理論頻數」柱狀圖隨著 m 增大&#xff0c;兩組柱狀…

通過 API 對接應用網絡商城實現訂單自動化

前言 API&#xff08;Application Programming Interface&#xff09;即應用程序編程接口&#xff0c;是一種允許不同軟件應用程序之間進行交互和數據共享的工具。它通過定義一組明確的規則和協議&#xff0c;使得各個軟件系統能夠以標準化的方式相互通信。 在支付領域&#x…

openwrt作旁路由時的幾個常見問題 openwrt作為旁路由配置zerotier 圖文講解

1 先看openwrt時間&#xff0c;一定要保證時間和瀏覽器和服務器是一致的&#xff0c;不然無法更新 2 openwrt設置旁路由前先測試下&#xff0c;路由器能否ping通主路由&#xff0c;是否能夠連接外網&#xff0c;好多旁路由設置完了&#xff0c;發現還不能遠程好多就是旁路由本…

FANUC機器人GI與GO位置數據傳輸設置

FANUC機器人GI與GO位置數據傳輸設置&#xff08;整數小數分開發&#xff09; 一、概述 在 Fanuc 機器人應用中&#xff0c;如果 IO 點位足夠&#xff0c;可以利用機器人 IO 傳輸位置數據及偏移位置數據等。 二、操作步驟 1、確認通訊軟件安裝 首先確認機器人控制柜已經安裝…

UE5 Assimp 自用

記錄一下配assimp庫到ue中的過程。因為想在ue里面實現一些幾何處理(雖然ue好像有相關的geo的代碼&#xff09;&#xff0c;遂配置了一下assimp。 1. 編譯整理生成自己所需要的文件。cmake編譯&#xff0c;下載github 的官方的assimp-master&#xff0c;然后cmake都是默認的就行…

第18章:MCP在創作領域中的應用

第18章:MCP在創作領域中的應用 創意過程,無論是寫作、繪畫、音樂創作還是設計,往往充滿了不確定性、迭代和靈感的迸發。傳統 AI 在創意領域的應用常常局限于風格遷移、簡單內容生成等。MCP 框架通過其對記憶、上下文和規劃的整合,為 AI Agent 參與和輔助更深層次的創意活動…

電子電子架構 --- 主機廠視角下ECU開發流程

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 簡單,單純,喜歡獨處,獨來獨往,不易合同頻過著接地氣的生活,除了生存溫飽問題之外,沒有什么過多的欲望,表面看起來很高冷,內心熱情,如果你身…

【Agent】LangManus深度解析:AI自動化框架的對比與langgraph原理

LangManus深度解析&#xff1a;AI自動化框架的技術演進與實踐 本文將帶你深入探索LangManus這一AI自動化框架的核心技術與其基于langgraph的實現原理&#xff0c;并與OpenManus進行全面對比&#xff0c;助你掌握多智能體系統的前沿技術。 本文3萬字&#xff0c;沒有時間的話可以…

機器學習-08-推薦算法-案例

總結 本系列是機器學習課程的系列課程&#xff0c;主要介紹機器學習中關聯規則 參考 機器學習&#xff08;三&#xff09;&#xff1a;Apriori算法&#xff08;算法精講&#xff09; Apriori 算法 理論 重點 MovieLens:一個常用的電影推薦系統領域的數據集 23張圖&#x…

OpenCV 圖形API(63)圖像結構分析和形狀描述符------計算圖像中非零像素的邊界框函數boundingRect()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 計算點集或灰度圖像非零像素的 upright&#xff08;不旋轉&#xff09;邊界矩形。 該函數計算并返回指定點集或灰度圖像非零像素的最小 upright …

Redis ⑥-string | hash | list

string類型基本介紹 Redis 中的字符串&#xff0c;是直接按照二進制的方式進行存儲的。也就是說&#xff0c;在存取的過程中&#xff0c;是不會做任何編碼轉換的。存的是啥&#xff0c;取的時候就是啥。 Redis 的這個機制&#xff0c;就使得 Redis 非常適合用來存儲各種各樣的…

星火燎原:大數據時代的Spark技術革命在數字化浪潮席卷全球的今天,海量數據如同奔涌不息的洪流,傳統的數據處理方式已難以滿足實時、高效的需求。

星火燎原&#xff1a;大數據時代的Spark技術革命 在數字化浪潮席卷全球的今天&#xff0c;海量數據如同奔涌不息的洪流&#xff0c;傳統的數據處理方式已難以滿足實時、高效的需求。Apache Spark作為大數據領域的璀璨明星&#xff0c;憑借其卓越的性能和強大的功能&#xff0c…

通信算法之273 : 循環自相關函數和自相關函數

一、循環自相關函數定義與計算流程 ?定義式?: 循環自相關函數為時間平均自相關函數的傅里葉變換: Rxα(τ)=1T∫?T/2T/2Rx(t+τ2,t?τ2)e?j2παtdtRxα?(τ)=T1?∫?T/2T/2?Rx?(t+2τ?,t?2τ?)e?j2παtdt 其中,Rx(t,τ)Rx?(t,τ) 是信號的自相關函數,α為循…

使用 VMware 安裝一臺 Linux 系統之Centos

使用 VMware 安裝一臺 Linux 系統之Centos 想體驗一下 Linux 的魅力&#xff0c;又不想在現有電腦上進行大刀闊斧的改動&#xff1f;使用 VMware 虛擬機是一個絕佳的選擇。它能讓你在 Windows 或 macOS 系統中輕松創建一個獨立的 Linux 環境。本文將手把手帶你完成從下載 VMwa…

uniapp-商城-36-shop 購物車 選好了 進行訂單確認2 支付方式顏色變化和顏色濾鏡filter

顏色濾鏡&#xff0c;在好多網頁都這樣使用&#xff0c;濾掉彩色&#xff0c;顯示黑白&#xff0c;這在一些關鍵的日子中都這樣使用。 1、依然回到訂單確認頁面 看到支付的顏色了嘛&#xff1f; <view class"payType"><view class"box" :class&q…

gerbera文件轉PCB文件-Altium Designer

gerbera文件轉PCB文件-Altium Designer 1. 新建 CAM 文檔2. 導入 Gerber 文件和鉆孔文件導入 Gerber 文件導入鉆孔文件&#xff08;NC Drill&#xff09; 3. 提取網絡表4. 檢查并設置層映射5. 導出為 PCB 文件 1. 新建 CAM 文檔 打開 Altium Designer&#xff0c;執行以下操作…

Flask 請求數據獲取方法詳解

一、工作原理 在 Flask 中&#xff0c;所有客戶端請求的數據都通過全局的 request 對象訪問。該對象是 請求上下文 的一部分&#xff0c;僅在請求處理期間存在。Flask 在收到請求時自動創建 request 對象&#xff0c;并根據請求類型&#xff08;如 GET、POST&#xff09;和內容…