今回は、Min Heap(Pythonではヒープキューと呼ばれています)について詳しく説明します。
Pythonのヒープとそのライブラリ関数(heapqモジュール)については既に学びました。
ここでは、ミニヒープとその実装について学び、さらに heapify
, heappush
, heappop
関数を自分自身で実装するための Python コードを見ていきます。
簡単に復習しておきましょう。
この記事もチェック:PythonのOshashモジュールを使ってハッシュ関数を実装する方法
Minヒープとは?
最小ヒープとは、完全な二分木(完全な二分木とは、最深部/最終レベルの右端ノードを除いて完全に埋まっている木)であり、各ノードはそのすべての子より小さいか等しくなっています。
したがって、ヒープのルートノードは最小の要素です。
ミニヒープのデータ構造は、一般に優先度待ち行列を表現するのに使われる。
import sys
#defining a class min_heap for the heap data structure class min_heap:
def __init__( self , sizelimit):
self .sizelimit = sizelimit
self .cur_size = 0
self .Heap = [ 0 ] * ( self .sizelimit + 1 )
self .Heap[ 0 ] = sys.maxsize * - 1
self .root = 1
# helper function to swap the two given nodes of the heap
# this function will be needed for heapify and insertion to swap nodes not in order
def swapnodes( self , node1, node2):
self .Heap[node1], self .Heap[node2] = self .Heap[node2], self .Heap[node1]
# THE MIN_HEAPIFY FUNCTION
def min_heapify( self , i):
# If the node is a not a leaf node and is greater than any of its child
if not (i > = ( self .cur_size / / 2 ) and i < = self .cur_size):
if ( self .Heap[i] > self .Heap[ 2 * i] or self .Heap[i] > self .Heap[( 2 * i) + 1 ]):
if self .Heap[ 2 * i] < self .Heap[( 2 * i) + 1 ]:
# Swap the node with the left child and then call the min_heapify function on it
self .swapnodes(i, 2 * i)
self .min_heapify( 2 * i)
else :
# Swap the node with right child and then call the min_heapify function on it
self .swapnodes(i, ( 2 * i) + 1 )
self .min_heapify(( 2 * i) + 1 )
# THE HEAPPUSH FUNCTION
def heappush( self , element):
if self .cur_size > = self .sizelimit :
return
self .cur_size + = 1
self .Heap[ self .cur_size] = element
current = self .cur_size
while self .Heap[current] < self .Heap[current / / 2 ]:
self .swapnodes(current, current / / 2 )
current = current / / 2
# THE HEAPPOP FUNCTION
def heappop( self ):
last = self .Heap[ self .root]
self .Heap[ self .root] = self .Heap[ self .cur_size]
self .cur_size - = 1
self .min_heapify( self .root)
return last
# THE BUILD_HEAP FUNCTION
def build_heap( self ):
for i in range ( self .cur_size / / 2 , 0 , - 1 ):
self .min_heapify(i)
# helper function to print the heap
def print_heap( self ):
for i in range ( 1 , ( self .cur_size / / 2 ) + 1 ):
print ( "Parent Node is " + str ( self .Heap[i]) + " Left Child is " + str ( self .Heap[ 2 * i]) + " Right Child is " + str ( self .Heap[ 2 * i + 1 ]))
# Driver Code minHeap = min_heap( 10 )
minHeap.heappush( 15 )
minHeap.heappush( 7 )
minHeap.heappush( 9 )
minHeap.heappush( 4 )
minHeap.heappush( 13 )
minHeap.print_heap() |
H
Understanding the functions used in the implementation of Min Heap
1. min-heapify 関数
この関数は、あるノードとそのすべての子孫ノード(子ノードとその子)を ヒープ属性に従わせる。
ヒープの性質に従い、与えられたヒープがその部分木の最小ノードになるように、ノードをスワップして並べ替えます。
この関数は、まず、与えられたノードとその子供のうち、最も小さい値を持つノードを見つける。
そして、与えられたノード(iとする)を、見つかった最小値のノード(jとする)と交換し、ノードjに対して(再帰的に)min-heapify関数を呼び出す。
これにより、ノードjに割り当てられた新しい値が、その部分木のヒープ特性を破らないことが確認される。
この関数は、せいぜい木の深さまで走査しなければならないので、その時間計算量はO(d)(dは深さ、ノード数でいえばO(log n)、nはヒープ内の要素数)です。
2. ビルドヒープ関数
この関数は、任意のリスト(または他の任意の反復可能ファイル)からヒープを構築 します。
すなわち、リストを受け取り、ヒープ特性を満たすように各要素を並べ替 える。
これは、各ノードに対してmin-heapifyを繰り返し適用することにより、単純に実装することができます。
この関数の時間計算量はO(n)であり、ここでnはヒープ内の要素数です。
3. ヒープポップ関数
この関数はヒープの最小値(ルート要素)をポップアウトします。
これは実際には、ルートノードと最後のノードを交換し、(最小値を含む)最後のノードを削除し、スワップによる変更後もヒープ特性を維持するように、ルートノードに対してmin-heapifyを呼び出すことによって行われる。
子孫を処理するだけなので、時間計算量はO(log n)(nは要素数)、またはO(h)(hは木の高さ)で、完全木であるためlog nとなります。
4. heappush関数
この関数は、新しい要素をヒープにプッシュし、ヒープのプロパティを維持したまま、正しい位置に配置します。
これは実際にはヒープの末尾に新しいノードを追加することで行われます。
さて、ヒープ特性を維持するために、最後のノードから上にトラバースし(必要に応じてスワップし)、違反している可能性のあるヒープ特性を修正します。
heappopと同様に、サブツリーの高さをトラバースするだけなので、ここでの時間複雑性はO(log n)です。
5. extractMin関数
この関数はヒープから最も優先度の高いもの(ルート要素)を返す。
ルートの値を返すだけでヒープに変更を加えず、ルートには O(1) 時間でアクセスできるので、この関数の時間複雑度は O(1) となります。
Min Heap データ構造の完全な Python 実装
以下は、PythonでMin Heapを実装するための完全なプログラムです。
Parent Node is 4 Left Child is 7 Right Child is 9
Parent Node is 7 Left Child is 15 Right Child is 13
|
出力。
コクルージョン
この記事では、min heapについて学びました。
heapify、
heappush、
heappop`の関数がどのように動作するのかを勉強した。
さらに、pythonでゼロからmin heapのデータ構造を実装しました。
今後も有益な記事を期待しています。