【數據結構】(C語言):堆(二叉樹的應用)

堆:

  • 此處堆為二叉樹的應用,不是計算機中用于管理動態內存的堆。
  • 形狀是完全二叉樹。
  • 堆分兩種:最大堆,最小堆。
  • 最大堆:每個節點比子樹所有節點的數值都大,根節點為最大值。
  • 最小堆:每個節點比子樹所有節點的數值都小,根節點為最小值。
  • 左右節點的數值沒有順序要求,但有左子節點才能有右子節點。
  • 一般用數組實現堆。最小堆可以實現優先隊列。

注:完全二叉樹:每個節點最多2個節點,倒數第二層級(含)之前層級的所有節點都有元素,最后一層級從左到右依次有元素(中間不能斷)。

子樹:節點及其所有子節點形成子樹。(即節點,左右子節點,左右子節點的左右子節點,。。。)

根節點:沒有父節點。

兄弟節點:其父節點是同一個節點。

父子節點在數組中的索引號
節點索引號(根節點為0)
節點x
父節點(x-1)// 2
左兄弟節點(右節點才有)x - 1
右兄弟節點(左節點才有)x + 1
左子節點2x + 1
右子節點2x + 2


C語言實現:(使用數組實現最小堆)

創建堆(結構體數據類型):記錄數組地址和元素個數

// 堆(結構體數據類型)
typedef struct Heap
{int *p;			// 記錄數組地址int n;			// 記錄元素個數
} Heap;             // 別名

?(函數)堆初始化:

// 堆初始化
void init(Heap *heap, int length)
{heap->p = (int *)malloc(length * sizeof(int));    // 分配內存空間if(heap->p == NULL){perror("Memory allocation failed");exit(-1);}heap->n = 0;            // 元素個數,初始化為0
}

?創建堆變量,并初始化

Heap heap;         // 創建堆變量
init(&heap, 8);    // 設置數組最大元素個數為8

添加元素:

1、先在末尾添加元素。

2、(向上調整)與父節點比較大小,若小于父節點,與父節點交換位置,直到開頭位置(根節點,數組第一個元素)。

