數據結構初階:二叉樹(四)

概述:本篇博客主要介紹鏈式結構二叉樹的實現。

目錄

1.實現鏈式結構二叉樹

1.1 二叉樹的頭文件(tree.h)

1.2 創建二叉樹?

?1.3 前中后序遍歷

1.3.1 遍歷規則?

1.3.1.1 前序遍歷代碼實現

1.3.1.2??中序遍歷代碼實現

1.3.1.3? 后序遍歷代碼實現

?1.4 二叉樹結點的個數

?1.5 二叉樹葉子結點個數

1.6? 二叉樹第k層結點個數

1.7? 二叉樹的深度/高度

?編輯

?1.8 查找值為x的結點

1.9 二叉樹的銷毀?

2. 小結?


1.實現鏈式結構二叉樹

1.1 二叉樹的頭文件(tree.h)
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//定義鏈式結構二叉樹
//二叉樹結點的結構
typedef char BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;//前序遍歷
void preOrder(BTNode* root);
//中序遍歷
void InOrder(BTNode* root);
//后序遍歷
void postOrder(BTNode* root);//二叉樹結點個數
int BinaryTreeSize(BTNode* root);
//void BinaryTreeSize(BTNode* root,int* psize);//二叉樹葉子結點個數
int BinaryTreeLeafSize(BTNode* root);//二叉樹第k層結點個數
int BinaryTreeLevelKSize(BTNode* root, int k);//二叉樹的深度/高度
int BinaryTreeDepth(BTNode* root);//二叉樹查找值為x的結點
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);//二叉樹銷毀
void BinaryTreeDestroy(BTNode** root);//層序遍歷
void LevelOrder(BTNode* root);//判斷二叉樹是否是完全二叉樹
bool BinaryTreeComplete(BTNode* root);
1.2 創建二叉樹?

?用鏈表來表示一顆二叉樹,即用鏈來指示元素的邏輯關系。通常的方法是鏈表中每個結點由三個域組成,數據域和左右指針域左右指針分別用來給出該結點左孩子和右孩子所在的鏈結點的存儲地址,其結構如下:

//定義鏈式結構二叉樹
//二叉樹結點的結構
typedef char BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;  // 指向當前結點左孩子struct BinaryTreeNode* right; // 指向當前結點右孩子
}BTNode;

二叉樹的創建方式比較復雜,為了更好走進二叉樹的學習中,我們先手動構建一顆鏈式二叉樹。?

#include"Tree.h"
BTNode* buyNode(char x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));node->data = x;node->left = node->right = NULL;return node;
}
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;
}

回顧二叉樹的概念,二叉樹分為空樹和非空二叉樹非空二叉樹根結點根結點的左子樹根結點的右子樹組成的。?

?

?根結點的左子樹和右子樹分別又是由子樹結點、子樹結點的左子樹子樹結點的右子樹組成的,因此二叉樹定義式遞歸式的,后續鏈式二叉樹的操作基本都是按照該概念實現的。

?1.3 前中后序遍歷

二叉樹的操作離不開樹的遍歷,我們先來看一下二叉樹的遍歷有哪些方式。?

?

1.3.1 遍歷規則?

?按照規則,二叉樹的遍歷有:前序/中序/后序的遞歸結構遍歷:

1)前序遍歷(Preorder Traversal 亦稱先序遍歷):訪問根結點的操作發生在遍歷其左右子樹之前

訪問順序為:根結點、左子樹、右子樹

?2)中序遍歷(Inorder Traversal):訪問根結點的操作發?在遍歷其左右子樹之中(間)

訪問順序為:左子樹、根結點、右子樹?

3)后序遍歷(Postorder Traversal):訪問根結點的操作發生在遍歷其左右子樹之后

?訪問順序為:左子樹、右子樹、根結點

1.3.1.1 前序遍歷代碼實現
void preOrder(BTNode* root)
{if(root == NULL){printf("NULL ");return;}printf("%c ", root->data);preOrder(root->left);preOrder(root->right);
}

邏輯概述:?

?這段 代碼定義了一個先序遍歷二叉樹的函數 `preOrder`。函數的參數是一個指向二叉樹節點的指針 `root`。

如果 `root` 為空,函數會輸出 `NULL` 并返回。否則,函數會先輸出當前節點的數據,然后對左子樹和右子樹分別遞歸調用 `preOrder` 函數進行先序遍歷。

