Some Familiar Data Structures in a Functional Setting
Prev: Persistence Next: Lazy Evaluation
Prev: Persistence Next: Lazy Evaluation
3.1 Leftist Heaps
Exercises
Exercise 3.1
Prove that the right spine of a leftist heap of size contains at most elements. All logarithms in this book are base 2 unless otherwise indicated.
Exercise 3.2
Define insert directly rather than via a call to merge.
Exercise 3.3
Implement a function fromList of type Elem.T list -> Heap that produces a leftist heap from an unordered list of elements by first converting each element into a singleton heap and then merging the heaps until only one heap remains.
Instead of merging the heaps in one right-to-left or left-to-right pass using foldr or foldl, merge the heaps in passes, where each pass merges adjacent pairs of heaps. Show that fromList takes only time.
Exercise 3.4
Weight-biased leftist heaps are an alternative to leftist heaps that replace the leftist property with the weight-biased leftist property: the size of any left child is at least as large as the size of its right sibling.
- Prove that the right spine of a weight-biased leftist heap contains at most elements.
- Modify the implementation in Figure 3.2 to obtain weight-biased leftist heaps.
- Currently,
mergeoperates in two passes: a top-down pass consisting of calls tomerge, and a bottom-up pass consisting of calls to the helper functionmakeT. Modifymergefor weight-biased leftist heaps to operate in a single, top-down pass. - What advantages would the top-down version of
mergehave in a lazy environment? In a concurrent environment?
3.2 Binomial Heaps
Exercises
Exercise 3.5
Define findMin directly rather than via a call to removeMinTree.
Exercise 3.6
Most of the rank annotations in this representation of binomial heaps are redundant because we know that the children of a node of rank have ranks . Remove the rank annotations from each node and instead pair each top-level tree with its rank:
datatype Tree = Node of Elem x Tree list
type Heap = (int * Tree) listReimplement binomial heaps with this new representation.
Exercise 3.7
One clear advantage of leftist heaps over binomial heaps is that findMin takes only time rather than time. The following functor skeleton improves the running time of findMin to by storing the minimum element separately from the rest of the heap:
functor ExplicitMin (H : HEAP) : HEAP =
struct
structure Elem = H.Elem
datatype Heap = E | NE of Elem.T * H.Heap
endComplete this functor so that findMin takes time, and insert, merge, and deleteMin take time, assuming that all four take time or better for the underlying implementation H.
3.3 Red-Black Trees
Exercises
Exercise 3.8
Prove that the maximum depth of a node in a red-black tree of size is at most .
Exercise 3.9
Write a function fromOrdList of type Elem list -> Tree that converts a sorted list with no duplicates into a red-black tree. Your function should run in time.
Exercise 3.10
The balance function currently performs several unnecessary tests. For example, when the ins function recurses on the left child, there is no need for balance to test for red-red violations involving the right child.
- Split
balanceinto two functions,lbalanceandrbalance, that test for violations involving the left child and right child, respectively. Replace the calls tobalanceininswith calls to eitherlbalanceorrbalance. - Extending the same logic one step further, one of the remaining tests on the grandchildren is also unnecessary. Rewrite
insso that it never tests the color of nodes not on the search path.