(注:子節點索引號為x,父節點索引號為(x-1)//2)

void add(Heap *heap, int data)		// add a element to the heap
{// 往末尾添加元素heap->p[heap->n] = data;// (向上調整) 與父節點比較,小于父節點的值,與父節點交換位置int cur = heap->n;while(cur > 0){int parent = ceil((cur - 1) / 2);if(heap->p[parent] > data){heap->p[cur] = heap->p[parent];heap->p[parent] = data;cur = parent;}else break;}// 每添加一個元素,元素個數+1heap->n++;
}

刪除(根節點):

1、記錄根節點(數組第一個元素)和末尾節點(數組最后一個元素)。

2、末尾節點的值換到根節點位置,元素個數-1。

3、(向下調整)從根節點開始,依次與左右子節點比較大小,數值小的是父節點,直到比對到末尾。

(注:父節點索引號為x,左子節點索引號為2x+1,右子節點索引號為2x+2)

int delete(Heap *heap)			// delete root from the heap
{if(heap->n == 0) return -1;    // 空樹heap->n--;                     // 每刪除一次根節點,元素個數-1int root = heap->p[0], enddata = heap->p[heap->n];heap->p[0] = enddata;	       // 末尾元素換到第一個位置// (向下調整) 與左右子節點比較,若子節點小,與較小子節點交換位置int cur = 0;while(cur <= heap->n){int left = cur * 2 + 1, right = cur * 2 + 2, minchild;if(left > heap->n) break;				// 沒有左子節點if(right > heap->n) minchild = left;	// 沒有右子節點,有左子節點else									// 左右子節點都有的情況{// 左右子節點比較,找到較小子節點if(heap->p[right] < heap->p[left]) minchild = right;else minchild = left;// 父節點與較小子節點比較,若子節點小,與子節點交換位置if(heap->p[minchild] < enddata){heap->p[cur] = heap->p[minchild];heap->p[minchild] = enddata;cur = minchild;}else break;}}return root;
}

獲取根節點:(數組第一個元素)

int getroot(Heap *heap)			// get the root from the heap
{if(heap->n == 0){printf("Empty heap\n");exit(-1);}return heap->p[0];
}

遍歷堆:(類似廣度遍歷二叉樹)

每個節點比子樹的所有節點都小,但左右節點沒有順序要求。

void traverse(Heap *heap)		// show element one by one (like breadth traverse the tree)
{if(heap->n == 0) return ;printf("elements(%d): ", heap->n);for(int k = 0; k < heap->n; k++){printf("%d  ", heap->p[k]);}printf("\n");
}

清空堆:

釋放數組內存空間,指向數組的指針指向NULL,元素個數為0。

void clear(Heap *heap)		// clear the heap (free memory space of the array)
{free(heap->p);          // 釋放數組內存空間heap->p = NULL;         // 指針指向NULL,避免野指針heap->n = 0;            // 元素個數為0
}

?


完整代碼:(heap.c)

#include <stdio.h>
#include <math.h>
#include <stdlib.h>/* structure */
typedef struct Heap
{int *p;			// memory address of the heap (array)int n;			// the number of the heap
} Heap;/* function prototype */
void init(Heap *, int);		// heap initialization
void add(Heap *, int);		// add a element to the heap
int delete(Heap *);			// delete root from the heap
int getroot(Heap *);		// get the root from the heap
void traverse(Heap *);		// show element one by one (likely breadth traverse the tree)
void clear(Heap *);			// clear the heap (free memory space of the array)/* main function */
int main(void)
{Heap heap;init(&heap, 8);printf("length: %d\n", heap.n);add(&heap, 5);	printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);add(&heap, 8);	add(&heap, 3);	add(&heap, 9);	add(&heap, 2);printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);delete(&heap);	printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);delete(&heap);	printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);clear(&heap);printf("length: %d\n", heap.n);printf("root(the minimum): %d\n", getroot(&heap));return 0;
}/* subfunction */
void init(Heap *heap, int length)		// heap initialization
{heap->p = (int *)malloc(length * sizeof(int));if(heap->p == NULL){perror("Memory allocation failed");exit(-1);}heap->n = 0;
}void add(Heap *heap, int data)		// add a element to the heap
{// add a element to the end of the heapheap->p[heap->n] = data;// (adjust up) compair with parent,if smaller than parent, change the positionint cur = heap->n;while(cur > 0){int parent = ceil((cur - 1) / 2);if(heap->p[parent] > data){heap->p[cur] = heap->p[parent];heap->p[parent] = data;cur = parent;}else break;}heap->n++;
}int delete(Heap *heap)			// delete root from the heap
{if(heap->n == 0) return -1;heap->n--;int root = heap->p[0], enddata = heap->p[heap->n];heap->p[0] = enddata;	// put the last element to the first position// (adjust down) compair with left and right child, minimun is parentint cur = 0;while(cur <= heap->n){int left = cur * 2 + 1, right = cur * 2 + 2, minchild;if(left > heap->n) break;				// no left childif(right > heap->n) minchild = left;	// have left child, no right childelse									// have left child and right child{// compair left child and right child, find smaller oneif(heap->p[right] < heap->p[left]) minchild = right;else minchild = left;// smaller child compair with parent,if child is the smallest, changeif(heap->p[minchild] < enddata){heap->p[cur] = heap->p[minchild];heap->p[minchild] = enddata;cur = minchild;}else break;}}return root;
}int getroot(Heap *heap)			// get the root from the heap
{if(heap->n == 0){printf("Empty heap\n");exit(-1);}return heap->p[0];
}void traverse(Heap *heap)		// show element one by one (like breadth traverse the tree)
{if(heap->n == 0) return ;printf("elements(%d): ", heap->n);for(int k = 0; k < heap->n; k++){printf("%d  ", heap->p[k]);}printf("\n");
}void clear(Heap *heap)		// clear the heap (free memory space of the array)
{free(heap->p);heap->p = NULL;heap->n = 0;
}

編譯鏈接: gcc -o heap heap.c

執行可執行文件:?./heap

?

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

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

相關文章

python-opencv多態模板匹配簡單代碼實現

