[數據結構——lesson8.樹]

目錄

引言

學習目標

1.樹的概念及結構

1.1樹的定義

1.2樹的基本概念

1.3 樹的表示

(1)雙親表示法

(2)孩子表示法

(3)左孩子右兄弟表示法

1.4 樹在實際中的運用(表示文件系統的目錄樹結構)

結束語:


引言

之前我們學習了棧和隊列數據結構,接下來我們學習一種新的數據結構——

學習目標

  • 為什么要學習為什么要學習非線性結構 ---- 樹(Tree)
  • 數的定義和基本概念
  • 樹的表示
  • 樹的實際應用
  • 樹的性質

為什么要學習非線性結構 ---- 樹(Tree)

線性結構的優缺點

在線性結構中,無論是順序存儲,還是鏈式存儲,線性表均有其優缺點:

  • 順序表優點:
    1:順序存儲可以在 O(1) 的時間內找到特定次序的元素(下標的隨機訪問)
    2:CPU 高速緩存,命中率較高
  • 順序表缺點:?
    1:順序存儲在,數據中間、頭部 的插入和刪除元素需要挪動大量元素,需要時間O(n)
    2: ?順序存儲時,會出現空間不足,只能進行空間的擴容(異地擴容代價比較大)

  • 鏈表優點:
    1:在任意位置進行數據的插入和刪除的效率高,所需時間為O(1)
    2: ?按需申請空間和釋放,不存在擴容
  • 鏈表的缺點:
    1:在尋找特定次序的元素需要從鏈表頭部向后查找,需要時間O(n)
    2:? CPU高速緩存,命中率低?


?其實鏈表和順序表是一個互補的數據結構
?

優化方案 ----- 樹(Tree)

樹形結構:很好的結合了順序表和鏈表的優點,可以在O(logn)的時間內完成查找、更新、插入、刪除等操作,在實際的應用中,很多算法可以借助于樹形結構高效的實現很多功能。

樹的講解流程

此時此刻大家肯定很想了解什么是樹,在本篇博客中,并不能把所有樹的結構在此篇文章中進行詳細的介紹,我會通過步步延申的方式去講解樹。
樹 ? 二叉樹? 搜索二叉樹 ? 平衡搜索二叉樹 (AVL樹和紅黑樹) ? M叉多叉平衡搜索樹 (B樹和B+樹)

1.樹的概念及結構

1.1樹的定義

樹是一種非線性的數據結構,它是由nn>=0)個有限結點組成一個具有層次關系的集合。把它叫做樹是因
為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的
  • 有一個特殊的結點,稱為根結點,根結點沒有前驅結點
  • 除根結點外,其余結點被分成M(M>0)互不相交的集合T1T2……Tm,其中每一個集合Ti(1<= i <= m)又是一棵結構與樹類似的子樹。每棵子樹的根結點有且只有一個前驅,可以有0個或多個后繼
  • 因此,樹是遞歸定義的。

注意:樹形結構中,子樹之間不能有交集,否則就不是樹形結構。

1.2樹的基本概念

我們根據這棵樹來介紹一下樹的基本概念

  • 節點的度:一個節點含有的子樹的個數稱為該節點的度,比如說節點1的度為2
  • 葉節點或終端節點:度為0的節點,比如說4,5,6節點
  • 非終端節點或分支節點:度不為0的節點,比如說2,3節點
  • 雙親結點或父節點:若一個節點含有子節點,則這個節點稱為其子節點的父節點。比如? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 說2是4,5的父節點
  • 孩子節點或子節點:一個節點含有的子樹的根節點稱為該節點的子節點,比如說4,5是? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2的子節點
  • 兄弟節點:具有相同父節點的節點互稱為兄弟節點,比如說4,5就是兄弟節點
  • 樹的度:一棵樹中,最大的節點的度稱為樹的度,比如說上面這棵樹的度為2
  • 節點的層次:從根開始定義起,根為第1層,根的子節點為第2層,以此類推
  • 樹的高度或深度:樹中節點的最大層次,比如說上面這棵樹的高度為3
  • 堂兄弟節點:雙親在同一層的節點互為堂兄弟,比如說5,6節點
  • 節點的祖先:從根到該節點所經分支上的所有節點,比如說1就是所有節點的祖先
  • 子孫:以某節點為根的子樹中任一節點都稱為該節點的子孫,比如說所有節點都是1的? ? ? ? ? ? ?子孫
  • 森林:由m(m>0)棵互不相交的樹的集合稱為森林

