數據結構自學Days10 -- 二叉樹的常用實現

? 一、為什么要學習二叉樹?

1. 📦 組織數據的高效方式

  • 二叉樹可以快速插入、刪除、查找數據,尤其在平衡時,時間復雜度為 $O(\log n)$。

  • 適合表示分層結構(如組織結構、文件系統、語法樹)。

2. 💡 各種高級結構的基礎

很多更復雜的數據結構都以二叉樹為基礎,例如:

  • 堆(Heap):用于實現優先隊列

  • 平衡樹(如 AVL、紅黑樹):用于快速搜索和動態數據更新

  • 線段樹、區間樹、樹狀數組:用于范圍查詢

  • 表達式樹、Huffman 樹:用于編譯器、壓縮算法等

3. 🧠 算法題中的常客

  • 很多算法競賽、筆試題會考查二叉樹的構造、遍歷、查找、平衡、路徑計算等問題。

  • 是程序員面試中的高頻知識點

4、二叉樹的常用功能

功能

說明

? 遍歷

先序、中序、后序、層序遍歷

🔍 搜索

二叉搜索樹(BST)可高效查找

📁 分層結構表示

文件系統、組織架構樹、語法樹

🧮 表達式處理

表達式樹支持中綴轉后綴、求值

🧠 平衡維護

AVL、紅黑樹保證查找平衡性

🔧 范圍查詢

線段樹、區間樹等支持快速區間操作

🔗 哈夫曼編碼

構造最優前綴編碼

🔄 結構轉換

鏡像、翻轉、扁平化等結構操作

二叉樹是一種既基礎又強大的數據結構,學習它不僅是算法的入門,也是邁向更高階算法和工程應用的必經之路。

下面我們總結一下對于二叉樹言的常用接口包括:

二、二叉樹的常用實現

1、如何創建二叉樹。2、銷毀創建的二叉樹釋放內存。3、計算二叉樹的節點個數。4、計算二叉樹葉節點的個數。5、計算二叉樹第k層的節點個數。6、找到二叉樹中指定的節點。7、二叉樹的前序,后序,中序。8、層序遍歷(利用隊列實現)。9、判斷是否為完全二叉樹。

1、如何創建二叉樹

代碼實現:

typedef char BTreeDataType;typedef struct BTreeNode
{BTreeDataType _data;struct BTreeNode* _left;struct BTreeNode* _right;
}BTreeNode;BTreeNode* CreateTree(BTreeDataType* str,int* pi){if(*str == '\0'){return NULL;}if(str[*pi] == '#'){(*pi)++;return NULL;}BTreeNode* root = (BTreeNode*)malloc(sizeof(BTreeNode));root->_data = str[*pi];(*pi)++;root->_left = CreateTree(str,pi);root->_right = CreateTree(str,pi);return root;
}

測試函數:

int main(){char str[100] = {0};scanf("%s",str);int i = 0;BTreeNode* root = CreateTree(str,&i);}

輸入:ABC##DE#G##F###,注意這里我們構建二叉樹是通過“前序遍歷的思想”

2、銷毀創建的二叉樹釋放內存

void BTree_Destroy(BTreeNode* root){if(!root){return;}BTree_Destroy(root->_left);BTree_Destroy(root->_right);free(root);root = NULL;
}

3、計算二叉樹的節點個數

? ? ? ? 利用前序遍歷的思想進行二叉樹的遍歷,統計非空子樹即可,可參考二叉樹的前序遍歷。

int BTreeSize(BTreeNode* root){if(!root){return 0;}return 1+ BTreeSize(root->_left)+BTreeSize(root->_right);
}

4、計算二叉樹葉節點的個數

?? ? ? ?同樣你可以利用前序遍歷的思想,但是統計葉節點,需滿足左右子樹為空才統計

int BTreeLeafSize(BTreeNode* root){if(!root){return 0;}if(!(root->_left) && !(root->_right)){return 1;}return (BTreeLeafSize(root->_left)+BTreeLeafSize(root->_right));
}

5、計算二叉樹第k層的節點個數。

? ? ? ? 這里我們需要輸入k這個參數,首先我們需要找到第k層,當遍歷二叉樹時,遍歷至當前節點的左右子樹,則k--,知道k==0時,就是我們的第k層,然后在統計節點個數就行。? ? ? ??

