pull/2/head
Oliver Kennedy 2022-10-25 23:06:25 -04:00
parent 02f58e72ce
commit aec81ce02f
Signed by: okennedy
GPG Key ID: 3E5F9B3ABD3FDB60
4 changed files with 546 additions and 106 deletions

View File

@ -383,6 +383,8 @@ schedule:
- date: 10/26/22
topic: Trees
dow: Wed
section_b:
slides: slide/23b-OrderedTrees.html
- date: 10/28/22
topic: Binary Search Trees, Tree Iteration
dow: Fri

View File

@ -347,109 +347,3 @@ cat: graphics/22b/cat.png
<dd class="fragment"><b>Total: </b> Worst-case $O(\log(n))$</dd>
</dl>
</section>
<section>
<h4 class="slide_title">Heap Sort</h4>
<ul>
<li>Insert items into priority queue with enqueue</li>
<li>Reconstruct sequence (in reverse order) with dequeue</li>
</ul>
</section>
<section>
<h4 class="slide_title">Heap Sort</h4>
<svg data-src="graphics/22b/heapsort.svg" />
</section>
<section>
<h4 class="slide_title">Heap Sort</h4>
<ul>
<dt>Enqueue Element $i$</dt>
<dd class="fragment">$O(\log(i))$</dd>
<dt class="fragment">Dequeue Element $i$</dt>
<dd class="fragment">$O(\log(n-i))$</dd>
</ul>
<p class="fragment">
$$\left(\sum_{i=1}^n O(\log(i))\right) + \left(\sum_{i=1}^n O(\log(n-i))\right)$$
</p>
<p class="fragment">
$$< O(n\log(n))$$
</p>
</section>
<section>
<h4 class="slide_title">Updating Heap Elements</h4>
<p>
After updating <tt>current</tt>, <tt>fixUp</tt> or <tt>fixDown</tt>.
</p>
<p class="fragment">
If new <tt>current > parent</tt>, <tt>current</tt> moves up.<br/>
If new <tt>current < parent</tt>, <tt>current</tt> moves down.
</p>
<p class="fragment">
How do we know where the value appears in the heap?
</p>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<p><b>Input: </b> Array</p>
<p><b>Output: </b> Array reorderd to be a heap</p>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<dl>
<div class="fragment">
<dt>Level $\log(n)$</dt>
<dd><tt>fixDown</tt> all $\frac{n}{2}$ nodes at this level (max $0$ swaps each)</dd>
</div>
<div class="fragment">
<dt>Level $\log(n)-1$</dt>
<dd><tt>fixDown</tt> all $\frac{n}{4}$ nodes at this level (max $1$ swaps each)</dd>
</div>
<div class="fragment">
<dt>Level $\log(n)-2$</dt>
<dd><tt>fixDown</tt> all $\frac{n}{8}$ nodes at this level (max $2$ swaps each)</dd>
</div>
</dl>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<div style="font-size: 70%">
<p>$$O\left(\sum_{i = 1}^{\log(n)} \frac{n}{2^{i}} \cdot (i+1) \right)$$</p>
<p class="fragment">$$O\left(n \sum_{i = 1}^{\log(n)} \frac{i}{2^{i}} + \frac{1}{2^i}\right)$$</p>
<p class="fragment">$$O\left(n \sum_{i = 1}^{\log(n)} \frac{i}{2^{i}}\right)$$</p>
<p class="fragment">$$O\left(n \sum_{i = 1}^{\infty} \frac{i}{2^{i}}\right)$$</p>
<p class="fragment">$\sum_{i = 1}^{\infty} \frac{i}{2^{i}}$ is known to converge to a constant.</p>
<p class="fragment">$$O\left(n\right)$$</p>
</div>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<p>We can go from an unsorted array to a heap in $O(n)$</p>
<p class="fragment">(but heap sort still requires $n \log(n)$ for dequeueing)</p>
</section>
<section>
<h4 class="slide_title">Next Time...</h4>
<p>Sets, Bags, and Binary Search Trees</p>
</section>

