CSC 329 · QUIZ 3 + QUIZ 4

Quiz 3 & Quiz 4 Study Guide

Two focused sections · Quiz 3: Heaps & Priority Queues · Quiz 4: Sorting & Hash Tables · Based on Prof. Hoskey’s lecture slides
EARLIER QUIZ

Quiz 3: Heaps & Priority Queues

Heap structure, array formulas, heapify operations, priority queue implementations, complexity and practice.

01

Heap Basics

What a heap is

  • A heap has a binary tree structure.
  • A heap is not a binary search tree.
  • It must be an almost complete tree.
  • Nodes on the last level must be as far left as possible.
  • The lecture uses an array-based min-heap.
MIN-HEAP PROPERTY Every node is greater than its parent and less than its children. Therefore the smallest element is always at the root.

Valid min-heap example

          10
        /    \
      20      40
     /  \    / \
   60   30  70  50

Each child is greater than its parent. The heap does not need to be fully sorted from left to right.

Heap vs. BST — quiz trap

StructureOrdering rule
Min-heapParent is smaller than its children
Binary Search TreeLeft subtree keys are smaller; right subtree keys are larger
DO NOT MIX THESE UP A heap is a binary tree, but the lecture explicitly says it is not a binary search tree.
02

Array-Based Heap

Parent / child formulas — memorize these

LEFT CHILD
2i + 1
RIGHT CHILD
2i + 2
PARENT
⌊(i - 1) / 2⌋
INDEXING These formulas use a zero-based array, so the root is at index 0.

Example from the heap layout

Index:  0   1   2   3   4   5
Value: 10  20  40  60  30  70

For the item 30, its index is i = 4.

RelationshipCalculationResult
Parent⌊(4 - 1) / 2⌋index 1 → 20
Left child2(4) + 1index 9
Right child2(4) + 2index 10

If those child indexes are outside the current heap size, the node has no child there.

Fast mental check

For index i = 5:

Parent      = ⌊(5 - 1) / 2⌋ = 2
Left child  = 2(5) + 1       = 11
Right child = 2(5) + 2       = 12
03

Heap Add & Heapify Up

How add works

  1. Copy the new item into the left-most open position on the last level.
  2. Compare the new item with its parent.
  3. If the new item is smaller than its parent, swap them.
  4. Continue moving upward until the heap property is restored.
MEMORY RULE Add goes UP → heapify up.

Lecture-style pseudocode

Copy new item into left-most open item of last level

While item < parentOfItem
    swap(item, parentOfItem)
    item = parentOfItem

Example: add 5

Before

       10
      /  \
    20    30

Insert at next open spot

       10
      /  \
    20    30
   /
  5

Compare 5 with 20 → swap. Then compare 5 with 10 → swap.

        5
      /   \
    10     30
   /
  20

Big-O

add = O(log n)

The copy into the open slot is O(1), while heapify up is O(log n). The total is therefore O(log n).

04

getMin & Heapify Down

What getMin does

In this lecture's heap implementation, getMin() returns and removes the root element.

  1. Save the root value in a local variable.
  2. Copy the right-most item on the last level into the root.
  3. Decrease the heap size.
  4. Compare the copied item with its children.
  5. If necessary, swap it with its smaller child.
  6. Continue downward until the heap property is restored.
  7. Return the saved minimum.
MEMORY RULE getMin removes the root and goes DOWN → heapify down.

Lecture-style pseudocode

Save root into minVal
Copy right-most item of last level into root

item = root
While item > leastChildOfItem
    swap(item, leastChildOfItem)
    item = leastChildOfItem

return minVal

leastChildOfItem means the smaller of the left and right children.

Why the smaller child?

In a min-heap, the replacement value must end up below a value that is no greater than it. Choosing the smaller child preserves the min-heap ordering as the item moves down.

Big-O

getMin = O(log n)

Overwriting the root is O(1). Heapify down is O(log n). Total: O(log n).

05

Delete an Arbitrary Heap Item

