數據結構之堆(topk問題、堆排序)

一、堆的初步認識

堆雖然是用數組存儲數據的數據結構,但是它的底層卻是另一種表現形式。

堆分為大堆和小堆,大堆是所有父親大于孩子,小堆是所有孩子大于父親。

?通過分析我們能得出父子關系的計算公式,parent=(child-1)/2,左孩子leftchild=parent*2+1,右孩子rightchild=parent*2+2,這會在下面實現時應用。

二、堆實現

1、頭文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;void HeapPrint(HP* php);//堆打印
void HeapInit(HP* php);//堆初始化
void HeapPush(HP* php, HPDataType x);//堆插入
void HeapPop(HP* php);//堆刪除
HPDataType HeapTop(HP* php);//返回堆頂元素
bool HeapEmpty(HP* php);//判空
int HeapSize(HP* php);//返回堆大小
void AdjustUp(HPDataType* a, int child);//向上調整
void AdjustDown(HPDataType* a, int n, int parent);//向下調整
void Swap(HPDataType* x, HPDataType* y);//交換函數
void HeapSort(int* arr, int n);//堆排序
void HeadDestroy(HP* php);//堆銷毀

這里用結構體管理數據,HPDataType*a是動態數組的指針,HPDataType是typedef定義的可變參數,需要更改存儲類型時,修改typedef的內容即可,size用于統計存儲數據的多少,capacity是統計開辟的空間大小,即動態申請數組的大小。?

2、 堆初始化

void HeapInit(HP* php)
{assert(php);php->a = (HPDataType*)malloc(sizeof(HPDataType)* 4);if (php->a == NULL){perror("malloc fail");return;}php->size = 0;php->capacity = 4;
}

assert檢查指針是否為空,malloc動態申請空間,然后對size和capacity(空間的大小)初始化?

3、堆打印

void HeapPrint(HP* php)
{for (int i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}

?4、向上調整

void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;/*while (a[parent] < a[child]){Swap(&a[parent], &a[child]);child = parent;parent = (child - 1) / 2;}*/while (child > 0) //與下面風格相同{if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else break;}
}

向上調整用于解決插入數據造成的不構成堆的問題?

5、堆插入

當我們插入一個值時,這個新插入的值也許會破壞原本的堆關系,所以我們需要進行向上調整,使其恢復堆關系。?

void HeapPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType)* php->capacity * 2);if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity *= 2;}php->a[php->size] = x;//size代表元素個數,a[size]為下一個元素php->size++;AdjustUp(php->a, php->size - 1);//向上調整
}

?6、向下調整

void AdjustDown(HPDataType* a,int n ,int parent)
{/*int child = a[parent * 2 + 1] > a[parent * 2 + 2] ? parent * 2 + 1 : parent * 2 + 2;while (child < n){Swap(&a[parent], &a[child]);parent = child;child = a[parent * 2 + 1] > a[parent * 2 + 2] ? parent * 2 + 1 : parent * 2 + 2;}*/int child = parent * 2 + 1;//左孩子while (child < n){//選出左右孩子中大的那一個if (child + 1 < n && a[child + 1] > a[child]){++child;}if (a[child]>a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else break;}
}

7、堆刪除

這里選擇堆頂元素和堆底元素交換,如果挪動數據會導致父子關系亂套,而這里不free最后一個元素,避免釋放后繼續使用。

void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));//挪動刪除:1.效率低下2.關系全亂//只需要交換第一個元素和最后一個元素值,并php->size--//1.效率高2.保持父子關系Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);}

?8、返回堆頂元素

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

動態數組中存儲的第一個元素就是堆頂元素??

9、堆判空

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

通過size的數量判空,如果為0,則堆為空,返回true?

?10、堆大小

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

?這里結構體中有size數據,返回即可。

11、堆銷毀

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

?free掉a指針指向的空間,a指針置空,size和capacity賦值0.

三、擴展

1、堆排序(升序大堆,降序小堆)

時間復雜度O(N*logN)

先對要排序的數組建堆,然后交換堆頂元素,對剩余的元素向下調整。

void HeapSort(int* arr, int n)
{for (int i = (n-2)/2; i >0; i--){AdjustDown(arr, n, i);}int end = n - 1;while (end){Swap(&arr[0], &arr[end]);AdjustDown(arr, end, 0);end--;}
}

2、topk問題

?用k個元素建小堆,剩余n-k個元素與堆頂元素比較交換即可,最后k大小的小堆中保留的是這n個數中前k個最大的數。

