Week 06 · Lecture 7

Priority queues and heapsort

Maintain a partial order that makes the next minimum or maximum easy to remove. Separate one heap operation from building a whole heap.

Read alongside the document

Use the lecture headings below in the English–Turkish notes. Document lecture numbers and course week numbers are different.

  • Lecture 7: Heapsort / Priority Queues
    Warm-up: pairing numbers to minimise the largest pair sum; Why sorting matters so much; Practical details of sorting; What sorting makes easy; Selection sort revisited: the data structure matters; Priority queues; Heaps; Inserting: bubble up; Extracting the minimum: bubble down; Building a heap in linear time; Heapsort.

Download the bilingual notes

Why does a heap avoid searching every item for the next minimum?

Insert 1 into the min-heap [2,4,3], using array positions starting at 1.

1234
A min-heap after inserting 1. Every parent is at most its children.
Step 1

Append 1 at position 4: [2,4,3,1].

Step 2

Compare with its parent at position 2; swap: [2,1,3,4].

Step 3

Compare with the root; swap: [1,2,3,4].

Step 4

There are at most O(log n) levels. Bottom-up construction of an entire heap is O(n), because most nodes have very small height.

Change the case. A heap is not a fully sorted array. Its root is extreme; siblings need not be ordered. Heapsort is O(n log n) in the worst case.

Explain before coding

State the input and required output. Trace a small example. Explain why each step is valid, count the work under a stated model, and test an edge case.

Python support for this week

Parent index is i//2 with 1-based positions. Python uses 0-based lists, so keep the convention explicit.

import heapq
heap = [2, 4, 3]
heapq.heappush(heap, 1)
print(heap)  # [1, 2, 3, 4]

Run this small demonstration after predicting its result. It illustrates the selected example; its input assumptions are part of the example.

Open the optional Python support library. Programming fluency is not required to complete the paper trace.

Read the related bilingual explanations here

Sections from the supplied lecture notes. Turkish paragraphs appear in red. Use this as a reference after the worked example.

Lecture 7 · Warm-up: pairing numbers to minimise the largest pair sum

Hazırlık: en büyük çift toplamını en aza indirecek biçimde sayıları eşleştirme

Given 2n numbers, split them into n pairs so that the largest pair sum is as small as possible. For (1, 3, 5, 9) the options are pairs summing to (4, 14), (6, 12) or (10, 8); the last one is best, with a maximum of 10.

Verilen 2n sayıyı, en büyük çift toplamı mümkün olduğunca küçük olacak biçimde n çifte ayırın. (1, 3, 5, 9) için seçenekler, toplamları (4, 14), (6, 12) veya (10, 8) olan çiftlerdir. Maksimumu 10 olan son seçenek en iyisidir.

The O(n log n) answer: sort the numbers, then pair the smallest with the largest, the second smallest with the second largest, and so on. Every big number is “cushioned” by a small one. Sorting costs O(n log n) and the pairing is a single O(n) pass.

O(n log n) çözümü: sayıları sıralayın; ardından en küçüğü en büyükle, ikinci en küçüğü ikinci en büyükle eşleştirin ve sürdürün. Her büyük sayı, küçük bir sayıyla “dengelenir”. Sıralama O(n log n) tutar; eşleştirme ise tek bir O(n) taramadır.

Lecture 7 · Why sorting matters so much

Sıralama neden bu kadar önemlidir?

Computers spend a great deal of their time sorting; historically about a quarter of mainframe cycles.

Bilgisayarlar zamanlarının önemli bir kısmını sıralamaya harcar; tarihsel olarak ana bilgisayar işlem çevrimlerinin yaklaşık dörtte biri buna ayrılmıştır.

Sorting is the most thoroughly studied problem in computer science, with many known algorithms.

Sıralama, birçok bilinen algoritmasıyla bilgisayar bilimlerinde en ayrıntılı incelenmiş problemdir.

Most of the big ideas of this course (divide and conquer, randomised algorithms, lower bounds) can be taught in the context of sorting.

Bu dersin büyük fikirlerinin çoğu (böl ve yönet, rastgeleleştirilmiş algoritmalar, alt sınırlar) sıralama bağlamında öğretilebilir.

Once data is sorted, lots of other problems become easy, and an O(n log n) sort leads directly to sub-quadratic algorithms for them.