View File

@ -0,0 +1,544 @@
---
template: templates/cse250_2022_slides.erb
title: Heaps, Sets, Bags, and Ordered Trees
date: Oct 26, 2022
textbook: Ch. 18, 16
cat: graphics/23b/cat.png
---
<section>
<h2>Heaps (contd...)</h2>
</section>
<section>
<h4 class="slide_title">Analysis</h4>
<dl>
<dt>Enqueue</dt>
<dd class="fragment"><b>Append to ArrayBuffer: </b> <span class="fragment">$O(n)$, Amortized $O(1)$</span></dd>
<dd class="fragment"><b>fixUp: </b> <span class="fragment">$O(\log(n))$ fixes, each $O(1)$ = $O(\log(n))$</span></dd>
<dd class="fragment"><b>Total: </b> Amortized $O(\log(n))$, Worst-case $O(n)$</dd>
<dt class="fragment">Dequeue</dt>
<dd class="fragment"><b>Remove End of ArrayBuffer: </b> <span class="fragment">$O(1)$</span></dd>
<dd class="fragment"><b>fixDown: </b> <span class="fragment">$O(\log(n))$ fixes, each $O(1)$ = $O(\log(n))$</span></dd>
<dd class="fragment"><b>Total: </b> Worst-case $O(\log(n))$</dd>
</dl>
</section>
<section>
<h4 class="slide_title">Heap Sort</h4>
<ul>
<li>Insert items into priority queue with enqueue</li>
<li>Reconstruct sequence (in reverse order) with dequeue</li>
</ul>
</section>
<section>
<h4 class="slide_title">Heap Sort</h4>
<svg data-src="graphics/22b/heapsort.svg" />
</section>
<section>
<h4 class="slide_title">Heap Sort</h4>
<ul>
<dt>Enqueue Element $i$</dt>
<dd class="fragment">$O(\log(i))$</dd>
<dt class="fragment">Dequeue Element $i$</dt>
<dd class="fragment">$O(\log(n-i))$</dd>
</ul>
<p class="fragment">
$$\left(\sum_{i=1}^n O(\log(i))\right) + \left(\sum_{i=1}^n O(\log(n-i))\right)$$
</p>
<p class="fragment">
$$< O(n\log(n))$$
</p>
</section>
<section>
<h4 class="slide_title">Updating Heap Elements</h4>
<p>
After updating <tt>current</tt>, <tt>fixUp</tt> or <tt>fixDown</tt>.
</p>
<p class="fragment">
If new <tt>current > parent</tt>, <tt>current</tt> moves up.<br/>
If new <tt>current < parent</tt>, <tt>current</tt> moves down.
</p>
<p class="fragment">
How do we know where the value appears in the heap?
</p>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<p><b>Input: </b> Array</p>
<p><b>Output: </b> Array reorderd to be a heap</p>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<dl>
<div class="fragment">
<dt>Level $\log(n)$</dt>
<dd><tt>fixDown</tt> all $\frac{n}{2}$ nodes at this level (max $0$ swaps each)</dd>
</div>
<div class="fragment">
<dt>Level $\log(n)-1$</dt>
<dd><tt>fixDown</tt> all $\frac{n}{4}$ nodes at this level (max $1$ swaps each)</dd>
</div>
<div class="fragment">
<dt>Level $\log(n)-2$</dt>
<dd><tt>fixDown</tt> all $\frac{n}{8}$ nodes at this level (max $2$ swaps each)</dd>
</div>
</dl>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<div style="font-size: 70%">
<p>$$O\left(\sum_{i = 1}^{\log(n)} \frac{n}{2^{i}} \cdot (i+1) \right)$$</p>
<p class="fragment">$$O\left(n \sum_{i = 1}^{\log(n)} \frac{i}{2^{i}} + \frac{1}{2^i}\right)$$</p>
<p class="fragment">$$O\left(n \sum_{i = 1}^{\log(n)} \frac{i}{2^{i}}\right)$$</p>
<p class="fragment">$$O\left(n \sum_{i = 1}^{\infty} \frac{i}{2^{i}}\right)$$</p>
<p class="fragment">$\sum_{i = 1}^{\infty} \frac{i}{2^{i}}$ is known to converge to a constant.</p>
<p class="fragment">$$O\left(n\right)$$</p>
</div>
</section>
<section>
<h4 class="slide_title">Heapify</h4>
<p>We can go from an unsorted array to a heap in $O(n)$</p>
<p class="fragment">(but heap sort still requires $n \log(n)$ for dequeueing)</p>
</section>
<section>
<h2>Sets and Bags</h2>
</section>
<section>
<h4 class="slide_title">Set</h4>
<div style="text-align: left">
<p>An <u>unordered</u> collection of <u>unique</u> elements.</p>
<ul>
<li>Order doesn't matter</li>
<li>At most one copy of each item <span class="fragment">(key)</span>.</li>
</ul>
</div>
<div class="fragment" style="text-align: left">
<tt>mutable.Set[T]</tt>
<dl>
<dt style="font-family: courier, monospace;">add(element: T): Unit</dt>
<dd>Store one copy of element if not already present.</dd>
<dt style="font-family: courier, monospace;">apply(element: T): Boolean</dt>
<dd>Return true if the element is present.</dd>
<dt style="font-family: courier, monospace;">remove(element: T): Boolean</dt>
<dd>Remove the element if present or return false if not.</dd>
</dl>
</div>
</section>
<section>
<h4 class="slide_title">Bag</h4>
<div style="text-align: left">
<p>An <u>unordered</u> collection of <u>non-unique</u> elements.</p>
<ul>
<li>Order doesn't matter</li>
<li>Multiple copies of a key allowed.</li>
</ul>
</div>
<div style="text-align: left">
<tt>mutable.Bag[T]</tt>
<dl>
<dt style="font-family: courier, monospace;">add(element: T): Unit</dt>
<dd>Register the presence of a new (copy of) the element.</dd>
<dt style="font-family: courier, monospace;">apply(element: T): Int</dt>
<dd>Return the number of copies of the element present.</dd>
<dt style="font-family: courier, monospace;">remove(element: T): Boolean</dt>
<dd>Remove one copy the element if present or return false if not.</dd>
</dl>
</div>
</section>
<section>
<h4 class="slide_title">Collection ADTs</h4>
<table>
<tr>
<th>Property</th>
<th>Seq</th>
<th>Set</th>
<th>Bag</th>
</tr>
<tr>
<td>Explicit Order</td>
<td>✓</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Enforced Uniqueness</td>
<td></td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>Iterable</td>
<td>✓</td>
<td>✓</td>
<td>✓</td>
</tr>
</table>
</section>
<section>
<h2>(Rooted) Trees</h2>
</section>
<section>
<h4 class="slide_title">Tree Terminology</h4>
<dl>
<dt>Rooted, Directed Tree</dt>
<dd><b>Root</b> is the source node</dd>
<dt><u>Parent</u> of node X</dt>
<dd>A node with an out-edge to X (Note: Max in-degree of 1)</dd>
<dt><u>Child</u> of node X</dt>
<dd>A node with an in-edge from X</dd>
<dt><u>Depth</u> of a node X</dt>
<dd>Number of edges in the path from X to the root.</dd>
<dt><u>Height</u> of a node</dt>
<dd>Number of edges in the path from X to the deepest leaf.</dd>
</dl>
</section>
<section>
<h4 class="slide_title">Tree Terminology</h4>
<dl>
<dt><u>Level</u> of a node.</dt>
<dd>Depth +1</dd>
<dt><u>Size</u> of a tree ($n$)</dt>
<dd>The number of nodes in the tree</dd>
<dt>Height/Depth of a tree< ($d$)/dt>
<dd>The height of the root / depth of the deepest leaf.</dd>
</dl>
</section>
<section>
<h4 class="slide_title">Tree Terminology</h4>
<dl>
<dt><u>Binary Tree</u></dt>
<dt>Every vertex has at most 2 children</dt>
<dt><u>Complete Binary Tree</u></dt>
<dt>All leaf vertices at the deepest 2 levels.</dt>
<dt><u>Full Binary Tree</u></dt>
<dt>All leaf vertices at the deepest level.</dt>
<dt>(Every vertex has exactly 0 or 2 children)</dt>
<dt>$$d = \log(n)$$</dt>
</dl>
</section>
<section>
<h4>Scala Aside</h4>
</section>
<section>
<h4 class="slide_title">Tree Nodes (via Option)</h4>
<pre><code class="scala">
class TreeNode[T](
var _value: T,
var _left: Option[TreeNode[T]]
var _right: Option[TreeNode[T]]
)
class Tree[T] {
var root: Option[TreeNode[T]] = None // empty tree
}
</code></pre>
</section>
<section>
<h4 class="slide_title">Tree Nodes (via Traits)</h4>
<pre><code class="scala">
trait Tree[+T]
case class TreeNode[T](
value: T,
left: Tree[T],
right: Tree[T]
) extends Tree[T]
case object EmptyTree extends Tree[Nothing]
</code></pre>
</section>
<section>
<h4 class="slide_title">Case Classes/Objects</h4>
<dl>
<dt>Feature 1: Inline constructors (no <tt>new</tt>)</dt>
<dd><tt>TreeNode(10, EmptyTree, EmptyTree)</tt></dd>
<dt>Feature 2: Match deconstructors</dt>
<dd><tt>foo match { case TreeNode(v, l, r) => ... }</tt></dd>
</dl>
</section>
<section>
<h4 class="slide_title">Case Classes/Objects</h4>
<pre><code class="scala">
def printTree[T](root: ImmutableTree[T], indent: Int) =
{
root match {
case TreeNode(v, left, right) =>
print((“ “ * indent) + v)
printTree(left, indent + 2)
printTree(right, indent + 2)
case EmptyTree =>
/* Do Nothing */
}
}
</code></pre>
</section>
<section>
<h4 class="slide_title">Computing Tree Height</h4>
<p>The height of a tree is the height of the root.</p>
<div class="fragment">
$$h(root) = \begin{cases}
0 & \textbf{if the tree is empty}
1 + max(h(\texttt{root.left}), h(\texttt{root.right})) & \textbf{otherwise}
\end{cases}$$
</div>
</section>
<section>
<h4 class="slide_title">Computing Tree Height</h4>
$$h(root) = \begin{cases}
0 & \textbf{if the tree is empty}
1 + max(h(\texttt{root.left}), h(\texttt{root.right})) & \textbf{otherwise}
\end{cases}$$
<pre><code class="scala">
def height[T](root: Tree[T]): Int =
{
root match {
case EmptyTree =>
-1
case TreeNode(v, left, right) =>
1 + Math.max( height(left), height(right) )
}
}
</code></pre>
</section>
<section>
<h4 class="slide_title">Binary Search Tree</h4>
<p>A <b>Binary Tree</b> over where each node stores a unique key, and a value's keys are ordered.</p>
<div style="text-align: left" class="fragment">
<h5>Enforce Constraints</h5>
<ul>
<li class="fragment">No duplicate keys</li>
<li class="fragment">For every node $X_L$ in the left sub-tree of a node $X_1$: $X_L\texttt{.key} < X_1\texttt{.key}</li>
<li class="fragment">For every node $X_R$ in the left sub-tree of a node $X_1$: $X_R\texttt{.key} > X_1\texttt{.key}</li>
</ul>
</div>
<p class="fragment">$X_1$ partitions its children.</p>
</section>
<section>
<h4 class="slide_title">Find</h4>
<p>
<b>Goal: </b>Find an item with key $k$ in a BST rooted at <tt>root</tt>
</p>
<ul>
<li class="fragment">Is root empty? <span class="fragment">(if so, not present)</span></li>
<li class="fragment">Does <tt>root.value</tt> have key $k$? <span class="fragment">(If so, done!)</span></li>
<li class="fragment">Is <tt>root.value</tt>'s key greater than $k$? <span class="fragment">(Must be down left subtree)</span></li>
<li class="fragment">Is <tt>root.value</tt>'s key lesser than $k$? <span class="fragment">(Must be down right subtree)</span></li>
</ul>
</section>
<section>
<h4 class="slide_title">Find</h4>
<pre><code class="scala">
def find[V: Ordering](root: BST[V], target: V): Option[V] =
{
root match {
case TreeNode(v, left, right) =>
if(Ordering[V].lt( target, v ) ){
return find(left, target)
} else if(Ordering[V].lt( v, target ) ){
return find(right, target)
} else {
return Some(v)
}
case EmptyTree =>
return None
}
}
</code></pre>
<p class="fragment">What's the complexity? <span class="fragment">(how many times do we call 'find'?)</span> <span class="fragment">$O(d)$</span></p>
</section>
<section>
<h4 class="slide_title">Insert</h4>
<p>
<b>Goal: </b>Insert an item with key $k$ in a BST rooted at <tt>root</tt>
</p>
<ul>
<li class="fragment">Is root empty? <span class="fragment">(if so, insert here)</span></li>
<li class="fragment">Does <tt>root.value</tt> have key $k$? <span class="fragment">(If so, already present!)</span></li>
<li class="fragment">Is <tt>root.value</tt>'s key greater than $k$? <span class="fragment">(Insert down left subtree)</span></li>
<li class="fragment">Is <tt>root.value</tt>'s key lesser than $k$? <span class="fragment">(Insert down right subtree)</span></li>
</ul>
</section>
<section>
<h4 class="slide_title">Insert</h4>
<pre><code class="scala">
def insert[V: Ordering](root: BST[V], value: V): BST[V] =
{
node match {
case TreeNode(v, left, right) =>
if(Ordering[V].lt( target, v ) ){
return TreeNode(v, insert(left, target), right)
} else if(Ordering[V].lt( v, target ) ){
return TreeNode(v, left, insert(right, target))
} else {
return node // already present
}
case EmptyTree =>
return TreeNode(value, EmptyTree, EmptyTree)
}
}
</code></pre>
<p class="fragment">What's the complexity? <span class="fragment">$O(d)$</span></p>
</section>
<section>
<h4 class="slide_title">Remove</h4>
<p>
<b>Goal: </b>Remove the item with key $k$ from a BST rooted at <tt>root</tt>
</p>
<ul>
<li><tt>Find</tt> the item</li>
<li>Replace the node with the right subtree.</li>
<li>Insert the left subtree under the right.</li>
</ul>
<p class="fragment">What's the complexity? <span class="fragment">$O(d)$</span></p>
</section>
<section>
<h4 class="slide_title">BST Mutations</h4>
<table>
<tr>
<th>Operation</th>
<th>Runtime</th>
</tr>
<tr>
<td><tt>find</tt></td>
<td>$O(d)$</td>
</tr>
<tr>
<td><tt>insert</tt></td>
<td>$O(d)$</td>
</tr>
<tr>
<td><tt>remove</tt></td>
<td>$O(d)$</td>
</tr>
</table>
</section>
<section>
<h4 class="slide_title">Bags</h4>
<p>How do we implement bags?</p>
<p class="fragment"><b>Idea 1:</b> Just allow multiple copies ($X_L \leq X_1$)</p>
<p class="fragment"><b>Idea 2:</b> One copy, but store a count</p>
</section>
<section>
<h4 class="slide_title">Distinct Key/Value</h4>
<pre><code class="scala">
trait Tree[+K, +V]
case class TreeNode[K, V](
key: K,
value: V,
left: Tree[K, V],
right: Tree[K, V]
) extends Tree[K, V]
case object EmptyTree extends Tree[Nothing, Nothing]
</code></pre>
</section>
<section>
<h4 class="slide_title">Next time...</h4>
<p>Balancing Trees</p>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB