LoginSignup
0
1

More than 1 year has passed since last update.

素敵なデータ構造:ヒープ by Python

Last updated at Posted at 2021-05-14

データ構造の説明

ヒープとは、
・二分木を用いるデータ構造で、
・木の深さh-1以下の部分については完全二分木を形成し、
・各頂点と親頂点との間に親頂点≧子頂点の関係が成立し、
・値xの検索には適さないですが、最大値の取得が得意
なようです。

heap.py
class Heap():
    heap = []

    # 値の追加
    # 一番最後の葉に追加したのち、「自分の親と比較して逆転していれば入れ替える」を繰り返す
    def push(self, x):
        self.heap.append(x)
        i = len(self.heap)-1
        while i > 0:
            p = (i-1)//2
            if self.heap[p] >= x:
                break
            self.heap[i] = self.heap[p]
            i = p
        self.heap[i] = x
        return self.heap

    # 最大値の取得
    def top(self):
        if self.heap != "":
            return self.heap[0]
        else:
            return -1

    # 最大値の削除
    # 一番最後の葉を根と入れ替えたのち、「自分の子と比較して逆転していれば入れ替える」を繰り返す
    def pop(self):
        if self.heap == "":
            return
        x = self.heap[-1]
        self.heap.pop()
        i = 0
        while i*2+1 < len(self.heap):
            child1 = i*2+1
            child2 = i*2+2
            if child2 < len(self.heap) and self.heap[child2] > self.heap[child1]:
                child1 = child2
            if self.heap[child1] <= x:
                break
            self.heap[i] = self.heap[child1]
            i = child1
        self.heap[i] = x
        return self.heap

h = Heap()
h.push(3)
h.push(43)
h.push(15)
h.push(29)
h.pop()
h.push(732)
h.push(88)
h.push(14)
h.push(51)
h.pop()

# 出力 [88, 29, 51, 3, 15, 14]

アルゴリズムへの適用

ダイクストラ法

Dijkstra-heap.py
import heapq

# アルゴリズム定義
# ヒープを用いたダイクストラ法
def Dijkstraheap(G, dist, s):
    used = [False for i in range(N)]
    dist[s] = 0    
    que = []
    heapq.heappush(que, (dist[s], s))

    while que:
        v = que[0][1]
        d = que[0][0]
        heapq.heappop(que)

        if d > dist[v]:
            continue

        for e in range(len(G[v])):
            if dist[G[v][e][0]] > dist[v] + G[v][e][1]:
                dist[G[v][e][0]] = dist[v] + G[v][e][1]
                heapq.heappush(que, (dist[G[v][e][0]], G[v][e][0]))

# 入力受取
# 頂点数、辺数、始点
N, M, s = map(int, input().split())

# グラフの生成
# 重み付き単方向グラフ
G = [[] for i in range(N)]
for i in range(M):
    a, b, w = map(int, input().split())
    G[a].append([b, w])

# ダイクストラ法の結果を格納するリストの生成 
# 初期値として無限大の代わりに10000を格納
dist = [10000 for i in range(N)]    

# アルゴリズム実行
# ヒープを用いたダイクストラ法
Dijkstraheap(G, dist, s)

# 結果出力
# sから各頂点への最短距離を出力
for i in range(N):
    print(i, ": ", dist[i])

# 入力
# 6 9 0
# 0 1 3
# 0 2 5
# 1 2 4
# 1 3 12
# 2 3 9
# 2 4 4
# 3 5 2
# 4 3 7
# 4 5 8

# 出力
# 0 :  0
# 1 :  3
# 2 :  5
# 3 :  14
# 4 :  9
# 5 :  16
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1