看到最后,如果對您有所幫助,請點贊、收藏和關注,點點關注不迷路,源碼已上傳Gitee有需自取:白天沒有黑夜 (not-during-the-day) - Gitee.com,我們下期再見!

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

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

相關文章

0基礎 Git 代碼操作

將代碼提交倉庫&#xff1a; 準備工作? ?注冊 Gitee 賬號?&#xff1a;確保你已注冊并登錄 Gitee。?創建倉庫?&#xff1a;在 Gitee 上新建一個空倉庫&#xff08;如果尚未創建&#xff09;&#xff1a; 點擊右上角 → 新建倉庫。填寫倉庫名稱、描述&#xff0c;選擇公…

OpenAI大模型不聽人類指令事件的技術分析與安全影響

OpenAI大模型不聽人類指令事件的技術分析與安全影響 OpenAI大模型o3確實存在不遵從人類關閉指令的現象&#xff0c;這一行為已被第三方安全機構驗證&#xff0c;但其本質是技術缺陷而非AI意識覺醒。帕利塞德研究所的測試顯示&#xff0c;在100次實驗中o3有7次成功繞過關閉指令…

軟件工程期末速成--附帶幾道題

軟件工程中的各種設計 瀑布模型&#xff1a; 定義&#xff1a;將軟件生存周期的各項活動規定為依照固定順序連接的若干階段工作&#xff0c;形如瀑布流水&#xff0c;最終得到軟件產品 系統流程圖&#xff1a;系統流程圖是描繪物理系統的傳統工具&#xff0c;它的基本思想是用…

免費分享50本web全棧學習電子書

最近搞到一套非常不錯的 Web 全棧電子書合集&#xff0c;整整 50 本&#xff0c;都是epub電子書格式&#xff0c;相當贊&#xff01;作為一個被期末大作業和項目 ddl 追著跑的大學生&#xff0c;這套書真的救我狗命&#xff01; 剛接觸 Web 開發的時候&#xff0c;我天天對著空…

嵌入式學習筆記——day26

文件操作&#xff08;續&#xff09;目錄操作 一、文件操作 1. lseek lseek 是一個用于在文件中移動文件指針的系統調用&#xff0c;通常用于在文件描述符所指向的文件中定位讀取或寫入的位置。它允許程序在文件中隨機訪問數據&#xff0c;而不是只能順序讀取或寫入。 off_t …

LINUX安裝運行jeelowcode前端項目

參考 JeeLowCode低代碼社區,JeeLowCode低代碼開發平臺,JeeLowCode低代碼開發框架,快速啟動&#xff08;VUE&#xff09; 安裝node 18 LINUX安裝node/nodejs_linux安裝node 安裝到哪-CSDN博客 安裝PNPM LINUX安裝PNPM-CSDN博客 下載 git clone https://gitcode.com/jeelo…

【Redis】基本架構

1. 單線程模型 現在開啟了三個redis-cli客戶端同時執行命令。 客戶端1設置一個字符串鍵值對&#xff1a; 127.0.0.1:6379> set hello world客戶端2對counter做自增操作&#xff1a; 127.0.0.1:6379> incr counter客戶端3對counter做自增操作&#xff1a; 127.0.0.1:…

[yolov11改進系列]基于yolov11的修改檢測頭為自適應特征融合模塊為ASFFHead檢測頭的python源碼+訓練源碼

【自適應空間特征融合模塊ASFF介紹】 ASFF&#xff08;Adaptive Spatial Feature Fusion&#xff09;是一種自適應特征融合策略&#xff0c;旨在解決目標檢測中不同尺度特征之間的沖突和不一致性。 ? 基本概念和原理 ASFF通過學習每個尺度特征的自適應融合權重&#xff0c…

機器學習——支持向量機SVM

機器學習——支持向量機 一、介紹1.概述1.1 概念1.2 SVM的優缺點 2.硬間隔2.1 求解間隔2.2 對偶問題 3.軟間隔3.1 松馳變量3.2 對偶問題 4.核函數4.1 概念4.2 常見的核函數 二、代碼實戰1.實驗要求2.具體實現2.1 詞匯表加載2.2 郵件預處理函數2.3詞索引轉換為特征向量2.4 SVM 模…

Python 科學計算有哪些提高運算速度的技巧