How delete works

  1. Do a linear search through the array to find the item.
  2. Copy the right-most item on the last level into the deleted item's position.
  3. Check whether the replacement violates the heap property.
  4. If the replacement is smaller than its parent, heapify up.
  5. Otherwise, heapify down as necessary.
KEY DIFFERENCE Delete can require heapify up or down, depending on where the replacement value came from and how it compares with its new parent and children.

Big-O analysis

StepCost
Find the itemO(n)
Replace it with last itemO(1)
Heapify up or downO(log n)
TotalO(n)
QUIZ TRAP Even though heapifying is only O(log n), deleting an arbitrary item is O(n) because finding that item takes linear search.
06

Priority Queue

Definition

A priority queue is an ADT in which only the item with the highest priority can be accessed.

  • It is similar to a queue, but priority determines which item comes out first.
  • The highest-priority item is logically at the front.
  • Items can be represented as <data, priority> pairs.
  • The most important operations in the lecture are add and getMin.

Lecture example: lower value = higher priority

The slides explicitly make this assumption for the example.

Insert:

14, 32, 11

Logical priority order:

Front → 11 → 14 → 32 → Rear

Then enqueue 22:

Front → 11 → 14 → 22 → 32 → Rear

Logical view vs. actual heap storage

A heap-based priority queue may feel fully ordered from the user's perspective, but the actual heap is not fully sorted.

WHAT IS GUARANTEED? The highest-priority element is at the root. The rest of the heap only has to satisfy the parent/child heap property.
07

Priority Queue Implementations & Big-O

The table to memorize

ImplementationaddgetMinMain idea
Unsorted array O(1) O(n) Add quickly; search for minimum later
Sorted array O(n) O(n)* Maintain order; shifting is required
Heap O(log n) O(log n) Balanced performance for both operations

*The slides state getMin = O(n) for the sorted array implementation when items are shifted after removal.

Why the costs differ

Unsorted array

add = O(1)

getMin = O(n)

No work is needed to preserve order during insertion, but locating the minimum requires a scan.

Heap

add = O(log n)

getMin = O(log n)

Heapify up and heapify down follow the height of the heap.

08

Quiz 3 Cram Sheet — Heaps & Priority Queues

Know these cold

  1. Array formulas: left = 2i + 1, right = 2i + 2, parent = ⌊(i - 1) / 2⌋.
  2. Heapify direction: add → UP, getMin → DOWN, delete → UP or DOWN.
  3. Heap Big-O: add O(log n), getMin O(log n), delete O(n).
  4. Priority queue implementations: unsorted array O(1)/O(n), sorted array O(n)/O(n), heap O(log n)/O(log n).

Ultra-short version

MIN HEAP
root = minimum
parent <= children
almost complete binary tree
not a BST
not fully sorted

ARRAY INDEXES
left   = 2i + 1
right  = 2i + 2
parent = floor((i - 1) / 2)

HEAP OPERATIONS
add     → heapify UP   → O(log n)
getMin  → heapify DOWN → O(log n)
delete                 → O(n)

PRIORITY QUEUE
highest priority removed first
lecture example: lower number = higher priority

PQ IMPLEMENTATIONS
unsorted array: add O(1),     getMin O(n)
sorted array:   add O(n),     getMin O(n)
heap:           add O(log n), getMin O(log n)

Common quiz traps

  1. A heap is not a BST.
  2. A heap is not fully sorted; only the heap property is guaranteed.
  3. getMin() in these slides removes the root.
  4. Heap add inserts at the next open position first, then heapifies up.
  5. Heapify down compares against the smaller child.
  6. Arbitrary delete is O(n) because finding the item is linear.
  7. The slide example assumes lower numbers have higher priority.
09

Quiz 3 Practice — Heaps & Priority Queues

