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

1. 堆的基本了解

? ? ? ? 堆(heap)是計算機科學中一種特殊的數據結構,通常被視為一個完全二叉樹,并且可以用數組來存儲。堆的主要應用是在一組變化頻繁(增刪查改的頻率較高)的數據集中查找最值。堆分為大根堆和小根堆,大根堆中任意節點的值都大于其子樹中節點的值,而小根堆則相反。堆的存儲方式遵循層序遍歷的規則,這樣可以高效地利用存儲空間。在數組中,根節點的下標為0,節點的左右孩子的下標可以通過特定的公式計算得出。堆的實現通常利用動態數組,這樣可以快速擴展容量而不造成空間浪費。

堆的一些性質:1.堆中某個結點的值總是不大于或不小于其父結點的值;

? ? ? ? ? ? ? ? ? ? ? ? ?2.堆總是一棵完全二叉樹。

2. 堆的實現

?我們知道堆的邏輯結構是一個完全二叉樹,但是其物理結構仍然是一個數組,所以實現堆創建一個數組即可。

typedef int HPDateType;typedef struct Heap
{HPDateType* 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->a);php->a = NULL;php->capacity = php->size = 0;
}void Swap(HPDateType* p1, HPDateType* p2)
{HPDateType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDateType* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDateType x)
{if (php->capacity == php->size){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDateType* tmp = (HPDateType*)realloc(php->a, sizeof(HPDateType) * newcapacity);if (tmp = NULL){perror("realloc");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}
void AdjustDown(HPDateType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] > a[child + 1]){child++;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 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--;AdjustDown(php->a, php->size, 0);
}HPDateType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
2.1 堆的插入

大堆的父節點均大于子節點,小堆恰好相反,自然實現邏輯各不相同,這里主要有兩個主要的思想就是"父子值交換","父子址交換"。解釋就是(以小堆為例):

如果對一個已有的小堆插入新的數據(葉子),如果這個葉子與他的父節點相比更小,就與父節點交換,再與交換后節點所屬的父節點對比,如果還是小于就繼續交換。

?代碼解釋如下:?

當要插入數據時先將其放在葉子節點(數組尾部),通過AdjustUp函數可以實現向上比較的動作,當然插入前判斷空間是否充足,適當擴容即可。

void AdjustUp(HPDateType* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDateType x)
{if (php->capacity == php->size){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDateType* tmp = (HPDateType*)realloc(php->a, sizeof(HPDateType) * newcapacity);if (tmp = NULL){perror("realloc");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}
2.2 堆的刪除

堆的刪除就是將根節點與葉子節點交換后直接刪除交換后的葉子節點(即最初的跟節點數據),然后將交換后的根節點逐漸向下交換,如圖所示:

?通過代碼展示就是,先交換根節點與葉子結點(即數組頭尾交換)然后直接刪除交換后的葉子結點。創建一個AdjustDown函數,逐層下沉交換后的跟節點,保持仍然是一個堆。

void AdjustDown(HPDateType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] > a[child + 1]){child++;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 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--;AdjustDown(php->a, php->size, 0);
}

3.堆排序

主要思路:升序建大堆,降序建小堆

解釋:以升序為例,創建一個大堆,即根節點為最大的數據,此時要排序,就直接將根節點與葉子結點交換(數組首尾交換),然后數組末尾的下標向前移動(此時數組末尾的數據不會參與后續運算),然后將交換后的跟節點使用AdjustDown函數下沉,以此類推,最后原數組就是一個升序排列。同理小堆也是如此。

為什么升序不用小堆呢,因為小堆每一次運算都要再次創建一個數組,浪費更多的內存,可以使用但是不推薦。同理這也是為什么降序使用小堆。

具體代碼如下

void HeapSort(int* a, int n)
{// 降序,建小堆// 升序,建大堆for (int i = 1; i < n; i++){AdjustUp(a, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

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

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

相關文章

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 異常模型入…

純正英語新聞 5.15

seizing territory &#xff1a;奪取領土 battlefield:戰場 shrinking&#xff1a;縮小 paramedic&#xff1a;醫護人員 mercilessly destroy&#xff1a;無情地摧殘 blown up&#xff1a;炸毀 northern outskirts :北郊 terrified&#xff1a;害怕 shelling&#xff…

西南大學計算機考研,選學碩還是專碩?西南大學計算機考研考情分析!

西南大學&#xff08;Southwest University&#xff09;是教育部直屬&#xff0c;教育部、農業農村部、重慶市共建的重點綜合大學&#xff0c;是國家首批"雙一流"建設高校&#xff0c;"211工程"和"985工程優勢學科創新平臺"建設高校。現任黨委書…

【嵌入式大賽應用賽道】機械手臂

電機 進步電機&#xff1a;它的轉動是以確定的步數進行的&#xff0c;只要計算好脈沖數量和頻率&#xff0c;就可以準確預測和控制電機的轉動角度、速度以及停止的位置 伺服電機&#xff1a;將輸入的電信號&#xff08;如電壓或電流指令&#xff09;轉換成軸上的精確旋轉運動…

大模型算法(一):從Transformer到ViT再到LLaMA

單任務/單領域模型 深度學習最早的研究集中在針對單個領域或者單個任務設計相應的模型。 對于CV計算機視覺領域&#xff0c;最常用的模型是CNN卷積模型。其中針對計算機視覺中的不同具體任務例如分類任務&#xff0c;目標檢測任務&#xff0c;圖像分割任務&#xff0c;以CNN作…

【傳知代碼】VRT: 關于視頻修復的模型(論文復現)

前言&#xff1a;隨著數字媒體技術的普及&#xff0c;制作和傳播視頻內容變得日益普遍。但是&#xff0c;視頻中由于多種因素&#xff0c;例如傳輸、存儲和錄制設備等&#xff0c;經常出現質量上的問題&#xff0c;如圖像模糊、噪聲干擾和低清晰度等。這類問題對用戶的體驗和觀…

hive動態分區

hive動態分區概念:允許插入數據到分區表時,根據插入的數據內容自動創建相應的分區 1.啟用動態分區功能 hive.exec.dynamic.partitiontrue; 2.分區字段設置 在insert語句中, 動態分區的字段必須放在select語句的末尾,hive會根據這個字段的值來創建分區目錄 示例: --創建分區表…

幾個排序器的verilog及其資源占用、延時分析

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 前言 因為課題需要&#xff0c;調研了幾個快速排序方法&#xff0c;并手寫或者改進了若干待測試對象&#xff0c;包括記分板型冒泡排序&#xff08;這個是別人的&#xff09…

樹莓派|I2C通信

什么是I2C通信 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一種串行通信協議&#xff0c;用于在集成電路(IC)之間傳輸數據。它由飛利浦公司&#xff08;現在的恩智浦半導體公司&#xff09;在20世紀80年代開發&#xff0c;并且成為了廣泛應用于各種電子設備中的通…

Spring Security 6.x 系列【73】認證篇之同端互斥登錄

有道無術,術尚可求,有術無道,止于術。 本系列Spring Boot 版本 3.1.0 本系列Spring Security 版本 6.1.0 源碼地址:https://gitee.com/pearl-organization/study-spring-security-demo 文章目錄 1. 概述2. 實現方案3. 案例演示3.1 內存會話3.1.1 并發控制流程分析3.1.2 功…