1.3 樹的表示

我們有三種方法表示上面這棵樹:

(1)雙親表示法

雙親表示法是用順序表,也就是數組對樹進行表示的。即用順序表存儲各個節點的數據,并且同時存儲其雙親節點的下標。

注意:根節點沒有雙親節點,所以特別記為-1。

聲明如下:

如下圖所示:

存儲方式如下:

說明:

  1. 因為根節點沒有父節點,將其父節點數組下標設置為-1,根節點存儲在順序表的第1個位置。
  2. 數據元素2、3、4的父節點為0,父節點數組下標為0,分別存儲在順序表的2、3、4個位置。
  3. 數據元素5、6的父節點為1,父節點數組下標為1,分別存儲在順序表的第5、6個位置。
  4. 數據元素7的父節點為3,父節點數組下標為3,存儲在順序表的第7個位置。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef int DataType;
typedef struct TreeNode
{DataType data;int parent;
}Node;typedef struct ParentTree
{// 數據結構的樹節點Node Tnode[MAXSIZE];int n;		//當前節點個數
}Ptree;// 初始化樹
void TreeInit(Ptree* ptree, int x, int parentIndex) 
{if (ptree->n >= MAXSIZE) {printf("Tree is full!\n");return;}ptree->Tnode[ptree->n].data = x;ptree->Tnode[ptree->n].parent = parentIndex;ptree->n++; // 增加節點計數  
}

雙親表示法的特點:

  • 優點:快速查找一個結點的父結點(直接通過parent字段獲取),結構簡單,空間開銷小(僅需存儲值和一個索引)。
  • 缺點:查找子結點時效率低(需遍歷整個數組,判斷哪些結點的parent等于當前結點的索引),不適合頻繁查找子結點的場景。
(2)孩子表示法

樹的孩子表示法就是采用順序表與鏈表結合的形式,用順序表存儲樹的值與鏈表的頭節點,而鏈表的頭節點存儲其孩子節點在順序表中的下標,若沒有則記為空(NULL)。

相當于對樹進行這樣的處理:

存儲方式如下:

說明:

添加一個數據(插入一個結點)

  1. 既要在數組中依次添加新的數據。
  2. 也要在其父節點后面用頭插法插入。

優缺點:

  • 優點:簡單且易于理解,適用于需要頻繁查找孩子節點的應用場景。
  • 缺點:不容易直接獲取節點的父節點。