Try these without looking above

  1. For a heap item at index 6, what are the indexes of its left child, right child, and parent?
  2. In a min-heap, where is the smallest value located?
  3. When a new value is inserted into a min-heap, where is it placed before any swaps occur?
  4. Which operation normally uses heapify up: add or getMin?
  5. During heapify down, which child should be used for the comparison in a min-heap?
  6. What are the Big-O costs of add, getMin, and arbitrary delete in the lecture's array-based heap?
  7. For an unsorted-array priority queue, what are the Big-O costs of add and getMin?
  8. For a heap-based priority queue, what are the Big-O costs of add and getMin?
  9. Starting with an empty min-heap, insert 10, 7, 19, 5, 16. What value ends up at the root?

Mini heap tracing

Start with this min-heap:

        4
      /   \
     9     7
    / \
   15 12
  1. If 5 is added, where is it inserted initially?
  2. After heapify up finishes, what is the root?
  3. If getMin() is then called, what value is returned?
  4. After the root is removed, which existing item is copied into the root before heapify down?

Answer Key

Show all 13 answers
  1. Left = 13, right = 14, parent = 2.
  2. At the root.
  3. In the left-most open position on the last level.
  4. add. Add uses heapify up; getMin uses heapify down.
  5. The smaller / least child.
  6. add O(log n), getMin O(log n), delete O(n).
  7. add O(1), getMin O(n).
  8. add O(log n), getMin O(log n).
  9. 5.
  10. At the next open slot: the left child of 7.
  11. 4. The inserted 5 moves above 7 but not above 4.
  12. 4.
  13. The right-most item on the last level. With this insertion sequence, that item is 7.
NEXT QUIZ

Quiz 4: Sorting Algorithms & Hash Tables

Heapsort, selection sort, quicksort, Map ADT, hashing, collisions, separate chaining and resizing.

10

Heapsort

Main idea

The lecture's heapsort uses a min-heap.

  • The heap holds the unsorted data.
  • The array holds the sorted data.
  • Repeatedly take the minimum element from the heap and place it into the next open location in the sorted region.
  • This is similar to selection sort because both repeatedly select the minimum remaining item.

Heapsort pseudocode

Create an empty heap h

For all items in unsorted array
    h.add(current item)

sortedNextOpen = 0

While heap not empty
    min = h.getMin()
    Copy min to array[sortedNextOpen]
    Increment sortedNextOpen

Lecture example

Original list:

10, 7, 19, 5, 16

After all values are added to the min-heap:

        5
      /   \
     7     19
    / \
   10 16

Repeated getMin() calls produce:

5, 7, 10, 16, 19

Heapsort trace: build the min-heap (slides 7–12)

The lecture starts with [10, 7, 19, 5, 16] and inserts each value into an initially empty min-heap. Place it in the next open position of the complete tree, then heapify up if it is smaller than its parent.

InsertHeap in level-order array formWhat changes?
10[10]10 is the root.
7[7, 10]7 swaps with parent 10.
19[7, 10, 19]19 already satisfies the min-heap rule.
5[5, 7, 19, 10]5 swaps upward past 10, then 7.
16[5, 7, 19, 10, 16]16 stays below parent 7.
Heap after all insertions:
       5
     /   \
    7     19
   / \
 10  16
QUIZ CHECK The heap's level-order array is [5,7,19,10,16], NOT the sorted sequence. Only the root is guaranteed to be the minimum.

Source: Heapsort, pp. 7–12.

Heapsort trace: remove the minimum five times (slides 13–28)

getMin() removes the root in the lecture's heap implementation: move the last heap element into the root, reduce the heap size, and heapify down by swapping with the smaller child as needed. Then write the removed minimum to array[sortedNextOpen] and advance that index.

CallRemoved minHeap left afterward (level order)Sorted array prefix
15[7,10,19,16][5]
27[10,16,19][5,7]
310[16,19][5,7,10]
416[19][5,7,10,16]
519[][5,7,10,16,19]

First removal in slow motion:

Start:         [5, 7, 19, 10, 16]
Save min = 5; move last item to root:
               [16, 7, 19, 10]
Swap 16 with smaller child 7:
               [7, 16, 19, 10]
