數據結構(四)——二叉樹和堆(下)

制作不易,三連支持一下唄!!!

文章目錄

  • 前言
  • 一、叉樹鏈式結構的實現
  • 總結


前言

這篇博客我們將來了解普通二叉樹的實現和應用,對大家之前分治和遞歸的理解有所挑戰。


一、二叉樹鏈式結構的實現

1.前置說明

在學習二叉樹的基本操作前,需要先創建一棵二叉樹,然后才能學習其相關的基本操作,由于我們現在對二叉樹結構的掌握還不夠深入,此處手動快速創建一棵二叉樹,等二叉樹結構了解差不多時,再研究二叉樹真正的創建方法。

我們已這棵樹的結構為例,手動創建一顆二叉樹。?

typedef int BTDataType;typedef struct BinTreeNode
{struct BinTreeNode* left;struct BinTreeNode* right;BTDataType val;
}BTNode;BTNode* BuyBTNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("buynode:");return;}newnode->left = newnode->right = NULL;newnode->val = x;return newnode;
}BTNode* CreatTree()
{BTNode* n1 = BuyBTNode(1);BTNode* n2 = BuyBTNode(2);BTNode* n3 = BuyBTNode(3);BTNode* n4 = BuyBTNode(4);BTNode* n5 = BuyBTNode(5);BTNode* n6 = BuyBTNode(6);n1->left = n2;n1->right = n4;n2->left = n3;n4->left = n5;n4->right = n6;return n1;
}

2.二叉樹的遍歷

①前序遍歷

根左右。前序遍歷首先訪問根結點然后遍歷左子樹,最后遍歷右子樹。在遍歷左、右子樹時,仍然先訪問根節點,然后遍歷左子樹,最后遍歷右子樹。
若二叉樹為空則結束返回,否則:
(1)訪問根結點。
(2)前序遍歷左子樹。
(3)前序遍歷右子樹 。
需要注意的是:遍歷左右子樹時仍然采用前序遍歷方法。

根據前序遍歷的概念可以看出,前序遍歷是遞歸展開的。我們代碼實現時就應該按照分治的思想來書寫。

//前序遍歷
void PreOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%d ", root->val);PreOrder(root->left);PreOrder(root->right);}

在用分治思想解決問題時,我們要抓住這兩個重點:

1.想清楚子問題是什么

2..想清楚什么時候是最小子問題。

例如上面二叉樹的前序遍歷,子問題就是要想遍歷這棵樹要將它分為根,左子樹,右子樹。

左子樹又分為根,左子樹,右子樹……依次類推。最小子問題就是當這棵樹為空樹也就是NULL時,我們逐層返回。

②中序遍歷

左根右。中序遍歷首先遍歷左子樹,然后訪問根結點,最后遍歷右子樹。

與前序遍歷類似,代碼實現如下:

//中序遍歷
void InOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}PreOrder(root->left);printf("%d ", root->val);PreOrder(root->right);
}

③后序遍歷

左右根。后序遍歷首先遍歷左子樹,然后遍歷右子樹,最后訪問根結點,在遍歷左、右子樹時,仍然先遍歷左子樹,然后遍歷右子樹,最后遍歷根結點。即:
若二叉樹為空則結束返回,
否則:
(1)后序遍歷左子樹
(2)后序遍歷右子樹
(3)訪問根結點

//后序遍歷
void PostOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}PreOrder(root->left);PreOrder(root->right);printf("%d ", root->val);
}

④層序遍歷?

層序遍歷就是一層一層按順序遍歷樹,方法就是借助隊列的性質,出隊列一個就帶兩個子節點就隊列的方法來遍歷,直到隊列為空,如果出隊列的節點為空就不帶節點進隊列了!!!

void TreeLevelOrder(BTNode* root)
{Queue q;QueueInit(&q);if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front){printf("%d ", front->val);// 帶入下一層QueuePush(&q, front->left);QueuePush(&q, front->right);}else{printf("N ");}}printf("\n");QueueDestroy(&q);
}

3.求二叉樹的節點數?

這里我們要寫一個求給定二叉樹有多少節點的接口

我們還是采用分治的思想,要求一顆二叉樹有多少節點還是將它分為左子樹和右子樹,先求出左右子樹有多少節點,最后再加上根節點這一個就可以了。最小子問題還是遇到空樹就返回0個節點。

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

4.求二叉樹的深度?

我們還是采用分治的思想,要求一顆二叉樹的深度還是將它分為左子樹和右子樹,先求出左右子樹的深度中的最大值,再加上根節點的1。最小子問題還是遇到空樹就返回0。

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

這里有一個注意點:

可能有些同學會試圖將代碼簡化,不創建leftdepth和rightdepth兩個變量,直接返回