Veriler sıralandığında birçok başka problem kolaylaşır; O(n log n) maliyetli bir sıralama, doğrudan bu problemler için karesel-altı algoritmalara götürür.

The gap between quadratic and n log n sorting is enormous:

Karesel sıralama ile n log n sıralama arasındaki fark çok büyüktür:

nn²/4n lg n
nn²/4n lg n
102533
102533
1002,500664
1002,500664
1,000250,0009,965
1,000250,0009,965
10,00025,000,000132,877
10,00025,000,000132,877
100,0002,500,000,0001,660,960
100,0002,500,000,0001,660,960
1,000,000250,000,000,00013,815,551
1,000,000250,000,000,00013,815,551

Large-scale data processing is impossible with an Ω(n²) sort.

Ω(n²) maliyetli bir sıralamayla büyük ölçekli veri işleme mümkün değildir.

Lecture 7 · Practical details of sorting

Sıralamanın uygulamadaki ayrıntıları

Comparison functions. “Sorted” only means something once you say what “before” means. Is Skiena the same key as skiena? Does Brown-Williams come before or after Brown, John? Increasing or decreasing? All of this is decided by the comparison function given to the sorting routine, which is asked “does x come before y?” for pairs of items.

Karşılaştırma fonksiyonları. “Sıralı” ancak “önce”nin ne anlama geldiği söylendiğinde anlam kazanır. Skiena ile skiena aynı anahtar mıdır? Brown-Williams, Brown, John’dan önce mi sonra mı gelir? Artan mı, azalan mı? Bütün bunları, sıralama yordamına verilen ve eleman çiftleri için “x, y’den önce mi gelir?” sorusunu yanıtlayan karşılaştırma fonksiyonu belirler.

Equal elements. Items with equal keys end up next to each other, but their relative order may matter (sort by surname, then by first name). Secondary keys belong in the comparison function. Some algorithms, quicksort in particular, need care to stay fast when there are many equal keys.

Eşit elemanlar. Eşit anahtarlı elemanlar yan yana gelir, ancak kendi aralarındaki göreli sıra önemli olabilir (önce soyadına, sonra ada göre sıralama). İkincil anahtarlar karşılaştırma fonksiyonunda yer almalıdır. Bazı algoritmalarda, özellikle hızlı sıralamada, çok sayıda eşit anahtar varken hızın korunması için dikkat gerekir.

Library functions. Every serious language has a built-in sort (C’s qsort, for example). You are almost always better off calling it than writing your own.

Kütüphane fonksiyonları. Her ciddi dilin yerleşik bir sıralama yordamı vardır (örneğin C’de qsort). Kendi yordamınızı yazmak yerine bunu çağırmak neredeyse her zaman daha iyidir.

Lecture 7 · What sorting makes easy

Sıralama neleri kolaylaştırır?

ProblemAfter sorting
ProblemSıralamadan sonra
SearchingBinary search answers “is x here?” in O(log n). Preprocessing for search is probably the single most important use of sorting.
Aramaİkili arama, “x burada mı?” sorusunu O(log n) sürede yanıtlar. Arama için ön işleme, muhtemelen sıralamanın en önemli tek kullanım alanıdır.
Closest pairThe two closest numbers must be neighbours in sorted order, so one O(n) scan finds them.
En yakın çiftBirbirine en yakın iki sayı, sıralı düzende komşu olmak zorundadır; dolayısıyla tek O(n) taramayla bulunur.
Element uniquenessAny duplicate must be a pair of equal neighbours; scan adjacent pairs in O(n).
Eleman benzersizliğiHer tekrar, eşit komşulardan oluşan bir çift olarak görünür; bitişik çiftleri O(n) sürede tarayın.
Mode / frequency countsEqual items form runs; measure run lengths in one scan. The count of a given key can even be found in O(log n) by binary-searching for the first and last occurrence.
Mod / frekans sayımlarıEşit elemanlar bloklar oluşturur; blok uzunluklarını tek taramada ölçün. Belirli bir anahtarın sayısı, ilk ve son görülme konumlarını ikili aramayla bularak O(log n) sürede bile hesaplanabilir.
Median and selectionThe kth largest item sits in position k of the sorted array, found in O(1). (A cleverer O(n) algorithm exists, based on partial sorting.)
Medyan ve seçimk’ncı en büyük eleman sıralı dizinin k konumundadır ve O(1) sürede bulunur. (Kısmi sıralamaya dayanan daha akıllı bir O(n) algoritması da vardır.)
Convex hullsThe smallest polygon containing all the points, like a rubber band stretched around them. Sort the points by x-coordinate, then insert them left to right: the newest point is always on the boundary, and adding it may only delete some earlier hull points.
Dışbükey zarflarBütün noktaları içeren en küçük çokgen; noktaların çevresine gerilmiş bir lastik bant gibi. Noktaları x koordinatına göre sıralayın, sonra soldan sağa ekleyin: en yeni nokta her zaman sınırdadır ve eklenmesi yalnızca önceki bazı zarf noktalarını silebilir.
Lecture 7 · Selection sort revisited: the data structure matters

