Joseph Haugh
University of New Mexico
Assume #include <stdio.h>
is included in all programs.
This program causes a segmentation fault, why?
void intToStr(int n) {
if (n / 10) {
intToStr(n);
}
putchar(n % 10 + '0');
}
void main(void) {
intToStr(342);
}
Because it calls itself infinitely!
void intToStr(int n) {
if (n / 10) {
intToStr(n / 10);
}
putchar(n % 10 + '0');
}
void main(void) {
intToStr(342);
}
intToStr(342)
intToStr(34)
intToStr(3)
putchar('3')
putchar('4')
putchar('2')
int fibonacci(int n) {
int f0 = 1, f1 = 1, f2, i;
for (i = 0; i < n; i++) {
printf("%d, ", f0);
f2 = f0 + f1;
f0 = f1;
f1 = f2;
}
return f0;
}
int main() {
printf("\n%d\n", fibonacci(20));
}
int fibonacci(int n) {
if (n == 0 || n == 1) return 1;
return fibonacci(n-1) + fibonacci(n-2);
}
void main(void) {
printf("%d\n", fibonacci(20));
}
Each function call gets its own separate copy of all automatic variables.
Quicksort is a divide and conquer algorithm that sorts by selecting a pivot and partitioning the array into elements less than and greater than the pivot.
/* Used for display code, not part of algorithm. */
int arraySize;
int level;
void main(void) {
int v[] = {23, 13, 82, 33, 51, 17, 45, 75, 11, 27};
arraySize = sizeof(v)/sizeof(int);
level = 0;
quicksort(v, 0, arraySize-1);
}
/* Fancy output, not part of sort */
void printArray(int levelCode, int v[],
int left, int right) {
int i=0;
if (levelCode < 0) {
printf(" Done%2d [", -levelCode);
}
else {
printf("Level=%2d [",levelCode);
}
for(i=0; iright) printf(" ");
else printf("%2d ", v[i]);
}
printf("]\n");
}
swap
helper function to swap two elements in an array.
void swap(int v[], int i, int j) {
int temp = v[i];
v[i] = v[j];
v[j] = temp;
}
int i, last;
level++;
printArray(level, v, left, right);
/* nothing to sort if fewer than two elements */
if (left < right) {
/* Partition array - shown on next slide */
quicksort(v, left, last-1);
quicksort(v, last+1, right);
printArray(-level, v, left, right);
}
level--;
/* Using middle element for pivot */
/* Move pivot out partition range */
swap(v, left, (left+right)/2);
last = left;
for (i= left + 1; i <= right; i++) {
if (v[i] < v[left]) {
last++;
swap(v, last, i);
}
}
/* restore pivot */
swap(v, left, last);
Level= 1 [23 13 82 33 51 17 45 75 11 27 ]
Level= 2 [27 13 33 23 17 45 11 ]
Level= 3 [11 13 17 ]
Level= 4 [11 ]
Level= 4 [ 17 ]
Done 3 [11 13 17 ]
Level= 3 [ 33 45 27 ]
Level= 4 [ 27 33 ]
Level= 5 [ ]
Level= 5 [ 33 ]
Done 4 [ 27 33 ]
Level= 4 [ ]
Done 3 [ 27 33 45 ]
Done 2 [11 13 17 23 27 33 45 ]
Level= 5 [ 33 ]
Done 4 [ 27 33 ]
Level= 4 [ ]
Done 3 [ 27 33 45 ]
Done 2 [11 13 17 23 27 33 45 ]
Level= 2 [ 82 75 ]
Level= 3 [ 75 ]
Level= 3 [ ]
Done 2 [ 75 82 ]
Done 1 [11 13 17 23 27 33 45 51 75 82 ]
Quicksort has an average performance of O(nlog n), but its worst-case performance is O(n2), depending on pivot selection.
What if we chose a different pivot?