堆的實現(堆的插入、堆的刪除等)超級全

堆的實現(堆的插入、堆的刪除等)超級全

在這里插入圖片描述

文章目錄

  • 堆的實現(堆的插入、堆的刪除等)超級全
    • 一、前期基礎知識
      • 1.樹結構
        • ①樹的定義
        • ②樹的相關概念
        • ③二叉樹
        • ④滿二叉樹和完全二叉樹
          • a.滿二叉樹
          • b.完全二叉樹
        • ⑤二叉樹的性質
        • ⑥二叉樹順序結構的存儲和鏈式結構的存儲
          • a.順序結構存儲
          • b.鏈式結構存儲
      • 2.堆結構
    • 二、堆結構/二叉樹順序結構存儲的實現
      • 1.堆的初始化
      • 2.堆的銷毀
      • 3.堆的插入
      • 4.堆的刪除
      • 5.取堆頂數據
      • 6.堆的數據個數
      • 7.堆的判空

一、前期基礎知識

1.樹結構

①樹的定義

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

②樹的相關概念

在這里插入圖片描述
節點的度:一個節點含有的子樹的個數稱為該節點的度; 如上圖:A的為6。
葉節點或終端節點:度為0的節點稱為葉節點; 如上圖:B、C、H、I…等節點為葉節點。
非終端節點或分支節點:度不為0的節點; 如上圖:D、E、F、G…等節點為分支節點。
樹的度:一棵樹中,最大的節點的度稱為樹的度; 如上圖:樹的度為6。
節點的層次:從根開始定義起,根為第1層,根的子節點為第2層,以此類推。
樹的高度或深度:樹中節點的最大層次; 如上圖:樹的高度為4。
n個結點的樹,有n-1條邊。

一棵樹有以下三部分組成
根節點,無前驅結點。
葉結點,度為0,又稱終端結點
非終端節點,分支節點,度不為0

一棵樹是由根節點和n顆子樹構成的,子樹一定不能相交,除了根節點外,每一個結點都有且僅有一個父節點。

如果不是樹結構,那就是圖結構。

③二叉樹

每一個結點的度不一定都是2,整個二叉樹里不存在度大于2的結點。

  1. 或者為空
  2. 由一個根節點加上兩棵別稱為左子樹和右子樹的二叉樹組成

在這里插入圖片描述
在這里插入圖片描述

④滿二叉樹和完全二叉樹
a.滿二叉樹

滿二叉樹
一個二叉樹,如果每一個層的結點數都達到最大值,則這個二叉樹就是滿二叉樹。也就是說,如果一個二叉樹的層數為K,且結點總數是2 ^ k - 1 ,則它就是滿二叉樹。

b.完全二叉樹

完全二叉樹
前(n - 1)層是滿的
最后一層不滿,但是從左到右必須連續排布,最少1個,最多2 ^ (n - 1)個。

⑤二叉樹的性質
  1. 若規定根節點的層數為1,則一棵非空二叉樹的第i層上最多有2 ^ (i - 1)個結點.
  2. 若規定根節點的層數為1,則深度為h的二叉樹的最大結點數是2 ^ h - 1
  3. 對任何一棵二叉樹, 如果度為0其葉結點個數為n0 , 度為2的分支結點個數為n2 ,則有n0 = n2 + 1
  4. 若規定根節點的層數為1,具有n個結點的滿二叉樹的深度,h= log2底(n + 1)。(ps: 是log以2為底,n+1為對數)
  5. 將二叉樹的每一個結點按層次從0到n編號:
    0
    1 2
    3 4 5 6
    7 8 (7,8為3的子節點)
    舉個例子,這就是一個完全二叉樹,0 = (1 - 1) / 2, 0 = (2 - 1) / 2,所以parent = (child - 1) / 2, leftchild = parent * 2 + 1, rightchild = leftchild + 1。
    但是注意,一定要在范圍里。
⑥二叉樹順序結構的存儲和鏈式結構的存儲
a.順序結構存儲

