Skip to content

Commit

Permalink
Added answers to ch08
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxinyu95 committed Apr 17, 2023
1 parent 35d5156 commit 3b075f8
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 12 deletions.
86 changes: 80 additions & 6 deletions datastruct/heap/binary-heap/bheap-en.tex
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ \subsection{Heap sort}
\EndFunction
\end{algorithmic}

\begin{Exercise}
\begin{Exercise}\label{ex:arrayed-binary-heap}
\Question{Consider another idea about in-place heap sort: Build a min-heap from the array $A$, the first element $a_1$ is in the right position. Treat the rest $[a_2, a_3, ..., a_n]$ as the new heap, and apply \textproc{Heapify} from $a_2$. Repeat this till the last element. Is this method correct?
\begin{algorithmic}[1]
\Function{Heap-Sort}{$A$}
Expand All @@ -284,8 +284,9 @@ \subsection{Heap sort}
}
\end{Exercise}

\begin{Answer}
\begin{Answer}[ref = {ex:arrayed-binary-heap}]
\Question{No, it is not correct. The sub-array $[a_2, a_3, ..., a_n]$ can't map back to binary heap. It's insufficient to only apply \textproc{Heapify} from $a_2$, we need run \textproc{Build-Heap} to rebuild the heap.}

\Question{For the same reason, it does not work.}
\end{Answer}

Expand Down Expand Up @@ -651,13 +652,86 @@ \section{Summary}

We give the generic definition of binary heap in this chapter. There are several implementations. The array based representation is suitable for imperative implementation. It maps a complete binary tree to array, supports random access any element. We also directly use the binary tree to implement the heap in functional way. Most operations are bound to $O(\lg n)$ time, some are $O(1)$ amortized time. Okasaki gave detailed analysis\cite{okasaki-book}. When extend from binary tree to $k$-ary tree, we obtain binomial heap, Fibonacci heap, and pairing heap. We introduce these heaps in chapter 10.

\begin{Exercise}
\Question{Realize leftist heap, skew heap, and splay heap in imperative approach.}
\begin{Exercise}\label{ex:other-binary-heaps}
\Question{Realize leftist heap and skew heap in imperative approach.} % exclude splay heap
\Question{Define fold for heap.}
\end{Exercise}

\begin{Answer}
\Question{Realize leftist heap, skew heap, and splay heap in imperative approach.}
\begin{Answer}[ref = {ex:other-binary-heaps}]
\Question{Realize leftist heap and skew heap in imperative approach.

We add a parent reference in the node definition for easy back-tracking.

\begin{Bourbaki}
data Node<T> {
T value
Int rank = 1
Node<T> left = null
Node<T> right = null
Node<T> parent = null
}
\end{Bourbaki}

When merge two leftist heaps, we firstly top-down merge along the right sub-tree, then bottom-up update the rank along the parent reference, swap the sub-trees if the left has the smaller rank. To simplify the empty tree handling, we use a sentinel node.

\begin{Bourbaki}
Node<T> merge(Node<T> a, Node<T> b) {
var h = Node(null) // the sentinel node
while a != null and b != null {
if b.value < a.value then swap(a, b)
var c = Node(a.value, parent = h, left = a.left)
h.right = c
h = c
a = a.right
}
h.right = if a != null then a else b
while h.parent != null {
if rank(h.left) < rank(h.right) then swap(h.left, h.right)
h.rank = 1 + rank(h.right)
h = h.parent
}
h = h.right
if h != null then h.parent = null
return h
}

Int rank(Node<T> x) = if x != null then x.rank else 0

Node<T> insert(Node<T> h, T x) = merge(Node(x), h)

T top(Node<T> h) = h.value

Node<T> pop(Node<T> h) = merge(h.left, h.right)
\end{Bourbaki}

The skew heap is more simple. We needn't update the rank, nor need the parent and back-track.

\begin{Bourbaki}
data Node<T> {
T value
Node<T> left = null
Node<T> right = null
}
\end{Bourbaki}

Below is the merge function, the others are same as the leftist heap.
\begin{Bourbaki}
Node<T> merge(Node<T> a, Node<T> b) {
var h = Node(None)
var root = h
while a != null and b != null {
if b.value < a.value then swap(a, b)
var c = Node(a.value, left = null, right = a.left)
h.left = c
h = c
a = a.right
}
h.left = if a != null then a else b
root = root.left
return root
}
\end{Bourbaki}
}
\Question{Define fold for heap.

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

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

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

我们先实现左偏堆,为了方便回溯,我们在节点中增加一个父引用:
\begin{Bourbaki}
Expand Down
5 changes: 1 addition & 4 deletions datastruct/heap/binary-heap/src/SplayHeap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@

module SplayHeap where

import System.Random -- only for testing

-- Definition
import System.Random -- for testing

data STree a = E -- Empty
| Node (STree a) a (STree a) -- left, element, right
Expand Down Expand Up @@ -132,7 +130,6 @@ toStr E = "."
toStr (Node l x r) = "(" ++ (toStr l) ++ " " ++
(show x) ++ " " ++ (toStr r) ++ ")"


--testSplay :: IO (STree Int)
testSplay = do
xs <- sequence (replicate 1000 (randomRIO(1, 10)))
Expand Down

0 comments on commit 3b075f8

Please sign in to comment.