Swap 16 with smaller child 10:
               [7, 10, 19, 16]
Write array[0] = 5; sortedNextOpen = 1

The other four removals follow the same remove → repair heap → append to sorted region pattern. After the fifth call, the heap is empty and the array is sorted.

Source: Heapsort, pp. 13–28. Heap contents are shown in array/level order to make each slide's tree easier to trace.

Heapsort Big-O

Heapsort = O(n log n)
WorkCost
Create heap instanceO(1)
Add n items; each add is O(log n)O(n log n)
Remove n items; each getMin is O(log n)O(n log n)
TotalO(n log n)

Heapsort best, average and worst cases (slides 30–31)

Input (distinct keys)ΩOΘ
Best: already sorted low to highn log nn log nn log n
Averagen log nn log nn log n
Worst: sorted high to lown log nn log nn log n

Total for the method taught: O(1) + O(n log n) + O(n log n) = O(n log n).

SLIDE NOTE Page 30 mentions an alternative way to build a heap more efficiently, but does not teach that construction method. The overall sorting time is still O(n log n) either way.

Source: Heapsort, pp. 30–31.

11

Selection Sort

Idea and algorithm

Selection sort is an elementary in-place sort. Divide the array into a growing sorted left part and a shrinking unsorted right part. To sort ascending, repeatedly find the minimum element in the unsorted part, swap it to the beginning of that part, and advance the boundary.

  1. Initialize unsortedStart = 0.
  2. Linearly search indexes unsortedStart through the end for the minimum.
  3. Swap the minimum with data[unsortedStart] (a swap may be unnecessary).
  4. Increment unsortedStart; repeat until everything is sorted.
MEMORY RULE Find minimum → swap into first unsorted slot → move boundary right. The minimum is now in its final position.

Lecture walkthrough — 10, 7, 19, 5, 16

PassMinimumList after pass (bold = sorted)
Start—10 7 19 5 16
15; swap with 105 7 19 10 16
27; no swap needed5 7 19 10 16
310; swap with 195 7 10 19 16
416; swap with 195 7 10 16 19
519; no swap needed5 7 10 16 19
unsortedStart = 0
while unsortedStart < n:
    minIndex = unsortedStart
    for j = unsortedStart + 1 to n - 1:
        if data[j] < data[minIndex]:
            minIndex = j
    swap(data[unsortedStart], data[minIndex])
    unsortedStart++

Source: Selection Sort, pp. 4–22. The overview once says “highest,” but the pseudocode and complete ascending trace clearly select the minimum.

Complexity / exam traps

Best = Average = Worst = Θ(n²)
  • It searches each unsorted suffix even when the input is already sorted: best is still O(n²).
  • Extra space: O(1), in-place.
  • Stability: ordinary swap-based selection sort is not stable, although a stable variation can be written (as noted in the Quicksort slides).
COMMON MISTAKE Selection sort is not O(n) just because the list starts sorted.

Source: Selection Sort, pp. 24–25; Quicksort, pp. 5–6.

12

Quicksort

Divide and conquer + pivot

Quicksort recursively partitions an array around a pivot. Values below the pivot go left; values above the pivot go right. When a partition pass ends, the pivot occupies its final sorted position. Recursively sort the two remaining parts, excluding that pivot; stop at subarrays containing zero or one item.

WHICH VERSION? The lecture covers Lomuto-style partitioning with the first item as the pivot. Hoare partitioning and last-element-pivot variants have different intermediate traces.

Lecture trace: first pivot = 50

Original:
50  40  10  70  60  20  90  80  30
^ pivot

After one partition:
30  40  10  20  |50|  70  90  80  60
   lower         pivot      higher

The pivot 50 is now in the correct place, but the elements within each partition are not yet fully sorted. Quicksort next sorts [30,40,10,20] and [70,90,80,60].

Source: Quicksort, pp. 7–8 and following partition slides.

First partition, step by step: i and j