Seçmeli sıralamaya yeniden bakış: veri yapısı önemlidir

Selection sort (Lecture 3) is really a loop of two operations, done n times:

Seçmeli sıralama (Ders 3), gerçekte n kez yapılan iki işlemden oluşan bir döngüdür:

A: find the smallest of the remaining items;

A: kalan elemanların en küçüğünü bul;

B: pull it out and put it next.

B: onu çıkar ve sıradaki yere koy.

So it costs O(n × (cost of A + cost of B)). With an array or unsorted list, A is O(n) and B is O(1): total O(n²). With a balanced search tree or a heap, both A and B are O(log n): total O(n log n). That algorithm is heapsort. The key question to ask whenever an algorithm is slow: “can we use a different data structure?”

Dolayısıyla maliyeti O(n × (A’nın maliyeti + B’nin maliyeti)) olur. Dizi veya sırasız listeyle A, O(n); B, O(1)’dir: toplam O(n²). Dengeli arama ağacı veya öbekle hem A hem B, O(log n)’dir: toplam O(n log n). Bu algoritma öbek sıralamasıdır. Bir algoritma yavaş olduğunda sorulacak temel soru: “Farklı bir veri yapısı kullanabilir miyiz?”

Lecture 7 · Priority queues

Öncelik kuyrukları

A priority queue is a container that supports three operations:

Öncelik kuyruğu, üç işlemi destekleyen bir kapsayıcı yapıdır:

Insert(Q, x): add item x with its key.

Insert(Q, x): x elemanını anahtarıyla birlikte ekle.

Find-Minimum(Q) (or Find-Maximum): return the item with the smallest (largest) key.

Find-Minimum(Q) (veya Find-Maximum): en küçük (en büyük) anahtarlı elemanı döndür.

Delete-Minimum(Q) (or Delete-Maximum): remove that item.

Delete-Minimum(Q) (veya Delete-Maximum): bu elemanı kaldır.

Each can be done in O(log n) using a heap or a balanced binary tree. The reason to want a priority queue rather than sorting once is that jobs arrive at arbitrary times: inserting a new job is far cheaper than re-sorting everything.

Her biri öbek veya dengeli ikili ağaç kullanılarak O(log n) sürede yapılabilir. Bir kez sıralamak yerine öncelik kuyruğu istememizin nedeni, işlerin gelişigüzel zamanlarda gelmesidir: yeni bir iş eklemek, her şeyi yeniden sıralamaktan çok daha ucuzdur.

Two of Skiena’s applications: a dating queue (retrieve people by desirability, not by name; scores change so you re-insert with the new score; nobody needs deleting until they reach the top) and discrete event simulation (airports, parking lots: whichever event is scheduled soonest happens next). A stack and a queue are just special cases where the priority is arrival time.

Skiena’nın iki uygulaması: bir flört kuyruğu (kişileri adlarına değil, ne kadar arzu edildiklerine göre getir; puanlar değiştiğinden yeni puanla yeniden ekle; tepeye ulaşana kadar kimseyi silmeye gerek yoktur) ve ayrık olay benzetimi (havaalanları, otoparklar: hangi olay en erken zamana planlandıysa sırada o gerçekleşir). Yığın ve kuyruk, önceliğin geliş zamanı olduğu özel durumlardır.

Lecture 7 · Heaps

Öbekler (heaps)

A binary heap is a binary tree with a key in each node such that:

İkili öbek, her düğümünde bir anahtar bulunan ve şu koşulları sağlayan ikili ağaçtır:

All leaves are on at most two adjacent levels.

Bütün yapraklar en fazla iki komşu düzeyde bulunur.