順序結構存儲就是使用數組來存儲,一般使用數組只適合表示完全二叉樹因為不是完全二叉樹會有空間的浪費。而現實中使用中只有堆才會使用數組來存儲。二叉樹順序存儲在物理上是一個數組,在邏輯上是一顆二叉樹。
在這里插入圖片描述

b.鏈式結構存儲

二叉樹的鏈式存儲結構是指,用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關系。 通常的方法是鏈表中每個結點由三個域組成,數據域和左右指針域,左右指針分別用來給出該結點左孩子和右孩子所在的鏈結點的存儲地址 。鏈式結構又分為二叉鏈和三叉鏈,二叉鏈就是兩個指針+數據域,三叉鏈就是兩個指針+指向父節點+數據域,我們暫時先不做重點講解,后續筆者會進行講解。

2.堆結構

1.一段連續的數組數據看作完全二叉樹
2.必須是小堆或者大堆
小堆:任意一個父節點小于等于子節點
大堆:任意一個父節點大于等于子節點

typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;

大家不妨再思考一下,數據結構的目的到底是什么,就是為了方便我們在內存中管理數據,再加上一些可以實現對這段數據進行操作的接口函數來實現我們的目的。

二、堆結構/二叉樹順序結構存儲的實現

1.堆的初始化

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

2.堆的銷毀

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

3.堆的插入

void Swap(HPDataType* p1, HPDataType* p2)
{assert(p1 && p2);HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void HPAdjustUp(HPDataType* p, int child)
{assert(p);int parent = (child - 1) / 2;while (child > 0){if (p[child] < p[parent]){Swap(( & p[child]), ( & p[parent]));child = parent;parent = (parent - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : 2 * (php->capacity);HPDataType* tmp = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc");exit(-1);}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;HPAdjustUp(php->a, (php->size - 1));
}

當你插入一個新的數據到堆里后,一定要記得你的結構實際是一個二叉樹,而且以小堆為例,如果你插入的數據,比這個結點的父節點小,那就需要向上調整。

4.堆的刪除

void HPAdjustDown(HP* p, int parent)
{assert(p);int child = parent * 2 + 1;//使用假設法while (child < (p->size)){if ((child + 1 < p->size) && (p->a[child + 1] < p->a[child]))//這個真的很重要,值得反復思考,進行交換{child = child + 1;}if (p->a[child] < p->a[parent]){Swap(&(p->a[child]), &(p->a[parent]));parent = child;child = child * 2 + 1;}else{break;}}
}void HPPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&(php->a[0]), &(php->a[(php->size) - 1]));php->size--;HPAdjustDown(php, 0);
}

相信大家一定會有一些問題,因為堆的刪除,是刪除堆頂元素,大家可能會疑問,為什么不能直接頭刪。
原因有以下兩點:
1.順序表時間復雜度是O(N),過于復雜。
2.如果頭刪之后,整個數組是要向前挪一位的,整棵樹的結構就全部改變了,父子關系,大小關系全部亂了,需要重新改。

所以我們重新選擇一個方法,就是我們將堆頂元素和最后一個元素互換,再尾刪,這樣可以保證兩顆子樹從上到下的整個順序都沒有被改變,向下調整就只需要進入一顆子樹繼續調整就好啦。

5.取堆頂數據

HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);//使用sizereturn php->a[0];
}

6.堆的數據個數

int HPSize(HP* php)
{assert(php);return (php->size);
}

7.堆的判空

bool HPEmpty(HP* php)
{assert(php);/*if (php->size == 0){return true;}else{return false;}*/return (php->size == 0);
}

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

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

相關文章

每日OJ題_算法_雙指針_力扣11. 盛最多水的容器

力扣11. 盛最多水的容器 11. 盛最多水的容器 - 力扣&#xff08;LeetCode&#xff09; 難度 中等 給定一個長度為 n 的整數數組 height 。有 n 條垂線&#xff0c;第 i 條線的兩個端點是 (i, 0) 和 (i, height[i]) 。 找出其中的兩條線&#xff0c;使得它們與 x 軸共同構成…

