堆排序 堆的模擬

2022-09-21 13:48:11 字數 2379 閱讀 4642

一般用陣列來表示堆,下標從0開始。則下標為 i 的節點的父節點下標為(i-1)/2,其左右子節點分別為(2i + 1)(2i + 2)

下標從1開始 左右節點2i 、 2i+1i / 2

利用大頂堆(小頂堆)堆頂記錄的是最大(小)關鍵字這一特性,每次從無序陣列中選出最大(最小)值。

1、將待排序序列造成乙個最大堆,此時根節點為最大值

2、依次將根節點與待排序序列最後乙個元素交換

3、維護從根節點到該元素的前乙個節點為最大堆

down:把數往下沉,從而再次變成堆的操作,要考慮和兩個左右子節點比較。

up:底下的數往上走,再次變成堆的操作,只要和父節點比較就可以。

插入乙個數:heap[++size], up(size)

刪除最小值:把最後乙個元素覆蓋到堆頂,heap[1] = heap[size], size--, down(1)

刪除任意乙個元素:heap[k]=heap[size];size--;down(k);up(k);dwon和up只會執行乙個

修改任意元素:heap[k]=x;down();up()

時間複雜度:nlog n

堆排序:每次取出堆頂後,把最後乙個數放到堆頂,進行下沉操作,直到堆最後只剩乙個元素為止。

模板

#include#includeusing namespace std;

const int n = 100010;

int h[n], mysize;

int n, m;

void down(int u)

}int main()

return 0;

}

模擬堆

維護乙個集合,初始時集合為空,支援如下幾種操作:

i x,插入乙個數 x;

pm,輸出當前集合中的最小值;

dm,刪除當前集合中的最小值(資料保證此時的最小值唯一);

d k,刪除第 k 個插入的數;

c k x,修改第 k個插入的數,將其變為 x;

現在要進行 n次操作,對於所有第 22 個操作,輸出當前集合的最小值。

定義兩個陣列:分別是 hp 和 ph

hp-->堆陣列中下標 -> 第k個插入heap pointer

ph-->第k個插入 -> 堆陣列中下標pointer heap

這兩個函式是互為反函式的。

當在堆中交換兩個元素時,那麼第k個插入的數的下標要變化、下標對應的數是第幾個也要變化。swap操作傳入需要交換的堆陣列的下標

int h[n], mysize, cnt; // cnt記錄第k次插入

int ph[n], hp[n];

// ph[k]: 第k個插入 --> 下標

// hp[k]: 下標k -->第幾個插入

// 交換堆中的兩個數,那麼下標和第幾次插入的關係也要變化

void swap_heap(int a, int b)

void down(int i)

}void up(int i)

}// 插入乙個數,在最後插入

void insert(int x)

// 刪除第k個插入數

void del(int k)

// 刪除最小值,堆頂

void del()

// 修改第k個插入的數

void change(int k, int x)

int main() else if(op == "pm") else if(op == "d") else if(op == "dm") else

}return 0;

}

堆排序 模擬堆排序

838.堆排序 輸入乙個長度為n的整數數列,從小到大輸出前m小的數。輸入格式 第一行包含整數n和m。第二行包含n個整數,表示整數數列。輸出格式 共一行,包含m個整數,表示整數數列中前m小的數。資料範圍 1 m n 1051 m n 105,1 數列中元素 1091 數列中元素 109 輸入樣例 5 ...

排序 4 堆排序

將待排序的序列構成乙個大頂堆。此時,序列的最大值就是堆頂的根結點。將它移走 就是,將其與堆陣列的末尾元素交換,此時末尾的元素就是最大值 然後將剩餘的n 1個序列重新構成乙個堆,如此反覆。其中關鍵問題 1 如何將無序序列構成乙個堆 2 輸出堆頂元素後,如何調整公升序元素為乙個堆 4.堆排序 堆調整 v...

排序二 堆排序

子結點的鍵值或索引總是小於 或者大於 它的父節點。堆通過一維陣列實現。在起始陣列為 0 的情形中 父節點i的左子節點在位置 2 i 1 父節點i的右子節點在位置 2 i 2 子節點i的父節點在位置 floor i 1 2 堆中的最大值總是位於根節點。堆中定義以下幾種操作 1 最大堆調整 max he...