All levels except the lowest are completely full, and the leaves on the lowest level are packed to the left.

En alt düzey dışındaki bütün düzeyler tamamen doludur; en alt düzeydeki yapraklar sola yaslanmıştır.

The key in each node is ≤ the keys of its children, and the left and right subtrees are themselves heaps. (This is a min-heap; flip the inequality for a max-heap.)

Her düğümün anahtarı çocuklarının anahtarlarından ≤ büyüklüğündedir; sol ve sağ alt ağaçların kendileri de öbektir. (Bu bir minimum öbektir; maksimum öbek için eşitsizliği ters çevirin.)

Rules 1 and 2 fix the shape of the tree; rule 3 is the labelling. The labelling rule imposes a partial order: weaker than sorted order (so it is cheap to maintain) but stronger than random order (so the minimum can be found instantly; it is always the root).

1. ve 2. kurallar ağacın biçimini belirler; 3. kural etiketlemeye ilişkindir. Etiketleme kuralı bir kısmi sıra dayatır: sıralı düzenden daha zayıftır (dolayısıyla sürdürülmesi ucuzdur), fakat rastgele düzenden daha güçlüdür (dolayısıyla minimum anında bulunur; her zaman köktedir).

Storing a heap in an array. Because the shape is so regular, no pointers are needed. Number the nodes level by level from 1. Then:

Öbeği dizide saklama. Biçim çok düzenli olduğundan işaretçi gerekmez. Düğümleri 1’den başlayarak düzey düzey numaralandırın. O zaman:

the left child of node k is at position 2k;

k düğümünün sol çocuğu 2k konumundadır;

the right child is at position 2k + 1;

sağ çocuğu 2k + 1 konumundadır;

the parent of node k is at position ⌊k/2⌋.

k düğümünün ebeveyni ⌊k/2⌋ konumundadır.

The slides’ example is a heap of years: 1492 at the root, children 1783 and 1776, grandchildren 1804, 1865, 1945, 1963, and so on; as an array it reads 1492, 1783, 1776, 1804, 1865, 1945, 1963, 1918, 2001, 1941. This implicit layout only works because the tree is nearly full; a sparse tree would waste every missing slot, which is exactly why rules 1 and 2 are insisted upon. The trade-off is flexibility: an array-based tree cannot be restructured as freely as a pointer-based one.

Slaytlardaki örnek yıllardan oluşan bir öbektir: kökte 1492; çocukları 1783 ve 1776; torunları 1804, 1865, 1945, 1963 vb. Dizide 1492, 1783, 1776, 1804, 1865, 1945, 1963, 1918, 2001, 1941 biçiminde görünür. Bu örtük yerleşim yalnızca ağaç neredeyse dolu olduğu için çalışır; seyrek bir ağaçta her eksik göz boşa giderdi. 1. ve 2. kurallarda ısrar edilmesinin nedeni tam olarak budur. Ödün verilen özellik esnekliktir: dizi tabanlı bir ağaç, işaretçi tabanlı bir ağaç kadar serbestçe yeniden yapılandırılamaz.

Height. A heap of n items has height ⌊lg n⌋, because all levels but the last are full and 1 + 2 + 4 + … + 2ʰ = 2ʰ⁺¹ − 1 ≥ n.

Yükseklik. n elemanlı bir öbeğin yüksekliği ⌊lg n⌋’dir; çünkü son düzey dışındaki bütün düzeyler doludur ve 1 + 2 + 4 + … + 2ʰ = 2ʰ⁺¹ − 1 ≥ n.

Lecture 7 · Inserting: bubble up

Ekleme: yukarı taşıma (bubble up)

Put the new item in the leftmost open slot (position n + 1). It may now be smaller than its parent, breaking rule 3. Fix it by swapping with the parent, and repeat upward until the parent is smaller or the root is reached:

Yeni elemanı en soldaki boş göze (n + 1 konumu) koyun. Eleman artık ebeveyninden küçük olabilir; bu, 3. kuralı bozar. Ebeveyniyle yer değiştirerek düzeltin; ebeveyni daha küçük olana veya köke ulaşana kadar yukarı doğru tekrarlayın:

insert(Q, x):
    n = n + 1
    Q[n] = x
    bubble_up(Q, n)

bubble_up(Q, p):
    if p is the root: return
    if Q[parent(p)] > Q[p]:
        swap Q[p] and Q[parent(p)]
        bubble_up(Q, parent(p))
insert(Q, x):
    n = n + 1
    Q[n] = x
    bubble_up(Q, n)

bubble_up(Q, p):
    if p kök ise: return
    if Q[parent(p)] > Q[p]:
        Q[p] ile Q[parent(p)] yer değiştir
        bubble_up(Q, parent(p))

Each swap moves the item one level up, so insertion costs O(log n). Building a heap by n insertions therefore costs Θ(n log n): the last n/2 insertions each cost about lg n.

Her yer değiştirme elemanı bir düzey yukarı taşır; bu yüzden ekleme O(log n) tutar. Dolayısıyla n eklemeyle öbek kurmak Θ(n log n) maliyetlidir: son n/2 eklemenin her biri yaklaşık lg n tutar.

Lecture 7 · Extracting the minimum: bubble down

Minimumu çıkarma: aşağı taşıma (bubble down)

The minimum is the root. Remove it, move the last item of the array into the root slot (keeping the shape rules intact), then repair rule 3 downward: compare the node with its two children, swap with the smaller child if that child is smaller, and repeat:

Minimum köktür. Onu kaldırın, dizinin son elemanını kök gözüne taşıyın (biçim kurallarını koruyarak); ardından 3. kuralı aşağı yönde onarın: düğümü iki çocuğuyla karşılaştırın, küçük çocuk düğümden de küçükse onunla yer değiştirin ve tekrarlayın:

extract_min(Q):
    min = Q[1]
    Q[1] = Q[n]
    n = n − 1
    bubble_down(Q, 1)
    return min

bubble_down(Q, p):
    find the smallest among Q[p] and its (up to two) children
    if that smallest is a child c:
        swap Q[p] and Q[c]
        bubble_down(Q, c)
extract_min(Q):
    min = Q[1]
    Q[1] = Q[n]
    n = n − 1
    bubble_down(Q, 1)
    return min

bubble_down(Q, p):
    Q[p] ve (en fazla iki) çocuğu arasındaki en küçüğü bul
    if bu en küçük eleman bir c çocuğu ise:
        Q[p] ile Q[c] yer değiştir
        bubble_down(Q, c)

Again each swap moves one level, so O(log n).

Yine her yer değiştirme bir düzey ilerler; dolayısıyla O(log n).

Lecture 7 · Building a heap in linear time

Doğrusal zamanda öbek kurma

There is a faster way to build a heap from n items than n insertions. Notice that two heaps plus a fresh item can be merged into one heap by making the item the root and bubbling it down. So: copy the items into the array in any order, then call bubble_down on positions n/2, n/2 − 1, …, 1 (positions above n/2 are leaves, which are already tiny heaps). This is called heapify.

n elemandan öbek kurmanın n eklemeden daha hızlı bir yolu vardır. İki öbek ve yeni bir elemanın, eleman kök yapılıp aşağı taşınarak tek öbekte birleştirilebildiğine dikkat edin. O hâlde elemanları diziye herhangi bir sırayla kopyalayın; sonra n/2, n/2 − 1, …, 1 konumlarında bubble_down çağırın (n/2’den büyük indisli konumlar yapraktır; zaten küçük öbeklerdir). Buna öbekleştirme (heapify) denir.

Why is this only O(n)? Because most of the sub-heaps being merged are tiny. In a full binary tree of n nodes there are at most ⌈n/2ʰ⁺¹⌉ nodes at height h, and bubbling one of them down costs O(h). The total is

Bu neden yalnızca O(n)’dir? Çünkü birleştirilen alt öbeklerin çoğu çok küçüktür. n düğümlü dolu bir ikili ağaçta h yüksekliğinde en fazla ⌈n/2ʰ⁺¹⌉ düğüm vardır; bunlardan birini aşağı taşımak O(h) tutar. Toplam şöyledir:

The sum Σ h/2ʰ is not quite a geometric series, but it converges, to 2. (Differentiate the geometric series identity Σ xᵏ = 1/(1 − x) to get Σ k xᵏ⁻¹ = 1/(1 − x)², multiply by x, and put x = 1/2.) So building a heap takes at most about 2n comparisons: linear time.