在代碼中,`printf("%c ", root->data);` 用于輸出當前節點的數據,假設 `data` 是字符類型。?

1.3.1.2??中序遍歷代碼實現
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%c ", root->data);InOrder(root->right);
}

邏輯概述:?

這段代碼是一個二叉樹的中序遍歷函數。其功能是:如果根節點為空,輸出"NULL "并返回;否則,先對左子樹進行中序遍歷,然后輸出根節點的數據,最后對右子樹進行中序遍歷。其實現過程與常見的二叉樹中序遍歷的邏輯一致。?

1.3.1.3? 后序遍歷代碼實現
void postOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}postOrder(root->left);postOrder(root->right);printf("%c ", root->data);
}

邏輯概述:?

?這段代碼定義了一個二叉樹的后序遍歷函數 `postOrder` 。函數的作用是:如果根節點為空,輸出 `"NULL "` 并返回;否則,先對左子樹進行后序遍歷,再對右子樹進行后序遍歷,最后輸出根節點的數據。這符合二叉樹后序遍歷的邏輯,即先遍歷左子樹,再遍歷右子樹,最后訪問根節點。?

?1.4 二叉樹結點的個數
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return 1 + BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

邏輯概述:?

?這段代碼定義了一個計算二叉樹節點個數的函數 `BinaryTreeSize` 。

函數的邏輯是如果根節點為空,返回 0;如果根節點的左右子樹都為空,返回 1;否則,返回 1 加上左子樹的節點個數和右子樹的節點個數。其中,左子樹和右子樹的節點個數通過遞歸調用 `BinaryTreeLeafSize` 函數來計算。?

?

?1.5 二叉樹葉子結點個數
//二叉樹葉子結點個數
int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

?邏輯概述:

?這段代碼定義了一個計算二叉樹葉子結點個數的函數`BinaryTreeLeafSize`

函數的邏輯是:如果根節點為空,返回0;如果根節點的左右子樹都為空,說明該節點為葉子節點,返回1;否則,通過遞歸調用函數本身分別計算左子樹和右子樹的葉子節點個數,并將它們相加后返回。?

1.6? 二叉樹第k層結點個數
// 計算二叉樹第 k 層結點個數
int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL) {return 0;}if (k == 1){return 1;}return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

?邏輯概述:

這段代碼的功能是計算二叉樹中第k層的節點個數如果根節點為空,返回0。如果k等于1說明當前根節點就是第k層的節點,返回1否則,通過遞歸調用函數本身,分別計算左子樹和右子樹中第k - 1層的節點個數,并將它們相加后返回。

1.7? 二叉樹的深度/高度
//二叉樹的深度/高度
int BinaryTreeDepth(BTNode* root)
{if (root == NULL){return 0;}int leftDep = BinaryTreeDepth(root->left);int rightDep = BinaryTreeDepth(root->right);return 1 + (leftDep > rightDep ? leftDep : rightDep);
}

邏輯概述:?

?這段代碼定義了一個計算二叉樹深度(高度)的函數 `BinaryTreeDepth` 。

函數的邏輯是:如果根節點為空,返回 0 。然后分別計算左子樹和右子樹的深度,記為 `leftDep` 和 `rightDep` 。最后,二叉樹的深度為 1 加上 `leftDep` 和 `rightDep` 中的較大值。?

?1.8 查找值為x的結點
//二叉樹查找值為x的結點
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* leftFind = BinaryTreeFind(root->left, x);if (leftFind){return leftFind;}BTNode* rightFind = BinaryTreeFind(root->right, x);if (rightFind){return rightFind;}return NULL;
}

邏輯概述:?

?這段代碼定義了一個在二叉樹中查找值為`x`的節點的函數`BinaryTreeFind`。

函數的執行過程如下:
- 如果根節點為空,直接返回`NULL`,表示未找到。
- 如果根節點的值等于`x`,則返回根節點。
- 然后在左子樹中遞歸查找值為`x`的節點,如果找到則返回該節點。
- 如果在左子樹中未找到,再在右子樹中遞歸查找值為`x`的節點,如果找到則返回該節點。
- 如果在整個二叉樹中都未找到值為`x`的節點,則最終返回`NULL`。?

