Joseph Haugh
University of New Mexico
What does this code print with array = {4,2,6,7,1,3,5}
?
void foo(int array[], int n) {
int i, swap = 1;
while(swap) {
swap = 0;
for (i = 0; i < n - 1; i++) {
if (array[i] <= array[i+1]) {
printf("Swap: array[%d]=%d with array[%d]=%d\n",
i, array[i], i+1, array[i+1]);
int tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
swap = 1;
}}}}
Swap: array[1]=2 with array[2]=6
Swap: array[2]=2 with array[3]=7
Swap: array[4]=1 with array[5]=3
Swap: array[5]=1 with array[6]=5
Swap: array[0]=4 with array[1]=6
Swap: array[1]=4 with array[2]=7
Swap: array[3]=2 with array[4]=3
Swap: array[4]=2 with array[5]=5
Swap: array[0]=6 with array[1]=7
Swap: array[3]=3 with array[4]=5
Swap: array[2]=4 with array[3]=5
So what is a heap then?
We can represent a complete binary tree as an array.
{ x, s, m, p, c, l, k, e, a }
x
/ \
s m
/ \ / \
p c l k
/ \
e a
What if l
had children and c
did not?
Wouldn’t we have empty spaces in the array?
This is why the heap is filled left to right!
void heapsort(char a[], int n) {
int end;
heapify(a, n);
for(end = n - 1; end > 0; end--) {
printf(" Sorting: %s, end=%d\n", a, end);
swap(a, 0, end);
siftDown(a, 0, end);
}
}
void swap(char a[], int i, int j) {
char tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
void heapify(char a[], int n) {
int i;
/* Parent of n is (n-2)/2 */
for(i = (n - 2) / 2; i >= 0; i--) {
siftDown(a, i, n);
}
}
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
/* Is a child larger than this node? */
if(left < n && a[left] > a[largest]) {
largest = left;
}
if(right < n && a[right] > a[largest]) {
largest = right;
}
/* if child is larger, swap and fix subtree */
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}}
void main(void) {
char data[] = "CELKMSPXA";
printf("Original: %s\n", data);
heapsort(data, 9);
printf(" Sorted: %s\n", data);
}
Original: CELKMSPXA
Sorting: XMSKCLPEA, end=8
Sorting: SMPKCLAEX, end=7
Sorting: PMLKCEASX, end=6
Sorting: MKLACEPSX, end=5
Sorting: LKEACMPSX, end=4
Sorting: KCEALMPSX, end=3
Sorting: ECAKLMPSX, end=2
Sorting: CAEKLMPSX, end=1
Sorted: ACEKLMPSX
{ C, E, L, K, M, S, P, X, A }
C
/ \
E L
/ \ / \
K M S P
/ \
X A
for(i = (n-2)/2; i >= 0; i--) {
siftDown(a, i, n);
}
i = 3, n = 9
{ C, E, L, K, M, S, P, X, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
K M S P
/ \
X A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 3, n = 9, left = 7, right = 8, largest = 3
{ C, E, L, K, M, S, P, X, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
K M S P
/ \
X A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 3, n = 9, left = 7, right = 8, largest = 3
{ C, E, L, K, M, S, P, X, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
K M S P
/ \
X A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, E, L, K, M, S, P, X, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
K M S P
/ \
X A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, E, L, K, M, S, P, X, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
K M S P
/ \
X A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, E, L, K, M, S, P, X, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
K M S P
/ \
X A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 7, n = 9, left = 15, right = 16, largest = 7
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 7, n = 9, left = 15, right = 16, largest = 7
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 7, n = 9, left = 15, right = 16, largest = 7
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 7, n = 9, left = 15, right = 16, largest = 7
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
for(i = (n-2)/2; i >= 0; i--) {
siftDown(a, i, n);
}
i = 2, n = 9
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 2, n = 9, left = 5, right = 6, largest = 2
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 2, n = 9, left = 5, right = 6, largest = 2
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 2, n = 9, left = 5, right = 6, largest = 5
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 2, n = 9, left = 5, right = 6, largest = 5
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 2, n = 9, left = 5, right = 6, largest = 5
{ C, E, L, X, M, S, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E L
/ \ / \
X M S P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 2, n = 9, left = 5, right = 6, largest = 5
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
for(i = (n-2)/2; i >= 0; i--) {
siftDown(a, i, n);
}
i = 1, n = 9
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 1, n = 9, left = 3, right = 4, largest = 1
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 1, n = 9, left = 3, right = 4, largest = 1
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 1, n = 9, left = 3, right = 4, largest = 3
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 1, n = 9, left = 3, right = 4, largest = 3
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 1, n = 9, left = 3, right = 4, largest = 3
{ C, E, S, X, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
E S
/ \ / \
X M L P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 1, n = 9, left = 3, right = 4, largest = 3
{ C, X, S, E, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
E M L P
/ \
K A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 3, n = 9, left = 7, right = 8, largest = 3
{ C, X, S, E, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
E M L P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 3, n = 9, left = 7, right = 8, largest = 3
{ C, X, S, E, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
E M L P
/ \
K A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, X, S, E, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
E M L P
/ \
K A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, X, S, E, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
E M L P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, X, S, E, M, L, P, K, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
E M L P
/ \
K A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 3, n = 9, left = 7, right = 8, largest = 7
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
for(i = (n-2)/2; i >= 0; i--) {
siftDown(a, i, n);
}
i = 0, n = 9
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 0, n = 9, left = 1, right = 2, largest = 0
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 0, n = 9, left = 1, right = 2, largest = 0
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 0, n = 9, left = 1, right = 2, largest = 1
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 0, n = 9, left = 1, right = 2, largest = 1
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 0, n = 9, left = 1, right = 2, largest = 1
{ C, X, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
C
/ \
X S
/ \ / \
K M L P
/ \
E A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 0, n = 9, left = 1, right = 2, largest = 1
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
void siftDown(char a[], int i, int n) {
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
i = 1, n = 9, left = 3, right = 4, largest = 1
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 1, n = 9, left = 3, right = 4, largest = 1
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
if(left < n && a[left] > a[largest]) {
largest = left;
}
i = 1, n = 9, left = 3, right = 4, largest = 3
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 1, n = 9, left = 3, right = 4, largest = 3
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
if(right < n && a[right] > a[largest]) {
largest = right;
}
i = 1, n = 9, left = 3, right = 4, largest = 4
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 1, n = 9, left = 3, right = 4, largest = 4
{ X, C, S, K, M, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
C S
/ \ / \
K M L P
/ \
E A
if(largest != i) {
swap(a, i, largest);
siftDown(a, largest, n);
}
i = 1, n = 9, left = 3, right = 4, largest = 4
{ X, M, S, K, C, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
M S
/ \ / \
K C L P
/ \
E A
swap(a, 0, end);
end = 8
{ X, M, S, K, C, L, P, E, A }
0 1 2 3 4 5 6 7 8
X
/ \
M S
/ \ / \
K C L P
/ \
E A
swap(a, 0, end);
end = 8
{ X, M, S, K, C, L, P, E, A }
0 1 2 3 4 5 6 7 8
A
/ \
M S
/ \ / \
K C L P
/ \
E X
Phew! That was a lot, from there on you
just need to call siftDown
on the root
until everything is sorted.