Σ h/2ʰ toplamı tam olarak geometrik seri değildir; ancak 2’ye yakınsar. (Σ xᵏ = 1/(1 − x) geometrik seri özdeşliğinin türevini alarak Σ k xᵏ⁻¹ = 1/(1 − x)² elde edin, x ile çarpın ve x = 1/2 koyun.) Böylece öbek kurmak en fazla yaklaşık 2n karşılaştırma gerektirir: doğrusal zaman.

Skiena’s meta-lesson: “doing at most x operations of at most y time each” gives O(xy), which is always true but sometimes a big over-estimate. Here the lazy bound is O(n log n); the careful bound is O(n). Ask whether your analysis is tight.

Skiena’nın genel dersi: “Her biri en fazla y zaman alan en fazla x işlem yapmak” O(xy) verir; bu her zaman doğrudur, ancak bazen büyük bir fazla tahmindir. Burada özensiz sınır O(n log n), dikkatli sınır ise O(n)’dir. Analizinizin sıkı olup olmadığını sorun.

Lecture 7 · Heapsort

Öbek sıralaması (heapsort)

heapsort(s, n):
    build a heap from s (linear time)
    for i from 1 to n:
        s[i] = extract_min(heap)
heapsort(s, n):
    s'den bir öbek kur (doğrusal zaman)
    for i from 1 to n:
        s[i] = extract_min(heap)

Building costs O(n) and each of the n extractions costs O(log n), so heapsort is O(n log n). It cannot be O(n) because extracting n minimums in order is sorting, and Lecture 9 shows sorting needs Ω(n log n) comparisons.

Kurma O(n), n çıkarma işleminin her biri O(log n) tutar; dolayısıyla öbek sıralaması O(n log n)’dir. O(n) olamaz; çünkü n minimumu sırayla çıkarmak sıralamadır ve Ders 9’da sıralamanın Ω(n log n) karşılaştırma gerektirdiği gösterilir.

Done carefully, heapsort needs no extra memory: build the heap inside the original array, and after each extraction put the removed element into the hole left at the end of the array (with a max-heap, this fills the array from the back with the largest items, leaving it sorted in increasing order).

Dikkatli gerçekleştirilirse öbek sıralaması ek bellek gerektirmez: öbeği özgün dizinin içinde kurun; her çıkarmadan sonra çıkarılan elemanı dizinin sonunda kalan boşluğa koyun. (Maksimum öbekle bu işlem, diziyi arkadan başlayarak en büyük elemanlarla doldurur ve artan sırada sıralı bırakır.)

Begin with the easy tests and the worked example. Remaining questions provide repeated teaching practice; hard questions are optional depth. Some tests revisit earlier prerequisites. Answers stay visible.

Practice with answers

10 test questions · 14 written questions · 24 total

Each question is followed by its answer and explanation. Hard questions also include a starting hint and smaller reasoning steps.

Test questions

Choose one option. Cost questions state their model and whether the bound is tight, expected or worst-case. Here lg means log₂, and heap positions start at 1.

Question 1 · easy

Which structure guarantees constant-time access by arbitrary numeric index i in the standard fixed-size-word RAM model?

  1. a linked list
  2. an array
  3. a binary search tree
  4. a queue

Answer: option B. The address of slot i is start + i × item size.

Question 2 · easy

Push 5, 6, 7 onto a stack, then pop once. You get:

  1. 5
  2. 6
  3. 7
  4. nothing

Answer: option C. Last in, first out.

Question 3 · easy

Which array (positions 1 to 5) is a valid min-heap?

  1. [1, 3, 2, 5, 4]
  2. [1, 5, 2, 3, 4]
  3. [2, 1, 3, 4, 5]
  4. [1, 2, 3, 1, 0]

Answer: option A. In (b) the 5 at position 2 is bigger than its child 3; in (c) the root exceeds a child; in (d) position 2’s child 1 is smaller than 2.

Question 4 · easy

In the array layout of a heap, the parent of position 9 is position:

  1. 3
  2. 4
  3. 5
  4. 18

Answer: option B. Parent of k is ⌊k/2⌋.

Question 5 · easy

The root of a max-heap holds:

  1. the minimum
  2. the median
  3. the maximum
  4. an arbitrary key

Answer: option C. Every parent is at least as large as its children.

Question 6 · easy

What is the tightest listed worst-case upper bound for standard heapsort?

  1. O(n)
  2. O(n log n)
  3. O(n²)
  4. O(log n)

Answer: option B. Linear build plus n extractions at O(log n).

Question 7 · easy