Start with pivot 50 at index 0, i = 1 and j = 1. j scans the array; i is the next opening in the lower-than-pivot partition. The lower partition occupies indexes 1 through i - 1.

Scan index jCompare with pivot 50i after processing
1: 40Smaller: swap with itself2
2: 10Smaller: swap with itself3
3: 70Larger: no swap3
4: 60Larger: no swap3
5: 20Smaller: swap 20 with 70 at index 34
6: 90Larger: no swap4
7: 80Larger: no swap4
8: 30Smaller: swap 30 with 60 at index 45
Initial:
50  40  10  70  60  20  90  80  30

After processing j = 5 (20 swaps with 70):
50  40  10  20  60  70  90  80  30

After processing j = 8 (30 swaps with 60):
50  40  10  20  30  70  90  80  60

Scan complete: i = 5
Swap pivot data[0] with data[i - 1] = data[4]:
30  40  10  20 |50| 70  90  80  60
EXAM RULE Increment j after every examined item, but increment i only after moving an item below the pivot into the lower section. Finally, swap the pivot with data[i-1].

Source: Quicksort, pp. 9–22.

Finish the lecture's Quicksort recursion

After placing pivot 50 at index 4, recursively sort the lower partition first, then the higher partition. Each recursive call picks the first element of its own subarray as the pivot.

Subarray being sortedPivotAfter this partition
Indexes 0–85030 40 10 20 |50| 70 90 80 60
Indexes 0–33020 10 |30| 40
Indexes 0–12010 |20|
Indexes 5–87060 |70| 80 90
Indexes 7–880|80| 90
Recursive call order (first-element pivot):
quicksort(0,8)    pivot 50
├─ quicksort(0,3) pivot 30
│  ├─ quicksort(0,1) pivot 20
│  │  ├─ quicksort(0,0) → base case
│  │  └─ quicksort(2,1) → empty
│  └─ quicksort(3,3) → base case
└─ quicksort(5,8) pivot 70
   ├─ quicksort(5,5) → base case
   └─ quicksort(7,8) pivot 80
      ├─ quicksort(7,6) → empty
      └─ quicksort(8,8) → base case

Final array:
10  20  30  40  50  60  70  80  90

Base case: if low >= high, there are zero or one elements in the region, so no partition is needed. After a partition, the pivot is already final; recursive calls exclude the pivot index.

Source: Quicksort, pp. 23–58; recursive call syntax summarized from the lecture's pseudocode on p. 59.

Partition pointers and pseudocode

SymbolMeaning in the lecture
lowFirst index of current subarray and pivot location
i = low + 1Next open slot for a value smaller than the pivot
jIndex of element currently being inspected
i - 1Final pivot index after scanning and swapping
quicksort(low, high):
    if low >= high: return
    p = partition(low, high)
    quicksort(low, p - 1)
    quicksort(p + 1, high)

partition(low, high):
    pivot = data[low]
    i = low + 1
    for j = low + 1 to high:
        if data[j] < pivot:
            swap(data[j], data[i])
            i++
    swap(data[low], data[i - 1])
    return i - 1
REMEMBER If data[j] < pivot, swap data[j] into the lower section and increment i. At the end, exchange the pivot with data[i-1].

Big-O, recursion, and properties

CaseTimeReason
BestO(n log n)Balanced splits; log n levels
AverageO(n log n)Typically reasonably balanced splits
WorstO(n²)Repeated partitions of sizes 0 and n − 1
  • One partition of n values scans n items: O(n).
  • Balanced recursion has about log n levels; terrible pivots yield about n levels.
  • With a fixed first-element pivot, already sorted or reverse-sorted values may lead to the worst case.
  • Quicksort rearranges the same array (in-place), although recursive calls need O(log n) average / balanced stack space and can reach O(n) worst case.
  • Quicksort is not stable: duplicates need not retain their input order.

Source: Quicksort, pp. 5–6 and 60–64.

Randomized quicksort