1.9 二叉樹的銷毀?
//二叉樹銷毀
void BinaryTreeDestroy(BTNode** root)
{if (*root == NULL){return;}BinaryTreeDestroy(&((*root)->left));BinaryTreeDestroy(&((*root)->right));*root == NULL;
}

2. 小結?

以上便是本篇博客的所有內容了,如果這篇博客能給大家帶來知識,還請大家多多點贊。?

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

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

相關文章

Electron Forge【實戰】桌面應用 —— AI聊天(下)

此為系列教程&#xff0c;需先完成 Electron Forge【實戰】桌面應用 —— AI聊天&#xff08;上&#xff09;Electron Forge【實戰】桌面應用 —— AI聊天&#xff08;中&#xff09; 會話列表按更新時間倒序加載 src/db.ts db.version(1).stores({// 主鍵為id&#xff0c;且…

[架構之美]Ubuntu源碼部署APISIX全流程詳解(含避坑指南)

[架構之美]Ubuntu源碼部署APISIX全流程詳解(含避坑指南) 一、離線安裝場景需求分析 1.1 典型應用場景 金融/政務內網環境生產環境安全合規要求邊緣計算節點部署1.2 離線安裝難點 #mermaid-svg-B25djI0XquaOb1HM {font-family:"trebuchet ms",verdana,arial,sans-s…

多頭注意力(Multi?Head Attention)

1. 多頭注意力&#xff08;Multi?Head Attention&#xff09;原理 設輸入序列表示為矩陣 X ∈ R B L d model X\in\mathbb{R}^{B\times L\times d_{\text{model}}} X∈RBLdmodel?&#xff0c;其中 B B B&#xff1a;批大小&#xff08;batch size&#xff09;&#xff0c…

系列位置效應——AI與思維模型【80】

一、定義 系列位置效應思維模型是指在一系列事物或信息的呈現過程中&#xff0c;人們對于處于系列開頭和結尾部分的項目的記憶效果優于中間部分項目的現象。具體而言&#xff0c;開頭部分的記憶優勢被稱為首因效應&#xff0c;結尾部分的記憶優勢被稱為近因效應。這種效應反映…

MyBatis XML 配置完整示例(含所有核心配置項)

MyBatis XML 配置完整示例&#xff08;含所有核心配置項&#xff09; 1. 完整 mybatis-config.xml 配置文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""htt…

電商數據中臺架構:淘寶 API 實時采集與多源數據融合技術拆解

引言 在當今競爭激烈的電商領域&#xff0c;數據已成為企業決策和業務發展的核心驅動力。電商數據中臺能夠整合和管理企業內外部的各種數據&#xff0c;為業務提供有力支持。其中&#xff0c;淘寶 API 實時采集與多源數據融合技術是數據中臺架構中的關鍵部分。本文將深入探討這…

ubuntu22.04部署Snipe-IT

文章目錄 參考鏈接一、寫在前二、安裝操作系統三、安裝 PHP四、下載 Snipe-IT五、安裝依賴六、安裝數據庫并創建用戶七、安裝 Snipe-IT八、安裝 Nginx九、Web 繼續安裝 Snipe-IT補充&#xff1a;20250427補充&#xff1a; 最后 參考鏈接 How to Install Snipe-IT on Ubuntu 22…

圖論---Bellman-Ford算法

適用場景&#xff1a;有邊數限制 ->&#xff08;有負環也就沒影響了&#xff09;&#xff0c;存在負權邊&#xff0c;O( n * m )&#xff1b; 有負權回路時有的點距離會是負無窮&#xff0c;因此最短路存在的話就說明沒有負權回路。 從1號點經過不超過k條邊到每個點的距離…

A. Ideal Generator