代碼實現:

int BTreeLevelKSize(BTreeNode* root,int k){if(!root){return 0;}k--;if(k == 0){return 1;}return (BTreeLevelKSize(root->_left,k)+BTreeLevelKSize(root->_right,k));
}

6、找到二叉樹中指定的節點

?? ? ? ?只需判斷節點值是否為指定值,是就直接返回當前節點,否則繼續遍歷。

代碼實現:

BTreeNode* BTreeFind(BTreeNode* root,int _val){if(!root){return NULL;}if(root->_data == _val){return root;}BTreeNode* node = BTreeFind(root->_left,_val);if(node){return node;}node = BTreeFind(root->_right,_val);if(node){return node;}return NULL;
}

7、二叉樹的前序,后序,中序

?? ? ? ?這部分內容我們已經實現過很多次了,這里直接給出源碼

代碼實現:

//前序
void PreOrder(BTreeNode* root){if(!root){printf("NULL");return;}printf("%c ",root->_data);PreOrder(root->_left);PreOrder(root->_right);return;
}
//中序
void InOrder(BTreeNode* root){if(!root){printf("NULL");return;}InOrder(root->_left);printf("%c ",root->_data);InOrder(root->_right);return;
}
//后序
void PostOrder(BTreeNode* root){if(!root){printf("NULL");return;}PostOrder(root->_left);PostOrder(root->_right);printf("%c ",root->_data);return;
}

8、層序遍歷(利用隊列實現)

? ? ? ? 這里我們需要使用到隊列的思想,“先進先出”當前節點不為空,我們把當前節點放入隊列中,然后再輸出該節點,然后將該節點的左右子節點放入隊列,然后再刪除左節點,再把左節點的左右子節點再放入,當節點為空時不再放入,當隊列為空時不在放出,不斷重復放入放出。就是層序遍歷。

思維導圖:

代碼實現:

//隊列的聲明
typedef struct Queue
{QueueDataType btnode;struct Queue* next;}Queue;typedef struct my_Queue{Queue* _head;Queue* _tail;
}my_Queue;//隊列初始化
my_Queue* Queue_Init(){my_Queue* pq = (my_Queue*)malloc(sizeof(my_Queue));pq->_head = pq->_tail = NULL;return pq;
}
//隊列的摧毀
void QueueDestroy(my_Queue* pq){assert(pq);Queue* Cur = pq->_head;while (Cur){Queue* Del = Cur;Cur = Cur->next;free(Del);}pq->_head = pq->_tail = NULL;return;
}
//插入元素
void QueuePush(my_Queue* pq,QueueDataType _val){assert(pq);Queue* NewNode = (Queue*)malloc(sizeof(Queue));NewNode->btnode = _val;NewNode->next = NULL;if(pq->_head == NULL){pq->_tail = NewNode;pq->_head = NewNode;  }else{pq->_tail->next = NewNode;pq->_tail = NewNode;}
}
// 刪除元素
void QueuePop(my_Queue* pq){assert(pq);if(pq->_head == NULL){return;}else{Queue* Cur = pq->_head;pq->_head = (pq->_head)->next;free(Cur);}if(pq->_head == NULL){pq->_tail = NULL;}return;
}// 返回隊列開頭元素
QueueDataType QueueFront(my_Queue* pq){assert(pq);if(pq->_head){return pq->_head->btnode;}return NULL;
}//判斷隊列是否為空
bool IsQueueEmpty(my_Queue* pq){assert(pq);return !pq->_head;
}

隊列的構建以及常用函數的實現:參考棧與隊列的實現

//層序遍歷
void BTree_LevelOrder(BTreeNode* root){if(!root){printf("NULL");return;}my_Queue* BTqueue = Queue_Init();QueuePush(BTqueue,root);while (!IsQueueEmpty(BTqueue)){QueueDataType Front = QueueFront(BTqueue);printf("%c ",Front->_data);QueuePop(BTqueue);if(Front->_left){QueuePush(BTqueue,Front->_left);};if(Front->_right){QueuePush(BTqueue,Front->_right);}}QueueDestroy(BTqueue);BTqueue = NULL;return;
}

9、判斷是否為完全二叉樹。