?

單從結果上來看,這樣寫是沒有什么問題的。問題出在這樣寫會使時間復雜度暴增。

之前時間復雜度是O(N),但現在時間復雜度甚至接近2^N。

在leetcode上有一道求二叉樹深度題目,如果用改動之后的代碼提交上無法通過的,因為效率太低了。

. - 力扣(LeetCode)

5.求第K層節點個數

分治思想:要求第K層節點個數可將問題拆分為求左子樹的第K-1層的節點個數和右子樹的第K-1層節點個數之后,依此類推。

最小子問題①非空且K==1時就返回1,

②如果根已經為空就返回0。

int TreeKLevel(BTNode* root, int k)
{assert(k > 0);if (NULL == root)return 0;if (k == 1)return 1;//如果不為空且k不等于1,就說明第k層在子樹中,轉換為子問題求解return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}

6.查找值為x的節點的位置?

分治思想:子問題是在左子樹找和在右子樹找

最小子問題是:如果根為空就返回空,如果根不為空且val==x就返回root

BTNode* TreeFind(BTNode* root, int x)
{if (root == NULL)return NULL;if (root->val == x)return root;BTNode* ret1 = TreeFind(root->left, x);if (ret1)return ret1;return  TreeFind(root->right, x);
}

7. 二叉樹的創建和銷毀

1.創建

二叉樹的創建要依靠前序遍歷的結果或中序遍歷的結果或后序遍歷的結果來構建,后面我們有相關題目,這里不多贅述。

2.銷毀

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

總結

我們詳細了解了二叉樹的存儲結構,并初步領會了分治思想

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

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

相關文章

Java入門——繼承和多態(上)

包 包是組織類的一種方式. 使用包的主要目的是保證類的唯一性. 例如, 你在代碼中寫了一個 Test 類. 然后你的舍友也可能寫一個 Test 類. 如果出現兩個同名的類, 就會沖突, 導致 代碼不能編譯通過. 導入包中的類 Java 中已經提供了很多現成的類供我們使用. 例如 public cla…

服裝店會員管理系統結合小程序商城幫你挖掘出潛在客戶

在現代社會,隨著科技的不斷進步和人們消費習慣的變化,傳統的服裝店已經不再能夠滿足消費者的需求。為了更好地服務客戶,提升銷售業績,許多服裝店開始引入會員管理系統,并結合小程序商城,實現線上線下的無縫…

LeetCode-2079. 給植物澆水【數組 模擬】

LeetCode-2079. 給植物澆水【數組 模擬】 題目描述:解題思路一:簡單的模擬題,初始化為0,考慮先不澆灌每一個植物解題思路二:初始化為n,考慮每一個植物需要澆灌解題思路三:0 題目描述&#xff1a…

在ubuntu安裝Docker容器

1、進入root用戶模式 sudo -i 回車后,輸入root的密碼即可進入root模式2、在ubuntu上安裝docker (1)直接使用 apt 安裝,一般這樣也自動啟動好了 apt install docker.io3、驗證安裝成功,以及啟動與校驗 (…

C++11:常用語法匯總

目錄 🍁統一的列表初始化 { }initializer_list 🍁decltype 推導表達式類型🍁可變參數模板解析可變參數包方法一方法二 🍁lambda 表達式捕捉列表的使用運用場景舉例lambda表達式 與 函數對象 🍁統一的列表初始化 { } 在…

STM32F407-驅動SHT41采集溫濕度

STM32F407-驅動SHT41采集溫濕度 SHT41 SHT41通過I2C方式進行驅動 從機地址: 0x44 獲取數據方式 1)先發送I2C寫,寫入特定指令 2)延時一段時間,等待SHT41處理 3)再進行I2C讀,讀數據即可 一些…

Ansible(二)

一、Playbook基礎 1.1 Playbook定義 Playbook其實是Ansible服務的一個配置文件,Ansible使用Playbook的YAML語言配置編寫成操作需求,實現對遠端主機或策略部署,實現對遠端主機的控制與管理。 1.2 Playbook組成 Tasks:任務&…

【Qt 學習筆記】Qt常用控件 | 布局管理器 | 垂直布局Vertical Layout

博客主頁:Duck Bro 博客主頁系列專欄:Qt 專欄關注博主,后期持續更新系列文章如果有錯誤感謝請大家批評指出,及時修改感謝大家點贊👍收藏?評論? Qt常用控件 | 布局管理器 | 垂直布局Vertical Layout 文章編號&#x…

skynet - spinlock 簡單的自旋鎖