Pick a pivot index uniformly at random, swap that value into the first slot, and perform the usual partition. A median pivot would balance the partitions ideally, but choosing the median is not required.

randIndex = randomly choose from low to high
swap(data[low], data[randIndex])
// continue with first-element-pivot partition
  • Expected: O(n log n), including for initially sorted input.
  • Absolute worst case: O(n²); unlucky pivots are still possible.
QUIZ TRAP Randomization improves expected performance but does not remove the theoretical quadratic worst case. The lecture also says not to use the master theorem for randomized quicksort.

Source: Quicksort, pp. 65–69.

13

Map ADT & Hashing Fundamentals

Map vs. hash table vs. hash set

  • Map ADT: associates a unique key with a value, e.g. "Yankees" → 1.
  • Operations: add/put(key,value), find/get(key), delete/remove(key).
  • Hash table: an implementation of a map; alternatives include lists and binary search trees.
  • Hash set: an unordered collection of unique values, not a collection of explicit key/value pairs.
  • Hash function: transforms a key into an array index (the bucket) where its information is stored or searched for.
KEY POINT A map hashes the key, not the associated value.

Bucket formula, collisions and a better hash

bucket = key % numBuckets

This is the lecture's simplified teaching example. With 10 buckets:

KeyMathBucket
5252 % 102
7171 % 101
4343 % 103
41 and 9141 % 10 = 91 % 10Both bucket 1

A collision occurs when different keys map to the same bucket. The slides explain that practical hashing usually transforms the key before using modulo, helping distribute keys more evenly.

hash(key):
    transformedKey = transform(key)
    return transformedKey % numBuckets

Searching costs — important comparison

StructureFindWhy?
Unsorted array or linked listO(n)Search each item
Balanced BSTO(log n)Tree height
Hash table (good hash)O(1) expectedDirect bucket + short chain
LOOKUP TRAP Reading an array at a known index is O(1). Searching an unsorted array to find an item's index is O(n). Hashing calculates a bucket index.

SUHA, load factor and perfect hashing

KEYS
n
BUCKETS
m
LOAD FACTOR
n / m

Simple Uniform Hashing Assumption (SUHA): every key independently hashes to each bucket with equal probability. Under this assumption the expected bucket length is n/m, also called the load factor.

A perfect hash function has no collisions for a known set of keys. The slides note that it requires knowing possible keys beforehand; more keys than slots make collisions unavoidable.

Source: Hash Table Overview, pp. 3–6, 19–31.

14

Hash Table — Separate Chaining

How linked-list buckets handle collisions

Separate chaining uses an array of buckets, where each bucket is an unsorted linked list of nodes. Each node contains a key/value pair. Several different keys can occupy one bucket without replacing each other.

hash(key) = key % 10

bucket 0: [10] → [50] → [80]
bucket 1: [91] → [11] → [71]
bucket 2: [22] → [82] → [52]
bucket 3: [33]
bucket 4: [94] → [14]
bucket 5: empty
...
bucket 9: [49] → [19]

These diagrams show keys for simplicity, but the underlying nodes also hold values, e.g. <50, "Phone">.

Source: Separate Chaining, pp. 3–6.

add, find and delete

OperationActionsSlide example
add(key,value)Compute bucket → insert node43 % 10 = 3; add <43,"Computer">
find(key)Compute bucket → search only its list14 % 10 = 4; look in bucket 4
delete(key)Compute bucket → remove matching node52 % 10 = 2; remove from bucket 2
add(key, value):
    index = hash(key)
    insert (key, value) into table[index]

find(key):
    index = hash(key)
    search table[index] for matching key
    return its associated value if found

delete(key):
    index = hash(key)
    remove matching node from table[index]
REMEMBER Hashing avoids searching the whole table; find and delete only search the selected bucket's linked list.

Resize when projected load factor exceeds 0.75

Load factor = number of stored keys / number of buckets = n / m. The lecture checks before inserting: if the new item would make (n+1)/m > 0.75, resize.