代碼如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>#define MAXSIZE 10
typedef int DataType;
typedef struct ListNode
{int index;struct ListNode* next;
}ListNode;typedef struct TreeNode
{DataType data;ListNode* child;
}TNode;typedef struct Tree
{TNode nodes[MAXSIZE];int n;
}Tree;// 創建一個新的ListNode  
ListNode* createListNode(int index) 
{ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));if (newNode == NULL){perror("malloc fail:");exit(0);}newNode->index = index;newNode->next = NULL;return newNode;
}// 初始化樹  
void TreeInit(Tree* t, DataType x) 
{if (t->n >= MAXSIZE) {printf("Tree is full!\n");return;}t->nodes[t->n].data = x;t->nodes[t->n].child = NULL;  t->n++;
}// 向節點的子鏈表中添加一個新節點  
void InsertChild(Tree* t, int parentIndex, int childIndex)
{if (parentIndex >= t->n || childIndex >= t->n) {printf("error\n");return;}ListNode* newNode = createListNode(childIndex);if (newNode == NULL){perror("malloc fail:");return; // 內存分配失敗  }newNode->next = t->nodes[parentIndex].child;t->nodes[parentIndex].child = newNode;
}
(3)左孩子右兄弟表示法

最常用表示樹的的方法就是左孩子右兄弟表示法,即定義兩個指針,讓左指針指向子節點,右指針指向兄弟節點。如果沒有節點,則都指向空(NULL)。

如圖所示:

  • 基本原理:在這種表示法中,每個節點包含一個數據域和兩個指針域。其中一個指針指向該節點的第一個孩子節點(左孩子),另一個指針指向該節點的下一個兄弟節點(右兄弟)。通過這種方式,可將任意一棵多叉樹轉化為一棵二叉樹來表示。

節點定義:在 C++ 中,可按如下方式定義節點結構:

代碼如下:

#include <stdio.h>
#include <stdlib.h>
typedef int DataType;typedef struct TreeNode
{DataType data;struct TreeNode* leftChild;  // 指向左孩子  struct TreeNode* rightBro; // 指向右兄弟  
} TNode;// 創建一個新的樹節點
TNode* createTreeNode(DataType x)
{TNode* newNode = (TNode*)malloc(sizeof(TNode));if (newNode == NULL){perror("malloc fail:");exit(0);}newNode->data = x;newNode->leftChild = NULL;newNode->rightBro = NULL;return newNode;
}void InsertChild(TNode* t, DataType x, int isLeftChild) 
{if (t == NULL) {printf("Cannot insert into NULL node\n");return;}TNode* newNode = createTreeNode(x);if (newNode == NULL) {return;}// 如果isLeftChild為1,表示新節點應該作為左孩子插入  if (isLeftChild) {// 如果當前節點還沒有右兄弟,則直接將新節點設置為右兄弟if (t->leftChild == NULL) {t->leftChild = newNode;}// 如果當前節點已經有左孩子,則遍歷左孩子的右兄弟鏈表// 找到最后一個右兄弟,并將新節點插入為它的下一個右兄弟else {TNode* tmp = t->leftChild;while (tmp->rightBro != NULL) {tmp = tmp->rightBro;}tmp->rightBro = newNode;}}// 如果isLeftChild為0,表示新節點應該作為右兄弟插入else{// 如果當前節點還沒有右兄弟,則直接將新節點設置為右兄弟if (t->rightBro == NULL) {t->rightBro = newNode;}// 如果當前節點已經有右兄弟,則遍歷右兄弟鏈表// 找到最后一個右兄弟,并將新節點插入為它的下一個右兄弟else {TNode* tmp = t->rightBro;while (tmp->rightBro != NULL) {tmp = tmp->rightBro;}tmp->rightBro = newNode;}}
}

1.4 樹在實際中的運用(表示文件系統的目錄樹結構)

在linux環境下目錄結構就是有一顆樹構成,而在Windows環境下,目錄許多內容并不交叉,所以是由森林構成。

?樹的性質(重點)

?性質1:樹中的節點數等于所有節點度數加 1
????????從上圖可知,有 12 個節點 ?,A的度為:3, B的度為2, C 的度為1, D的度為2, E的度為1, F的度為0, G的度為2, H的度為0 , I的度為0,J的度為0,K的度0,L的度為0。


????????由性質 1 可知 樹的節點個數 = 每個節點的度數 + 1?

所以上圖 樹的節點數 = (3+2+1+2+1+0+2+0+0+0+0+0)+1 = 12
?

性質2:度為 m 的樹中第 i 層至多有 m^i-1 個節點(i>=1)

性質3:高度為 h 的 m 叉樹至多有? m^h-1/m-1 個節點

性質4:具有n個結點的m叉樹的最小高度為?logm(n*(m-1)+1)?

結束語:

下一節我們將繼續深入學習樹的知識

感謝你的三連支持!!!

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

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

相關文章

告別雙系統——WSL2+UBUNTU在WIN上暢游LINUX

在Windows 11上配置WSL開發環境指南 最近換工作需要深入研究代碼&#xff0c;發現WSL&#xff08;Windows Subsystem for Linux&#xff09;是微軟為Windows開發者提供的強大工具&#xff0c;可以在Windows上直接運行Ubuntu子系統&#xff0c;無需雙系統或虛擬機&#xff08;滿…

Python爬蟲實戰:研究Ticks and spines模塊,構建電商數據采集和分析系統

1. 引言 1.1 研究背景 在信息時代,互聯網數據呈現爆炸式增長,涵蓋社會、經濟、文化等多個領域,具有極高的研究與應用價值。如何高效獲取目標數據并進行深度分析,成為信息處理領域的重要課題。Python 憑借其豐富的庫支持和簡潔的語法,在數據爬取與分析領域得到廣泛應用:…

前端基礎 —— B / CSS基礎

一、CSS 基礎概述定義&#xff1a;層疊樣式表&#xff08;Cascading Style Sheets&#xff09;作用&#xff1a;美化頁面、實現樣式與結構分離二、CSS 基本語法與引入方式1. 語法規范選擇器 {一條/N條聲明}選擇器決定針對誰修改 (找誰) 聲明決定修改啥. (干啥)<style> p…

智能農機無人駕駛作業套圈路徑規劃

國產輕量級桌面GIS軟件Snaplayers實踐&#xff1a;智能農機無人駕駛作業套圈路徑規劃1、選擇地塊角點坐標文件2、加載地塊到地圖中3、設置套圈作業路徑規劃參數4、生成套圈作業路徑5、查看套圈路徑6、查看套圈路徑8、完成本算法已經在國內外等農場已經使用多年。Snaplayers研發…

Java Collection集合框架:體系、核心與選型

目錄 一、集合框架的頂層設計&#xff1a;接口與層次 1. 兩大核心接口&#xff1a;Collection 和 Map 2. Collection接口的三大派系 二、核心實現類詳解 1. List家族實現 2. Set家族實現 3. Queue/Deque家族實現 PriorityQueue&#xff1a; ArrayDeque&#xff1a; 三…

“計算機基礎、軟件工程、設計模式、數據結構算法、操作系統、數據庫、網絡、法律法規”是計算機領域從基礎理論到工程實踐

“計算機基礎、軟件工程、設計模式、數據結構算法、操作系統、數據庫、網絡、法律法規”是計算機領域從基礎理論到工程實踐、再到合規規范的核心知識體系&#xff0c;覆蓋了軟件開發、系統架構、技術合規等關鍵維度。以下將對每個領域進行系統拆解&#xff0c;包括核心內容、學…

利用Rancher平臺搭建Swarm集群

一、Rancher概述1、rancher平臺Rancher是一個開源的企業級容器管理平臺&#xff0c;它可以幫助企業在生產環境中輕松快捷地部署和管理容器&#xff0c;也可以輕松管理各種環境的Kubernetes&#xff0c;并提供對DevOps的支持。Rancher目前已經具備全棧化一鍵部署應用、各種編排調…

Debezium日常分享系列之:MongoDB 新文檔狀態提取

Debezium日常分享系列之&#xff1a;MongoDB 新文檔狀態提取變更事件結構行為配置數組編碼嵌套結構展平MongoDB $unset 處理確定原始操作添加元數據字段選擇性應用轉換的選項配置選項已知限制Debezium MongoDB 連接器會發出數據變更消息&#xff0c;以表示 MongoDB 集合中發生的…

OpenCV:圖像透視變換

文章目錄一、透視變換是什么&#xff1f;二、透視變換的核心原理1. 關鍵概念&#xff1a;透視變換矩陣2. 核心條件&#xff1a;4對對應點三、OpenCV實現透視變換的關鍵步驟步驟1&#xff1a;讀取并預處理圖像步驟2&#xff1a;尋找目標物體的4個頂點步驟3&#xff1a;計算透視變…

commons-csv

maven依賴<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-csv</artifactId><version>1.14.1</version></dependency…

LeetCode 1446.連續字符

給你一個字符串 s &#xff0c;字符串的「能量」定義為&#xff1a;只包含一種字符的最長非空子字符串的長度。 請你返回字符串 s 的 能量。 示例 1&#xff1a; 輸入&#xff1a;s “leetcode” 輸出&#xff1a;2 解釋&#xff1a;子字符串 “ee” 長度為 2 &#xff0c;只包…

CTFHub SSRF通關筆記9:302跳轉 Bypass 原理詳解與滲透實戰

目錄 一、SSRF與302跳轉 1、SSRF 2、302響應 3、SSRF與302結合 &#xff08;1&#xff09;SSRF源碼分析 &#xff08;2&#xff09;攻擊鏈條&#xff08;Flow of Exploit&#xff09; 二、滲透實戰 1、打開靶場 2、嘗試127.0.0.1訪問 3、file協議分析源碼 &#xff…

Windows-Use實戰:AI驅動的Windows自動化

Windows-Use實戰:AI驅動的Windows自動化 前言 項目介紹與準備工作 Windows-Use是什么? 系統要求 必需環境 步驟一:安裝Python和基礎環境 1.1 安裝Python 檢查Python版本 Python安裝步驟 1.2 創建項目目錄 步驟二:安裝Windows-Use 2.1 使用pip安裝(推薦) 步驟三:運行和基…

STM32-FreeRTOS操作系統-二值信號量與計數信號量

引言在嵌入式開發領域&#xff0c;任務同步與通信是系統穩定運行的核心。STM32配合FreeRTOS操作系統&#xff0c;為開發者提供了強大的工具支持。其中&#xff0c;二值信號量和計數信號量作為FreeRTOS的關鍵同步機制&#xff0c;分別用于任務間的簡單同步和資源計數控制。二值信…

MarTech營銷技術全景解析:概念、圖譜與最新實踐案例

一、引言&#xff1a;為什么企業越來越依賴MarTech&#xff1f;在數字化浪潮下&#xff0c;企業營銷環境正發生深刻變化&#xff1a;客戶觸點增加&#xff1a;從官網、社交媒體到短視頻、展會&#xff0c;信息渠道呈指數級增長。決策鏈條復雜&#xff1a;B2B客戶通常需要多輪調…

服務器 - 從一臺服務器切換至另一臺服務器(損失數十條訪客記錄)

服務器 - 從一臺服務器切換至另一臺服務器(損失數十條PV記錄為代價) 看著四年的服務器正式到期&#xff0c;沒什么轟轟烈烈的告別&#xff0c;就像目送老朋友轉身走遠&#xff0c;只默默記下&#xff1a;哦&#xff0c;原來它陪了我這么久啊。 前言 一臺陪伴了我4年的服務器昨…

《云原生邊緣與AI訓練場景:2類高頻隱蔽Bug的深度排查與架構修復》

在云原生技術向邊緣計算與AI訓練場景滲透的過程中&#xff0c;基礎設施層的問題往往會被場景特性放大——邊緣環境的弱網絡、異構硬件&#xff0c;AI訓練的高資源依賴、分布式協作&#xff0c;都可能讓原本隱藏的Bug以“業務故障”的形式爆發。這些問題大多不具備直觀的報錯信息…

【51單片機】【protues仿真】基于51單片機數控直流穩壓電源系統

目錄 一、主要功能 二、使用步驟 三、硬件資源 四、軟件設計 五、實驗現象 一、主要功能 1、數碼管顯示輸出電壓值 2、滑動電阻調節輸出電壓 3、電壓輸出范圍0-15V&#xff0c;步進值1 二、使用步驟 基于51單片機的數控直流穩壓電源是一種通過數字控制實現電壓調節的智…

xtuoj Rectangle

題目思路將矩形間的相交情況通過投影轉化為x、y兩個方向下的線段是否相交&#xff0c;即前面的題目&#xff0c;判斷兩個區間是否相交&#xff0c;x投影的每個區間的左端點是每個矩形x的min&#xff0c;右端點是每個矩形的x的max&#xff0c;y投影情況同理&#xff0c;只要x軸的…

【深度學習踩坑實錄】從 Checkpoint 報錯到 TrainingArguments 精通:QNLI 任務微調全流程復盤

作為一名深度學習初學者&#xff0c;最近在基于 Hugging Face Transformers 微調 BERT 模型做 QNLI 任務時&#xff0c;被Checkpoint 保存和TrainingArguments 配置這兩個知識點卡了整整兩天。從磁盤爆滿、權重文件加載報錯&#xff0c;到不知道如何控制 Checkpoint 數量&#…