Skip to content

Commit

Permalink
Added imperative impelementation of leftist heap
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxinyu95 committed Apr 17, 2023
1 parent d6899df commit bfee90e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 9 deletions.
9 changes: 5 additions & 4 deletions datastruct/heap/binary-heap/bheap-zh-cn.tex
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ \subsection{堆排序}
\EndFunction
\end{algorithmic}

\begin{Exercise}
\begin{Exercise}\label{ex:arrayed-binary-heap}
\Question{考虑另外一种实现原地堆排序的想法:第一步先从待排序数组构建一个最小堆$A$,此时,第一个元素$a_1$已经在正确的位置了。接下来,将剩余的元素$[a_2, a_3, ..., a_n]$当成一个新的堆,并从$a_2$开始执行\textproc{Heapify}。重复这一从左向右的步骤完成排序。这一方法正确么?
\begin{algorithmic}[1]
\Function{Heap-Sort}{$A$}
Expand All @@ -284,8 +284,9 @@ \subsection{堆排序}
}
\end{Exercise}

\begin{Answer}
\begin{Answer}[ref = {ex:arrayed-binary-heap}]
\Question{不正确。$[a_2, a_3, ..., a_n]$的结构不再是一个堆,仅对第一个元素使用\textproc{Heapify}是不够的,需要用\textproc{Build-Heap}重建堆。}

\Question{不可以,原因同上。}
\end{Answer}

Expand Down Expand Up @@ -656,12 +657,12 @@ \section{小结}

本章中,我们介绍了通用的二叉堆概念。只要满足堆的性质,可以使用各种形式的二叉树来实现。用数组作为存储结构适于命令式实现,它将一棵完全二叉树映射为数组。方便进行随机访问。我们还介绍了直接用二叉树实现的堆,适于函数式实现。大部分操作的时间复杂度可以达到$O(\lg n)$,有些操作的分摊时间复杂度是$O(1)$的。冈崎在\cite{okasaki-book}中给出了详细分析。一个自然的想法是将二叉树扩展到多叉树,这样就会得到其它数据结构如二项式堆、斐波那契堆和配对堆。参见第十章。

\begin{Exercise}
\begin{Exercise}\label{ex:other-binary-heaps}
\Question{用命令式的方式实现左偏堆、斜堆、伸展堆。}
\Question{定义堆的叠加操作}
\end{Exercise}

\begin{Answer}
\begin{Answer}[ref = {ex:other-binary-heaps}]
\Question{用命令式的方式实现左偏堆、斜堆、伸展堆。}
\Question{定义堆的叠加操作

Expand Down
10 changes: 5 additions & 5 deletions datastruct/heap/binary-heap/src/LeftistHeap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ module LeftistHeap where

-- Definition

data LHeap a = E -- Empty
data LHeap a = E -- Empty
| Node Int a (LHeap a) (LHeap a) -- rank, element, left, right
deriving (Eq, Show)

merge::(Ord a)=>LHeap a -> LHeap a -> LHeap a
merge :: (Ord a) => LHeap a -> LHeap a -> LHeap a
merge E h = h
merge h E = h
merge h1@(Node _ x l r) h2@(Node _ y l' r') =
merge h1@(Node _ x l r) h2@(Node _ y l' r') =
if x < y then makeNode x l (merge r h2)
else makeNode y l' (merge h1 r')

makeNode::a -> LHeap a -> LHeap a -> LHeap a
makeNode :: a -> LHeap a -> LHeap a -> LHeap a
makeNode x a b = if rank a < rank b then Node (rank a + 1) x b a
else Node (rank b + 1) x a b

Expand Down Expand Up @@ -62,4 +62,4 @@ heapSort = hsort . fromList where

testFromList = fromList [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]

testHeapSort = heapSort [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
testHeapSort = heapSort [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
75 changes: 75 additions & 0 deletions datastruct/heap/binary-heap/src/leftistheap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from random import sample, randint

class Node:
def __init__(self, value, rank = 1, left = None, right = None, parent = None):
self.value = value
self.rank = rank
self.left = left
self.right = right
self.parent = parent

def rank(x):
return x.rank if x else 0

def merge(a, b):
h = Node(None) # the sentinel node
while a and b:
if b.value < a.value:
a, b = b, a
c = Node(a.value, parent = h, left = a.left)
h.right = c
h = c
a = a.right
h.right = a if a else b
while h.parent:
h.rank = 1 + rank(h.right)
h = h.parent
h = h.right
if h:
h.parent = None
return h

def insert(h, x):
return merge(Node(x, 1), h)

def top(h):
return h.value

def pop(h):
return h.value, merge(h.left, h.right)

def fromlist(xs):
h = None
for x in xs:
h = insert(h, x)
return h

def hsort(xs):
h = fromlist(xs)
ys = []
while h:
y, h = pop(h)
ys.append(y)
return ys

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

def prop_heap(xs):
h = fromlist(xs)
if xs:
a = top(h)
b = min(xs)
assert a == b, f"violate heap: top = {a}, min = {b}"

def prop_heapsort(xs):
ys = hsort(xs)
zs = sorted(xs)
assert ys == sorted(xs), f"violate heap sort, xs = {xs}, ys = {ys}, zs = {zs}"

if __name__ == "__main__":
test(prop_heap)
test(prop_heapsort)

0 comments on commit bfee90e

Please sign in to comment.