由堆到堆排序

2021-09-13 14:19:45 字數 1717 閱讀 5920

堆通常是乙個可以被看做一棵樹的陣列物件。堆總是滿足下列性質:

堆總是一棵完全二叉樹。

堆中某個節點的值總是不大於或不小於其父節點的值;

將根節點最大的堆叫做最大堆或大根堆,根節點最小的堆叫做最小堆或小根堆。常見的堆有二叉堆、斐波那契堆 等。

這裡主要介紹二叉堆

上面是邏輯上結構, 下面則是實際的儲存結構,我將陣列和樹的都從1開始編號。

以下標pos為5,即值為4的點為例

pos的父親節點為 pos>>1 = 2, 值為3, 左兒子節點為 pos<<1 = 10 值為 10, 右兒子節點為 pos<<1|1 = 11 值為 9

這圖就是乙個小根堆,大根堆也就容易理解了

題目鏈結

題目很簡單,用優先佇列就能過。優先佇列本質還是用堆實現的。

那我們還是用堆來實現。

根據題目要求,我們使用小根堆顯然比較合適些;

//操作1 x,就將x放入陣列的末尾

/*dui陣列用於儲存堆元素

x 是要插入的元素

因為是向上更新的,所以函式名為 up

*/voidup(

int x)}/*

這樣,就能保證每次插入新的元素之後,dui[1] 是堆中的最小值

*/

操作 2

就直接輸出 dui[

1] 就好了

//操作3 移除最小的元素

/*如果只是單純的移除掉根節點,肯定是不行的

所以,我們就把 dui 陣列的最後乙個元素覆蓋掉 根節點 ,同時還要對堆進行維護, 使之依然是 小根堆

*/void

down()

else

break;}

}

本來想上圖的,不過自己畫的真的醜,自己隨便模擬下就可以了
這樣這個題目就能很輕鬆了水過去了

堆排序就簡單了啊,就是上面兩個函式的結合啊。

上面的 操作1 就相當於 輸入元素。

操作3 就不是覆蓋了,是將 根節點 和 最後乙個節 點交換了。

#include

const

int maxn =

100005

;using namespace std;

typedef

long

long ll;

int dui[maxn]

, len;

// len 堆的實際長度

voidup(

int pos)

}void

down

(int pos)

else

break;}

}int

main()

for(

int i=

1; i

)for

(int i=

1; i<=n; i++

)printf

("%d "

, dui[i]);

return0;

}

上面是利用小根堆, 將陣列按降序排列

公升序怎麼辦??

陣列倒著輸出就好了啊

還有大根堆啊

排序 4 堆排序

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

排序二 堆排序

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

排序七 堆排序

時間複雜度 最好 o n o n 平均o n o nlogn 最差o n o nlogn 空間複雜度 o n o 1 穩定性 不穩定 堆 順序儲存的完全二叉樹,其每個結點均小於等於或大於等於其子節點。小根堆 每個結點元素的值都小於等於其子節點元素的值的堆。s i s 2 i 1 s i s 2 i ...