Before addAfter addResize?
2 keys / 4 buckets = 0.503/4 = 0.75No (not above 0.75)
3 keys / 4 buckets = 0.754/4 = 1.00Yes
6 keys / 8 buckets = 0.757/8 = 0.875Yes
  1. Allocate a larger array (slides first illustrate roughly doubling the bucket count).
  2. Rehash and reinsert every existing key/value pair since its bucket may change.
  3. Insert the new entry.
PRIME-SIZE DETAIL After showing simplified doubling diagrams, the slides recommend using the first prime number larger than twice the old bucket count to improve distribution.

Source: Separate Chaining, pp. 15–23.

Resize walkthrough from the slides: 16, 58, 19, 85

The lecture first uses exactly doubling as a simple illustration, starting with 2 buckets, hash(key) = key % bucketCount, and a threshold of 0.75.

ActionCapacity / load factorWhere each key goes
Start with 162 buckets; 1/2 = 0.50Bucket 0: 16
Add 58Projected 2/2 = 1.00; resize to 4Bucket 0: 16; bucket 2: 58
Add 193/4 = 0.75; no resizeBucket 3: 19
Add 85Projected 4/4 = 1.00; resize to 8Bucket 0: 16; 2: 58; 3: 19; 5: 85
2 buckets, before adding 58:
0: [16]
1: []

4 buckets, after adding 58 and 19:
0: [16]
1: []
2: [58]
3: [19]

8 buckets, after adding 85:
0: [16]   1: []    2: [58]   3: [19]
4: []     5: [85]  6: []     7: []
TWO DISTINCT IDEAS These slide diagrams use 2 → 4 → 8 to illustrate resizing. The lecture then recommends the first prime larger than twice the old bucket count for a practical resize. The exact bucket locations above belong to the doubling illustration, not the prime-size recommendation.

Source: Separate Chaining, pp. 15–23.

Why resizing by a constant amount breaks amortized O(1)

A resize takes O(n) because every stored key/value entry must be rehashed and inserted into the new array. The lecture's O(1) amortized insertion relies on increasing the array size by a multiplicative factor (doubling or close to doubling).

  • Roughly doubling: after each resize, capacity for many future insertions is available. Cheap adds between resizes can account for the occasional expensive copy.
  • Adding just 100 buckets each time: the number of adds between resizes stays roughly fixed while the number of elements copied at each resize keeps growing. The cheap adds cannot cover increasingly expensive copies at constant amortized cost.
  • Tradeoff: expanding aggressively uses more unused buckets but makes resizing less frequent; expanding too slowly saves some capacity but increases copying work.
EXAM DISTINCTION A single add that triggers resizing may cost O(n). The lecture's O(1) amortized claim describes the cost averaged across a sequence of adds with suitable geometric growth, not a guarantee for every add.

Source: Separate Chaining, pp. 17, 22–23 and 25–28 (especially the fixed-100-bucket counterexample on p. 26).

Performance — expected, amortized and worst case

OperationGood hash + proper resizingPossible worst case
addO(1) amortizedO(n) if resizing
findO(1) expectedO(n) long collision chain
deleteO(1) expectedO(n) long collision chain
resizeO(n)O(n)

Amortized O(1) add means occasional expensive resizing is spread across many inexpensive additions. Expected O(1) find and delete depend on good hashing (SUHA) and periodic resizing — they are not hard worst-case guarantees.

WHEN A HASH TABLE MAY BE WRONG The lecture warns that strict real-time systems (such as air traffic control or critical medical devices) may not tolerate an occasional O(n) insert; a balanced BST offers more predictable bounds.

Source: Separate Chaining, pp. 17, 25–29.

15

Quiz 4 Cram Sheet — Sorting & Hashing

Sorting Big-O comparison

AlgorithmBestAverageWorst
Selection sortO(n²)O(n²)O(n²)
QuicksortO(n log n)O(n log n)O(n²)
Randomized quicksortO(n log n)O(n log n) expectedO(n²) absolute
Heapsort (earlier lesson)O(n log n)O(n log n)O(n log n)