What is the tightest listed upper bound for building a binary heap using bottom-up heapify?

  1. O(n)
  2. O(n log n)
  3. O(n²)
  4. O(log n)

Answer: option A. Most nodes are near the bottom and cost almost nothing to bubble down.

Question 8 · medium

Growing a full dynamic array from capacity 1 to capacity 1,024 by doubling copies exactly how many existing items in total?

  1. 1,024 items
  2. 1,023 items
  3. 10,240 items
  4. 1,048,576 items

Answer: option B. 1 + 2 + 4 + … + 512 = 1,023, less than n.

Question 9 · medium

Insert 1 into the min-heap [2, 4, 3]. The final array is:

  1. [2, 4, 3, 1]
  2. [1, 2, 3, 4]
  3. [1, 4, 3, 2]
  4. [1, 3, 2, 4]

Answer: option B. 1 lands at position 4 under 4, swaps up to position 2, then swaps with the root 2.

Question 10 · medium

Extract the minimum from the min-heap [1, 3, 2, 7, 4]. The remaining heap is:

  1. [2, 3, 4, 7]
  2. [3, 2, 4, 7]
  3. [2, 4, 3, 7]
  4. [3, 7, 2, 4]

Answer: option A. The last element 4 moves to the root, then swaps with its smaller child 2.

Written questions

Read each question together with its explanation, trace or proof. Numbering continues from the test questions.

Question 11 · easy

Give three reasons the course spends so much time on sorting.

Answer & reasoning

computers spend a large share of their time sorting; it is the best-studied problem, with many algorithms to compare; and most big ideas (divide and conquer, randomisation, lower bounds) can be taught through it. Also, once data is sorted many other problems become easy.

Question 12 · easy

Is the array [3, 5, 4, 10, 8, 7] (positions 1 to 6) a valid min-heap?

Answer & reasoning

yes. Position 1 (3) has children 5 and 4; position 2 (5) has children 10 and 8; position 3 (4) has child 7. Every parent is ≤ its children.

Question 13 · easy

In the array layout of a heap, where are the children of position 6, and where is the parent of position 13?

Answer & reasoning

children at 12 and 13; parent of 13 is ⌊13/2⌋ = 6.

Question 14 · easy

What sits at the root of a max-heap, and where could the smallest element be?

Answer & reasoning

The root holds a largest key. With distinct keys, a smallest key must be a leaf and can be at any leaf. If duplicates are allowed, a minimum can also occur at an internal node; for example, an all-equal heap.

Question 15 · easy

Insert 2 into the min-heap [3, 5, 4, 10, 8, 7]. Show the bubble-up steps and the final array.

Answer & reasoning

append 2 at position 7 (child of position 3, which holds 4). 4 > 2, swap: [3, 5, 2, 10, 8, 7, 4]. Its parent is now position 1 (3); 3 > 2, swap: [2, 5, 3, 10, 8, 7, 4]. At the root, stop.

Question 16 · easy

Extract the minimum from [2, 5, 3, 10, 8, 7, 4]. Show the steps and the resulting heap.

Answer & reasoning

remove 2, move the last element 4 to the root: [4, 5, 3, 10, 8, 7]. Children of 4 are 5 and 3; the smaller, 3, is smaller than 4, so swap: [3, 5, 4, 10, 8, 7]. Position 3 (4) now has child 7 only; 7 > 4, stop.

Question 17 · easy

What two operations does heapsort consist of, and what does each cost?

Answer & reasoning

build a heap from all n items once (O(n) with heapify), then extract the minimum n times (O(log n) each). Total O(n log n).

Question 18 · medium

Turn [9, 4, 7, 1, 3, 8, 2] into a min-heap with the linear-time heapify (bubble down positions 3, 2, 1 in that order). Show the array after each position.

Answer & reasoning

position 3 holds 7 with children 8 and 2; swap with 2 → [9, 4, 2, 1, 3, 8, 7]. Position 2 holds 4 with children 1 and 3; swap with 1 → [9, 1, 2, 4, 3, 8, 7]. Position 1 holds 9 with children 1 and 2; swap with 1 → [1, 9, 2, 4, 3, 8, 7]; 9 now at position 2 has children 4 and 3; swap with 3 → [1, 3, 2, 4, 9, 8, 7]. Done, and every parent is ≤ its children.

Question 19 · medium

