二叉樹的順序結構(堆的實現)

前言

普通的二叉樹是不適合用數組來存儲的,因為可能會存在大量的空間浪費。而完全二叉樹更適合使用順序結 構存儲。
現實中我們通常把堆 ( 一種二叉樹 ) 使用順序結構的數組來存儲,需要注意的是這里的堆和操作系統 虛擬進程地址空間中的堆是兩回事,一個是數據結構,一個是操作系統中管理內存的一塊區域分段。

1.堆的概念及結構

如果有一個關鍵碼的集合 K = { k0, k1,k2,…,k(n-1)},把它的所有元素按完全二叉樹的順序存儲方式存儲 在一個一維數組中,并滿足:Ki?<=K(2*i+1)且Ki<=K(2*i+2)(Ki?>=K(2*i+1)且Ki>=K(2*i+2) ?i =0 1 , 2…,則稱為小堆 (或大堆) 。將根結點最大的堆叫做最大堆或大根堆,根結點最小的堆叫做最小堆或小根堆。(這里的數字都是對應的下標
堆的性質:
堆中某個結點的值總是不大于或不小于其父結點的值;
堆總是一棵完全二叉樹。

2.堆的創建和功能實現

2.1堆的基本結構的創建和相關函數聲明。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include  <stdbool.h>typedef int  Datatype;
typedef  struct Heap {Datatype* a;int size;int capacity;
}HP;
// 堆的初始化
void HeapInit(HP* hp);
// 堆的銷毀
void HeapDestory(HP* hp);
// 堆的插入
void HeapPush(HP* hp, Datatype x);
// 堆的刪除
void HeapPop(HP* hp);
// 取堆頂的數據
Datatype HeapTop(HP* hp);
// 堆的數據個數
bool HeapSize(HP* hp);
// 堆的判空
int HeapEmpty(HP* hp);
//向上調整
void Adjustup(Datatype* a, int child);
//向下調整
void Adjustdown(Datatype* a, int n, int parent);
//數據交換
void Swap(Datatype* p1, Datatype* p2);

2.2 各函數的實現與講解

2.1堆的初始化和銷毀

堆的初始化和銷毀與以前的動態數組實現順序表和棧的初始化和銷毀基本是一樣的,在這里小編就不多解釋了。

// 堆的初始化
void HeapInit(HP* hp) {assert(hp);hp->a = NULL;hp->size = hp->capacity = 0;
}
// 堆的銷毀
void HeapDestory(HP* hp) {assert(hp);free(hp->a);hp->a = NULL;hp->size = hp->capacity = 0;
}
2.2堆數據的插入
補充向上調整法
隨便給出一個數組,這個數組邏輯上可以看做一顆完全二叉樹,但是還不是一個堆,現在我們通過算法,把它構建成一個堆。根結點左右子樹不是堆,我們怎么調整呢?
向上調整法
通過比較新插入元素與其父節點的值來判斷是否需要進行交換。如果新插入元素的值大于父節點的值,就將它們進行交換,并更新索引值。這樣,逐步向上調整,直到新插入元素找到了合適的位置,保證了堆的性質。
//向上調整
void Adjustup(Datatype* a,int child) {int parent = (child - 1) / 2;while (child > 0) {if (a[child] > a[parent]) {Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}

這個是建立大堆的向上調整,建立小堆的話直接改成小于

每插入一個元素,調用一次向上調整函數。

// 堆的插入
void HeapPush(HP* hp, Datatype x) {assert(hp);if (hp->size == hp->capacity) {int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;Datatype* temp = (Datatype*)realloc(hp->a, sizeof(Datatype) * newcapacity);if (temp == NULL) {perror("realloc fail");return;}hp->a = temp;hp->capacity = newcapacity;}hp->a[hp->size] = x;hp->size++;Adjustup(hp->a, hp->size-1);
}

例如數組a[]={1, 5, 3, 8, 7, 6},依次插入并建立大堆后的順序是:

  1. 插入 1,堆變為 [1]
  2. 插入 5,堆變為 [5, 1]
  3. 插入 3,堆變為 [5, 1, 3]
  4. 插入 8,堆變為 [8, 5, 3, 1]
  5. 插入 7,堆變為 [8, 7, 3, 1, 5]
  6. 插入 6,堆變為 [8, 7, 6, 1, 5, 3]

所以,建立大堆后的順序是 [8, 7, 6, 1, 5, 3]。

2.3堆的刪除
補充向下調整法

在這里慣性思維是直接刪除頭頂數據,然后重新建堆,通過向上調整法,但是我們需要從最后一個元素依次遍歷向上調整。

這里我們采用向下調整法。

刪除堆是刪除堆頂的數據,將堆頂的數據根最后一個數據一換,然后刪除數組最后一個數據,再進行向下調整算法。
本張圖是小堆的刪除。大堆的刪除方式是一樣的。
因為堆數據插入是建立大堆的,所以這里的代碼是大堆的向下調整。
//向下調整
void Adjustdown(Datatype* a, int n, int parent) {//假設法,假設左孩子大int child = parent * 2 + 1;while (child < n ) {if (child + 1 < n && a[child + 1] > a[child])//a[child+1]<a[child]child = child + 1;if (a[child] > a[parent]) {  //a[child]<a[parent]Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else break;}
}

堆的刪除

// 堆的刪除
void HeapPop(HP* hp) {assert(hp);assert(hp->size > 0);Swap(&hp->a[0], &hp->a[hp->size - 1]);hp->size--;Adjustdown(hp->a, hp->size, 0);
}

最后我們會發現刪除的數據是從大到小排列的,這里就可以牽扯到堆排序的應用,小編在下節會講解的。

2.4其他函數實現(交換,判空,堆頂數據,數據個數)
//數據交換
void Swap(Datatype* p1, Datatype* p2) {Datatype temp = *p1;*p1 = *p2;*p2 = temp;
}
// 取堆頂的數據
Datatype HeapTop(HP* hp) {assert(hp);assert(hp->size > 0);return hp->a[0];
}
// 堆的數據個數
int HeapSize(HP* hp) {assert(hp);return hp->size;
}
// 堆的判空
bool HeapEmpty(HP* hp) {assert(hp);return hp->size == 0;}

3.代碼測試

#include "Heap.h"
void TestHeap1()
{int a[] = { 4,2,8,1,5,6,9,3,2,23,55,232,66,222,33,7,66,3333,999 };//int a[] = { 1,5,3,8,7,6 };HP hp;HeapInit(&hp);for (int i = 0; i < sizeof(a) / sizeof(int); i++){HeapPush(&hp, a[i]);}printf("堆的大小為%d\n", HeapSize(&hp));int i = 0;while (!HeapEmpty(&hp)){printf("%d ", HeapTop(&hp));//a[i++] = HPTop(&hp);HeapPop(&hp);}printf("\n");
}
/*// 找出最大的前k個int k = 0;scanf("%d", &k);while (k--){printf("%d ", HeapTop(&hp));HeapPop(&hp);}printf("\n");HeapDestory(&hp);
}*/
int main(){
TestHeap1();
return 0;
}

4.堆的選擇題(方便大家理解)

1. 下列關鍵字序列為堆的是:(A)
A 100 , 60 , 70 , 50 , 32 , 65? ? ? ? ? ?? B 60 , 70 , 65 , 50 , 32 , 100? ? ? ? ? ?? C 65 , 100 , 70 , 32 , 50 , 60
D 70 , 65 , 100 , 32 , 50 , 60? ? ? ? ? ?? E 32 , 50 , 100 , 70 , 65 , 60? ? ? ? ? ?? F 50 , 100 , 70 , 65 , 60 , 32
2. 已知小根堆為 8 , 15 , 10 , 21 , 34 , 16 , 12 ,刪除關鍵字 8 之后需重建堆,在此過程中,關鍵字之間的比較次數是(C)。
A 1? ? ? ? ? ? ? ? ? ? ? B 2? ? ? ? ? ? ? ? ? ? ? ? C 3? ? ? ? ? ? ? ? ? ? ? ? D 4
3. 最小堆 [ 0 , 3 , 2 , 5 , 7 , 4 , 6 , 8 ], 在刪除堆頂元素 0 之后,其結果是(C)
A [ 3 2 5 7 4 6 8 ]? ? ? ? ? ? ? ? ? B [ 2 3 5 7 4 6 8 ]
C [ 2 3 4 5 7 8 6 ]? ? ? ? ? ? ? ? ? D [ 2 3 4 5 6 7 8 ]

本節內容到此結束,下次小編將講解堆排序的知識,歡迎大家捧場!!!

期待各位友友的三連和評論!!!

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

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

相關文章

問題:8255A的端口A工作在方式2時,使用端口C的______作為與CPU和外部設備的聯絡信號。 #媒體#經驗分享#其他

問題&#xff1a;8255A的端口A工作在方式2時&#xff0c;使用端口C的______作為與CPU和外部設備的聯絡信號。 參考答案如圖所示

郵件安全證書,保障通信安全的必備利器

在數字通信日益普及的今天&#xff0c;電子郵件的安全性越來越受到人們的關注。郵件安全證書&#xff0c;作為保障郵件通信安全的重要工具&#xff0c;逐漸走進了大眾的視野。本文將為大家揭秘郵件安全證書&#xff0c;解答關于它的常見問題&#xff0c;幫助大家更好地了解和使…

學習好困-合理調整下

學習時感到困倦是一種常見現象&#xff0c;可能由多種因素引起&#xff0c;如環境、身體狀況、學習方法等。以下是一些原因及其解決方法&#xff1a; 可能的原因 環境因素&#xff1a; - 光線不足&#xff1a;昏暗的環境容易讓人感到疲倦。 - 空氣不流通&#xff1a;缺乏…

浮點數的精度和精度丟失,如何規避,有簡單操作

在日常工作中&#xff0c;如果做財務軟件相關肯定會遇到這種問題&#xff0c;憑證金額表面上看是相等的&#xff0c;但程序運算出的結果卻是FALSE。 例如&#xff1a;驗證憑證金額借方總金額是否等于貸方總金額&#xff1f; 直接sum&#xff08;借方分錄金額1.1借方分錄金額2.…

RK3568技術筆記之一 RK3568總體介紹

RK3568是瑞芯微開發出一款很好用的芯片。我先把ROCKCHIP的原廠信息搬過來看看。 首先聲明一下&#xff0c;這篇文章里的資訊版權歸瑞芯微電子股份有限公司。畢竟是我轉過來的嘛。 我自己的心得&#xff0c;版權就歸我啦。 主要特性 Quad-core Cortex-A55 up to 2.0GHzMali-G…

認識HTTP狀態碼(status code)

目錄 1、200 OK&#xff08;訪問成功&#xff09;&#x1f447; 2、404 Not Found &#xff08;沒有找到資源&#xff09;&#x1f447; 3、403 Forbidden &#xff08;訪問拒絕&#xff09;&#x1f447; 4、405 Method Not Allowed&#x1f447; 6、504 Gateway Timeout…

CV Method:經典CNN Backbone總結

文章目錄 前言一、ResNet二、ResNeXt三、Res2Net四、SeNet五、ResNeSt六、DenseNet七、CSPNetPytorch Model Code總結 前言 Backbone作為一切深度學習任務的基礎&#xff0c;不論是理論還是實際應用都有重要的意義&#xff0c;本文針對經典Backbone進行總結&#xff0c;這些Ba…

[word] word怎樣轉換成pdf #職場發展#經驗分享#職場發展

word怎樣轉換成pdf word怎樣轉換成pdf&#xff1f;word格式是辦公中常會用到的格式&#xff0c;word格式編輯好了要想轉換成pdf格式再來傳輸的話需要怎么操作呢&#xff1f;小編這就給大家分享下操作方法&#xff0c;一起來學習下吧&#xff01; 1、安裝得力PDF轉換器&#x…

【stm32/CubeMX、HAL庫】swjtu嵌入式實驗七 ADC 實驗

相關電路與IO引腳 注意&#xff1a;串口打印重定向后使用printf打印需要在keil里勾選 Use MicroLIB &#xff0c;否則會卡住。 參看&#xff1a;https://zhuanlan.zhihu.com/p/565613666 串口重定向&#xff1a; /* USER CODE BEGIN Includes */#include <stdio.h>//…

銳捷校園網自助服務系統 login_judge.jsf 任意文件讀取漏洞復現(XVE-2024-2116)

0x01 產品簡介 銳捷校園網自助服務系統是銳捷網絡推出的一款面向學校和校園網絡管理的解決方案。該系統旨在提供便捷的網絡自助服務,使學生、教職員工和網絡管理員能夠更好地管理和利用校園網絡資源。 0x02 漏洞概述 校園網自助服務系統/selfservice/selfservice/module/sc…

求解數組中N數之和最接近目標值的算法詳解

目錄 問題定義問題背景常見解決思路 暴力枚舉法排序雙指針法動態規劃法 具體實現方法 暴力枚舉法的實現排序雙指針法的實現動態規劃法的實現 優化技巧總結 問題定義 給定一個整數數組 nums 和一個目標值 target&#xff0c;需要在數組中找到 n 個數&#xff0c;使得這 n 個數…

apollo 環境配置

輸入法 安裝輸入google pinyin法 sudo apt install fcitx-bin sudo apt install fcitx-table sudo apt-get install fcitx fcitx-googlepinyin -y 最后需要reboot 系統環境 修改文件夾名稱為英文 將Ubuntu主文件夾里的中文文件夾名稱改成英文_番茄炒雞蛋z的博客-CSDN博客…

selenium中switch_to.window切換窗口的用法

打開百度多個窗口&#xff0c;遍歷切換每個窗口&#xff0c;切到【百度地圖】就停止。 使用了driver.switch_to.window&#xff08;&#xff09; 來切換&#xff0c; 參數是handle值 from selenium import webdriver import time# 創建瀏覽器驅動對象 from selenium.webdrive…

JSQLParser用于解析SQL語句并創建抽象語法樹(AST)

JSQLParser簡介 JSQLParser是一個Java庫&#xff0c;用于解析SQL語句并創建抽象語法樹(AST)。該庫非常強大&#xff0c;可以解析大多數標準SQL語法&#xff0c;并支持許多數據庫的專用語法。 主要特點 語法支持廣泛&#xff1a;支持大多數SQL語法&#xff0c;包括SELECT、IN…

java中事務中遇到鎖會造成什么問題,以及該如何解決?

在spring中實現事務有多種方式&#xff0c;主要是兩種&#xff1a;一種是聲明式事務&#xff0c;一種是編程式事務&#xff0c;今天我們就講聲明式事務中的一種&#xff0c;使用注解Transactional&#xff0c;這個注解的作用就是幫助我們在代碼執行完畢之后自動提交事務&#x…

淘寶評論數據爬取全攻略

一、淘寶評論數據爬取的背景與意義 隨著互聯網的快速發展&#xff0c;電子商務平臺如淘寶、京東等在我國市場占有率逐年上升。消費者在購買商品時&#xff0c;除了關注商品的價格、質量等因素外&#xff0c;還會參考其他消費者的評價和評論。淘寶評論數據爬取是指通過技術手段…

C# NX二次開發-設置背景顏色

使用UF函數能直接設置UG背景顏色: 1.設置背景顏色選項為純色: 2.編寫更新背景顏色代碼: var nxColor NXColor.Factory._Get(186);var rgb nxColor.GetRgb();double[] arr [rgb.R, rgb.G, rgb.B];theUf.Disp.SetColor(UFConstants.UF_DISP_BACKGROUND_COLOR, UFConstants.UF…

oracle刪除表空間和用戶命令

創建表空間和用戶可參考 ORACLE創建表空間,用戶,修改密碼,分配權限,以及導入導出_oracle表空間的密碼-CSDN博客 1.刪除表空間 --刪除空的表空間&#xff0c;但是不包含物理文件 drop tablespace tablespace_name; --刪除非空表空間&#xff0c;但是不包含物理文件 drop tabl…

化妝品FDA認證需要注意哪方面

化妝品FDA認證概述 化妝品FDA認證是指化妝品產品通過美國食品藥品監督管理局&#xff08;FDA&#xff09;的審核和認證&#xff0c;證明其符合相關法規和標準&#xff0c;具備在美國市場合法銷售的條件。這一認證過程不僅涉及產品的成分合規性&#xff0c;還包括產品的標簽、安…

C#字符串格式化之$語法

引言 字符串是編程中使用較廣的一種數據&#xff0c;它由數字、字母、下劃線等組成。在使用過程中會對字符串進行格式化。在C#語言中&#xff0c;.NET 6及以上使用字符串插值&#xff08;$""語法&#xff09;對字符串格式化。 $語法 .NET 6 及以上提供的一種新的語…