? ? ? ? 完全二叉樹的概念是?除最后一層外,其他層都是滿的,且最后一層從左到右連續填滿

這里我們需要利用層序遍歷的思想去判斷是否為完全二叉樹。

思維導圖:

代碼實現:

bool IsCompleteTree(BTreeNode* root){if(!root){return true;}my_Queue* BTqueue = Queue_Init();QueuePush(BTqueue,root);bool null_seen = false;while (!IsQueueEmpty(BTqueue)){QueueDataType Front = QueueFront(BTqueue);QueuePop(BTqueue);if(Front == NULL){null_seen = true;}else{if(null_seen){QueueDestroy(BTqueue);BTqueue = NULL;return false;}QueuePush(BTqueue,Front->_left);QueuePush(BTqueue,Front->_right); }}QueueDestroy(BTqueue);BTqueue = NULL;return true;
}

10、測試函數如下:

//測試函數
int main(){char str[100] = {0};scanf("%s",str);int i = 0;BTreeNode* root = CreateTree(str,&i);PreOrder(root);printf("\n");printf("%d ",BTreeSize(root));printf("%d ",BTreeLeafSize(root));printf("%d ",BTreeLevelKSize(root,3));BTreeNode* target = BTreeFind(root,'D');printf("%c ",target->_data);BTree_LevelOrder(root);if(IsCompleteTree(root)){printf("yes\n");}else{printf("No\n");}
}

好了,關于二叉樹的c語言相關的內容就分享到這了,后續有關二叉樹的內容我們利用c++實現。

謝謝大家的點贊和收藏!👍

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

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

相關文章

Java注解家族--`@ResponseBody`

ResponseBody ResponseBody是 Spring 框架中的一個注解,在基于 Spring 的 Web 開發中扮演著重要角色,以下是對它的詳細總結: 1.定義與基本功能 定義:ResponseBody注解用于將 Controller 方法的返回值,通過適當的 HttpM…

react-window 大數據列表和表格數據渲染組件之虛擬滾動

簡介 React Window 是一個高效的 React 組件庫,專為渲染大數據列表和表格數據而設計。它通過”虛擬化”技術(也稱為”窗口化”或”列表虛擬化”)解決了在 React 應用中渲染大量數據時的性能問題。與傳統方法不同,React Window 只…

Eltable tree形式,序號列實現左對齊,并且每下一層都跟上一層的錯位距離拉大

要的是如圖所示效果序號加個class-name寫樣式然后給eltable加indent屬性就可以了,我設置的25

FOC算法中SIMULINK一些常用模塊(2)-Permanent Magnet Synchronous Machine模塊

一,介紹這三個模塊一起介紹了,由左到右,分別是電源模塊,驅動模塊和電機模塊。主要介紹一下電機模塊二,DC Voltage SourceDC Voltage Source 模塊是用于表示直流電壓源的基本組件,可以提供恒流直壓&#xff…

RPG62.制作敵人攻擊波數二:攻擊ui

1。經典創建userwidget,使用xmbtextblock,結構如下。然后設置動畫與音頻,上下的參數是一樣的,轉到圖表打開BP_SurvialGameMode2.再創建一個widget,結構如下新添的動畫打開XMBGameModeBase,創建構造函數AXMB…

DL00691-基于深度學習的軸承表面缺陷目標檢測含源碼python

DL00691-基于深度學習的軸承表面缺陷目標檢測含源碼python

Word 中為什么我的圖片一拖就亂跑,怎么精確定位?

核心原因:文字環繞方式 (Text Wrapping) 問題的根源在于圖片的**“文字環繞”**設置。 默認狀態:“嵌入型” (In Line with Text) 當您插入一張圖片時,Word默認會把它當作一個巨大的文字字符來處理。這就是為什么您拖動它時,它會像…

Linux物理地址空間入門:從硬件到內核內存的基石

目錄 一、物理地址空間是什么? 二、物理地址空間的構成:不僅僅是內存 三、Linux內核如何管理物理地址空間 (1)物理內存的碎片化問題 (2)物理地址的分區管理 (3)物理地址與內核…

【2025最新版】PDFelement全能PDF編輯器