在我實驗過程中發現&#xff0c;這種模板匹配如果不做任何處理只對原有圖像進行匹配的話&#xff0c;好像效果很瓜 貌似是模板是1 那就只能檢測出正常形態下的1&#xff0c;變大或者是 l 都不一定檢測到&#xff0c; 也就是說&#xff0c;只能檢測和模板圖片大小尺寸顏色類別…

docker 安裝 禪道

docker pull hub.zentao.net/app/zentao:20.1.1 sudo docker network create --subnet172.172.172.0/24 zentaonet 使用 8087端口號訪問 使用禪道mysql 映射到3307 sudo docker run \ --name zentao2 \ -p 8087:80 \ -p 3307:3306 \ --networkzentaonet \ --ip 172.172.172.…

電腦錄制視頻的軟件,電腦錄制,4款免費軟件推薦

在數字化時代&#xff0c;電腦錄制視頻的軟件已成為我們日常生活和工作中的得力助手&#xff0c;這些軟件可以幫助我們輕松捕獲到屏幕上的精彩瞬間。但同時市面上的錄制視頻軟件也層出不窮&#xff0c;讓人不知該如何選擇。到底怎樣才能選擇到一款適合自己的錄屏軟件呢&#xf…

【SpringBoot3學習 | 第2篇】SpringBoot3整合+SpringBoot3項目打包運行

文章目錄 一. SpringBoot3 整合 SpringMVC1.1 配置靜態資源位置1.2 自定義攔截器&#xff08;SpringMVC配置&#xff09; 二. SpringBoot3 整合 Druid 數據源三. SpringBoot3 整合 Mybatis3.1 Mybatis整合3.2 聲明式事務整合配置3.3 AOP整合配置 四. SpringBoot3 項目打包和運行…

k8s-第二節-常用操作

k8s命令行常用操作 k8s命令行 操作對象時都要前面聲明操作對象類型 kubectl get kubectl describe kubectl delete kubectl edit kubectl logs kubectl exec kubectl port-forward 端口轉發將pod 端口映射出來 kubectl cp 本地文件路徑:容器文件路徑 kubectl apply …

【JS場景題】判斷一個元素是否在可視區域內有哪些方法?

方法一、通過元素的位置信息和滾動條滾動的高度來判斷 前置知識 clientWidth: 元素的內容區域寬度加上左右內邊距寬度。offsetTop: 元素的上外邊框至包含元素的上內邊框之間的像素距離。document.documentElement.clientHeight&#xff1a; 獲取視口高度&#xff08;不包含滾動…

《Attention Is All You Need》解讀

一、簡介 “Attention Is All You Need” 是一篇由Ashish Vaswani等人在2017年發表的論文&#xff0c;它在自然語言處理領域引入了一種新的架構——Transformer。這個架構現在被廣泛應用于各種任務&#xff0c;如機器翻譯、文本摘要、問答系統等。Transformer模型的核心是“自…

小學vr虛擬課堂教學課件開發打造信息化教學典范

在信息技術的浪潮中&#xff0c;VR技術正以其獨特的魅力與課堂教學深度融合&#xff0c;引領著教育方式的創新與教學方法的變革。這一變革不僅推動了“以教促學”的傳統模式向“自主探索”的新型學習方式轉變&#xff0c;更為學生帶來了全新的學習體驗。 運用信息技術融合VR教學…

深度學習1

1.支持向量機Support Vector Machine&#xff08;SVM&#xff09;是一種對數據二分類的線性分類器&#xff0c;目的是尋找一個超平面對樣本進行分割&#xff0c;廣泛應用人像識別&#xff0c;手寫數字識別&#xff0c;生物信息識別。 二維空間分割界是一條直線&#xff0c;在三…

table = collections.defaultdict(list)申請的字典的類型是什么?

當你使用 collections.defaultdict(list) 來申請一個字典時&#xff0c;這個字典的類型是 defaultdict&#xff0c;但是其行為和表現方式在某些方面與普通的字典&#xff08;dict&#xff09;相似&#xff0c;主要區別在于它如何處理缺失的鍵。 defaultdict 是 Python 標準庫 …

【基礎篇】第4章 Elasticsearch 查詢與過濾