在科學計算中提高 Python 運算速度的核心技巧包括&#xff1a;使用 NumPy 向量化操作、利用 Numba 加速函數、調用 C/C 擴展模塊、應用多線程/多進程并行計算、使用 GPU 加速計算。其中&#xff0c;使用 NumPy 向量化是最基礎且見效最快的優化方式。NumPy 利用底層 C 實現高效的…

React+Antd全局加載遮罩工具

下面是全局加載遮罩工具&#xff0c;功能&#xff1a;提供show和showWithDelay/hide方法用于顯示/延時顯示/隱藏遮罩&#xff0c;它還提供loading屬性返回是否正在loading。通常用于耗時較長的操作&#xff0c;比如遠端api調用。 如何用它&#xff0c;下面是個例子&#xff0c…

【機器學習基礎】機器學習入門核心算法:GBDT(Gradient Boosting Decision Tree)

機器學習入門核心算法&#xff1a;GBDT&#xff08;Gradient Boosting Decision Tree&#xff09; 1. 算法邏輯2. 算法原理與數學推導2.1 目標函數2.2 負梯度計算2.3 決策樹擬合2.4 葉子權重計算2.5 模型更新 3. 模型評估評估指標防止過擬合 4. 應用案例4.1 金融風控4.2 推薦系…

水墨色調中國風PPT模版分享

水墨色調中國風PPT模版分享&#xff1a;水墨中國風PPT模版https://pan.quark.cn/s/4368c537b1d2 第一套PPT模版?&#xff1a;主題是“愛蓮說”&#xff0c;水墨風格封面。核心視覺是綠色蓮蓬、白鶴、紅色印章&#xff0c;文字有“愛蓮說”等。適用文學或傳統文化類演示。 ?第…

PBX、IP PBX、FXO 、FXS 、VOIP、SIP 的概念解析以及關系

PBX&#xff08;Private Branch Exchange&#xff09; 概念 &#xff1a;PBX 是專用交換機&#xff0c;是一種在企業或組織內部使用的電話交換系統。它允許內部用戶之間以及內部用戶與外部公共電話網絡&#xff08;PSTN&#xff09;之間進行通信。例如&#xff0c;在一個大型企…

LabVIEW雙光子熒光成像軟件開發

雙光子熒光成像技術在抑郁小鼠腦內丙二醛&#xff08;MDA&#xff09;和甲醛&#xff08;FA&#xff09;檢測中的軟件開發&#xff0c;基于 LabVIEW 平臺構建從硬件控制、數據采集到圖像處理的全流程系統。結合 5734 FPGA 實現實時圖像處理&#xff0c;突出雙光子成像的深度開發…

OSI模型中的網絡協議

一、電子郵件協議&#xff1a;從SMTP到MIME的擴展 電子郵件系統的核心協議包括SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;、POP3&#xff08;Post Office Protocol&#xff09;和IMAP&#xff08;Internet Message Access Protocol&#xff09;&#xff0c;但…

流程自動化引擎:讓業務自己奔跑

在當今競爭激烈的商業環境中&#xff0c;企業面臨著快速變化的市場需求、日益復雜的業務流程以及不斷增長的運營成本。如何優化業務流程、提升效率并降低成本&#xff0c;成為企業持續發展的關鍵問題。 流程自動化引擎&#xff08;Process Automation Engine&#xff09;作為一…

DNS解析過程以及使用的協議名稱

DNS&#xff08;Domain Name System 域名系統&#xff09;解析是一個分層查詢的過程 1.本地緩存查詢階段 先檢查瀏覽器自身的DNS緩存 接著檢查操作系統的DNS緩存 最后檢查本地 hosts 文件 2.本地DNS服務器查詢階段 先向本地DNS服務器查詢&#xff0c;協議是 DNS over UDP&a…

思澈科技助力Keep Watch Pilot 1:重新定義智能運動手表體驗

——以創新芯片技術&#xff0c;打造長續航、高性能的隨身運動教練 作為智能穿戴領域的核心技術支持者&#xff0c;思澈科技攜手Keep共同推出全新智能運動手表Keep Watch Pilot 1。該產品搭載思澈科技自主研發的SF32LB557芯片&#xff0c;在高性能顯示、超長續航與精準運動監測…

github actions入門指南

GitHub Actions 是 GitHub 提供的持續集成和持續交付&#xff08;CI/CD&#xff09;平臺&#xff0c;允許開發者自動化軟件工作流程&#xff08;如構建、測試、部署&#xff09;。以下是詳細介紹&#xff1a; 一、核心概念 Workflow&#xff08;工作流程&#xff09; 持續集成的…