【數據結構】C++語言實現二叉樹的介紹及堆的實現(詳細解讀)

9efbcbc3d25747719da38c01b3fa9b4f.gif

?c語言中的小小白-CSDN博客c語言中的小小白關注算法,c++,c語言,貪心算法,鏈表,mysql,動態規劃,后端,線性回歸,數據結構,排序算法領域.https://blog.csdn.net/bhbcdxb123?spm=1001.2014.3001.5343

給大家分享一句我很喜歡我話:

知不足而奮進,望遠山而前行!!!

鐵鐵們,成功的路上必然是孤獨且艱難的,但是我們不可以放棄,遠山就在前方,但我們能力仍然不足,所有我們更要奮進前行!!!

今天我們更新了二叉樹內容,

🎉 歡迎大家關注🔍點贊👍收藏??留言📝

首先我們為大家說一下樹的概念和結構,樹是一種非線性的數據結構,它是由n(n >= 0)個有限結點組成的一個具有層次關系的集合,把它叫做樹是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的

  • 有一個特殊的結點,稱為根結點,根節點沒有前驅結點。
  • 除跟根結點外,其余結點被分成M(M>0)個互不相交的集合T1、T2…Tm,其中每一個集合Ti(1<=i<=m)又是一棵結構與樹類似的子樹。每顆子樹的根節點有且只有一個前驅,可以有0個或多個后繼。
  • 因此,樹是遞歸定義的。

有關樹的一些概念:

  1. 節點的度:一個節點含有的子樹的個數稱為該節點的度;如上圖:A的為6
  2. 葉節點或終端節點:度為0的節點稱為葉節點;如上圖:B、C、H、I…等節點為葉節點非終端節點或分支節點:度不為0的節點;如上圖:D、E、F、G…等節點為分支節點
  3. 兄弟節點:具有相同父節點的節點互稱為兄弟節點;如上圖:B、C是兄弟節點
  4. 樹的度:一棵樹中,最大的節點的度稱為樹的度;如上圖:樹的度為6
  5. 節點的層次:從根開始定義起,根為第1層,根的子節點為第2層,以此類推;
  6. 樹的高度或深度:樹中節點的最大層次;如上圖:樹的高度為4(有兩種說法-從0開始還是從1開始,空樹-1,空樹0)
  7. 節點的祖先:從根到該節點所經分支上的所有節點;如上圖:A是所有節點的祖先
  8. 子孫:以某節點為根的子樹中任一節點都稱為該節點的子孫。如上圖:所有節點都是A的子孫
  9. 森林:由m (m>0)棵互不相交的多顆樹的集合稱為森林;(數據結構中的學習并查集本質就是一個森林)——(日常很少碰到森林,并查集就是一個森林)

其中這些概念中第 4、6、7條較為重要,其余了解一下即可。

樹的要求:

  • 子樹是不相交的
  • 除了根結點之外,每個結點有且僅有一個父結點
  • 一個N個結點的樹有N-1條邊

樹的表示

相對于線性表,樹的結構就復雜很多了。最常用的表示方法——孩子兄弟表示法。

二叉樹

與普通的樹最大的不同是它最多只有兩個子樹。

特殊的二叉樹

  1. 滿二叉樹:每一層都是滿的。

    假設一棵滿二叉樹的高度是 h,那么它的總結點個數是:20+21+22+…2(h-1) =N。

    推導公式:2^h-1 = N;h = log2N+1以2位底N的對數+1。

  2. 完全二叉樹

完全二叉樹是個效率很高的數據結構,完全二叉樹是由滿二叉樹引出來的。

假設樹的高度是h,前h-1層是滿的,最后一層不滿,但是最后一層從左往右都是連續的。

最后一層最少有一個結點。

結點個數為:2^h-1-X= N,高度近似為:h = log2N+1+X以二為底N的對數+1

圖有點難看不要介意

這些就是關于樹的一些基本概念,下面我們來介紹一下關于樹的實現。

堆的實現:

這里我們將會分為初始化、銷毀、建堆、堆的刪除、取出堆頂元素、判斷是否為空、向上調整和向下調整這幾步來完成。