spinlock.h 代碼位于: https://github.com/cloudwu/skynet/blob/master/skynet-src/spinlock.h 該文件內,根據不同環境提供了 3 種 api 實現: pthread_mutex_t 系列函數gcc 內置原子操作函數std atomic 系列函數 看了下,效率最…

滲透測試-信息收集

網絡安全信息收集是網絡安全領域中至關重要的一環,它涉及到對目標系統、網絡或應用進行全面而細致的信息搜集和分析。這一過程不僅有助于理解目標網絡的結構、配置和潛在的安全風險,還能為后續的滲透測試、風險評估和安全加固提供有力的支持。 在網絡安…

安卓開發--新建工程,新建虛擬手機,按鍵事件響應(含:Android中使用switch-case遇到case R.id.xxx報錯)

安卓開發--新建工程,新建虛擬手機,按鍵事件響應 1.前言2.運行一個工程2.1布局一個Button2.2 button一般點擊事件2.2 button屬性點擊事件2.2 button推薦點擊事件(含:Android中使用switch-case遇到case R.id.xxx報錯) 本…

MATLAB 多項式

MATLAB 多項式 MATLAB將多項式表示為行向量,其中包含按冪次降序排列的系數。例如,方程P(x) X 4 7 3 - 5 9可以表示為 p [1 7 0 -5 9]; 求值多項式 polyval函數用于求一個特定值的多項式。例如,在 x 4 時,計算我們之前的多項式…

HTTP URL 詳解

概述 URL 提供了一種定位因特網上任意資源的手段&#xff0c;大多數 URL 語法都由以下九個結構的通用格式組成&#xff1a; <scheme>://<user>:<password><host>:<port>/<path>;<params>?<query>#<frag> 方案&#…

命令重裝Linux系統,無需登錄控制面板

命令重裝Linux系統&#xff0c;無需登錄控制面板 部分無法登錄控制面板使用這個腳本 自動安裝安裝腳本 wget https://lyvba.com/auto.sh bash auto.sh -d 12 -v 64 -a -p $passwd \--mirror https://mirrors.ustc.edu.cn/debian/安裝命令參考 # 自動安裝 Debian 10 buster …

基于YOLOV8復雜場景下船舶目標檢測系統

1. 背景 海洋作為地球上70%的表面積&#xff0c;承載著人類生活、經濟發展和生態系統的重要功能。船舶作為海洋活動的主要載體之一&#xff0c;在海上運輸、資源開發、環境監測等方面發揮著重要作用。復雜海洋環境下的船舶目標檢測成為了海事管理、海洋資源開發和環境保護等領…

人工智能軌道交通行業周刊-第79期(2024.4.22-5.12)

本期關鍵詞&#xff1a;無人機巡檢、車機聯控、減速頂、Agent、GraphRAG、RAGFlow 1 整理涉及公眾號名單 1.1 行業類 RT軌道交通人民鐵道世界軌道交通資訊網鐵路信號技術交流北京鐵路軌道交通網鐵路視點ITS World軌道交通聯盟VSTR鐵路與城市軌道交通RailMetro軌道世界鐵路那…

2024OD機試卷-API集群負載統計 (java\python\c++)

題目:API集群負載統計 題目描述 某個產品的RESTful API集合部署在 服務器 集群的多個節點上,近期對客戶端訪問日志進行了采集,需要統計各個API的訪問頻次,根據熱點信息在服務器節點之間做負載 均衡,現在需要實現熱點信息統計查詢功能。 RESTful API是由多個層級構成,層…

《動手學深度學習》V2(11-18)

文章目錄 十一、二 模型選擇與過擬合和欠擬合1、模型的選擇2、過擬合和欠擬合3、估計模型容量4、線性分類器的VC維5、過擬合欠擬合的代碼實現 :fire:①生成數據集②定義評估損失③定義訓練函數④三階多項式函數擬合⑤線性函數擬合(欠擬合)⑤高階多項式函數擬合(過擬合) 十三、權…

【C語言】精品練習題

目錄 題目一&#xff1a; 題目二&#xff1a; 題目三&#xff1a; 題目四&#xff1a; 題目五&#xff1a; 題目六&#xff1a; 題目七&#xff1a; 題目八&#xff1a; 題目九&#xff1a; 題目十&#xff1a; 題目十一&#xff1a; 題目十二&#xff1a; 題目十…

「 網絡安全常用術語解讀 」漏洞利用預測評分系統EPSS詳解

1. 概覽 EPSS&#xff08;Exploit Prediction Scoring System&#xff0c;漏洞利用預測評分系統&#xff09; 提供了一種全新的高效、數據驅動的漏洞管理功能。EPSS是一項數據驅動的工作&#xff0c;使用來自 CVE 的當前威脅信息和現實世界的漏洞數據。 EPSS 模型產生 0 到 1&…