time limit per test 1 second memory limit per test 256 megabytes We call an array aa, consisting of kk positive integers, palindromic if [a1,a2,…,ak][ak,ak?1,…,a1][a1,a2,…,ak][ak,ak?1,…,a1]. For example, the arrays [1,2,1][1,2,1] and [5,1,1,5][5,…

[詳細無套路]MDI Jade6.5安裝包下載安裝教程

目錄 1. 軟件包獲取 2. 下載安裝 3. 啟動 4. 問題記錄 寫在前面: 垂死病中驚坐起,JAVA博主居然開始更博客了~ 最近忙項目了, 沒啥更新的動力,見諒~見諒~. 這次博主的化工友友突然讓幫安裝JADE6.5軟件,本來以為不就一個軟件,直接拿捏. 不料竟然翻了個小車, 反被拿捏了. 既…

Serverless 在云原生后端的實踐與演化:從函數到平臺的革新

??個人主頁??:慌ZHANG-CSDN博客 ????期待您的關注 ???? 一、引言:從服務器到“無服務器”的后端演變 在傳統后端開發中,我們需要為服務配置并維護服務器資源,無論是物理機、虛擬機還是容器化服務,都需要: 管理系統運行環境 監控負載與擴縮容 保證高可用與安…

【專題三】二分查找(2)

&#x1f4dd;前言說明&#xff1a; 本專欄主要記錄本人的基礎算法學習以及LeetCode刷題記錄&#xff0c;按專題劃分每題主要記錄&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代碼&#xff1b;&#xff08;2&#xff09;優質解法 優質代碼&#xff1b;&#xff…

MySQL 詳解之函數:數據處理與計算的利器

在 MySQL 中,函數可以接受零個或多個輸入參數,并返回一個值。這些函數可以在 SELECT 語句的字段列表、WHERE 子句、HAVING 子句、ORDER BY 子句以及 UPDATE 和 INSERT 語句中使用。合理利用函數,可以簡化 SQL 語句,提高開發效率。 MySQL 提供了大量的內置函數 (Built-in F…

探索具身智能協作機器人:技術、應用與未來

具身智能協作機器人&#xff1a;概念與特點 具身智能協作機器人&#xff0c;簡單來說&#xff0c;就是將人工智能技術與機器人實體相結合&#xff0c;使其能夠在與人類共享的空間中進行安全、高效協作的智能設備。它打破了傳統機器人只能在預設環境中執行固定任務的局限&#…

基于物聯網的園林防火監測系統

標題:基于物聯網的園林防火監測系統 內容:1.摘要 隨著全球氣候變化和人類活動影響&#xff0c;園林火災發生頻率呈上升趨勢&#xff0c;給生態環境和人類生命財產造成巨大損失。為有效預防和應對園林火災&#xff0c;本文提出基于物聯網的園林防火監測系統。該系統綜合運用傳感…

JAVA多線程(8.0)

目錄 線程池 為什么使用線程池 線程池的使用 工廠類Executors&#xff08;工廠模式&#xff09; submit 實現一個線程池 線程池 為什么使用線程池 在前面我們都是通過new Thread() 來創建線程的&#xff0c;雖然在java中對線程的創建、中斷、銷毀、等值等功能提供了支持…

用go從零構建寫一個RPC(仿gRPC,tRPC)--- 版本1

希望借助手寫這個go的中間件項目&#xff0c;能夠理解go語言的特性以及用go寫中間件的優勢之處&#xff0c;同時也是為了更好的使用和優化公司用到的trpc&#xff0c;并且作者之前也使用過grpc并有一定的興趣&#xff0c;所以打算從0構建一個rpc系統&#xff0c;對于生產環境已…

【學習筆記】Stata

一、Stata簡介 Stata 是一種用于數據分析、數據管理和圖形生成的統計軟件包&#xff0c;廣泛應用于經濟學、社會學、政治科學等社會科學領域。 二、Stata基礎語法 2.1 數據管理 Stata 支持多種數據格式的導入&#xff0c;包括 Excel、CSV、文本文件等。 從 Excel 文件導入…

Redis數據結構SDS,IntSet,Dict

目錄 1.字符串&#xff1a;SDS 1.1.為什么叫做動態字符串 2.IntSet 2.1.inset如何保存大于當前編碼的最大數字&#xff1f; 3.Dict 3.1Dict的擴容 3.2Dict的收縮 3.3.rehash 1.字符串&#xff1a;SDS SDS的底層是C語言編寫的構建的一種簡單動態字符串 簡稱SDS&#xff…

Maven的聚合工程與繼承

目錄 一、為什么需要使用Maven工程 二、聚合工程的結構 三、聚合工程實現步驟 四、父工程統一管理版本 五、編譯打包 大家好&#xff0c;我是jstart千語。想著平時開發項目似乎都是用maven來管理的&#xff0c;并且大多都是聚合工程。而且在maven的聚合工程中&#xff0c…