python 手動實現大根堆

2021-10-09 02:57:06 字數 2899 閱讀 9264

主要實現了四個函式:

add:往堆裡加新的值,相當於在list末尾新增值,然後siftup維護大根堆從上到下從大到小

class maxheap(object):

def __init__(self, maxsize):

self.maxsize = maxsize #堆的大小

self._elements = [0] * maxsize #初始化堆

self._count = 0 #索引

def add(self, value):

if self._count >= self.maxsize:

raise exception('full')

self._elements[self._count] = value #放到末尾

self._count += 1 #索引加一,這是當前的下乙個索引

self._siftup(self._count - 1) #siftup將當前索引值維護到堆的位置

def extract(self):

if self._count <= 0:

raise exception('empty')

value = self._elements[0] #記錄堆頂值

self._count-=1

self._elements[0] = self._elements[self._count] #末尾移到堆頂

self._siftdown(0) #從上到下維護堆

return value

def _siftup(self, index):

if index > 0:

parent = (index - 1) // 2 #當前索引的父索引

if self._elements[index] > self._elements[parent]: #當前值大於父,需要替換

self._elements[index], self._elements[parent] = self._elements[parent], self._elements[index]

self._siftup(parent) #加入的值換到了父索引位置,繼續向上看是不是比上一層的父更大

def _siftdown(self, index):

left = index * 2 + 1 #左子樹索引

right = index * 2 + 2 #右子樹索引

new_index = index #用乙個新索引,後面觀察需不需要換

if right < self._count: #有左右子樹的情況

if self._elements[left] <= self._elements[index] and self._elements[right] <= self._elements[index]: #當前比左右都大,不用操作

pass

else:

if self._elements[left] >= self._elements[right]:

new_index = left #左邊更大,且左邊大於當前,準備用左邊跟當前索引換

else:

new_index = right

elif left < self._count: #只有左子樹

if self._elements[left] >= self._elements[index]:

new_index = left

if new_index != index: #需要換

self._elements[new_index], self._elements[index] = self._elements[index], self._elements[new_index]

self._siftdown(new_index)

topk測試:

#測試**

import random

seq = list(range(10))

random.shuffle(seq)

heap = maxheap(len(seq))

for i in seq:

heap.add(i)

res =

for i in range(10):

heaqp用法:(heapq實現的是小根堆,用大根堆需要轉換成相反數)

將值item插入堆,並執行sift-up維持堆特性(列表末尾元素按規則向上移動)

將堆頂元素彈出,並執行sift-down位置堆特性(列表末尾元素賦值給list[0],並按規則向下移動)

4. heapq.heapreplace(heap, item)

和3的順序相反,先pop堆頂元素,然後push item入堆

5. heapq.heapify(x)

將列表x轉換為heap物件(inplace,線性時間)

6. heapq.merge(*iterables, key=none, reverse=false)

返回: 乙個iterable可迭代物件

操作: 將可迭代物件列表*iterables合併, 相當於對乙個大檔案分解的多個小檔案組合排序(具體原理見下方的磁碟排序)

引數: iterables: 多個輸入物件(已經從小到大排序), 例如多個已排序的小檔案

key: 用於比較大小的關鍵字字段, 預設為none

reverse: 預設輸出是從小到大, 設定為true後逆序輸出

7. heapq.nlargest(n, iterable, key=none)

返回乙個列表, 為根據key作為篩選條件從可迭代物件iterable中篩選的最大的n個元素

8. heapq.nsmallest(n, iterable, key=none)

返回乙個列表, 為根據key作為篩選條件從可迭代物件iterable中篩選的最小的n個元素

大根堆實現

堆 有兩種,一種是大根堆,另一種是小根堆。大根堆的意思是在跟的位置那個數是最大的。同理,小根堆的根元素是最小的。堆是乙個滿的二叉樹,除了最後乙個節點可能不是滿的。所以用陣列去陣列去實現它。乙個節點的index為i,則這個節點的兩個子節點的下標應該為2 i 1和2 i 2 父結點那就是 i 1 2 下...

C 實現大根堆

一 堆的定義 堆的物理儲存結構是一維陣列,邏輯儲存結構是完全二叉樹。堆的基本操作包括 insert 向堆中插入乙個元素,deletetop 刪除堆頂元素 上面的就是乙個大根堆,大根堆具有以下性質 每乙個節點的值都小於它父節點的值。我們也可以從上面的中看出來。但是需要注意的是,每乙個節點的值的大小與它...

堆(大根堆 小根堆)

堆又可稱之為完全二叉堆。這是乙個邏輯上基於完全二叉樹 物理上一般基於線性資料結構 如陣列 向量 鍊錶等 的一種資料結構。學習過完全二叉樹的同學們都應該了解,完全二叉樹在物理上可以用線性資料結構進行表示 或者儲存 例如陣列int a 5 就可以用來描述乙個擁有5個結點的完全二叉樹。那麼基於完全二叉樹的...