在Elasticsearch的世界里&#xff0c;高效地從海量數據中檢索出所需信息是其核心價值所在。本章將深入解析查詢與過濾的機制&#xff0c;從基礎查詢到復合查詢&#xff0c;再到全文搜索與分析器的定制&#xff0c;為你揭開數據檢索的神秘面紗。 4.1 基本查詢 4.1.1 Match查詢…

Java操作Excel最佳實踐

Java操作Excel最佳實踐 1、背景描述2、Apache POI簡介3、Java讀取Excel 1、背景描述 2、Apache POI簡介 官網&#xff1a;http://poi.apache.org/index.html 官方文檔&#xff1a;https://poi.apache.org/apidocs/index.html 3、Java讀取Excel 3.1、導入依賴 <dependency…

Qt——升級系列(Level Seven):事件、文件

目錄 Qt事件 事件介紹 事件的處理 按鍵事件 鼠標事件 定時器 事件分發器 事件過濾器 Qt文件 Qt文件概述 輸入輸出設備類 文件讀寫類 文件和目錄信息類 Qt事件 事件介紹 事件是應?程序內部或者外部產?的事情或者動作的統稱。在 Qt 中使??個對象來表??個事件。所有的 Qt …

工商業光伏項目如何快速開發?

一、前期調研與規劃 1、屋頂資源評估&#xff1a;詳細測量屋頂面積、承重能力及朝向&#xff0c;利用光伏業務管理軟件進行日照分析和發電量預測&#xff0c;確保項目可行性。 2、政策與補貼研究&#xff1a;深入了解當地政府對工商業光伏項目的政策支持和補貼情況&#xff0…

Java面試過程中遇到的問題

Java面試過程中遇到的問題 介紹工作經驗項目 介紹項目 為什么選用這個技術 報表服務怎么實現的 java框架 1、spring clound特性&#xff0c;組件有那些以及作用 springCloud是一套微服務組件&#xff0c; 常用的Eureka&#xff0c;Ribbon&#xff0c;Hystrix&#xff0c;Fe…

第三方支付平臺如何完美契合跨境電商?

在全球化的大潮中&#xff0c;跨境電商"Eurasia Boutique"的創始人艾米麗&#xff0c;帶著她的夢想和手工藝品&#xff0c;踏上了進入中國市場的征程。這是一個充滿挑戰和機遇的旅程&#xff0c;艾米麗和她的企業需要面對和解決一系列復雜的問題。 合規的門檻 艾米…

JVM原理(十四):JVM虛擬機運行時棧幀結構

Java虛擬機已方法作為最基本的執行單位。 棧幀&#xff1a;是支持Java虛擬機進行方法調用和方法執行背后的數據結構。 棧幀存儲了方法的 局部變量表、操作數棧、動態連接和放回地址等信息。 每一個方法的調用開始和執行結束&#xff0c;都對應著一個棧幀在虛擬機棧里面從入棧…

Linux文件與日志

目錄 1. Linux 文件系統 1.1 inode號 1.2 EXT類型文件恢復 1.3 xfs類型文件備份和恢復 2. 日志分析 2.1 日志類型 2.2日志配置文件 2.3 日志分析的重要性 在Linux系統中&#xff0c;文件和日志是管理和維護系統運行所不可或缺的。理解它們的工作原理和如何有效地管理和…

驅動開發:配置Visual Studio驅動開發環境

100編程書屋_孔夫子舊書網 配置驅動開發環境配置驅動開發模板配置驅動雙機調試 在正式開始驅動開發之前&#xff0c;需要自行搭建驅動開發的必要環境&#xff0c;首先我們需要安裝Visual Studio 2013這款功能強大的程序開發工具&#xff0c;在課件內請雙擊ISO文件并運行內部的…

2009-2024年第一季度上市公司華證ESG評級季度數據

2009-2024年第一季度上市公司華證ESG評級季度數據 1、時間&#xff1a;2009-2024年第一季度 2、指標&#xff1a;證券代碼、證券簡稱、評級日期、綜合評級、綜合得分、E評級、E得分、S評級、S得分、G評級、G得分、證監會行業&#xff08;新&#xff09;、同花順行業&#xff…