工具https://pan.quark.cn/s/a56d17fd05dd強大全能的PDF編輯神器PDFelementPro 全能PDF工具套裝 PDF閱讀器 PDF創建器 PDF編輯器 PDF注釋器 PDF轉換器 OCR識別工具 表單填寫和創建 數據提取 批量處理 更多詳情萬興PDF專業版特性。格式轉換:PDFelement輕松…

基于單片機汽車駕駛防瞌睡防疲勞報警器自動熄火設計

(一)系統功能設計 51單片機汽車駕駛防疲勞防瞌睡報警器自動熄火15 本系統由STC89C52單片機、蜂鳴器、ADXL345重力加速度傳感器、繼電器控制、按鍵、指示燈及電源組成。 1、通過按鍵點亮led燈,代表車輛啟動和熄火。 2、車輛啟動后,…

OpenCV中的卷積高斯模糊與中值模糊

目錄 一、卷積高斯模糊 (Gaussian Blur) 1. 原理與數學基礎 2. OpenCV函數實現 3. 關鍵參數說明 4. 代碼示例 5. 特點與應用 二、中值模糊 (Median Blur) 1. 原理與數學基礎 2. OpenCV函數實現 3. 關鍵參數說明 4. 代碼示例 5. 特點與應用 三、兩種模糊方法對比分析…

macbookpro m1 max本兒上速搭一個elasticsearch+kibana環境

一、找個目錄,新建一個: docker-compose.yml version: "3.9" services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0 # 與 Kibana 版本一致container_name: elasticsearchenvironment:- discovery.typesingle-node- xpa…

部署zabbix企業級分布式監控

一. 監控系統的功能概述監控、從中文的字義來看,有兩個內容,一是檢測,二是控制。重點在第一個字眼,即檢測、預防的意思。監控,對應的英文單詞是 Monitoring。在計算機領域,可以將其分為5種監控類型。應用性…

【重學MySQL】redolog binlog

目錄 Buffer Pool是什么? redo log(Innodb獨有) 為什么需要redolog? 類比的方式巧記redolog binlog(Server層獨有) binlog是干啥的? 為什么有了 binlog, 還要有 redo log&…

企業信息化建設技術底座建設解決方案

1、企業數字化底座與數字化綜述2、企業數字化底座與數字化總體架構3、企業數字化底座與數字化規劃設計4、企業數字化底座與數字化建設運營5、企業數字化底座與數字化未來展望篇幅有限以下只展示部分截圖:

Spring Cloud Alibaba 之 Nacos

Spring Cloud Alibaba 之 Nacos . Nacos官方文檔: https://nacos.io/docs/latest/overview/?spm5238cd80.47ee59c.0.0.770fcd36HoVbU6 1.什么是Nacos Nacos(Dynamic Naming and Configuration Service)是阿里巴巴開源的一款動態服務發現、…

Car Kit重構車機開發體驗,讓車載應用開發駛入快車道

在智能座艙成為汽車行業“新四化”核心戰場的今天,開發者們正面臨這樣的挑戰:如何讓手機應用快速適配車機場景?如何實現手機與車機無感流轉?如何在保障駕駛安全的前提下提供沉浸式交互體驗? HarmonyOS SDK 車服務&…

ruoyi-flowable-plus Excel 導入數據 Demo

📁 項目結構簡述 ruoyi-flowable-plus 是基于 RuoYi 的擴展項目,使用: 后端:Spring Boot MyBatis Flowable前端:Vue.js 📥 Excel 導入功能 Demo 以導入用戶數據為例,展示完整導入流程。 …

kafka 日志索引 AbstractIndex

AbstractIndexAbstractIndex 是 Kafka 日志(Log)子系統中一個至關重要的基礎類。它為 Kafka 的各種索引文件(如偏移量索引 .index 和時間戳索引 .timeindex)提供了一個統一的、抽象的框架。這個類的設計目標是實現極高的讀寫性能和…

重學前端008 --- 響應式網頁設計 CSS 無障礙 Quiz

文章目錄meta 總結html 頁面結構img 尺寸子選擇器 >a 錨點僅屏幕閱讀器可見li 元素的懸停設置小屏幕防止溢出meta 總結 <head><!-- 基礎字符編碼聲明 --><meta charset"UTF-8"><!-- 視口設置&#xff0c;響應式設計必備 --><meta nam…