頭文件及堆結構的定義:

#pragma once
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#include<cmath>
#include<utility>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;

初始化:

//初始化
void HPInit(HP* php)
{assert(php);php->a = NULL;php->capacity = php->size= 0;}

銷毀:

void HPDestroy(HP* php)
{assert(php);free(php);php->a = NULL;php->capacity = php->size = 0;}

向上調整:

//向上調整(小根堆)
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child>0){if (a[child] < a[parent])//小于就換就相當于建小堆//if (a[child] > a[parent])//大于就換就會變成大堆{std::swap(a[child], a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

建堆:

void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);if (tmp == NULL){perror("realloc failed!!!");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size++] = x;//向上調整AdjustUp(php->a, php->size - 1);
}

向下調整:

void AdjustDown(HPDataType* a, int n, int parent)
{//假設法//假設左孩子小int child = parent * 2 + 1;while(child<n){if (child + 1 < n &&a[child + 1] < a[child])//這里如果是左孩子大于右孩子,就要再加加child{++child;}if (a[child] < a[parent]){std::swap(a[child], a[parent]);parent = child;child = parent * 2 + 1;}else break;}}

刪除堆頂的數據:

HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}

判空:

bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

總代碼:

TEST.c:

#include"Heap.h"void TestHeap1()
{int a[] = { 4,2,8,1,5,6,7,9 };HP hp;HPInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));HPPop(&hp);}HPDestroy(&hp);
}void HeapSort(int* a, int n)
{//首先建堆//升序:建大堆//降序:建小堆for (int i=0;i<n;i++){AdjustUp(a, i);}int end = n - 1;///這里>0即可,因為=0時只剩下最后一個,就不再需要繼續進行了while (end>0)//思路就是:比如我們升序排序,那么我們就利用大根堆,每次都將最大的那個數放在最頂上,然后將它和最后一個交換,然后讓整體的大小--,那么最后一個就不再會受影響{std::swap(a[0], a[end]);AdjustDown(a, end, 0);--end;}}void TestHeap2()
{int a[] = { 4,2,8,1,5,6,9,7,3,10,23,14,125 };HeapSort(a, sizeof(a) / sizeof(0));for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){std::cout << a[i] << " ";}
}int main()
{TestHeap2();return 0;
}

Heap.c:

#include"Heap.h"//初始化
void HPInit(HP* php)
{assert(php);php->a = NULL;php->capacity = php->size= 0;}//銷毀
void HPDestroy(HP* php)
{assert(php);free(php);php->a = NULL;php->capacity = php->size = 0;}//向上調整(小根堆)
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child>0){if (a[child] < a[parent])//小于就換就相當于建小堆//if (a[child] > a[parent])//大于就換就會變成大堆{std::swap(a[child], a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}//建堆
void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);if (tmp == NULL){perror("realloc failed!!!");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size++] = x;//向上調整AdjustUp(php->a, php->size - 1);
}//向下調整
void AdjustDown(HPDataType* a, int n, int parent)
{//假設法//假設左孩子小int child = parent * 2 + 1;while(child<n){if (child + 1 < n &&a[child + 1] < a[child])//這里如果是左孩子大于右孩子,就要再加加child{++child;}if (a[child] < a[parent]){std::swap(a[child], a[parent]);parent = child;child = parent * 2 + 1;}else break;}}//刪除堆頂的數據
void HPPop(HP* php)
{assert(php);assert(php->size > 0);std::swap(php->a[0], php->a[php->size - 1]);//就是將第一個與最后一個換掉,然后將他們向下調整,php->size--;//直接size--刪去最后一個元素AdjustDown(php->a, php->size, 0);
}//取出堆頂數據
HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

Heap.h:

#pragma once
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#include<cmath>
#include<utility>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;//初始化
void HPInit(HP* php);//銷毀
void HPDestroy(HP* php);//建堆
void HPPush(HP* php,HPDataType x);//堆的刪除
void HPPop(HP* php);//取出堆頂數據
HPDataType HPTop(HP* php);bool HPEmpty(HP* php);void AdjustUp(HPDataType* a, int child);
void AdjustDown(HPDataType* a, int n, int parent);

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

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

相關文章

分布式系統的一致性與共識算法(三)

順序一致性(Sequential Consistency) ZooKeeper 一種說法是ZooKeeper是最終一致性&#xff0c;因為由于多副本、以及保證大多數成功的ZAB協議&#xff0c;當一個客戶端進程寫入一個新值&#xff0c;另外一個客戶端進程不能保證馬上就能讀到這個值&#xff0c;但是能保證最終能…

我的第一個網頁:武理天協

1. html代碼 1.1 首頁.html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>武理天協</title><link rel"stylesheet" href"./style.css"><link rel"stylesh…

【車載開發系列】SID$11服務配置

【車載開發系列】SID$11服務配置 前言 ECUReset(ECU重置),ECU作為Server端,執行Client發送來ECU Reset請求中重啟的類型(通過子服務區分)。對于UDS協議關于處理該請求的邏輯,沒有強制性定義。 Step1:SID和SubFunction的追加 BasicEditor→Dcm→DcmConfigSet→DcmDs…

vs2019 c++里用 typeid() . name () 與 typeid() . raw_name () 測試數據類型的區別

&#xff08;1&#xff09; 都知道&#xff0c;在 vs2019 里用 typeid 打印的類型不大準&#xff0c;會主動去掉一些修飾符&#xff0c; const 和引用 修飾符會被去掉。但也可以給咱們驗證學到的代碼知識提供一些參考。那么今天發現其還有 raw_name 成員函數&#xff0c;這個函…

AES分組密碼

一、AES明文和密鑰位數 RIJNDAEL 算法數據塊長度和密鑰長度都可獨立地選定為大于等于 128 位且小于等于 256 位的 32 位的任意倍數。 而美國頒布 AES 時卻規定數據塊的長度為 128 位、密鑰的長度可分別選擇為 128 位&#xff0c; 192 位或 256 位 1.1 狀態 中間結果叫做狀態…

建模:3dmax

3Dmax 制作模型和動畫&#xff08;橘肉&#xff09;&#xff1b; RizomUV 對模型進行展UV&#xff08;橘皮&#xff09;&#xff1b; Substance Painter 紋理手繪&#xff08;給橘皮制定想要的皮膚&#xff09;&#xff1b; 1.基礎 1.1可編輯多邊形、可編輯樣條線 體、面都需要…

Polylang Pro插件下載:多語言網站構建的終極解決方案

在全球化的今天&#xff0c;多語言網站已成為企業拓展國際市場的重要工具。然而&#xff0c;創建和管理一個多語言網站并非易事。幸運的是&#xff0c;Polylang Pro插件的出現&#xff0c;為WordPress用戶提供了一個強大的多語言解決方案。本文將深入探討Polylang Pro插件的功能…

linux上git 使用方法

一、git上新建倉庫 在git上新建倉庫&#xff0c;并命名 二、本地初始化 //命令行 ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" //ssh查看 cd /root/.ssh/ vim rsa.pub //復制后粘貼進git網頁設置里的ssh key //測試設置是否成功 ssh -T gitgithub.com/…

暴力數據結構之二叉樹(堆的相關知識)

1. 堆的基本了解 堆&#xff08;heap&#xff09;是計算機科學中一種特殊的數據結構&#xff0c;通常被視為一個完全二叉樹&#xff0c;并且可以用數組來存儲。堆的主要應用是在一組變化頻繁&#xff08;增刪查改的頻率較高&#xff09;的數據集中查找最值。堆分為大根堆和小根…

Spring事務的實現原理

Spring事務原理 Spring框架支持對于事務的管理功能&#xff0c;開發人員使用Spring框架能極大的簡化對于數據庫事務的管理操作&#xff0c;不必進行手動開啟事務&#xff0c;提交事務&#xff0c;回滾事務&#xff0c;就是在配置文件或者項目的啟動類配置Spring事務相關的注解…

什么是最大路徑?什么是極大路徑?

最近學習中&#xff0c;在這兩個概念上出現了混淆&#xff0c;導致了一些誤解&#xff0c;在此厘清。 最大路徑 在一個簡單圖G中&#xff0c;u、v之間的距離 d ( u , v ) min ? { u 到 v 的最短路的長度 } d(u,v) \min \{ u到v的最短路的長度 \} d(u,v)min{u到v的最短路的…

wefaf

c語言中的小小白-CSDN博客c語言中的小小白關注算法,c,c語言,貪心算法,鏈表,mysql,動態規劃,后端,線性回歸,數據結構,排序算法領域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 給大家分享一句我很喜歡我話&#xff1a; 知不足而奮進&#xff0c;望遠山而前行&am…

使用Bash腳本和Logrotate實現Nginx日志切割

Nginx是一個廣泛使用的高性能Web服務器&#xff0c;它能夠處理大量的并發連接&#xff0c;但同時也會生成大量的日志文件。為了有效管理這些日志文件并確保系統的正常運行&#xff0c;我們需要定期對Nginx的日志文件進行切割和歸檔。本文將介紹如何使用Bash腳本和Logrotate來實…

每天Get一個小技巧:用DolphinScheduler實現隔幾天調度

轉載自tuoluzhe8521 這篇小短文將教會你如何使用Apache DolphinScheduler實現隔幾天調度&#xff0c;有此需求的小伙伴學起來&#xff01; 1 場景分析 DolphinScheduler定時器模塊-定時調度時每3秒|每3分鐘|每3天這種定時&#xff0c;不能夠跨分鐘&#xff0c;跨小時&#x…

【C++】:string類的基本使用

目錄 引言一&#xff0c;string類對象的常見構造二&#xff0c;string類對象的容量操作三&#xff0c;string類對象的訪問及遍歷操作四&#xff0c;string類對象的修改操作五&#xff0c;string類非成員函數六&#xff0c;整形與字符串的轉換 引言 string 就是我們常說的"…

如何對SQL Server中的敏感數據進行加密解密?

為什么需要對敏感數據進行加密&#xff1f; 近幾年有不少關于個人數據泄露的新聞&#xff08;個人數據通常包含如姓名、地址、身份證號碼、財務信息等&#xff09;&#xff0c;給事發公司和被泄露人都帶來了不小的影響。 許多國家和地區都出臺了個人數據保護的法律法規&#…

Unity Animation--動畫窗口指南(使用動畫視圖)

Unity Animation--動畫窗口指南&#xff08;使用動畫視圖&#xff09; 使用動畫視圖 window -> Animation 即可打開窗口 查看GameObject上的動畫 window -> Animation -> Animation 默認快捷鍵 Ctrl 6 動畫屬性列表 在下面的圖像中&#xff0c;“動畫”視圖&am…

思科模擬器--2.靜態路由和默認路由配置24.5.15

首先&#xff0c;創建三個路由器和兩個個人電腦。 接著&#xff0c;配置兩臺電腦的IP&#xff0c;子網掩碼和默認網關 對Router 0&#xff0c;進行以下命令&#xff1a; 對Router進行以下命令&#xff1a; 對Router2進行以下命令&#xff1a; 本實驗完成。 驗證&#xff1a;PC…

Vue3+ts(day06:路由)

學習源碼可以看我的個人前端學習筆記 (github.com):qdxzw/frontlearningNotes 覺得有幫助的同學&#xff0c;可以點心心支持一下哈&#xff08;筆記是根據b站上學習的尚硅谷的前端視頻【張天禹老師】&#xff0c;記錄一下學習筆記&#xff0c;用于自己復盤&#xff0c;有需要學…

【ARMv8/v9 系統寄存器 5 -- ARMv8 Cache 控制寄存器 SCTRL_EL1 使用詳細介紹】

關于ARM Cache 詳細學習推薦專欄&#xff1a; 【ARM Cache 專欄】 【ARM ACE Bus 與 Cache 專欄】 文章目錄 ARMv8/v9 Cache 設置寄存器ARMv8 指令 Cache 使能函數測試代碼 ARMv8/v9 Cache 設置寄存器 關于寄存器SCTRL_EL1 的詳細介紹見文章&#xff1a;【ARMv8/v9 異常模型入…