Draw the binary search tree obtained by adding the values in S in sequence. Show each step
S=[3]. The root of the tree.
S=[3,42]. 42 becomes the right child of 3.
S=[3,42,39]. 39 becomes the left child of 42.
S=[3,42,39,86]. 86 becomes the right child of 42.
S=[3,42,39,86,49]. 49 becomes the left child of 86.
S=[3,42,39,86,49,89]. 89 becomes the right child of 86.
S=[3,42,39,86,49,89,99]. 99 becomes the right child of 89.
S=[3,42,39,86,49,89,99,20]. 20 becomes the left child of 39.
S=[3,42,39,86,49,89,99,20,88]. 88 becomes the right child of 86.
S=[3,42,39,86,49,89,99,20,88,51]. 51 becomes the right child of 49.
S=[3,42,39,86,49,89,99,20,88,51,64]. 64 becomes the left child of 51.
Problème 2.
Given an ordered list L and value v, the LowerBound algorithm provide the position p in list L such that p is the first offset in L of a value larger-equal to v. Hence, v≤L[p] (or, if no such offset exists, p=∣L∣). The LowerBound algorithm does so in Θ(log2(∣L∣)) comparisons. Argue that LowerBound is worst-case optimal: any algorithm that finds the correct position p for any inputs L and v using only comparisons will require Θ(log2(∣L∣)) comparisons.
Solution
For a list of size ∣L∣ there are ∣L∣+1 possible outcomes for the position p in the list. The minimum height of a binary tree needed for ∣L∣+1 outcomes is log2(∣L∣+1) (at most 2h leaves or 2h≥∣L∣+1→h≥log2(∣L∣+1)
From Stirling’s approximation, comparison-based sorting algorithm lower bound is Ω(nlog(n)). Given that the algorithm operates in Θ(log2(∣L∣)) comparisons, it matches with the theoretical lower bound for the search algorithm. Therefore, no comparison-based algorithm can guarantee a better worst-case performance for position p, making LowerBound the worst-case optimal.
Problème 3.
Min heaps and max heaps allow one to efficiently store values and efficiently look up and remove the smallest values and largest values, respectively. One cannot easily remove the largest value from a min heap or the smallest value from a max heap, however.
P3.1
Assume a value v is a part of a min heap of at-most n values and that we know v is stored at position p in that heap. Provide an algorithm that can remove v from the heap in worst-case O(log2(n))
Algorithm 28 RemoveValue(heap,p)
1:procedure RemoveValue(heap,i)
2:n←heap.length
3:temp←heap[p]
4:heap[p]←heap[n]
5:heap[n]←temp
6:heap←heap[:n]
7:HeapifyDown(heap,p)
8:end procedure
Algorithm 29 HeapifyDown(heap,p)
1:procedure HeapifyDown(heap,i)
2:n←size of heap
3:while lchild(i)≤n do
4:left←lchild(i)
5:right←rchild(i)
6:smallest←i
7:if left≤n and heap[left]<heap[smallest] then
8:smallest←left
9:end if
10:if right≤n and heap[right]<heap[smallest] then
11:smallest←right
12:end if
13:if smallest=i then
14:break
15:else
16:Swap heap[i] with heap[smallest]
17:i←smallest
18:end if
19:end while
20:end procedure
P3.2
Provide a data structure that allows one to efficiently store values and efficiently look up and remove both the smallest and the largest values: all three of these operations should be supported in Θ(log2(n))
We will implement a Double-ended Priority Queue (DEPQ), which is a min-max heap.
Algorithm 30 Insert(heap,v)
1:procedure Insert(heap,v)
2:heap.push(v)
3:Swim(heap,size(heap))
4:end procedure
Algorithm 31 RemoveMin(heap)
1:procedure RemoveMin(heap)
2:n←size(heap)
3:temp←heap[1]
4:heap[1]←heap[size(heap)]
5:heap[n]←temp
6:heap←heap[:n]
7:Sink(heap,1)
8:end procedure
Algorithm 32 RemoveMax(heap)
1:procedure RemoveMax(heap)
2:maxPos←argmax{heap[2],heap[3]}
3:heap[maxPos]←heap[size(heap)]
4:remove last el fromheap
5:Sink(heap,maxPos)
6:end procedure
Algorithm 33 Swim(heap,i)
1:procedure Swim(heap,i)
2:while i>1 do
3:parent←⌊i/2⌋
4:grandParent←⌊parent/2⌋
5:if (imod2=0 and heap[i]<heap[parent]) or (imod2=0 and heap[i]>heap[parent]) then
6:Swap(heap[i],heap[parent])
7:end if
8:if grandParent≥1 and (heap[i]<heap[grandParent] or heap[i]>heap[grandParent]) then
9:Swap(heap[i],heap[grandParent])
10:end if
11:i←parent
12:end while
13:end procedure
Algorithm 34 Sink(heap,i)
1:procedure Sink(heap,i)
2:n←size(heap)
3:while lchild(i)≤n do
4:left←lchild(i)
5:right←rchild(i)
6:target←i
7:if on min level and heap[left]<heap[target] then
8:target←left
9:else if on max level and heap[left]>heap[target] then
10:target←left
11:end if
12:if right≤size(heap) then
13:if on min level and heap[right]<heap[target] then
14:target←right
15:else if on max level and heap[right]>heap[target] then