Each bubble-down can cost O(log n), and heapify calls it n/2 times. Why is heapify O(n) rather than O(n log n)?

Answer & reasoning

the cost of a bubble-down is the height of the node, not log n. Half the nodes are leaves (height 0, cost nothing), a quarter have height 1, an eighth height 2, and so on. The total is n × Σ h/2ʰ⁺¹, and Σ h/2ʰ converges to 2, so the total is at most about 2n.

Question 20 · medium

Give two ways to find the k-th smallest of n numbers, one based on sorting and one on a heap, with their costs.

Answer & reasoning

sort and read position k: O(n log n). Or build a min-heap in O(n) and extract the minimum k times: O(n + k log n), which is better when k is small.

Question 21 · hard · optional challenge

Explain how heapsort sorts an array into ascending order in place, without a second array.

In simpler words: Use the unused end of the same array as the sorted output.

Starting hint: A max-heap already puts the largest remaining item at its root.

Answer & reasoning
Step by step
  1. Build a max-heap in the array.
  2. Swap its root with the last active slot; that slot now contains its final sorted value.
  3. Shorten the active heap, then bubble the new root down. Repeat; the sorted suffix grows and needs no second array.

build a max-heap inside the array. The largest item is at position 1; swap it with the last item, shrink the heap by one, and bubble the new root down. Repeat. Each round moves the current maximum into the final, still-unsorted position at the end, so the array fills with sorted items from the back.

Question 22 · hard · optional challenge

Numbers arrive one at a time. Design a structure that reports the current median after each arrival in O(log n) per number.

In simpler words: Keep the middle values at the tops of two heaps.

Starting hint: Separate the smaller half from the larger half.

Answer & reasoning
Step by step
  1. The smaller half is a max-heap, so its largest item is visible. The larger half is a min-heap, so its smallest is visible.
  2. After insertion, move a root across if the sizes differ by more than one. Keep every lower-half value ≤ every upper-half value.
  3. For odd size, report the larger heap’s root. For even size, report the mean of both roots. Each insertion needs only a constant number of O(log n) heap operations.

keep a max-heap of the smaller half and a min-heap of the larger half, with sizes differing by at most one. Insert into the appropriate heap, then move one root across if the sizes get out of balance. The median is the root of the bigger heap (or the average of the two roots when sizes are equal). Each step is a constant number of heap operations.

Question 23 · hard · optional challenge

Merge k nonempty sorted lists containing n elements in total, for 2 ≤ k ≤ n, in O(n log k) time.

In simpler words: Repeatedly choose the smallest of the current list heads.

Starting hint: Only one candidate from each list needs to be in the heap.

Answer & reasoning
Step by step
  1. Put the first item of each nonempty list into a min-heap, remembering its list.
  2. Remove the smallest, output it, then add the next item from the same list.
  3. The heap never exceeds k entries. Each of n outputs costs O(log k); bottom-up heap construction costs O(k).

put the first element of each list into a min-heap of size k. Repeatedly extract the minimum, append it to the output, and insert the next element from the list it came from. Each of the n elements passes through the heap once at O(log k).

Question 24 · hard · optional challenge

Prove that pairing the smallest number with the largest, the second smallest with the second largest, and so on, minimises the largest pair sum (the problem of the day from Lecture 7).

In simpler words: Pair very small values with very large values to control the worst pair.

Starting hint: Compare an arbitrary pairing with one that pairs the two extremes.

Answer & reasoning
Step by step
  1. Suppose the smallest a pairs with x and the largest z pairs with y.
  2. Replace these pairs by (a,z) and (x,y). Since a ≤ y and x ≤ z, both new sums are at most the old sum y+z.
  3. The maximum cannot increase. Fix the extremes together and apply the same argument to the remaining values. This is an exchange argument: improve the structure without worsening the objective.

sort the numbers a₁ ≤ … ≤ a₂ₙ. Take any optimal pairing in which a₁ is paired with some x and a₂ₙ with some y, x ≠ a₂ₙ. Re-pair them as (a₁, a₂ₙ) and (x, y). Since a₁ ≤ y, a₁ + a₂ₙ ≤ y + a₂ₙ; since x ≤ a₂ₙ, x + y ≤ a₂ₙ + y. Both new sums are at most the old pair sum a₂ₙ + y, so the maximum does not increase. Repeat the argument on the remaining numbers; by induction the fully sorted pairing is optimal.