Skip to content

Commit

Permalink
Added delete for pairing heap
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxinyu95 committed Apr 19, 2023
1 parent fe9a1a3 commit 2e9f4ab
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 47 deletions.
6 changes: 5 additions & 1 deletion datastruct/heap/other-heaps/kheap-zh-cn.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1084,10 +1084,14 @@ \subsection{删除}

因为删除算法调用弹出操作,我们猜想它的分摊性能也是对数时间$O(\lg n)$

\begin{Exercise}
\begin{Exercise}\label{ex:pairing-heap-del}
实现配对堆的删除。
\end{Exercise}

\begin{Answer}[ref ={ex:pairing-heap-del}]
实现配对堆的删除。
\end{Answer}

\section{小结}

本章中,我们将堆的实现从二叉树扩展到了更加丰富的数据结构。二项式堆和斐波那契堆使用多叉树森林作为底层数据结构,而配对堆实现为一棵多叉树。通过将某些耗时的操作延迟进行,可以获得总体上优异的分摊性能。这一点很具有启发性。
Expand Down
4 changes: 1 addition & 3 deletions datastruct/heap/other-heaps/src/PairingHeap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ deleteMin (Node _ hs) = mergePairs hs where
mergePairs [h] = h
mergePairs (h1:h2:hs) = merge (merge h1 h2) (mergePairs hs)

-- Helper functions

fromList :: (Ord a) => [a] -> PHeap a
fromList xs = foldl insert E xs

Expand All @@ -65,4 +63,4 @@ heapSort = hsort . fromList where
-- test

prop_sort :: [Int] -> Bool
prop_sort xs = heapSort xs == L.sort xs
prop_sort xs = heapSort xs == L.sort xs
118 changes: 75 additions & 43 deletions datastruct/heap/other-heaps/src/pairingheap.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/python

# pairingheap.py, pairing heap
# pairingheap.py, pairing heap
# Copyright (C) 2012, Liu Xinyu (liuxinyu95@gmail.com)
#
# This program is free software: you can redistribute it and/or modify
Expand All @@ -17,13 +17,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

#
# Based on Michael L. Fredman, Robert Sedgewick, Daniel D. Sleator,
# and Robert E. Tarjan. ``The Pairing Heap: A New Form of Self-Adjusting
# Based on Michael L. Fredman, Robert Sedgewick, Daniel D. Sleator,
# and Robert E. Tarjan. ``The Pairing Heap: A New Form of Self-Adjusting
# Heap'' Algorithmica (1986) 1: 111-129
#

import random # for testing only
from collections import deque # for right to left merge only
from functools import reduce
from random import sample, randint, choice
from collections import deque # for right to left merge

#
# Assume the heap is min-heap
Expand Down Expand Up @@ -65,7 +66,7 @@ def top(h):

def decrease_key(h, x, key):
x.key = key # assume key <= x.key
if x.parent is not None:
if x.parent:
x.parent.children.remove(x) # Sadly, this is O(N) operation.
x.parent = None
return merge(x, h)
Expand All @@ -86,18 +87,38 @@ def pop(h):
for y in lst:
x = merge(x, y)
return x

# helper functions

def lookup_node(h, x):
if h.key == x:
return h
for t in h.children:
node = lookup_node(t, x)
if node:
return node
return None

def delete(h, x):
node = lookup_node(h, x)
if not node:
return h
if node == h:
return pop(h)
node.parent.children.remove(node)
node.parent = None
return merge(pop(node), h)

def from_list(lst):
return reduce(insert, lst, None)
return reduce(insert, lst)

def heap_sort(lst):
h = from_list(lst)
res = []
while h is not None:
res.append(top(h))
def to_list(h):
xs = []
while h:
xs.append(top(h))
h = pop(h)
return res
return xs

def heap_sort(lst):
return to_list(from_list(lst))

def to_str(h):
s = "(" + str(h.key) + ", "
Expand All @@ -107,33 +128,44 @@ def to_str(h):
return s

# testing
def test_sort():
n = 1000
for i in range(n):
lst = random.sample(range(n), random.randint(1, n))
assert(heap_sort(lst) == sorted(lst))
print "heap-sort:", n, "test cases are OK."

def test_decrease_key():
n = 1000
m = 16 # too slow for big m
for i in range(m):
xs = random.sample(range(n), random.randint(1, n))
ns = [KTree(x) for x in xs]
h = reduce(insert_node, ns, None)
xs = [x - random.randint(1, n) for x in xs]
for node, x in zip(ns, xs):
h = decrease_key(h, node, x)
ys = []
while h is not None:
ys.append(top(h))
h = pop(h)
assert(ys == sorted(xs))
print "decrease-key:", m, "test cases are OK."

def test():
test_sort()
test_decrease_key()
def random_list(n = 1000):
return sample(range(n), randint(1, n))

def test(f):
for _ in range(100):
xs = random_list()
f(xs)
print(f"100 tests for {f} passed.")

def test_sort(xs):
ys = heap_sort(xs)
zs = sorted(xs)
assert ys == zs, f"heap sort fail: xs = {xs}, ys = {ys}, zs = {zs}"

def test_decrease_key(xs):
n = len(xs)
lst = xs.copy()
ns = [KTree(x) for x in xs]
h = reduce(insert_node, ns)
i = randint(0, n-1)
xs[i] = xs[i] - randint(1, n)
h = decrease_key(h, ns[i], xs[i])
ys = to_list(h)
zs = sorted(xs)
assert ys == zs, f"decease-key fail: xs = {lst}, changed to: {xs}, ys = {ys}, zs = {zs}"

def test_del(xs):
h = from_list(xs)
n = len(xs)
y = choice(xs)
h = delete(h, y)
ys = to_list(h)
zs = xs.copy()
zs.remove(y)
zs.sort()
assert ys == zs, f"del fail: xs = {xs}, y = {y}, ys = {ys}, zs = {zs}"

if __name__ == "__main__":
test()
test(test_sort)
test(test_decrease_key)
test(test_del)

0 comments on commit 2e9f4ab

Please sign in to comment.