2023 最新 PDF.js 在 Vue3 中的使用

因為自己寫業務要定制各種 pdf 預覽情況&#xff08;可能&#xff09;&#xff0c;所以采用了 pdf.js 而不是各種第三方封裝庫&#xff0c;主要還是為了更好的自由度。 一、PDF.js 介紹 官方地址 中文文檔 PDF.js 是一個使用 HTML5 構建的便攜式文檔格式查看器。 pdf.js 是社區…

人工智能教程(二):人工智能的歷史以及再探矩陣

目錄 前言 更多矩陣的知識 Pandas 矩陣的秩 前言 在上一章中&#xff0c;我們討論了人工智能、機器學習、深度學習、數據科學等領域的關聯和區別。我們還就整個系列將使用的編程語言、工具等做出了一些艱難的選擇。最后&#xff0c;我們還介紹了一點矩陣的知識。在本文中&am…

vue打包上傳服務器的總結筆記

經歷了3個小時教訓&#xff0c;還是自己總結一下吧&#xff0c;致未來傻x的自己。 第一步&#xff0c;打開b站。搜索【vue打包】找到一個視頻教程 前端Vue項目打包部署實戰教程_嗶哩嗶哩_bilibili 這步是在看不懂下面操作的情況下用的 第一步&#xff1a;找到nginx的配置文件…

需求變更導致估算不精準 6大措施

需求變更可能導致估算不精準、項目成本增加、進度延遲等問題&#xff0c;如果不能準確地估算項目&#xff0c;往往會造成資源浪費和開發效率的降低&#xff0c;因此亟需解決因需求變更導致地估算不精準的問題。 一般來說&#xff0c;主要是從以下6個方面入手解決&#xff1a; 1…

【maven】【IDEA】idea中使用maven編譯項目,報錯java: 錯誤: 找不到符號 【2】

idea中使用maven編譯項目,報錯java: 錯誤: 找不到符號 錯誤狀況展示: 如果報這種錯,是因為項目中真的找不到報錯的方法或者枚舉 字段之類的,但實際是 : 點擊 File Path

OSG粒子系統與陰影-霧效模擬(1)

虛擬現實中有很多效果&#xff0c;如雨效、雪效、霧效等&#xff0c;這些都可以通過粒子系統來實現。一個真實的粒子系統的模式能使三維場景達到更好的效果。 本章對OSG粒子系統的使用以及生成自定義粒子系統的方法進行了詳細介紹最后還附帶說明了陰影的使用方法。在實時的場景…

(HAL庫版)freeRTOS移植STMF103

正點原子關于freeRTOS的教程是比較好的&#xff0c;可惜移植的是標準庫&#xff0c;但是我學的是Hal庫&#xff0c;因為開發速度更快&#xff0c;從最后那個修改SYSTEM文件夾的地方開始替換為下面的內容就可以了 5.修改Systick中斷、SVC中斷、PendSV中斷 將SVC中斷、P…

pairplot

Python可視化 | Seaborn5分鐘入門(七)——pairplot - 知乎 (zhihu.com) Seaborn是基于matplotlib的Python可視化庫。它提供了一個高級界面來繪制有吸引力的統計圖形。Seaborn其實是在matplotlib的基礎上進行了更高級的API封裝&#xff0c;從而使得作圖更加容易&#xff0c;不需…

紅黑樹詳解

紅黑樹的概念與性質 前置知識 在學習紅黑樹之前&#xff0c;最好有二叉查找樹和AVL樹的基礎&#xff0c;因為紅黑樹本質就是一種特殊的二叉查找樹&#xff0c;而紅黑樹的操作中需要用到AVL樹中旋轉的相關知識。至于二叉查找樹和AVL樹&#xff0c;可以參考如下兩篇博客&#xf…

oracle安裝的肘腋之疾小合集