Nine facts to memorize

  1. Selection: repeated minimum + swap; Θ(n²) even on sorted input.
  2. Quicksort: pivot is final after partition; recursively sort either side.
  3. Randomized quicksort: expected O(n log n), absolute worst O(n²).
  4. Map: key/value pairs; set: unique values.
  5. Hash function: key → bucket; two keys at one bucket → collision.
  6. Separate chaining: bucket = unsorted linked list of key/value nodes.
  7. Load factor: n/m; resize on add when projected factor > 0.75 in lecture.
  8. Resize: all keys are rehashed into new buckets, O(n).
  9. Hash costs: add O(1) amortized; find/delete O(1) expected with good hashing and resizing.
16

Quiz 4 Practice — Sorting Algorithms

Selection Sort, Quicksort & Heapsort

  1. In the lecture's heapsort, insert 10, 7, 19, 5, 16 into an empty min-heap. What is the heap's final level-order array before removals?
  2. What sorted output does repeated getMin() produce for those five values, and what is heapsort's overall Big-O runtime?
  3. What does unsortedStart represent in selection sort?
  4. After one selection sort pass on [10,7,19,5,16], what is the array?
  5. What are selection sort's best, average and worst runtimes?
  6. Why does an already sorted array not speed up selection sort?
  7. Which element is chosen as pivot in the main quicksort lecture?
  8. After a partition pass, what is guaranteed about the pivot?
  9. What is the lecture's first partition result for [50,40,10,70,60,20,90,80,30]?
  10. What do i and j track while partitioning?
  11. What is the quicksort recursion base case?
  12. What split pattern produces O(n²) quicksort performance?
  13. What are randomized quicksort's expected and absolute worst-case runtimes?

Answer key

Show all 13 answers
  1. [5,7,19,10,16]. The heap obeys the parent-child ordering rule but is not completely sorted.
  2. [5,7,10,16,19], with overall time O(n log n).
  3. The index where the unsorted portion begins.
  4. [5,7,19,10,16].
  5. Θ(n²) in every case.
  6. Selection sort still scans the whole remaining suffix for its minimum on each pass.
  7. The first element of the current subarray.
  8. The pivot is in its final sorted position.
  9. [30,40,10,20,50,70,90,80,60].
  10. i marks the next lower-partition slot; j scans input.
  11. low >= high (zero or one element).
  12. Each pivot divides into 0 elements and n−1 elements.
  13. Expected O(n log n), absolute worst O(n²).
17

Quiz 4 Practice — Hash Tables

Hashing, Load Factor & Separate Chaining

  1. Name the three Map ADT operations.
  2. Under key % 10, what is the bucket for 87?
  3. Do keys 11 and 71 collide in a 10-bucket table? Why?
  4. What is stored in each node of a separate-chaining table?
  5. Where do you search for key 14 in a table of 10 buckets using modulo?
  6. What is the load factor for 75 keys and 100 buckets?
  7. With 6 keys and 8 buckets, would adding a seventh cause a resize under the lecture's threshold?
  8. Why does a resized table need to rehash all the keys?
  9. What is the runtime of resizing a hash table?
  10. Explain the difference between amortized O(1) add and expected O(1) find.
  11. Name a system where the lecture suggests a balanced BST instead of a hash table.

Answer key

Show all 11 answers
  1. add/put, find/get, delete/remove.
  2. 7.
  3. Yes; both keys have remainder 1 modulo 10.
  4. The key/value pair (with a link to the next node).
  5. Search the linked list in bucket 4.
  6. 0.75.
  7. Yes; 7/8 = 0.875, above 0.75.
  8. The bucket indices depend on the table's size, which changes.
  9. O(n), due to rehashing every existing entry.
  10. Amortized: costly resizes averaged over many cheap inserts. Expected: typical constant lookup under good hashing and resizing, not guaranteed in worst case.
  11. A strict real-time system like air traffic control or critical hospital equipment.