#臨時空間指定 export TMP/tmp export TMPDIR/tmp #圖形化顯示框不全 java問題&#xff0c;使用系統自帶的jre ./runInstaller -jreLoc/usr/local/jdk1.7.0_80/ #ins30131 Failed to access the temporary location 給/tmp/CVU*加x權限 #linux桌面太小 xrandr -s 1440x900_60…

Matplotlib圖形注釋_Python數據分析與可視化

Matplotlib圖形注釋 添加注釋文字、坐標變換 有的時候單單使用圖形無法完整清晰的表達我們的信息&#xff0c;我們還需要進行文字進行注釋&#xff0c;所以matplotlib提供了文字、箭頭等注釋可以突出圖形中重點信息。 添加注釋 為了使我們的可視化圖形讓人更加容易理解&#…

vue中父組件直接調用子組件方法

vue2 中&#xff0c;父組件如何調用子組件的方法 在Vue 2中&#xff0c;父組件可以通過使用ref屬性來引用子組件的實例&#xff0c;然后通過該實例調用子組件的方法。 首先&#xff0c;在父組件的模板中&#xff0c;給子組件添加一個ref屬性&#xff1a; <template>&l…

在工業生產環境下,服務器沒有互聯網,如何通過代理自己的電腦上互聯網?

服務器主機是CentOS7操作系統.&#xff0c;服務器的局域網是10.0.6.x網段。我的筆記本的以太網口的局域網ip是也是10.0.6.x&#xff0c;由于這個10.0.6.x的整個局域網是沒有撥號上網的所有無法訪問互聯網。 但是&#xff0c;如果筆記本臉上wifi&#xff0c;wifi的網段是192.168…

長度最小的子數組

給定一個含有 n 個正整數的數組和一個正整數 target 。 找出該數組中滿足其總和大于等于 target 的長度最小的 連續子數組 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其長度。如果不存在符合條件的子數組&#xff0c;返回 0 。 示例 1&#xff1a; 輸入&#x…

MySQL 有多個普通索引時會取哪一個索引?

我們都知道MySQL在查詢時底層會進行索引的優化&#xff0c;假設有兩個普通索引&#xff0c;且where 后面也根據這兩個普通索引查詢數據&#xff0c;那么執行查詢語句時會使用到那個索引&#xff1f; 為了方便演示&#xff0c;新建users表&#xff0c;新建idx_name、idx_city這兩…

前端vue導出PPT,使用pptxgen.js

前言 公司新需求需要導出ppt給業務用&#xff0c;查閱資料后發現也挺簡單的&#xff0c;記錄一下。 如有不懂的可以留言&#xff01;&#xff01;&#xff01; 1.安裝包 npm install pptxgenjs --save2.引入包 在需要使用的文件中引入 import Pptxgenfrom "pptxgenjs&…

Oracle研學-介紹及安裝

一 ORACLE數據庫特點: 支持多用戶&#xff0c;大事務量的事務處理數據安全性和完整性控制支持分布式數據處理可移植性(跨平臺&#xff0c;linux轉Windows) 二 ORACLE體系結構 數據庫&#xff1a;oracle是一個全局數據庫&#xff0c;一個數據庫可以有多個實例&#xff0c;每個…

nodejs+vue+python+PHP+微信小程序-留學信息查詢系統的設計與實現-安卓-計算機畢業設計

1、用戶模塊&#xff1a; 1&#xff09;登錄&#xff1a;用戶注冊登錄賬號。 2&#xff09;留學查詢模塊&#xff1a;查詢學校的入學申請條件、申請日期、政策變動等。 3&#xff09;院校排名&#xff1a;查詢國外各院校的實力排名。 4&#xff09;測試功能&#xff1a;通過入學…

Spring Boot WebSocket 客戶端

介紹 WebSocket 是一種在單個 TCP 連接上進行全雙工通信的協議&#xff0c;它可以提供實時的、雙向的數據傳輸。Spring Boot 提供了對 WebSocket 的支持&#xff0c;我們可以使用 Spring Boot WebSocket 客戶端來連接到 WebSocket 服務器&#xff0c;并進行實時通信。 本文將…