├── .gitignore ├── exercises ├── chapter1 │ ├── hello.c │ ├── 1-6-getchar-putchar.c │ ├── 1-8-charcount.c │ ├── 1-3-degrees-fc.c │ ├── 1-4-degrees-cf.c │ └── 1-9-echo-whitespace.c ├── chapter7 │ ├── testfile.txt │ ├── code-7-1-lower-stream.c │ ├── structtest.c │ ├── exercise-7-1-upper-lower-by-command.c │ └── exercise-7-2-sensible-input-printing.c ├── chapter5 │ ├── exercise-5-8-day-converter.c │ └── exercise-5-9-day-converter.c └── chapter2 │ └── getbits.c ├── algorithms ├── same-sign-test.c ├── hash-pointer.c ├── hash-int.c ├── utf-8-check.c ├── randomness.c ├── reverse-string.c ├── dice.c ├── generate_rand.c ├── bitwise-addition.c ├── compare-pointer.c ├── solve-linear.c ├── linear-one-variable.c ├── array-summation.c ├── string-reverse.c ├── hash-int.h ├── hash-pointer.h ├── compare-int.c ├── insertion-sort.c ├── bubble-sort.c ├── selection-sort.c ├── hash-string.h ├── experiment.c ├── hash-string.c ├── binary-search.c ├── string-sort.c ├── lcs.c ├── smiling-face.c ├── compare-pointer.h ├── bfs.c ├── compare-int.h ├── compare-string.c ├── merge-sort.c ├── compare-string.h ├── dice-monte-carlo.c ├── stack.c ├── popcount.c ├── queue.h ├── trie.h ├── queue.c ├── binary-heap.c ├── arraylist.c ├── set.h ├── hash-table.h ├── rb-tree.h ├── bloom-filter.c ├── list.h ├── slist.h ├── slist.c ├── bits.c ├── rb-tree.c ├── list.c ├── hash-table.c └── trie.c ├── auto ├── insertion-sort-asc.c ├── reverse.c ├── insertion-sort-desc.c └── htoi.c └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | c-note.iml 2 | /.idea 3 | -------------------------------------------------------------------------------- /exercises/chapter1/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("hello, world\n"); 6 | printf("hello, world at %d degrees.\n", 40); 7 | } 8 | -------------------------------------------------------------------------------- /exercises/chapter7/testfile.txt: -------------------------------------------------------------------------------- 1 | All Good Things Come to Those Who Wait. 2 | Now is the Time for All Good Men to come to the Aid of their Country. 3 | Nonsense: ����� 4 | -------------------------------------------------------------------------------- /algorithms/same-sign-test.c: -------------------------------------------------------------------------------- 1 | // Detect if two integers have opposite signs 2 | 3 | int x, y; // input values to compare signs 4 | 5 | bool f = ((x ^ y) < 0); // true if x and y have opposite signs -------------------------------------------------------------------------------- /exercises/chapter1/1-6-getchar-putchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int c; 6 | 7 | while ((c = getchar()) != EOF) { 8 | putchar(c); 9 | } 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /algorithms/hash-pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "hash-pointer.h" 4 | 5 | /* Hash function for a generic pointer */ 6 | 7 | unsigned int pointer_hash(void *location) { 8 | return (unsigned int) (unsigned long) location; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /exercises/chapter7/code-7-1-lower-stream.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | int c; 6 | 7 | while ((c = getchar()) != EOF) 8 | putchar(tolower(c)); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /algorithms/hash-int.c: -------------------------------------------------------------------------------- 1 | #include "hash-int.h" 2 | 3 | /* Hash function for a pointer to an integer */ 4 | 5 | unsigned int int_hash(void *vlocation) { 6 | int *location; 7 | 8 | location = (int *) vlocation; 9 | 10 | return (unsigned int) *location; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /algorithms/utf-8-check.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX_LENGTH 500 4 | 5 | int main() 6 | { 7 | int i; 8 | char test[MAX_LENGTH]; 9 | 10 | for (i = 0; i < MAX_LENGTH - 1 ; i++) { 11 | test[i] = ' '; 12 | } 13 | 14 | // in progress 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /algorithms/randomness.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | int r, a, b; 7 | 8 | puts("100 Random Numbers"); 9 | for (a = 0; a < 20; a++) { 10 | for (b = 0; b < 5; b++) { 11 | r = rand(); 12 | printf("%d\t", r); 13 | } 14 | putchar('\n'); 15 | } 16 | 17 | return (0); 18 | } 19 | -------------------------------------------------------------------------------- /algorithms/reverse-string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | char s[100], r[100]; 6 | int n, c, d; 7 | 8 | printf("Input a string\n"); 9 | gets(s); 10 | 11 | n = strlen(s); 12 | 13 | for (c = n - 1, d = 0; c >= 0; c--, d++) 14 | r[d] = s[c]; 15 | 16 | r[d] = '\0'; 17 | 18 | printf("%s\n", r); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /algorithms/dice.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) { 6 | printf("Enter the number of dice: "); 7 | 8 | int n, i; 9 | scanf("%d", &n); 10 | printf("The values on dice are: ( "); 11 | for (i = 0; i < n; i++) 12 | printf("%d ", (rand() % 6) + 1); // terrible rand 13 | 14 | printf(")"); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /algorithms/generate_rand.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | int num; 8 | 9 | /* Seed number for rand() */ 10 | srand((unsigned int) time(0) + getpid()); 11 | 12 | printf("\nGenerating a random number using srand and rand function.\n"); 13 | num = rand(); 14 | 15 | printf("%d\n", num); 16 | 17 | return EXIT_SUCCESS; 18 | } -------------------------------------------------------------------------------- /algorithms/bitwise-addition.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int bitwiseadd(int x, int y) { 4 | while (y != 0) { 5 | int carry = x & y; 6 | x = x ^ y; 7 | y = carry << 1; 8 | } 9 | 10 | return x; 11 | } 12 | 13 | int main() { 14 | int num1, num2; 15 | printf("\nEnter two numbers to perform addition using bitwise operators: "); 16 | scanf("%d%d", &num1, &num2); 17 | printf("\nSum is %d\n", bitwiseadd(num1, num2)); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /algorithms/compare-pointer.c: -------------------------------------------------------------------------------- 1 | #include "compare-pointer.h" 2 | 3 | /* Comparison functions for a generic void pointer */ 4 | 5 | int pointer_equal(void *location1, void *location2) { 6 | return location1 == location2; 7 | } 8 | 9 | int pointer_compare(void *location1, void *location2) { 10 | if (location1 < location2) { 11 | return -1; 12 | } else if (location1 > location2) { 13 | return 1; 14 | } else { 15 | return 0; 16 | } 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /algorithms/solve-linear.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float solve_for_y(float a, float b, float c) 5 | { 6 | float Y = Y = -(b + c) / a; 7 | return Y; 8 | } 9 | 10 | main() 11 | { 12 | float a, b, c, Y; 13 | printf("\nEnter a linear equation in one variable of the form aY + b + c = 0 "); 14 | printf("\nEnter the value of a, b, c respectively: "); 15 | scanf("%f%f%f", &a, &b, &c); 16 | Y = solve_for_y(a, b, c); 17 | printf("\nSolution is Y = %f", Y); 18 | } -------------------------------------------------------------------------------- /exercises/chapter1/1-8-charcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int c, blanks, tabs, newlines; 6 | 7 | blanks = 0; 8 | tabs = 0; 9 | newlines = 0; 10 | 11 | while ((c = getchar()) != EOF) { 12 | if (c == ' ') { 13 | blanks++; 14 | } else if (c == '\n') { 15 | newlines++; 16 | } else if (c == '\t') { 17 | tabs++; 18 | } 19 | } 20 | 21 | printf("Consisted of %d blanks, %d tabs, %d newlines.", blanks, tabs, newlines); 22 | } -------------------------------------------------------------------------------- /algorithms/linear-one-variable.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float solve_for_y(float a, float b, float c) 5 | { 6 | float Y = Y = -(b + c) / a; 7 | return Y; 8 | } 9 | 10 | int main(int argc, char* argv[]) 11 | { 12 | float a, b, c, Y; 13 | printf("\nEnter a linear equation in one variable of the form aY + b + c = 0 "); 14 | printf("\nEnter the value of a, b, c respectively with spaces between, (ex: 2 16 8.3): "); 15 | scanf("%f%f%f", &a, &b, &c); 16 | Y = solve_for_y(a, b, c); 17 | printf("\nSolution is Y = %f\n", Y); 18 | 19 | } -------------------------------------------------------------------------------- /exercises/chapter1/1-3-degrees-fc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* print Fahrenheit-Celsius table 4 | for fahr = 0, 20, ..., 300 (floating point) */ 5 | 6 | int main() 7 | { 8 | float fahr, celsius; 9 | int lower, upper, step; 10 | 11 | lower = 0; 12 | upper = 300; 13 | step = 20; 14 | 15 | fahr = lower; 16 | printf(" F C\n"); 17 | printf("--- ---\n"); 18 | while (fahr <= upper) { 19 | celsius = (5.0/9.0) * (fahr - 32.0); 20 | printf("%3.0f %6.1f\n", fahr, celsius); 21 | fahr = fahr + step; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /exercises/chapter1/1-4-degrees-cf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* print Celsius-Fahrenheit table 4 | for celsius = 0, 20, ..., 300 */ 5 | 6 | int main() 7 | { 8 | float fahr, celsius; 9 | int lower, upper, step; 10 | 11 | lower = -20; 12 | upper = 150; 13 | step = 5; 14 | 15 | celsius = lower; 16 | 17 | printf(" C F\n"); 18 | printf("___ ___\n"); 19 | 20 | while (celsius <= upper) { 21 | fahr = ((9.0/5.0) * celsius) + 32.0; 22 | printf("%6.1f %3.1f\n", celsius, fahr); 23 | 24 | celsius += step; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /exercises/chapter7/structtest.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | 5 | struct automobile { 6 | float length; 7 | float height; 8 | float width; 9 | float weight; 10 | int year; 11 | char make[20]; 12 | char model[20]; 13 | }; 14 | 15 | struct automobile jeep = { 16 | 12.5, 17 | 6.6, 18 | 5.7, 19 | 3834, 20 | 2015, 21 | "Jeep", 22 | "Wrangler" 23 | }; 24 | 25 | printf("It's a %d %s %s\n", jeep.year, jeep.make, jeep.model); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /algorithms/array-summation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int i, n, sum = 0; 6 | int *a; 7 | 8 | printf("Enter the size of array A\n"); 9 | scanf("%d", &n); 10 | 11 | a = (int *) malloc(n * sizeof(int)); 12 | 13 | printf("Enter Elements of First List\n"); 14 | for (i = 0; i < n; i++) { 15 | scanf("%d", a + i); 16 | } 17 | 18 | /*Compute the sum of all elements in the given array*/ 19 | for (i = 0; i < n; i++) { 20 | sum = sum + *(a + i); 21 | } 22 | 23 | printf("Sum of all elements in array = %d\n", sum); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /algorithms/string-reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char rev(char s[50], int, int); 5 | 6 | void main() { 7 | int i, l; 8 | char a[50], b[50]; 9 | clrscr(); 10 | printf("Enter the string\n"); 11 | gets(a); 12 | l = strlen(a); 13 | rev(a, 0, l - 1); 14 | printf("Reverse string is:"); 15 | puts(a); 16 | getch(); 17 | } 18 | 19 | char rev(char *s, int beg, int end) { 20 | char p; 21 | if (beg >= end) { 22 | return 0; 23 | } 24 | else { 25 | p = *(s + beg); 26 | *(s + beg) = *(s + end); 27 | *(s + end) = p; 28 | return rev(s, ++beg, --end); 29 | } 30 | } -------------------------------------------------------------------------------- /algorithms/hash-int.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hash-int.h 3 | * 4 | * Hash function for a pointer to an integer. See @ref int_hash. 5 | */ 6 | 7 | #ifndef ALGORITHM_HASH_INT_H 8 | #define ALGORITHM_HASH_INT_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * Generate a hash key for a pointer to an integer. The value pointed 16 | * at is used to generate the key. 17 | * 18 | * @param location The pointer. 19 | * @return A hash key for the value at the location. 20 | */ 21 | 22 | unsigned int int_hash(void *location); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /* #ifndef ALGORITHM_HASH_INT_H */ 29 | 30 | -------------------------------------------------------------------------------- /algorithms/hash-pointer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hash-pointer.h 3 | * 4 | * Hash function for a generic (void) pointer. See @ref pointer_hash. 5 | */ 6 | 7 | #ifndef ALGORITHM_HASH_POINTER_H 8 | #define ALGORITHM_HASH_POINTER_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * Generate a hash key for a pointer. The value pointed at by the pointer 16 | * is not used, only the pointer itself. 17 | * 18 | * @param location The pointer 19 | * @return A hash key for the pointer. 20 | */ 21 | 22 | unsigned int pointer_hash(void *location); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /* #ifndef ALGORITHM_HASH_POINTER_H */ 29 | 30 | 31 | -------------------------------------------------------------------------------- /exercises/chapter7/exercise-7-1-upper-lower-by-command.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | 7 | int c; 8 | char *p; 9 | char lower[] = "lower"; 10 | char upper[] = "upper"; 11 | 12 | for (p = argv[0]; *p == '.' || *p == '/'; p++) 13 | ; 14 | 15 | printf("Filename: %s\n", p); 16 | printf("Output:\n"); 17 | 18 | bool isUpper = (strcmp(p, upper) == 0); 19 | bool isLower = (strcmp(p, lower) == 0); 20 | 21 | while ((c = getchar()) != EOF) { 22 | if (isUpper) { 23 | putchar(toupper(c)); 24 | } else if (isLower) { 25 | putchar(tolower(c)); 26 | } 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /algorithms/compare-int.c: -------------------------------------------------------------------------------- 1 | #include "compare-int.h" 2 | 3 | /* Comparison functions for a pointer to an integer */ 4 | 5 | int int_equal(void *vlocation1, void *vlocation2) { 6 | int *location1; 7 | int *location2; 8 | 9 | location1 = (int *) vlocation1; 10 | location2 = (int *) vlocation2; 11 | 12 | return *location1 == *location2; 13 | } 14 | 15 | int int_compare(void *vlocation1, void *vlocation2) { 16 | int *location1; 17 | int *location2; 18 | 19 | location1 = (int *) vlocation1; 20 | location2 = (int *) vlocation2; 21 | 22 | if (*location1 < *location2) { 23 | return -1; 24 | } else if (*location1 > *location2) { 25 | return 1; 26 | } else { 27 | return 0; 28 | } 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /algorithms/insertion-sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int n, array[1000], c, d, t; 5 | 6 | printf("Enter number of elements\n"); 7 | scanf("%d", &n); 8 | 9 | printf("Enter %d integers\n", n); 10 | 11 | for (c = 0; c < n; c++) { 12 | scanf("%d", &array[c]); 13 | } 14 | 15 | for (c = 1; c <= n - 1; c++) { 16 | d = c; 17 | 18 | while (d > 0 && array[d] < array[d - 1]) { 19 | t = array[d]; 20 | array[d] = array[d - 1]; 21 | array[d - 1] = t; 22 | 23 | d--; 24 | } 25 | } 26 | 27 | printf("Sorted list in ascending order:\n"); 28 | 29 | for (c = 0; c <= n - 1; c++) { 30 | printf("%d\n", array[c]); 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/bubble-sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int array[100], n, c, d, swap; 5 | 6 | printf("Enter number of elements\n"); 7 | scanf("%d", &n); 8 | 9 | printf("Enter %d integers\n", n); 10 | 11 | for (c = 0; c < n; c++) 12 | scanf("%d", &array[c]); 13 | 14 | for (c = 0; c < (n - 1); c++) { 15 | for (d = 0; d < n - c - 1; d++) { 16 | if (array[d] > array[d + 1]) /* For decreasing order use < */ 17 | { 18 | swap = array[d]; 19 | array[d] = array[d + 1]; 20 | array[d + 1] = swap; 21 | } 22 | } 23 | } 24 | 25 | printf("Sorted list in ascending order:\n"); 26 | 27 | for (c = 0; c < n; c++) 28 | printf("%d\n", array[c]); 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /auto/insertion-sort-asc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void insertionSort(int array[], int n) 4 | { 5 | int i, j, key; 6 | 7 | for (i = 0; i < n; i++) { 8 | j = i - 1; 9 | key = array[i]; 10 | 11 | while (j >= 0 && array[j] > key) { 12 | array[j + 1] = array[j]; 13 | j--; 14 | } 15 | 16 | array[j + 1] = key; 17 | } 18 | } 19 | 20 | void printArray(int array[], int n) 21 | { 22 | for (int i = 0; i < n; i++) { 23 | printf("%d ", array[i]); 24 | } 25 | 26 | printf("\n"); 27 | } 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | int list[] = {3, 5, 2, 7, 9, 14, -1, 4, 2, 5, -5, 1, 0, 38}; 32 | 33 | int size = sizeof(list) / sizeof(list[0]); 34 | 35 | insertionSort(list, size); 36 | 37 | printArray(list, size); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /auto/reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const char* reverse(char* word, int len) 4 | { 5 | int half = (len)/2 + 1; // added one for odd length 6 | int maxIndex = len - 1; 7 | static char rev[sizeof(word) + 1]; 8 | 9 | for (int i = 0; i < half; i++) { 10 | rev[i] = word[maxIndex - i]; 11 | rev[maxIndex - i] = word[i]; 12 | } 13 | 14 | rev[len] = '\0'; 15 | 16 | return rev; 17 | } 18 | 19 | int main(int argc, char* argv[]) 20 | { 21 | char phrase[] = "go backwards"; 22 | char time[] = "time"; 23 | char odd[] = "odd"; 24 | 25 | printf("should be 'sdrawkcab og': %s\n", reverse(phrase, sizeof(phrase)/sizeof(phrase[0]) - 1)); 26 | printf("should be 'emit': %s\n", reverse(time, sizeof(time)/sizeof(time[0]) - 1)); 27 | printf("should be 'ddo': %s\n", reverse(odd, sizeof(odd)/sizeof(odd[0]) - 1)); 28 | } -------------------------------------------------------------------------------- /algorithms/selection-sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int array[100], n, c, d, position, swap; 5 | 6 | printf("Enter number of elements\n"); 7 | scanf("%d", &n); 8 | 9 | printf("Enter %d integers\n", n); 10 | 11 | for (c = 0; c < n; c++) 12 | scanf("%d", &array[c]); 13 | 14 | for (c = 0; c < (n - 1); c++) { 15 | position = c; 16 | 17 | for (d = c + 1; d < n; d++) { 18 | if (array[position] > array[d]) 19 | position = d; 20 | } 21 | if (position != c) { 22 | swap = array[c]; 23 | array[c] = array[position]; 24 | array[position] = swap; 25 | } 26 | } 27 | 28 | printf("Sorted list in ascending order:\n"); 29 | 30 | for (c = 0; c < n; c++) 31 | printf("%d\n", array[c]); 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /auto/insertion-sort-desc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void insertionSortDesc(int array[], int n) 4 | { 5 | int i, j, key; 6 | 7 | for (i = 0; i < n; i++) { 8 | j = i - 1; 9 | key = array[i]; 10 | 11 | while (j >= 0 && array[j] < key) { 12 | array[j + 1] = array[j]; 13 | j--; 14 | } 15 | 16 | array[j + 1] = key; 17 | } 18 | } 19 | 20 | void printArray(int array[], int n) 21 | { 22 | for (int i = 0; i < n; i++) { 23 | printf("%d ", array[i]); 24 | } 25 | 26 | printf("\n"); 27 | } 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | int list[] = {3, 5, 2, 7, 9, 14, -1, 4, 2, 5, -5, 1, 0, 38}; 32 | 33 | int size = sizeof(list) / sizeof(list[0]); 34 | 35 | insertionSortDesc(list, size); 36 | 37 | printArray(list, size); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /exercises/chapter1/1-9-echo-whitespace.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int c, p, i; 6 | int input[100]; 7 | 8 | for (i = 0; i < 100; i++) { 9 | input[i] = 0; 10 | } 11 | 12 | p = 0; 13 | 14 | while ((c = getchar()) != EOF) { 15 | input[++p] = c; 16 | 17 | if (p == 100) { 18 | break; 19 | } 20 | } 21 | 22 | for (i = 0; i < 100; i++) { 23 | if (input[i] == '\t') { 24 | putchar('\\'); 25 | putchar('t'); 26 | } else if (input[i] == '\b') { 27 | putchar('\\'); 28 | putchar('b'); 29 | } else if (input[i] == '\\') { 30 | putchar('\\'); 31 | putchar('\\'); 32 | } else { 33 | putchar(input[i]); 34 | } 35 | } 36 | 37 | printf("\n"); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /algorithms/hash-string.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hash-string.h 3 | * 4 | * Hash functions for text strings. For more information 5 | * see @ref string_hash or @ref string_nocase_hash. 6 | */ 7 | 8 | #ifndef ALGORITHM_HASH_STRING_H 9 | #define ALGORITHM_HASH_STRING_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | /** 16 | * Generate a hash key from a string. 17 | * 18 | * @param string The string. 19 | * @return A hash key for the string. 20 | */ 21 | 22 | unsigned int string_hash(void *string); 23 | 24 | /** 25 | * Generate a hash key from a string, ignoring the case of letters. 26 | * 27 | * @param string The string. 28 | * @return A hash key for the string. 29 | */ 30 | 31 | unsigned int string_nocase_hash(void *string); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif /* #ifndef ALGORITHM_HASH_STRING_H */ 38 | 39 | -------------------------------------------------------------------------------- /algorithms/experiment.c: -------------------------------------------------------------------------------- 1 | #ifndef _ex19_h 2 | #define _ex19_h 3 | 4 | #include "object.h" 5 | 6 | struct Monster { 7 | Object proto; 8 | int hit_points; 9 | }; 10 | 11 | typedef struct Monster Monster; 12 | 13 | int Monster_attack(void *self, int damage); 14 | int Monster_init(void *self); 15 | 16 | struct Room { 17 | Object proto; 18 | 19 | Monster *bad_guy; 20 | 21 | struct Room *north; 22 | struct Room *south; 23 | struct Room *east; 24 | struct Room *west; 25 | }; 26 | 27 | typedef struct Room Room; 28 | 29 | void *Room_move(void *self, Direction direction); 30 | int Room_attack(void *self, int damage); 31 | int Room_init(void *self); 32 | 33 | 34 | struct Map { 35 | Object proto; 36 | Room *start; 37 | Room *location; 38 | }; 39 | 40 | typedef struct Map Map; 41 | 42 | void *Map_move(void *self, Direction direction); 43 | int Map_attack(void *self, int damage); 44 | int Map_init(void *self); 45 | 46 | #endif -------------------------------------------------------------------------------- /algorithms/hash-string.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "hash-string.h" 4 | 5 | /* String hash function */ 6 | 7 | unsigned int string_hash(void *string) { 8 | /* This is the djb2 string hash function */ 9 | 10 | unsigned int result = 5381; 11 | unsigned char *p; 12 | 13 | p = (unsigned char *) string; 14 | 15 | while (*p != '\0') { 16 | result = (result << 5) + result + *p; 17 | ++p; 18 | } 19 | 20 | return result; 21 | } 22 | 23 | /* The same function, with a tolower on every character so that 24 | * case is ignored. This code is duplicated for performance. */ 25 | 26 | unsigned int string_nocase_hash(void *string) { 27 | unsigned int result = 5381; 28 | unsigned char *p; 29 | 30 | p = (unsigned char *) string; 31 | 32 | while (*p != '\0') { 33 | result = (result << 5) + result + (unsigned int) tolower(*p); 34 | ++p; 35 | } 36 | 37 | return result; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /exercises/chapter7/exercise-7-2-sensible-input-printing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int isPrintable(int ch) 5 | { 6 | char *printable = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 !\"#%&'()*+,-./:;<=>?[\\]^_{|}~\t\f\v\r\n"; 7 | int found = 0; 8 | char *p = printable; 9 | 10 | while (found == 0 && *p != '\0') { 11 | if (*p++ == ch) { 12 | found = 1; 13 | } 14 | } 15 | 16 | return found; 17 | } 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | int c; 22 | int lineLength = 80; 23 | int charCount = 0; 24 | 25 | while ((c = getchar()) != EOF) { 26 | charCount++; 27 | if (charCount > lineLength || c == '\n') { 28 | printf("\n"); 29 | charCount = 0; 30 | } 31 | if (isPrintable(c)) { 32 | printf("%c", c); 33 | } else { 34 | printf("%x", c); 35 | } 36 | } 37 | 38 | return EXIT_SUCCESS; 39 | } 40 | -------------------------------------------------------------------------------- /algorithms/binary-search.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int c, first, last, middle, n, search, array[100]; 5 | 6 | printf("Enter number of elements:\n"); 7 | scanf("%d", &n); 8 | 9 | printf("Enter %d integers, separated by spaces:\n", n); 10 | 11 | for (c = 0; c < n; c++) 12 | scanf("%d", &array[c]); 13 | 14 | printf("Enter value to find:\n"); 15 | scanf("%d", &search); 16 | 17 | first = 0; 18 | last = n - 1; 19 | middle = (first + last) / 2; 20 | 21 | while (first <= last) { 22 | if (array[middle] < search) 23 | first = middle + 1; 24 | else if (array[middle] == search) { 25 | printf("%d found at location %d.\n", search, middle + 1); 26 | break; 27 | } 28 | else 29 | last = middle - 1; 30 | 31 | middle = (first + last) / 2; 32 | } 33 | if (first > last) 34 | printf("Not found! %d is not present in the list.\n", search); 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /algorithms/string-sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * C program to read N names, store them in the form of an array 3 | * and sort them in alphabetical order. Output the given names and 4 | * the sorted names in two columns side by side. 5 | */ 6 | #include 7 | #include 8 | 9 | void main() 10 | { 11 | char name[10][8], tname[10][8], temp[8]; 12 | int i, j, n; 13 | 14 | printf("Enter the value of n \n"); 15 | scanf("%d", &n); 16 | printf("Enter %d names n", \n); 17 | for (i = 0; i < n; i++) 18 | { 19 | scanf("%s", name[i]); 20 | strcpy(tname[i], name[i]); 21 | } 22 | for (i = 0; i < n - 1 ; i++) 23 | { 24 | for (j = i + 1; j < n; j++) 25 | { 26 | if (strcmp(name[i], name[j]) > 0) 27 | { 28 | strcpy(temp, name[i]); 29 | strcpy(name[i], name[j]); 30 | strcpy(name[j], temp); 31 | } 32 | } 33 | } 34 | printf("\n----------------------------------------\n"); 35 | printf("Input NamestSorted names\n"); 36 | printf("------------------------------------------\n"); 37 | for (i = 0; i < n; i++) 38 | { 39 | printf("%s\t\t%s\n", tname[i], name[i]); 40 | } 41 | printf("------------------------------------------\n"); 42 | } -------------------------------------------------------------------------------- /algorithms/lcs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX(a, b) (a > b ? a : b) 5 | 6 | int lcs (char *a, int n, char *b, int m, char **s) { 7 | int i, j, k, t; 8 | int *z = calloc((n + 1) * (m + 1), sizeof (int)); 9 | int **c = calloc((n + 1), sizeof (int *)); 10 | for (i = 0; i <= n; i++) { 11 | c[i] = &z[i * (m + 1)]; 12 | } 13 | for (i = 1; i <= n; i++) { 14 | for (j = 1; j <= m; j++) { 15 | if (a[i - 1] == b[j - 1]) { 16 | c[i][j] = c[i - 1][j - 1] + 1; 17 | } 18 | else { 19 | c[i][j] = MAX(c[i - 1][j], c[i][j - 1]); 20 | } 21 | } 22 | } 23 | t = c[n][m]; 24 | *s = malloc(t); 25 | for (i = n, j = m, k = t - 1; k >= 0;) { 26 | if (a[i - 1] == b[j - 1]) 27 | (*s)[k] = a[i - 1], i--, j--, k--; 28 | else if (c[i][j - 1] > c[i - 1][j]) 29 | j--; 30 | else 31 | i--; 32 | } 33 | free(c); 34 | free(z); 35 | return t; 36 | } 37 | 38 | int main () { 39 | char a[] = "ABCBDAB"; 40 | char b[] = "BDCABA"; 41 | int n = sizeof a - 1; 42 | int m = sizeof b - 1; 43 | char *s = NULL; 44 | int t = lcs(a, n, b, m, &s); 45 | printf("%.*s\n", t, s); // tsitest 46 | return 0; 47 | } -------------------------------------------------------------------------------- /algorithms/smiling-face.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | main() 6 | { 7 | int gd = DETECT, gm, area, temp1, temp2, left = 25, top = 75; 8 | void *p; 9 | 10 | initgraph(&gd,&gm,"C:\\TC\\BGI"); 11 | 12 | setcolor(YELLOW); 13 | circle(50,100,25); 14 | setfillstyle(SOLID_FILL,YELLOW); 15 | floodfill(50,100,YELLOW); 16 | 17 | setcolor(BLACK); 18 | setfillstyle(SOLID_FILL,BLACK); 19 | fillellipse(44,85,2,6); 20 | fillellipse(56,85,2,6); 21 | 22 | ellipse(50,100,205,335,20,9); 23 | ellipse(50,100,205,335,20,10); 24 | ellipse(50,100,205,335,20,11); 25 | 26 | area = imagesize(left, top, left + 50, top + 50); 27 | p = malloc(area); 28 | 29 | setcolor(WHITE); 30 | settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2); 31 | outtextxy(155,451,"Smiling Face Animation"); 32 | 33 | setcolor(BLUE); 34 | rectangle(0,0,639,449); 35 | 36 | while(!kbhit()) 37 | { 38 | temp1 = 1 + random ( 588 ); 39 | temp2 = 1 + random ( 380 ); 40 | 41 | getimage(left, top, left + 50, top + 50, p); 42 | putimage(left, top, p, XOR_PUT); 43 | putimage(temp1 , temp2, p, XOR_PUT); 44 | delay(100); 45 | left = temp1; 46 | top = temp2; 47 | } 48 | 49 | getch(); 50 | closegraph(); 51 | return 0; 52 | } -------------------------------------------------------------------------------- /algorithms/compare-pointer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file compare-pointer.h 3 | * 4 | * Comparison functions for generic (void) pointers. 5 | * 6 | * To find the difference between two pointers, use @ref pointer_compare. 7 | * 8 | * To find if two pointers are equal, use @ref pointer_equal. 9 | */ 10 | 11 | #ifndef ALGORITHM_COMPARE_POINTER_H 12 | #define ALGORITHM_COMPARE_POINTER_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /** 19 | * Compare two pointers to determine if they are equal. 20 | * 21 | * @param location1 The first pointer. 22 | * @param location2 The second pointer. 23 | * @return Non-zero if the pointers are equal, zero if they 24 | * are not equal. 25 | */ 26 | 27 | int pointer_equal(void *location1, void *location2); 28 | 29 | /** 30 | * Compare two pointers. 31 | * 32 | * @param location1 The first pointer. 33 | * @param location2 The second pointer. 34 | * @return A negative value if the first pointer is in a lower 35 | * memory address than the second, a positive value if 36 | * the first pointer is in a higher memory address than 37 | * the second, zero if they point to the same location. 38 | */ 39 | 40 | int pointer_compare(void *location1, void *location2); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif /* #ifndef ALGORITHM_COMPARE_POINTER_H */ 47 | -------------------------------------------------------------------------------- /exercises/chapter5/exercise-5-8-day-converter.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char daytab[2][13] = { 4 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 5 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 6 | }; 7 | 8 | /* Indexed */ 9 | 10 | int day_of_year(int year, int month, int day) 11 | { 12 | int i, leap; 13 | 14 | if (month < 1 || month > 12 || year < 0 || year > 9999 || day < 1 || day > 31) { 15 | printf("Invalid date\n"); 16 | return 0; 17 | } 18 | 19 | leap = year%4 == 0 && year%100 != 0 || year%400 == 0; 20 | for (i = 1; i < month; i++) 21 | day += daytab[leap][i]; 22 | 23 | return day; 24 | } 25 | 26 | void month_day(int year, int yearday, int *pmonth, int *pday) 27 | { 28 | int i, leap; 29 | 30 | if (yearday < 1 || yearday > 366 || year < 0 || year > 9999) { 31 | printf("Invalid date\n"); 32 | return; 33 | } 34 | 35 | leap = year%4 == 0 && year%100 != 0 || year%400 == 0; 36 | for (i = 1; yearday > daytab[leap][i]; i++) 37 | yearday -= daytab[leap][i]; 38 | *pday = yearday; 39 | *pmonth = i; 40 | } 41 | 42 | int main() 43 | { 44 | int day; 45 | int month; 46 | int year = 1977; 47 | int yearday; 48 | 49 | yearday = day_of_year_pointer(year, 5, 25); 50 | 51 | month_day_pointer(year, yearday, &month, &day); 52 | 53 | if (yearday > 0) { 54 | printf("yearday: %d\n", yearday); 55 | printf("date: %d/%d/%d\n", month, day, year); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /algorithms/bfs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation incomplete. 3 | * Will come back to this. 4 | */ 5 | 6 | #include "bool.h" 7 | #include "graph.h" 8 | #include "queue.h" 9 | 10 | bool processed[MAXV]; /* which vertices have been processed */ 11 | bool discovered[MAXV]; /* which vertices have been found */ 12 | int parent[MAXV]; /* discovery relation */ 13 | 14 | bool finished = FALSE; /* if true, cut off search immediately */ 15 | 16 | initialize_search(graph *g) 17 | { 18 | int i; /* counter */ 19 | 20 | for (i=1; i<=g->nvertices; i++) { 21 | processed[i] = discovered[i] = FALSE; 22 | parent[i] = -1; 23 | } 24 | } 25 | 26 | bfs(graph *g, int start) 27 | { 28 | queue q; /* queue of vertices to visit */ 29 | int v; /* current vertex */ 30 | int i; /* counter */ 31 | 32 | init_queue(&q); 33 | enqueue(&q,start); 34 | discovered[start] = TRUE; 35 | 36 | while (empty(&q) == FALSE) { 37 | v = dequeue(&q); 38 | process_vertex(v); 39 | processed[v] = TRUE; 40 | for (i=0; idegree[v]; i++) 41 | if (valid_edge(g->edges[v][i]) == TRUE) { 42 | if (discovered[g->edges[v][i]] == FALSE) { 43 | enqueue(&q,g->edges[v][i]); 44 | discovered[g->edges[v][i]] = TRUE; 45 | parent[g->edges[v][i]] = v; 46 | } 47 | if (processed[g->edges[v][i]] == FALSE) 48 | process_edge(v,g->edges[v][i]); 49 | } 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /algorithms/compare-int.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file compare-int.h 3 | * 4 | * Comparison functions for pointers to integers. 5 | * 6 | * To find the difference between two values pointed at, use 7 | * @ref int_compare. 8 | * 9 | * To find if two values pointed at are equal, use @ref int_equal. 10 | */ 11 | 12 | #ifndef ALGORITHM_COMPARE_INT_H 13 | #define ALGORITHM_COMPARE_INT_H 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /** 20 | * Compare the integer values pointed at by two pointers to determine 21 | * if they are equal. 22 | * 23 | * @param location1 Pointer to the first value to compare. 24 | * @param location2 Pointer to the second value to compare. 25 | * @return Non-zero if the two values are equal, zero if the 26 | * two values are not equal. 27 | */ 28 | 29 | int int_equal(void *location1, void *location2); 30 | 31 | /** 32 | * Compare the integer values pointed at by two pointers. 33 | * 34 | * @param location1 Pointer to the first value to compare. 35 | * @param location2 Pointer to the second value to compare. 36 | * @return A negative value if the first value is less than 37 | * the second value, a positive value if the first 38 | * value is greater than the second value, zero if 39 | * they are equal. 40 | */ 41 | 42 | int int_compare(void *location1, void *location2); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* #ifndef ALGORITHM_COMPARE_INT_H */ 49 | -------------------------------------------------------------------------------- /exercises/chapter5/exercise-5-9-day-converter.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char daytab[2][13] = { 4 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 5 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 6 | }; 7 | 8 | /* With Pointers */ 9 | 10 | int day_of_year_pointer(int year, int month, int day) 11 | { 12 | int i, leap; 13 | char *p; 14 | 15 | if (month < 1 || month > 12 || year < 0 || year > 9999 || day < 1 || day > 31) { 16 | printf("Invalid date\n"); 17 | return 0; 18 | } 19 | 20 | leap = year%4 == 0 && year%100 != 0 || year%400 == 0; 21 | 22 | p = &daytab[leap][1]; 23 | 24 | for (i = 1; i < month; i++) 25 | day += *p++; 26 | 27 | return day; 28 | } 29 | 30 | void month_day_pointer(int year, int yearday, int *pmonth, int *pday) 31 | { 32 | int i, leap; 33 | char *p; 34 | 35 | if (yearday < 1 || yearday > 366 || year < 0 || year > 9999) { 36 | printf("Invalid date\n"); 37 | return; 38 | } 39 | 40 | leap = year%4 == 0 && year%100 != 0 || year%400 == 0; 41 | 42 | p = &daytab[leap][1]; 43 | 44 | for (i = 1; yearday > *p; i++) 45 | yearday -= *p++; 46 | 47 | *pday = yearday; 48 | *pmonth = i; 49 | } 50 | 51 | 52 | int main() 53 | { 54 | int day; 55 | int month; 56 | int year = 1977; 57 | int yearday; 58 | 59 | yearday = day_of_year_pointer(year, 5, 25); 60 | 61 | month_day_pointer(year, yearday, &month, &day); 62 | 63 | if (yearday > 0) { 64 | printf("yearday: %d\n", yearday); 65 | printf("date: %d/%d/%d\n", month, day, year); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /exercises/chapter2/getbits.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned int getbits(unsigned int x, int p, int n) 4 | { 5 | return (x >> (p + 1 - n)) & ~(~0 << n); 6 | } 7 | 8 | const char* displaybits(unsigned int d) 9 | { 10 | int i = 0; 11 | int c; 12 | char rbits[sizeof(d) + 1]; 13 | static char bits[sizeof(d) + 1]; 14 | 15 | if (d == 0) { 16 | rbits[i++] = '0'; 17 | } else { 18 | while (d != 0) { 19 | rbits[i++] = (d & 1) == 1 ? '1' : '0'; 20 | d >>= 1; 21 | } 22 | } 23 | 24 | // reverse string 25 | // @todo create an in-place reverse string algorithm 26 | 27 | i--; 28 | 29 | for (c = 0; c <= i; c++) { 30 | bits[c] = rbits[i - c]; 31 | } 32 | 33 | bits[c] = '\0'; 34 | 35 | return bits; 36 | } 37 | 38 | int main() 39 | { 40 | printf("Should be 0: %s\n", displaybits(0)); 41 | printf("Should be 1: %s\n", displaybits(1)); 42 | printf("Should be 10: %s\n", displaybits(2)); 43 | printf("Should be 11: %s\n", displaybits(3)); 44 | printf("Should be 100: %s\n", displaybits(4)); 45 | printf("Should be 101: %s\n", displaybits(5)); 46 | printf("Should be 110: %s\n", displaybits(6)); 47 | printf("Should be 111: %s\n", displaybits(7)); 48 | printf("Should be 1000: %s\n", displaybits(8)); 49 | printf("Should be 10000: %s\n", displaybits(16)); 50 | printf("Should be 11111: %s\n", displaybits(16 + 8 + 4 + 2 + 1)); 51 | printf("Should be 11011: %s\n", displaybits(16 + 8 + 2 + 1)); 52 | printf("Should be 10011: %s\n", displaybits(16 + 2 + 1)); 53 | printf("Should be 10010: %s\n", displaybits(16 + 2)); 54 | 55 | return 0; 56 | } -------------------------------------------------------------------------------- /algorithms/compare-string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "compare-string.h" 6 | 7 | /* Comparison functions for strings */ 8 | 9 | int string_equal(void *string1, void *string2) { 10 | return strcmp((char *) string1, (char *) string2) == 0; 11 | } 12 | 13 | int string_compare(void *string1, void *string2) { 14 | int result; 15 | 16 | result = strcmp((char *) string1, (char *) string2); 17 | 18 | if (result < 0) { 19 | return -1; 20 | } else if (result > 0) { 21 | return 1; 22 | } else { 23 | return 0; 24 | } 25 | } 26 | 27 | /* Comparison functions for strings, which ignore the case of letters. */ 28 | 29 | int string_nocase_equal(void *string1, void *string2) { 30 | return string_nocase_compare((char *) string1, (char *) string2) == 0; 31 | } 32 | 33 | /* On many systems, strcasecmp or stricmp will give the same functionality 34 | * as this function. However, it is non-standard and cannot be relied 35 | * on to be present. */ 36 | 37 | int string_nocase_compare(void *string1, void *string2) { 38 | char *p1; 39 | char *p2; 40 | int c1, c2; 41 | 42 | /* Iterate over each character in the strings */ 43 | 44 | p1 = (char *) string1; 45 | p2 = (char *) string2; 46 | 47 | for (; ;) { 48 | 49 | c1 = tolower(*p1); 50 | c2 = tolower(*p2); 51 | 52 | if (c1 != c2) { 53 | 54 | /* Strings are different */ 55 | 56 | if (c1 < c2) { 57 | return -1; 58 | } else { 59 | return 1; 60 | } 61 | } 62 | 63 | /* End of string */ 64 | 65 | if (c1 == '\0') 66 | break; 67 | 68 | /* Advance to the next character */ 69 | 70 | ++p1; 71 | ++p2; 72 | } 73 | 74 | /* Reached the end of string and no difference found */ 75 | 76 | return 0; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /algorithms/merge-sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Function to merge the two haves arr[l..m] and arr[m+1..r] of array arr[] */ 5 | void merge(int arr[], int l, int m, int r) { 6 | int i, j, k; 7 | int n1 = m - l + 1; 8 | int n2 = r - m; 9 | 10 | /* create temp arrays */ 11 | int L[n1], R[n2]; 12 | 13 | /* Copy data to temp arrays L[] and R[] */ 14 | for (i = 0; i < n1; i++) 15 | L[i] = arr[l + i]; 16 | for (j = 0; j < n2; j++) 17 | R[j] = arr[m + 1 + j]; 18 | 19 | /* Merge the temp arrays back into arr[l..r]*/ 20 | i = 0; 21 | j = 0; 22 | k = l; 23 | while (i < n1 && j < n2) { 24 | if (L[i] <= R[j]) { 25 | arr[k] = L[i]; 26 | i++; 27 | } 28 | else { 29 | arr[k] = R[j]; 30 | j++; 31 | } 32 | k++; 33 | } 34 | 35 | /* Copy the remaining elements of L[], if there are any */ 36 | while (i < n1) { 37 | arr[k] = L[i]; 38 | i++; 39 | k++; 40 | } 41 | 42 | /* Copy the remaining elements of R[], if there are any */ 43 | while (j < n2) { 44 | arr[k] = R[j]; 45 | j++; 46 | k++; 47 | } 48 | } 49 | 50 | /* l is for left index and r is right index of the sub-array 51 | of arr to be sorted */ 52 | void mergeSort(int arr[], int l, int r) { 53 | if (l < r) { 54 | int m = l + (r - l) / 2; //Same as (l+r)/2, but avoids overflow for large l and h 55 | mergeSort(arr, l, m); 56 | mergeSort(arr, m + 1, r); 57 | merge(arr, l, m, r); 58 | } 59 | } 60 | 61 | 62 | /* UITLITY FUNCTIONS */ 63 | /* Function to print an array */ 64 | void printArray(int A[], int size) { 65 | int i; 66 | for (i = 0; i < size; i++) 67 | printf("%d ", A[i]); 68 | printf("\n"); 69 | } 70 | 71 | /* Driver program to test above functions */ 72 | int main() { 73 | int arr[] = {12, 11, 13, 5, 6, 7}; 74 | int arr_size = sizeof(arr) / sizeof(arr[0]); 75 | 76 | printf("Given array is \n"); 77 | printArray(arr, arr_size); 78 | 79 | mergeSort(arr, 0, arr_size - 1); 80 | 81 | printf("\nSorted array is \n"); 82 | printArray(arr, arr_size); 83 | return 0; 84 | } -------------------------------------------------------------------------------- /auto/htoi.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int htoi(char hex[]) 4 | { 5 | int c; 6 | int v; 7 | int n = 0; 8 | 9 | for (int i = 0; hex[i] != '\0'; i++) { 10 | c = hex[i]; 11 | if (c >= '0' && c <= '9') { 12 | v = c - '0'; 13 | } else if (c >= 'a' && c <= 'f') { 14 | v = c - 'a' + 10; 15 | } else if (c >= 'A' && c <= 'F') { 16 | v = c - 'A' + 10; 17 | } else { 18 | continue; 19 | } 20 | 21 | n = 16 * n + v; 22 | } 23 | 24 | return n; 25 | } 26 | 27 | int main() 28 | { 29 | printf("Should be 0: %d\n", htoi("0")); 30 | printf("Should be 1: %d\n", htoi("1")); 31 | printf("Should be 9: %d\n", htoi("9")); 32 | printf("Should be 10: %d\n", htoi("A")); 33 | printf("Should be 15: %d\n", htoi("F")); 34 | printf("Should be 16: %d\n", htoi("10")); 35 | printf("Should be 17: %d\n", htoi("11")); 36 | printf("Should be 21: %d\n", htoi("15")); 37 | printf("Should be 26: %d\n", htoi("1A")); 38 | printf("Should be 31: %d\n", htoi("1F")); 39 | printf("Should be 32: %d\n", htoi("20")); 40 | printf("Should be 48: %d\n", htoi("30")); 41 | printf("Should be 255: %d\n", htoi("FF")); 42 | printf("Should be 2048: %d\n", htoi("800")); 43 | printf("Should be 12113: %d\n", htoi("2F51")); 44 | printf("Should be 19008: %d\n", htoi("4A40")); 45 | printf("Should be 809149: %d\n", htoi("C58BD")); 46 | 47 | // mixed-case 48 | 49 | printf("Should be 12113: %d\n", htoi("2f51")); 50 | printf("Should be 809149: %d\n", htoi("c58bD")); 51 | 52 | // with 0x at beginning 53 | 54 | printf("Should be 12113: %d\n", htoi("0x2f51")); 55 | printf("Should be 809149: %d\n", htoi("0xc58bD")); 56 | 57 | // oddballs with non-hex characters 58 | 59 | printf("Should be 0: %d\n", htoi("")); 60 | printf("Should be 0: %d\n", htoi("^^^^")); 61 | printf("Should be 0: %d\n", htoi(" ")); 62 | printf("Should be 0: %d\n", htoi("!\nYo\t\a")); 63 | printf("Should be 0: %d\n", htoi("000")); 64 | printf("Should be 0: %d\n", htoi("0HK")); 65 | printf("Should be 0: %d\n", htoi("\05")); 66 | printf("Should be 4: %d\n", htoi("4HK")); 67 | printf("Should be 103: %d\n", htoi("6Z7Z")); 68 | printf("Should be 103: %d\n", htoi("-6Z7Z")); 69 | printf("Should be 365307: %d\n", htoi("M592FSUB")); 70 | 71 | return 0; 72 | } -------------------------------------------------------------------------------- /algorithms/compare-string.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file compare-string.h 3 | * 4 | * Comparison functions for strings. 5 | * 6 | * To find the difference between two strings, use @ref string_compare. 7 | * 8 | * To find if two strings are equal, use @ref string_equal. 9 | * 10 | * For case insensitive versions, see @ref string_nocase_compare and 11 | * @ref string_nocase_equal. 12 | */ 13 | 14 | #ifndef ALGORITHM_COMPARE_STRING_H 15 | #define ALGORITHM_COMPARE_STRING_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /** 22 | * Compare two strings to determine if they are equal. 23 | * 24 | * @param string1 The first string. 25 | * @param string2 The second string. 26 | * @return Non-zero if the strings are equal, zero if they are 27 | * not equal. 28 | */ 29 | 30 | int string_equal(void *string1, void *string2); 31 | 32 | /** 33 | * Compare two strings. 34 | * 35 | * @param string1 The first string. 36 | * @param string2 The second string. 37 | * @return A negative value if the first string should be 38 | * sorted before the second, a positive value if the 39 | * first string should be sorted after the second, 40 | * zero if the two strings are equal. 41 | */ 42 | 43 | int string_compare(void *string1, void *string2); 44 | 45 | /** 46 | * Compare two strings to determine if they are equal, ignoring the 47 | * case of letters. 48 | * 49 | * @param string1 The first string. 50 | * @param string2 The second string. 51 | * @return Non-zero if the strings are equal, zero if they are 52 | * not equal. 53 | */ 54 | 55 | int string_nocase_equal(void *string1, void *string2); 56 | 57 | /** 58 | * Compare two strings, ignoring the case of letters. 59 | * 60 | * @param string1 The first string. 61 | * @param string2 The second string. 62 | * @return A negative value if the first string should be 63 | * sorted before the second, a positive value if the 64 | * first string should be sorted after the second, 65 | * zero if the two strings are equal. 66 | */ 67 | 68 | int string_nocase_compare(void *string1, void *string2); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif /* #ifndef ALGORITHM_COMPARE_STRING_H */ 75 | -------------------------------------------------------------------------------- /algorithms/dice-monte-carlo.c: -------------------------------------------------------------------------------- 1 | /* dice: Gather statistics about rolling 2 | * two dice. A Monte Carlo simulation using 3 | * the random number generator rand() 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | void initarray(int d[]); 10 | 11 | void printarray(int d[]); 12 | 13 | void printstar(int n); 14 | 15 | void fancyprint(int d[]); 16 | 17 | int roll(void); 18 | 19 | int numrolls; 20 | 21 | int main(void) { 22 | 23 | int d[13]; /* 2-12 hold num of rolls */ 24 | int i; /* loop variable */ 25 | int starttime = time(NULL); /* clock time */ 26 | srand((long) starttime); 27 | printf("Enter # of rolls ---> "); 28 | scanf("%i", &numrolls); /* need & on var */ 29 | 30 | initarray(d); 31 | printf("Total rolls: %1d\n\n", numrolls); 32 | 33 | for (i = 0; i < numrolls; i++) 34 | d[roll() + roll()]++; 35 | printarray(d); 36 | fancyprint(d); 37 | printf("Elapsed time: %ld seconds\n", 38 | time(NULL) - starttime); 39 | return 0; 40 | } 41 | 42 | /* initarray: initialize statistic array */ 43 | void initarray(int d[]) { 44 | int i; 45 | for (i = 2; i < 13; i++) 46 | d[i] = 0; 47 | } 48 | 49 | /* printarray: print each num of rolls */ 50 | void printarray(int d[]) { 51 | int i; 52 | double e[] = {0, 0, 53 | 1.0 / 36.0, 2.0 / 36.0, 3.0 / 36.0, 4.0 / 36.0, 54 | 5.0 / 36.0, 6.0 / 36.0, 5.0 / 36.0, 4.0 / 36.0, 55 | 3.0 / 36.0, 2.0 / 36.0, 1.0 / 36.0}; 56 | printf("Sum Times Frequency"); 57 | printf(" Exact Diff\n\n"); 58 | for (i = 2; i < 13; i++) 59 | printf("%2d %7d %11.7f %10.7f %8.4f\n", 60 | i, 61 | d[i], 62 | (double) d[i] / numrolls * 100.0, 63 | 64 | e[i] * 100.0, 65 | ((double) (d[i]) - 66 | e[i] * numrolls) / numrolls * 100.0); 67 | } 68 | 69 | /* printstar: print n stars */ 70 | void printstar(int n) { 71 | while (n > 0) { 72 | printf("*"); 73 | n--; 74 | } 75 | } 76 | 77 | /* fancyprint: print bar graph */ 78 | void fancyprint(int d[]) { 79 | int i; 80 | printf("\n"); 81 | for (i = 2; i < 13; i++) { 82 | printf("Sum:%3d |", i); 83 | 84 | printstar(300 * d[i] / numrolls); 85 | 86 | printf("\n"); 87 | } 88 | printf("\n"); 89 | } 90 | 91 | /* roll: simulate rolling a die */ 92 | int roll(void) { 93 | return (int) (6.0 * (rand() / (double) RAND_MAX) 94 | + 1.0); 95 | } -------------------------------------------------------------------------------- /algorithms/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * C program to implement stack. Stack is a LIFO data structure. 3 | * Stack operations: PUSH(insert operation), POP(Delete operation) 4 | * and Display stack. 5 | */ 6 | #include 7 | 8 | #define MAXSIZE 5 9 | 10 | struct stack { 11 | int stk[MAXSIZE]; 12 | int top; 13 | }; 14 | typedef struct stack STACK; 15 | STACK s; 16 | 17 | void push(void); 18 | 19 | int pop(void); 20 | 21 | void display(void); 22 | 23 | int main() { 24 | int choice; 25 | int option = 1; 26 | s.top = -1; 27 | 28 | printf("STACK OPERATION\n"); 29 | while (option) { 30 | printf("------------------------------------------\n"); 31 | printf(" 1 --> PUSH \n"); 32 | printf(" 2 --> POP \n"); 33 | printf(" 3 --> DISPLAY \n"); 34 | printf(" 4 --> EXIT \n"); 35 | printf("------------------------------------------\n"); 36 | 37 | printf("Enter your choice\n"); 38 | scanf("%d", &choice); 39 | switch (choice) { 40 | case 1: 41 | push(); 42 | break; 43 | case 2: 44 | pop(); 45 | break; 46 | case 3: 47 | display(); 48 | break; 49 | case 4: 50 | return 0; 51 | } 52 | fflush(stdin); 53 | printf("Do you want to continue(Type 0 or 1)?\n"); 54 | scanf("%d", &option); 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | /* Function to add an element to the stack */ 61 | void push() { 62 | int num; 63 | if (s.top == (MAXSIZE - 1)) { 64 | printf("Stack is Full\n"); 65 | return; 66 | } 67 | else { 68 | printf("Enter the element to be pushed\n"); 69 | scanf("%d", &num); 70 | s.top = s.top + 1; 71 | s.stk[s.top] = num; 72 | } 73 | return; 74 | } 75 | 76 | /* Function to delete an element from the stack */ 77 | int pop() { 78 | int num; 79 | if (s.top == -1) { 80 | printf("Stack is Empty\n"); 81 | return (s.top); 82 | } 83 | else { 84 | num = s.stk[s.top]; 85 | printf("poped element is = %dn", s.stk[s.top]); 86 | s.top = s.top - 1; 87 | } 88 | return (num); 89 | } 90 | 91 | /* Function to display the status of the stack */ 92 | void display() { 93 | int i; 94 | if (s.top == -1) { 95 | printf("Stack is empty\n"); 96 | return; 97 | } 98 | else { 99 | printf("\n The status of the stack is \n"); 100 | for (i = s.top; i >= 0; i--) { 101 | printf("%d\n", s.stk[i]); 102 | } 103 | } 104 | printf("\n"); 105 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C Note 2 | 3 | Notes on C and some mini-programs. 4 | 5 | > Nevertheless, C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. 6 | 7 | ## References: 8 | 9 | ### C Language 10 | 11 | - http://c-faq.com/index.html 12 | - [Safety](safety.md) for string-safe functions 13 | - The GNU C Reference Manual: http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html 14 | - ACM: The C Reference Guide - https://www-s.acm.illinois.edu/webmonkeys/book/c_guide/ 15 | - MSDN: C Language Reference - https://msdn.microsoft.com/en-us/library/fw5abdx6.aspx 16 | 17 | ### Books 18 | 19 | #### Beginner 20 | 21 | - The C Programming Language 2nd Edition (1988): http://www.amazon.com/The-Programming-Language-Brian-Kernighan/dp/0131103628 22 | - Answers to the Book: http://clc-wiki.net/wiki/K%26R2_solutions 23 | - The C Answer Book: Solutions to the Exercises in 'The C Programming Language,' Second Edition: http://www.amazon.com/The-Answer-Book-Solutions-Programming/dp/0131096532 24 | - More solutions to exercises in The C Programming Language: https://github.com/anotherlin/tcpl 25 | - Programming in C (3rd Edition): http://www.amazon.com/dp/0672326663/ 26 | - A Book on C: Programming in C (4th Edition): http://www.amazon.com/dp/0201183994/ 27 | - C Primer Plus (6th Edition): http://www.amazon.com/Primer-Plus-Edition-Developers-Library/dp/0321928423/ 28 | - Pointers on C - 1st Edition: http://www.amazon.com/Pointers-C-Kenneth-Reek/dp/0673999866 29 | 30 | #### Intermediate 31 | 32 | - Object-oriented Programming with ANSI-C (Free PDF): http://www.planetpdf.com/codecuts/pdfs/ooc.pdf 33 | - 21st Century C: C Tips from the New School 1st Edition: http://www.amazon.com/dp/1449327141/ 34 | - Understanding and Using C Pointers 1st Edition - http://www.amazon.com/Understanding-Using-Pointers-Richard-Reese/dp/1449344186/ 35 | - C Interfaces and Implementations: Techniques for Creating Reusable Software 1st Edition: http://www.amazon.com/exec/obidos/ASIN/0201498413/ 36 | - C Programming: A Modern Approach, 2nd Edition: http://www.amazon.com/dp/0393979504 37 | - The Standard C Library 1st Edition: http://www.amazon.com/dp/0131315099/ 38 | 39 | #### Advanced 40 | 41 | - Expert C Programming: Deep C Secrets 1st Edition: http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298/ 42 | - Advanced Programming in the UNIX Environment, 3rd Edition: http://www.amazon.com/dp/0321637739/ 43 | - Advanced C Programming by Example: http://www.amazon.com/dp/0534951406/ 44 | 45 | #### General Reference 46 | 47 | - C Pocket Reference 1st Edition: http://www.amazon.com/C-Pocket-Reference-Peter-Prinz/dp/0596004362/ 48 | 49 | ### Algorithms in C 50 | 51 | - http://www.sanfoundry.com/c-programming-examples-numerical-problems-algorithms/ 52 | - https://github.com/fragglet/c-algorithms/tree/master/src 53 | - https://github.com/fragglet/c-algorithms/releases 54 | -------------------------------------------------------------------------------- /algorithms/popcount.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple 3 | */ 4 | 5 | int NumberOfSetBits(int i) 6 | { 7 | // C or C++: use uint32_t 8 | i = i - ((i >> 1) & 0x55555555); 9 | i = (i & 0x33333333) + ((i >> 2) & 0x33333333); 10 | return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; 11 | } 12 | 13 | 14 | /** 15 | * Advanced 16 | */ 17 | 18 | //types and constants used in the functions below 19 | 20 | const uint64_t m1 = 0x5555555555555555; //binary: 0101... 21 | const uint64_t m2 = 0x3333333333333333; //binary: 00110011.. 22 | const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ... 23 | const uint64_t m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones ... 24 | const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ... 25 | const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones 26 | const uint64_t hff = 0xffffffffffffffff; //binary: all ones 27 | const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3... 28 | 29 | //This is a naive implementation, shown for comparison, 30 | //and to help in understanding the better functions. 31 | //It uses 24 arithmetic operations (shift, add, and). 32 | int popcount_1(uint64_t x) { 33 | x = (x & m1 ) + ((x >> 1) & m1 ); //put count of each 2 bits into those 2 bits 34 | x = (x & m2 ) + ((x >> 2) & m2 ); //put count of each 4 bits into those 4 bits 35 | x = (x & m4 ) + ((x >> 4) & m4 ); //put count of each 8 bits into those 8 bits 36 | x = (x & m8 ) + ((x >> 8) & m8 ); //put count of each 16 bits into those 16 bits 37 | x = (x & m16) + ((x >> 16) & m16); //put count of each 32 bits into those 32 bits 38 | x = (x & m32) + ((x >> 32) & m32); //put count of each 64 bits into those 64 bits 39 | return x; 40 | } 41 | 42 | //This uses fewer arithmetic operations than any other known 43 | //implementation on machines with slow multiplication. 44 | //It uses 17 arithmetic operations. 45 | int popcount_2(uint64_t x) { 46 | x -= (x >> 1) & m1; //put count of each 2 bits into those 2 bits 47 | x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 48 | x = (x + (x >> 4)) & m4; //put count of each 8 bits into those 8 bits 49 | x += x >> 8; //put count of each 16 bits into their lowest 8 bits 50 | x += x >> 16; //put count of each 32 bits into their lowest 8 bits 51 | x += x >> 32; //put count of each 64 bits into their lowest 8 bits 52 | return x & 0x7f; 53 | } 54 | 55 | //This uses fewer arithmetic operations than any other known 56 | //implementation on machines with fast multiplication. 57 | //It uses 12 arithmetic operations, one of which is a multiply. 58 | int popcount_3(uint64_t x) { 59 | x -= (x >> 1) & m1; //put count of each 2 bits into those 2 bits 60 | x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 61 | x = (x + (x >> 4)) & m4; //put count of each 8 bits into those 8 bits 62 | return (x * h01)>>56; //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... 63 | } -------------------------------------------------------------------------------- /algorithms/queue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file queue.h 3 | * 4 | * @brief Double-ended queue. 5 | * 6 | * A double ended queue stores a list of values in order. New values 7 | * can be added and removed from either end of the queue. 8 | * 9 | * To create a new queue, use @ref queue_new. To destroy a queue, use 10 | * @ref queue_free. 11 | * 12 | * To add values to a queue, use @ref queue_push_head and 13 | * @ref queue_push_tail. 14 | * 15 | * To read values from the ends of a queue, use @ref queue_pop_head 16 | * and @ref queue_pop_tail. To examine the ends without removing values 17 | * from the queue, use @ref queue_peek_head and @ref queue_peek_tail. 18 | * 19 | */ 20 | 21 | #ifndef ALGORITHM_QUEUE_H 22 | #define ALGORITHM_QUEUE_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * A double-ended queue. 30 | */ 31 | 32 | typedef struct _Queue Queue; 33 | 34 | /** 35 | * A value stored in a @ref Queue. 36 | */ 37 | 38 | typedef void *QueueValue; 39 | 40 | /** 41 | * A null @ref QueueValue. 42 | */ 43 | 44 | #define QUEUE_NULL ((void *) 0) 45 | 46 | /** 47 | * Create a new double-ended queue. 48 | * 49 | * @return A new queue, or NULL if it was not possible to allocate 50 | * the memory. 51 | */ 52 | 53 | Queue *queue_new(void); 54 | 55 | /** 56 | * Destroy a queue. 57 | * 58 | * @param queue The queue to destroy. 59 | */ 60 | 61 | void queue_free(Queue *queue); 62 | 63 | /** 64 | * Add a value to the head of a queue. 65 | * 66 | * @param queue The queue. 67 | * @param data The value to add. 68 | * @return Non-zero if the value was added successfully, or zero 69 | * if it was not possible to allocate the memory for the 70 | * new entry. 71 | */ 72 | 73 | int queue_push_head(Queue *queue, QueueValue data); 74 | 75 | /** 76 | * Remove a value from the head of a queue. 77 | * 78 | * @param queue The queue. 79 | * @return Value that was at the head of the queue, or 80 | * @ref QUEUE_NULL if the queue is empty. 81 | */ 82 | 83 | QueueValue queue_pop_head(Queue *queue); 84 | 85 | /** 86 | * Read value from the head of a queue, without removing it from 87 | * the queue. 88 | * 89 | * @param queue The queue. 90 | * @return Value at the head of the queue, or @ref QUEUE_NULL if the 91 | * queue is empty. 92 | */ 93 | 94 | QueueValue queue_peek_head(Queue *queue); 95 | 96 | /** 97 | * Add a value to the tail of a queue. 98 | * 99 | * @param queue The queue. 100 | * @param data The value to add. 101 | * @return Non-zero if the value was added successfully, or zero 102 | * if it was not possible to allocate the memory for the 103 | * new entry. 104 | */ 105 | 106 | int queue_push_tail(Queue *queue, QueueValue data); 107 | 108 | /** 109 | * Remove a value from the tail of a queue. 110 | * 111 | * @param queue The queue. 112 | * @return Value that was at the head of the queue, or 113 | * @ref QUEUE_NULL if the queue is empty. 114 | */ 115 | 116 | QueueValue queue_pop_tail(Queue *queue); 117 | 118 | /** 119 | * Read a value from the tail of a queue, without removing it from 120 | * the queue. 121 | * 122 | * @param queue The queue. 123 | * @return Value at the tail of the queue, or QUEUE_NULL if the 124 | * queue is empty. 125 | */ 126 | 127 | QueueValue queue_peek_tail(Queue *queue); 128 | 129 | /** 130 | * Query if any values are currently in a queue. 131 | * 132 | * @param queue The queue. 133 | * @return Zero if the queue is not empty, non-zero if the queue 134 | * is empty. 135 | */ 136 | 137 | int queue_is_empty(Queue *queue); 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif /* #ifndef ALGORITHM_QUEUE_H */ 144 | -------------------------------------------------------------------------------- /algorithms/trie.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file trie.h 3 | * 4 | * @brief Fast string lookups 5 | * 6 | * A trie is a data structure which provides fast mappings from strings 7 | * to values. 8 | * 9 | * To create a new trie, use @ref trie_new. To destroy a trie, 10 | * use @ref trie_free. 11 | * 12 | * To insert a value into a trie, use @ref trie_insert. To remove a value 13 | * from a trie, use @ref trie_remove. 14 | * 15 | * To look up a value from its key, use @ref trie_lookup. 16 | * 17 | * To find the number of entries in a trie, use @ref trie_num_entries. 18 | */ 19 | 20 | #ifndef ALGORITHM_TRIE_H 21 | #define ALGORITHM_TRIE_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /** 28 | * A trie structure. 29 | */ 30 | 31 | typedef struct _Trie Trie; 32 | 33 | /** 34 | * Value stored in a @ref Trie. 35 | */ 36 | 37 | typedef void *TrieValue; 38 | 39 | /** 40 | * A null @ref TrieValue. 41 | */ 42 | 43 | #define TRIE_NULL ((void *) 0) 44 | 45 | /** 46 | * Create a new trie. 47 | * 48 | * @return Pointer to a new trie structure, or NULL if it 49 | * was not possible to allocate memory for the 50 | * new trie. 51 | */ 52 | 53 | Trie *trie_new(void); 54 | 55 | /** 56 | * Destroy a trie. 57 | * 58 | * @param trie The trie to destroy. 59 | */ 60 | 61 | void trie_free(Trie *trie); 62 | 63 | /** 64 | * Insert a new key-value pair into a trie. The key is a NUL-terminated 65 | * string. For binary strings, use @ref trie_insert_binary. 66 | * 67 | * @param trie The trie. 68 | * @param key The key to access the new value. 69 | * @param value The value. 70 | * @return Non-zero if the value was inserted successfully, 71 | * or zero if it was not possible to allocate 72 | * memory for the new entry. 73 | */ 74 | 75 | int trie_insert(Trie *trie, char *key, TrieValue value); 76 | 77 | /** 78 | * Insert a new key-value pair into a trie. The key is a sequence of bytes. 79 | * For a key that is a NUL-terminated text string, use @ref trie_insert. 80 | * 81 | * @param trie The trie. 82 | * @param key The key to access the new value. 83 | * @param key_length The key length in bytes. 84 | * @param value The value. 85 | * @return Non-zero if the value was inserted successfully, 86 | * or zero if it was not possible to allocate 87 | * memory for the new entry. 88 | */ 89 | 90 | int trie_insert_binary(Trie *trie, unsigned char *key, 91 | int key_length, TrieValue value); 92 | 93 | /** 94 | * Look up a value from its key in a trie. 95 | * The key is a NUL-terminated string; for binary strings, use 96 | * @ref trie_lookup_binary. 97 | * 98 | * @param trie The trie. 99 | * @param key The key. 100 | * @return The value associated with the key, or 101 | * @ref TRIE_NULL if not found in the trie. 102 | */ 103 | 104 | TrieValue trie_lookup(Trie *trie, char *key); 105 | 106 | /** 107 | * Look up a value from its key in a trie. 108 | * The key is a sequence of bytes; for a key that is a NUL-terminated 109 | * text string, use @ref trie_lookup. 110 | * 111 | * @param trie The trie. 112 | * @param key The key. 113 | * @param key_length The key length in bytes. 114 | * @return The value associated with the key, or 115 | * @ref TRIE_NULL if not found in the trie. 116 | */ 117 | 118 | TrieValue trie_lookup_binary(Trie *trie, unsigned char *key, int key_length); 119 | 120 | /** 121 | * Remove an entry from a trie. 122 | * The key is a NUL-terminated string; for binary strings, use 123 | * @ref trie_lookup_binary. 124 | * 125 | * @param trie The trie. 126 | * @param key The key of the entry to remove. 127 | * @return Non-zero if the key was removed successfully, 128 | * or zero if it is not present in the trie. 129 | */ 130 | 131 | int trie_remove(Trie *trie, char *key); 132 | 133 | /** 134 | * Remove an entry from a trie. 135 | * The key is a sequence of bytes; for a key that is a NUL-terminated 136 | * text string, use @ref trie_lookup. 137 | * 138 | * @param trie The trie. 139 | * @param key The key of the entry to remove. 140 | * @param key_length The key length in bytes. 141 | * @return Non-zero if the key was removed successfully, 142 | * or zero if it is not present in the trie. 143 | */ 144 | 145 | int trie_remove_binary(Trie *trie, unsigned char *key, int key_length); 146 | 147 | /** 148 | * Find the number of entries in a trie. 149 | * 150 | * @param trie The trie. 151 | * @return Count of the number of entries in the trie. 152 | */ 153 | 154 | unsigned int trie_num_entries(Trie *trie); 155 | 156 | #ifdef __cplusplus 157 | } 158 | #endif 159 | 160 | #endif /* #ifndef ALGORITHM_TRIE_H */ 161 | -------------------------------------------------------------------------------- /algorithms/queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "queue.h" 4 | 5 | /* malloc() / free() testing */ 6 | 7 | #ifdef ALLOC_TESTING 8 | #include "alloc-testing.h" 9 | #endif 10 | 11 | /* A double-ended queue */ 12 | 13 | typedef struct _QueueEntry QueueEntry; 14 | 15 | struct _QueueEntry { 16 | QueueValue data; 17 | QueueEntry *prev; 18 | QueueEntry *next; 19 | }; 20 | 21 | struct _Queue { 22 | QueueEntry *head; 23 | QueueEntry *tail; 24 | }; 25 | 26 | Queue *queue_new(void) { 27 | Queue *queue; 28 | 29 | queue = (Queue *) malloc(sizeof(Queue)); 30 | 31 | if (queue == NULL) { 32 | return NULL; 33 | } 34 | 35 | queue->head = NULL; 36 | queue->tail = NULL; 37 | 38 | return queue; 39 | } 40 | 41 | void queue_free(Queue *queue) { 42 | /* Empty the queue */ 43 | 44 | while (!queue_is_empty(queue)) { 45 | queue_pop_head(queue); 46 | } 47 | 48 | /* Free back the queue */ 49 | 50 | free(queue); 51 | } 52 | 53 | int queue_push_head(Queue *queue, QueueValue data) { 54 | QueueEntry *new_entry; 55 | 56 | /* Create the new entry and fill in the fields in the structure */ 57 | 58 | new_entry = malloc(sizeof(QueueEntry)); 59 | 60 | if (new_entry == NULL) { 61 | return 0; 62 | } 63 | 64 | new_entry->data = data; 65 | new_entry->prev = NULL; 66 | new_entry->next = queue->head; 67 | 68 | /* Insert into the queue */ 69 | 70 | if (queue->head == NULL) { 71 | 72 | /* If the queue was previously empty, both the head and 73 | * tail must be pointed at the new entry */ 74 | 75 | queue->head = new_entry; 76 | queue->tail = new_entry; 77 | 78 | } else { 79 | 80 | /* First entry in the list must have prev pointed back to this 81 | * new entry */ 82 | 83 | queue->head->prev = new_entry; 84 | 85 | /* Only the head must be pointed at the new entry */ 86 | 87 | queue->head = new_entry; 88 | } 89 | 90 | return 1; 91 | } 92 | 93 | QueueValue queue_pop_head(Queue *queue) { 94 | QueueEntry *entry; 95 | QueueValue result; 96 | 97 | /* Check the queue is not empty */ 98 | 99 | if (queue_is_empty(queue)) { 100 | return QUEUE_NULL; 101 | } 102 | 103 | /* Unlink the first entry from the head of the queue */ 104 | 105 | entry = queue->head; 106 | queue->head = entry->next; 107 | result = entry->data; 108 | 109 | if (queue->head == NULL) { 110 | 111 | /* If doing this has unlinked the last entry in the queue, set 112 | * tail to NULL as well. */ 113 | 114 | queue->tail = NULL; 115 | } else { 116 | 117 | /* The new first in the queue has no previous entry */ 118 | 119 | queue->head->prev = NULL; 120 | } 121 | 122 | /* Free back the queue entry structure */ 123 | 124 | free(entry); 125 | 126 | return result; 127 | } 128 | 129 | QueueValue queue_peek_head(Queue *queue) { 130 | if (queue_is_empty(queue)) { 131 | return QUEUE_NULL; 132 | } else { 133 | return queue->head->data; 134 | } 135 | } 136 | 137 | int queue_push_tail(Queue *queue, QueueValue data) { 138 | QueueEntry *new_entry; 139 | 140 | /* Create the new entry and fill in the fields in the structure */ 141 | 142 | new_entry = malloc(sizeof(QueueEntry)); 143 | 144 | if (new_entry == NULL) { 145 | return 0; 146 | } 147 | 148 | new_entry->data = data; 149 | new_entry->prev = queue->tail; 150 | new_entry->next = NULL; 151 | 152 | /* Insert into the queue tail */ 153 | 154 | if (queue->tail == NULL) { 155 | 156 | /* If the queue was previously empty, both the head and 157 | * tail must be pointed at the new entry */ 158 | 159 | queue->head = new_entry; 160 | queue->tail = new_entry; 161 | 162 | } else { 163 | 164 | /* The current entry at the tail must have next pointed to this 165 | * new entry */ 166 | 167 | queue->tail->next = new_entry; 168 | 169 | /* Only the tail must be pointed at the new entry */ 170 | 171 | queue->tail = new_entry; 172 | } 173 | 174 | return 1; 175 | } 176 | 177 | QueueValue queue_pop_tail(Queue *queue) { 178 | QueueEntry *entry; 179 | QueueValue result; 180 | 181 | /* Check the queue is not empty */ 182 | 183 | if (queue_is_empty(queue)) { 184 | return QUEUE_NULL; 185 | } 186 | 187 | /* Unlink the first entry from the tail of the queue */ 188 | 189 | entry = queue->tail; 190 | queue->tail = entry->prev; 191 | result = entry->data; 192 | 193 | if (queue->tail == NULL) { 194 | 195 | /* If doing this has unlinked the last entry in the queue, set 196 | * head to NULL as well. */ 197 | 198 | queue->head = NULL; 199 | 200 | } else { 201 | 202 | /* The new entry at the tail has no next entry. */ 203 | 204 | queue->tail->next = NULL; 205 | } 206 | 207 | /* Free back the queue entry structure */ 208 | 209 | free(entry); 210 | 211 | return result; 212 | } 213 | 214 | QueueValue queue_peek_tail(Queue *queue) { 215 | if (queue_is_empty(queue)) { 216 | return QUEUE_NULL; 217 | } else { 218 | return queue->tail->data; 219 | } 220 | } 221 | 222 | int queue_is_empty(Queue *queue) { 223 | return queue->head == NULL; 224 | } 225 | -------------------------------------------------------------------------------- /algorithms/binary-heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "binary-heap.h" 4 | 5 | /* malloc() / free() testing */ 6 | 7 | #ifdef ALLOC_TESTING 8 | #include "alloc-testing.h" 9 | #endif 10 | 11 | struct _BinaryHeap { 12 | BinaryHeapType heap_type; 13 | BinaryHeapValue *values; 14 | unsigned int num_values; 15 | unsigned int alloced_size; 16 | BinaryHeapCompareFunc compare_func; 17 | }; 18 | 19 | static int binary_heap_cmp(BinaryHeap *heap, BinaryHeapValue data1, 20 | BinaryHeapValue data2) { 21 | if (heap->heap_type == BINARY_HEAP_TYPE_MIN) { 22 | return heap->compare_func(data1, data2); 23 | } else { 24 | return -heap->compare_func(data1, data2); 25 | } 26 | } 27 | 28 | BinaryHeap *binary_heap_new(BinaryHeapType heap_type, 29 | BinaryHeapCompareFunc compare_func) { 30 | BinaryHeap *heap; 31 | 32 | heap = malloc(sizeof(BinaryHeap)); 33 | 34 | if (heap == NULL) { 35 | return NULL; 36 | } 37 | 38 | heap->heap_type = heap_type; 39 | heap->num_values = 0; 40 | heap->compare_func = compare_func; 41 | 42 | /* Initial size of 16 elements */ 43 | 44 | heap->alloced_size = 16; 45 | heap->values = malloc(sizeof(BinaryHeapValue) * heap->alloced_size); 46 | 47 | if (heap->values == NULL) { 48 | free(heap); 49 | return NULL; 50 | } 51 | 52 | return heap; 53 | } 54 | 55 | void binary_heap_free(BinaryHeap *heap) { 56 | free(heap->values); 57 | free(heap); 58 | } 59 | 60 | int binary_heap_insert(BinaryHeap *heap, BinaryHeapValue value) { 61 | BinaryHeapValue *new_values; 62 | unsigned int index; 63 | unsigned int new_size; 64 | unsigned int parent; 65 | 66 | /* Possibly realloc the heap to a larger size */ 67 | 68 | if (heap->num_values >= heap->alloced_size) { 69 | 70 | /* Double the table size */ 71 | 72 | new_size = heap->alloced_size * 2; 73 | new_values = realloc(heap->values, 74 | sizeof(BinaryHeapValue) * new_size); 75 | 76 | if (new_values == NULL) { 77 | return 0; 78 | } 79 | 80 | heap->alloced_size = new_size; 81 | heap->values = new_values; 82 | } 83 | 84 | /* Add to the bottom of the heap and start from there */ 85 | 86 | index = heap->num_values; 87 | ++heap->num_values; 88 | 89 | /* Percolate the value up to the top of the heap */ 90 | 91 | while (index > 0) { 92 | 93 | /* The parent index is found by halving the node index */ 94 | 95 | parent = (index - 1) / 2; 96 | 97 | /* Compare the node with its parent */ 98 | 99 | if (binary_heap_cmp(heap, heap->values[parent], value) < 0) { 100 | 101 | /* Ordered correctly - insertion is complete */ 102 | 103 | break; 104 | 105 | } else { 106 | 107 | /* Need to swap this node with its parent */ 108 | 109 | heap->values[index] = heap->values[parent]; 110 | 111 | /* Advance up to the parent */ 112 | 113 | index = parent; 114 | } 115 | } 116 | 117 | /* Save the new value in the final location */ 118 | 119 | heap->values[index] = value; 120 | 121 | return 1; 122 | } 123 | 124 | BinaryHeapValue binary_heap_pop(BinaryHeap *heap) { 125 | BinaryHeapValue result; 126 | BinaryHeapValue new_value; 127 | unsigned int index; 128 | unsigned int next_index; 129 | unsigned int child1, child2; 130 | 131 | /* Empty heap? */ 132 | 133 | if (heap->num_values == 0) { 134 | return BINARY_HEAP_NULL; 135 | } 136 | 137 | /* Take the value from the top of the heap */ 138 | 139 | result = heap->values[0]; 140 | 141 | /* Remove the last value from the heap; we will percolate this down 142 | * from the top. */ 143 | 144 | new_value = heap->values[heap->num_values - 1]; 145 | --heap->num_values; 146 | 147 | /* Percolate the new top value down */ 148 | 149 | index = 0; 150 | 151 | for (; ;) { 152 | 153 | /* Calculate the array indexes of the children of this node */ 154 | 155 | child1 = index * 2 + 1; 156 | child2 = index * 2 + 2; 157 | 158 | if (child1 < heap->num_values 159 | && binary_heap_cmp(heap, 160 | new_value, 161 | heap->values[child1]) > 0) { 162 | 163 | /* Left child is less than the node. We need to swap 164 | * with one of the children, whichever is less. */ 165 | 166 | if (child2 < heap->num_values 167 | && binary_heap_cmp(heap, 168 | heap->values[child1], 169 | heap->values[child2]) > 0) { 170 | next_index = child2; 171 | } else { 172 | next_index = child1; 173 | } 174 | 175 | } else if (child2 < heap->num_values 176 | && binary_heap_cmp(heap, 177 | new_value, 178 | heap->values[child2]) > 0) { 179 | 180 | /* Right child is less than the node. Swap with the 181 | * right child. */ 182 | 183 | next_index = child2; 184 | 185 | } else { 186 | /* Node is less than both its children. The heap 187 | * condition is satisfied. * We can stop percolating 188 | * down. */ 189 | 190 | heap->values[index] = new_value; 191 | break; 192 | } 193 | 194 | /* Swap the current node with the least of the child nodes. */ 195 | 196 | heap->values[index] = heap->values[next_index]; 197 | 198 | /* Advance to the child we chose */ 199 | 200 | index = next_index; 201 | } 202 | 203 | return result; 204 | } 205 | 206 | unsigned int binary_heap_num_entries(BinaryHeap *heap) { 207 | return heap->num_values; 208 | } 209 | -------------------------------------------------------------------------------- /algorithms/arraylist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "arraylist.h" 5 | 6 | /* malloc() / free() testing */ 7 | 8 | #ifdef ALLOC_TESTING 9 | #include "alloc-testing.h" 10 | #endif 11 | 12 | /* Automatically resizing array */ 13 | 14 | ArrayList *arraylist_new(unsigned int length) 15 | { 16 | ArrayList *new_arraylist; 17 | 18 | /* If the length is not specified, use a sensible default */ 19 | 20 | if (length <= 0) { 21 | length = 16; 22 | } 23 | 24 | /* Allocate the new ArrayList and fill in the fields. There are 25 | * initially no entries. */ 26 | 27 | new_arraylist = (ArrayList *) malloc(sizeof(ArrayList)); 28 | 29 | if (new_arraylist == NULL) { 30 | return NULL; 31 | } 32 | 33 | new_arraylist->_alloced = length; 34 | new_arraylist->length = 0; 35 | 36 | /* Allocate the data array */ 37 | 38 | new_arraylist->data = malloc(length * sizeof(ArrayListValue)); 39 | 40 | if (new_arraylist->data == NULL) { 41 | free(new_arraylist); 42 | return NULL; 43 | } 44 | 45 | return new_arraylist; 46 | } 47 | 48 | void arraylist_free(ArrayList *arraylist) 49 | { 50 | /* Do not free if a NULL pointer is passed */ 51 | 52 | if (arraylist != NULL) { 53 | free(arraylist->data); 54 | free(arraylist); 55 | } 56 | } 57 | 58 | static int arraylist_enlarge(ArrayList *arraylist) 59 | { 60 | ArrayListValue *data; 61 | unsigned int newsize; 62 | 63 | /* Double the allocated size */ 64 | 65 | newsize = arraylist->_alloced * 2; 66 | 67 | /* Reallocate the array to the new size */ 68 | 69 | data = realloc(arraylist->data, sizeof(ArrayListValue) * newsize); 70 | 71 | if (data == NULL) { 72 | return 0; 73 | } else { 74 | arraylist->data = data; 75 | arraylist->_alloced = newsize; 76 | 77 | return 1; 78 | } 79 | } 80 | 81 | int arraylist_insert(ArrayList *arraylist, unsigned int index, 82 | ArrayListValue data) 83 | { 84 | /* Sanity check the index */ 85 | 86 | if (index > arraylist->length) { 87 | return 0; 88 | } 89 | 90 | /* Increase the size if necessary */ 91 | 92 | if (arraylist->length + 1 > arraylist->_alloced) { 93 | if (!arraylist_enlarge(arraylist)) { 94 | return 0; 95 | } 96 | } 97 | 98 | /* Move the contents of the array forward from the index 99 | * onwards */ 100 | 101 | memmove(&arraylist->data[index + 1], 102 | &arraylist->data[index], 103 | (arraylist->length - index) * sizeof(ArrayListValue)); 104 | 105 | /* Insert the new entry at the index */ 106 | 107 | arraylist->data[index] = data; 108 | ++arraylist->length; 109 | 110 | return 1; 111 | } 112 | 113 | int arraylist_append(ArrayList *arraylist, ArrayListValue data) 114 | { 115 | return arraylist_insert(arraylist, arraylist->length, data); 116 | } 117 | 118 | int arraylist_prepend(ArrayList *arraylist, ArrayListValue data) 119 | { 120 | return arraylist_insert(arraylist, 0, data); 121 | } 122 | 123 | void arraylist_remove_range(ArrayList *arraylist, unsigned int index, 124 | unsigned int length) 125 | { 126 | /* Check this is a valid range */ 127 | 128 | if (index > arraylist->length || index + length > arraylist->length) { 129 | return; 130 | } 131 | 132 | /* Move back the entries following the range to be removed */ 133 | 134 | memmove(&arraylist->data[index], 135 | &arraylist->data[index + length], 136 | (arraylist->length - (index + length)) 137 | * sizeof(ArrayListValue)); 138 | 139 | /* Decrease the counter */ 140 | 141 | arraylist->length -= length; 142 | } 143 | 144 | void arraylist_remove(ArrayList *arraylist, unsigned int index) 145 | { 146 | arraylist_remove_range(arraylist, index, 1); 147 | } 148 | 149 | int arraylist_index_of(ArrayList *arraylist, 150 | ArrayListEqualFunc callback, 151 | ArrayListValue data) 152 | { 153 | unsigned int i; 154 | 155 | for (i=0; ilength; ++i) { 156 | if (callback(arraylist->data[i], data) != 0) 157 | return (int) i; 158 | } 159 | 160 | return -1; 161 | } 162 | 163 | void arraylist_clear(ArrayList *arraylist) 164 | { 165 | /* To clear the list, simply set the length to zero */ 166 | 167 | arraylist->length = 0; 168 | } 169 | 170 | static void arraylist_sort_internal(ArrayListValue *list_data, 171 | unsigned int list_length, 172 | ArrayListCompareFunc compare_func) 173 | { 174 | ArrayListValue pivot; 175 | ArrayListValue tmp; 176 | unsigned int i; 177 | unsigned int list1_length; 178 | unsigned int list2_length; 179 | 180 | /* If less than two items, it is always sorted. */ 181 | 182 | if (list_length <= 1) { 183 | return; 184 | } 185 | 186 | /* Take the last item as the pivot. */ 187 | 188 | pivot = list_data[list_length-1]; 189 | 190 | /* Divide the list into two lists: 191 | * 192 | * List 1 contains data less than the pivot. 193 | * List 2 contains data more than the pivot. 194 | * 195 | * As the lists are build up, they are stored sequentially after 196 | * each other, ie. list_data[list1_length-1] is the last item 197 | * in list 1, list_data[list1_length] is the first item in 198 | * list 2. 199 | */ 200 | 201 | list1_length = 0; 202 | 203 | for (i=0; idata, arraylist->length, 251 | compare_func); 252 | } 253 | -------------------------------------------------------------------------------- /algorithms/set.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file set.h 3 | * 4 | * @brief Set of values. 5 | * 6 | * A set stores a collection of values. Each value can only exist once in 7 | * the set. 8 | * 9 | * To create a new set, use @ref set_new. To destroy a set, use 10 | * @ref set_free. 11 | * 12 | * To add a value to a set, use @ref set_insert. To remove a value 13 | * from a set, use @ref set_remove. 14 | * 15 | * To find the number of entries in a set, use @ref set_num_entries. 16 | * 17 | * To query if a particular value is in a set, use @ref set_query. 18 | * 19 | * To iterate over all values in a set, use @ref set_iterate to initialise 20 | * a @ref SetIterator structure, with @ref set_iter_next and 21 | * @ref set_iter_has_more to read each value in turn. 22 | * 23 | * Two sets can be combined (union) using @ref set_union, while the 24 | * intersection of two sets can be generated using @ref set_intersection. 25 | */ 26 | 27 | #ifndef ALGORITHM_SET_H 28 | #define ALGORITHM_SET_H 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** 35 | * Represents a set of values. Created using the @ref set_new function and 36 | * destroyed using the @ref set_free function. 37 | */ 38 | 39 | typedef struct _Set Set; 40 | 41 | /** 42 | * An object used to iterate over a set. 43 | * 44 | * @see set_iterate 45 | */ 46 | 47 | typedef struct _SetIterator SetIterator; 48 | 49 | /** 50 | * Internal structure representing an entry in the set. 51 | */ 52 | 53 | typedef struct _SetEntry SetEntry; 54 | 55 | /** 56 | * A value stored in a @ref Set. 57 | */ 58 | 59 | typedef void *SetValue; 60 | 61 | /** 62 | * Definition of a @ref SetIterator. 63 | */ 64 | 65 | struct _SetIterator { 66 | Set *set; 67 | SetEntry *next_entry; 68 | unsigned int next_chain; 69 | }; 70 | 71 | /** 72 | * A null @ref SetValue. 73 | */ 74 | 75 | #define SET_NULL ((void *) 0) 76 | 77 | /** 78 | * Hash function. Generates a hash key for values to be stored in a set. 79 | */ 80 | 81 | typedef unsigned int (*SetHashFunc)(SetValue value); 82 | 83 | /** 84 | * Equality function. Compares two values to determine if they are 85 | * equivalent. 86 | */ 87 | 88 | typedef int (*SetEqualFunc)(SetValue value1, SetValue value2); 89 | 90 | /** 91 | * Function used to free values stored in a set. See 92 | * @ref set_register_free_function. 93 | */ 94 | 95 | typedef void (*SetFreeFunc)(SetValue value); 96 | 97 | /** 98 | * Create a new set. 99 | * 100 | * @param hash_func Hash function used on values in the set. 101 | * @param equal_func Compares two values in the set to determine 102 | * if they are equal. 103 | * @return A new set, or NULL if it was not possible to 104 | * allocate the memory for the set. 105 | */ 106 | 107 | Set *set_new(SetHashFunc hash_func, SetEqualFunc equal_func); 108 | 109 | /** 110 | * Destroy a set. 111 | * 112 | * @param set The set to destroy. 113 | */ 114 | 115 | void set_free(Set *set); 116 | 117 | /** 118 | * Register a function to be called when values are removed from 119 | * the set. 120 | * 121 | * @param set The set. 122 | * @param free_func Function to call when values are removed from the 123 | * set. 124 | */ 125 | 126 | void set_register_free_function(Set *set, SetFreeFunc free_func); 127 | 128 | /** 129 | * Add a value to a set. 130 | * 131 | * @param set The set. 132 | * @param data The value to add to the set. 133 | * @return Non-zero (true) if the value was added to the set, 134 | * zero (false) if it already exists in the set, or 135 | * if it was not possible to allocate memory for the 136 | * new entry. 137 | */ 138 | 139 | int set_insert(Set *set, SetValue data); 140 | 141 | /** 142 | * Remove a value from a set. 143 | * 144 | * @param set The set. 145 | * @param data The value to remove from the set. 146 | * @return Non-zero (true) if the value was found and removed 147 | * from the set, zero (false) if the value was not 148 | * found in the set. 149 | */ 150 | 151 | int set_remove(Set *set, SetValue data); 152 | 153 | /** 154 | * Query if a particular value is in a set. 155 | * 156 | * @param set The set. 157 | * @param data The value to query for. 158 | * @return Zero if the value is not in the set, non-zero if the 159 | * value is in the set. 160 | */ 161 | 162 | int set_query(Set *set, SetValue data); 163 | 164 | /** 165 | * Retrieve the number of entries in a set 166 | * 167 | * @param set The set. 168 | * @return A count of the number of entries in the set. 169 | */ 170 | 171 | unsigned int set_num_entries(Set *set); 172 | 173 | /** 174 | * Create an array containing all entries in a set. 175 | * 176 | * @param set The set. 177 | * @return An array containing all entries in the set, 178 | * or NULL if it was not possible to allocate 179 | * memory for the array. 180 | */ 181 | 182 | SetValue *set_to_array(Set *set); 183 | 184 | /** 185 | * Perform a union of two sets. 186 | * 187 | * @param set1 The first set. 188 | * @param set2 The second set. 189 | * @return A new set containing all values which are in the 190 | * first or second sets, or NULL if it was not 191 | * possible to allocate memory for the new set. 192 | */ 193 | 194 | Set *set_union(Set *set1, Set *set2); 195 | 196 | /** 197 | * Perform an intersection of two sets. 198 | * 199 | * @param set1 The first set. 200 | * @param set2 The second set. 201 | * @return A new set containing all values which are in both 202 | * set, or NULL if it was not possible to allocate 203 | * memory for the new set. 204 | */ 205 | 206 | Set *set_intersection(Set *set1, Set *set2); 207 | 208 | /** 209 | * Initialise a @ref SetIterator structure to iterate over the values 210 | * in a set. 211 | * 212 | * @param set The set to iterate over. 213 | * @param iter Pointer to an iterator structure to initialise. 214 | */ 215 | 216 | void set_iterate(Set *set, SetIterator *iter); 217 | 218 | /** 219 | * Determine if there are more values in the set to iterate over. 220 | * 221 | * @param iterator The set iterator object. 222 | * @return Zero if there are no more values in the set 223 | * to iterate over, non-zero if there are more 224 | * values to be read. 225 | */ 226 | 227 | int set_iter_has_more(SetIterator *iterator); 228 | 229 | /** 230 | * Using a set iterator, retrieve the next value from the set. 231 | * 232 | * @param iterator The set iterator. 233 | * @return The next value from the set, or @ref SET_NULL if no 234 | * more values are available. 235 | */ 236 | 237 | SetValue set_iter_next(SetIterator *iterator); 238 | 239 | #ifdef __cplusplus 240 | } 241 | #endif 242 | 243 | #endif /* #ifndef ALGORITHM_SET_H */ 244 | -------------------------------------------------------------------------------- /algorithms/hash-table.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hash-table.h 3 | * 4 | * @brief Hash table. 5 | * 6 | * A hash table stores a set of values which can be addressed by a 7 | * key. Given the key, the corresponding value can be looked up 8 | * quickly. 9 | * 10 | * To create a hash table, use @ref hash_table_new. To destroy a 11 | * hash table, use @ref hash_table_free. 12 | * 13 | * To insert a value into a hash table, use @ref hash_table_insert. 14 | * 15 | * To remove a value from a hash table, use @ref hash_table_remove. 16 | * 17 | * To look up a value by its key, use @ref hash_table_lookup. 18 | * 19 | * To iterate over all values in a hash table, use 20 | * @ref hash_table_iterate to initialise a @ref HashTableIterator 21 | * structure. Each value can then be read in turn using 22 | * @ref hash_table_iter_next and @ref hash_table_iter_has_more. 23 | */ 24 | 25 | #ifndef ALGORITHM_HASH_TABLE_H 26 | #define ALGORITHM_HASH_TABLE_H 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /** 33 | * A hash table structure. 34 | */ 35 | 36 | typedef struct _HashTable HashTable; 37 | 38 | /** 39 | * Structure used to iterate over a hash table. 40 | */ 41 | 42 | typedef struct _HashTableIterator HashTableIterator; 43 | 44 | /** 45 | * Internal structure representing an entry in a hash table. 46 | */ 47 | 48 | typedef struct _HashTableEntry HashTableEntry; 49 | 50 | /** 51 | * A key to look up a value in a @ref HashTable. 52 | */ 53 | 54 | typedef void *HashTableKey; 55 | 56 | /** 57 | * A value stored in a @ref HashTable. 58 | */ 59 | 60 | typedef void *HashTableValue; 61 | 62 | /** 63 | * Internal structure representing an entry in hash table 64 | * used as @ref HashTableIterator next result. 65 | */ 66 | 67 | typedef struct _HashTablePair { 68 | HashTableKey key; 69 | HashTableValue value; 70 | } HashTablePair; 71 | 72 | /** 73 | * Definition of a @ref HashTableIterator. 74 | */ 75 | 76 | struct _HashTableIterator { 77 | HashTable *hash_table; 78 | HashTableEntry *next_entry; 79 | unsigned int next_chain; 80 | }; 81 | 82 | /** 83 | * A null @ref HashTableValue. 84 | */ 85 | 86 | #define HASH_TABLE_NULL ((void *) 0) 87 | 88 | /** 89 | * Hash function used to generate hash values for keys used in a hash 90 | * table. 91 | * 92 | * @param value The value to generate a hash value for. 93 | * @return The hash value. 94 | */ 95 | 96 | typedef unsigned int (*HashTableHashFunc)(HashTableKey value); 97 | 98 | /** 99 | * Function used to compare two keys for equality. 100 | * 101 | * @return Non-zero if the two keys are equal, zero if the keys are 102 | * not equal. 103 | */ 104 | 105 | typedef int (*HashTableEqualFunc)(HashTableKey value1, HashTableKey value2); 106 | 107 | /** 108 | * Type of function used to free keys when entries are removed from a 109 | * hash table. 110 | */ 111 | 112 | typedef void (*HashTableKeyFreeFunc)(HashTableKey value); 113 | 114 | /** 115 | * Type of function used to free values when entries are removed from a 116 | * hash table. 117 | */ 118 | 119 | typedef void (*HashTableValueFreeFunc)(HashTableValue value); 120 | 121 | /** 122 | * Create a new hash table. 123 | * 124 | * @param hash_func Function used to generate hash keys for the 125 | * keys used in the table. 126 | * @param equal_func Function used to test keys used in the table 127 | * for equality. 128 | * @return A new hash table structure, or NULL if it 129 | * was not possible to allocate the new hash 130 | * table. 131 | */ 132 | 133 | HashTable *hash_table_new(HashTableHashFunc hash_func, 134 | HashTableEqualFunc equal_func); 135 | 136 | /** 137 | * Destroy a hash table. 138 | * 139 | * @param hash_table The hash table to destroy. 140 | */ 141 | 142 | void hash_table_free(HashTable *hash_table); 143 | 144 | /** 145 | * Register functions used to free the key and value when an entry is 146 | * removed from a hash table. 147 | * 148 | * @param hash_table The hash table. 149 | * @param key_free_func Function used to free keys. 150 | * @param value_free_func Function used to free values. 151 | */ 152 | 153 | void hash_table_register_free_functions(HashTable *hash_table, 154 | HashTableKeyFreeFunc key_free_func, 155 | HashTableValueFreeFunc value_free_func); 156 | 157 | /** 158 | * Insert a value into a hash table, overwriting any existing entry 159 | * using the same key. 160 | * 161 | * @param hash_table The hash table. 162 | * @param key The key for the new value. 163 | * @param value The value to insert. 164 | * @return Non-zero if the value was added successfully, 165 | * or zero if it was not possible to allocate 166 | * memory for the new entry. 167 | */ 168 | 169 | int hash_table_insert(HashTable *hash_table, 170 | HashTableKey key, 171 | HashTableValue value); 172 | 173 | /** 174 | * Look up a value in a hash table by key. 175 | * 176 | * @param hash_table The hash table. 177 | * @param key The key of the value to look up. 178 | * @return The value, or @ref HASH_TABLE_NULL if there 179 | * is no value with that key in the hash table. 180 | */ 181 | 182 | HashTableValue hash_table_lookup(HashTable *hash_table, 183 | HashTableKey key); 184 | 185 | /** 186 | * Remove a value from a hash table. 187 | * 188 | * @param hash_table The hash table. 189 | * @param key The key of the value to remove. 190 | * @return Non-zero if a key was removed, or zero if the 191 | * specified key was not found in the hash table. 192 | */ 193 | 194 | int hash_table_remove(HashTable *hash_table, HashTableKey key); 195 | 196 | /** 197 | * Retrieve the number of entries in a hash table. 198 | * 199 | * @param hash_table The hash table. 200 | * @return The number of entries in the hash table. 201 | */ 202 | 203 | unsigned int hash_table_num_entries(HashTable *hash_table); 204 | 205 | /** 206 | * Initialise a @ref HashTableIterator to iterate over a hash table. 207 | * 208 | * @param hash_table The hash table. 209 | * @param iter Pointer to an iterator structure to 210 | * initialise. 211 | */ 212 | 213 | void hash_table_iterate(HashTable *hash_table, HashTableIterator *iter); 214 | 215 | /** 216 | * Determine if there are more keys in the hash table to iterate 217 | * over. 218 | * 219 | * @param iterator The hash table iterator. 220 | * @return Zero if there are no more values to iterate 221 | * over, non-zero if there are more values to 222 | * iterate over. 223 | */ 224 | 225 | int hash_table_iter_has_more(HashTableIterator *iterator); 226 | 227 | /** 228 | * Using a hash table iterator, retrieve the next @ref HashTablePair. 229 | * 230 | * Note: To avoid @ref HashTableEntry internal @ref HashTablePair 231 | * from being tampered with, and potentially messing with 232 | * internal table structure, the function returns a copy 233 | * of @ref HashTablePair stored internally. 234 | * 235 | * @param iterator The hash table iterator. 236 | * @return The next @ref HashTablePair from the hash 237 | * table, or @ref HASH_TABLE_NULL of Key and 238 | * Value if there are no more keys to iterate 239 | * over. 240 | */ 241 | 242 | HashTablePair hash_table_iter_next(HashTableIterator *iterator); 243 | 244 | #ifdef __cplusplus 245 | } 246 | #endif 247 | 248 | #endif /* #ifndef ALGORITHM_HASH_TABLE_H */ 249 | -------------------------------------------------------------------------------- /algorithms/rb-tree.h: -------------------------------------------------------------------------------- 1 | /** @file rbtree.h 2 | * 3 | * @brief Balanced binary tree 4 | * 5 | * The red-black tree structure is a balanced binary tree which stores 6 | * a collection of nodes (see @ref RBTreeNode). Each node has 7 | * a key and a value associated with it. The nodes are sorted 8 | * within the tree based on the order of their keys. Modifications 9 | * to the tree are constructed such that the tree remains 10 | * balanced at all times (there are always roughly equal numbers 11 | * of nodes on either side of the tree). 12 | * 13 | * Balanced binary trees have several uses. They can be used 14 | * as a mapping (searching for a value based on its key), or 15 | * as a set of keys which is always ordered. 16 | * 17 | * To create a new red-black tree, use @ref rb_tree_new. To destroy 18 | * a red-black tree, use @ref rb_tree_free. 19 | * 20 | * To insert a new key-value pair into a red-black tree, use 21 | * @ref rb_tree_insert. To remove an entry from a 22 | * red-black tree, use @ref rb_tree_remove or @ref rb_tree_remove_node. 23 | * 24 | * To search a red-black tree, use @ref rb_tree_lookup or 25 | * @ref rb_tree_lookup_node. 26 | * 27 | * Tree nodes can be queried using the 28 | * @ref rb_tree_node_left_child, 29 | * @ref rb_tree_node_right_child, 30 | * @ref rb_tree_node_parent, 31 | * @ref rb_tree_node_key and 32 | * @ref rb_tree_node_value functions. 33 | */ 34 | 35 | #ifndef ALGORITHM_RB_TREE_H 36 | #define ALGORITHM_RB_TREE_H 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /** 43 | * A red-black tree balanced binary tree. 44 | * 45 | * @see rb_tree_new 46 | */ 47 | 48 | typedef struct _RBTree RBTree; 49 | 50 | /** 51 | * A key for an @ref RBTree. 52 | */ 53 | 54 | typedef void *RBTreeKey; 55 | 56 | /** 57 | * A value stored in an @ref RBTree. 58 | */ 59 | 60 | typedef void *RBTreeValue; 61 | 62 | /** 63 | * A null @ref RBTreeValue. 64 | */ 65 | 66 | #define RB_TREE_NULL ((void *) 0) 67 | 68 | /** 69 | * A node in a red-black tree. 70 | * 71 | * @see rb_tree_node_left_child 72 | * @see rb_tree_node_right_child 73 | * @see rb_tree_node_parent 74 | * @see rb_tree_node_key 75 | * @see rb_tree_node_value 76 | */ 77 | 78 | typedef struct _RBTreeNode RBTreeNode; 79 | 80 | /** 81 | * Type of function used to compare keys in a red-black tree. 82 | * 83 | * @param data1 The first key. 84 | * @param data2 The second key. 85 | * @return A negative number if data1 should be sorted 86 | * before data2, a positive number if data2 should 87 | * be sorted before data1, zero if the two keys 88 | * are equal. 89 | */ 90 | 91 | typedef int (*RBTreeCompareFunc)(RBTreeValue data1, RBTreeValue data2); 92 | 93 | /** 94 | * Each node in a red-black tree is either red or black. 95 | */ 96 | 97 | typedef enum { 98 | RB_TREE_NODE_RED, 99 | RB_TREE_NODE_BLACK, 100 | } RBTreeNodeColor; 101 | 102 | /** 103 | * A @ref RBTreeNode can have left and right children. 104 | */ 105 | 106 | typedef enum { 107 | RB_TREE_NODE_LEFT = 0, 108 | RB_TREE_NODE_RIGHT = 1 109 | } RBTreeNodeSide; 110 | 111 | /** 112 | * Create a new red-black tree. 113 | * 114 | * @param compare_func Function to use when comparing keys in the tree. 115 | * @return A new red-black tree, or NULL if it was not possible 116 | * to allocate the memory. 117 | */ 118 | 119 | RBTree *rb_tree_new(RBTreeCompareFunc compare_func); 120 | 121 | /** 122 | * Destroy a red-black tree. 123 | * 124 | * @param tree The tree to destroy. 125 | */ 126 | 127 | void rb_tree_free(RBTree *tree); 128 | 129 | /** 130 | * Insert a new key-value pair into a red-black tree. 131 | * 132 | * @param tree The tree. 133 | * @param key The key to insert. 134 | * @param value The value to insert. 135 | * @return The newly created tree node containing the 136 | * key and value, or NULL if it was not possible 137 | * to allocate the new memory. 138 | */ 139 | 140 | RBTreeNode *rb_tree_insert(RBTree *tree, RBTreeKey key, RBTreeValue value); 141 | 142 | /** 143 | * Remove a node from a tree. 144 | * 145 | * @param tree The tree. 146 | * @param node The node to remove 147 | */ 148 | 149 | void rb_tree_remove_node(RBTree *tree, RBTreeNode *node); 150 | 151 | /** 152 | * Remove an entry from a tree, specifying the key of the node to 153 | * remove. 154 | * 155 | * @param tree The tree. 156 | * @param key The key of the node to remove. 157 | * @return Zero (false) if no node with the specified key was 158 | * found in the tree, non-zero (true) if a node with 159 | * the specified key was removed. 160 | */ 161 | 162 | int rb_tree_remove(RBTree *tree, RBTreeKey key); 163 | 164 | /** 165 | * Search a red-black tree for a node with a particular key. This uses 166 | * the tree as a mapping. 167 | * 168 | * @param tree The red-black tree to search. 169 | * @param key The key to search for. 170 | * @return The tree node containing the given key, or NULL 171 | * if no entry with the given key is found. 172 | */ 173 | 174 | RBTreeNode *rb_tree_lookup_node(RBTree *tree, RBTreeKey key); 175 | 176 | /** 177 | * Search a red-black tree for a value corresponding to a particular key. 178 | * This uses the tree as a mapping. Note that this performs 179 | * identically to @ref rb_tree_lookup_node, except that the value 180 | * at the node is returned rather than the node itself. 181 | * 182 | * @param tree The red-black tree to search. 183 | * @param key The key to search for. 184 | * @return The value associated with the given key, or 185 | * RB_TREE_NULL if no entry with the given key is 186 | * found. 187 | */ 188 | 189 | RBTreeValue rb_tree_lookup(RBTree *tree, RBTreeKey key); 190 | 191 | /** 192 | * Find the root node of a tree. 193 | * 194 | * @param tree The tree. 195 | * @return The root node of the tree, or NULL if the tree is 196 | * empty. 197 | */ 198 | 199 | RBTreeNode *rb_tree_root_node(RBTree *tree); 200 | 201 | /** 202 | * Retrieve the key for a given tree node. 203 | * 204 | * @param node The tree node. 205 | * @return The key to the given node. 206 | */ 207 | 208 | RBTreeKey rb_tree_node_key(RBTreeNode *node); 209 | 210 | /** 211 | * Retrieve the value at a given tree node. 212 | * 213 | * @param node The tree node. 214 | * @return The value at the given node. 215 | */ 216 | 217 | RBTreeValue rb_tree_node_value(RBTreeNode *node); 218 | 219 | /** 220 | * Get a child of a given tree node. 221 | * 222 | * @param node The tree node. 223 | * @param side The side relative to the node. 224 | * @return The child of the tree node, or NULL if the 225 | * node has no child on the specified side. 226 | */ 227 | 228 | RBTreeNode *rb_tree_node_child(RBTreeNode *node, RBTreeNodeSide side); 229 | 230 | /** 231 | * Find the parent node of a given tree node. 232 | * 233 | * @param node The tree node. 234 | * @return The parent node of the tree node, or NULL if 235 | * this is the root node. 236 | */ 237 | 238 | RBTreeNode *rb_tree_node_parent(RBTreeNode *node); 239 | 240 | /** 241 | * Find the height of a subtree. 242 | * 243 | * @param node The root node of the subtree. 244 | * @return The height of the subtree. 245 | */ 246 | 247 | int rb_tree_subtree_height(RBTreeNode *node); 248 | 249 | /** 250 | * Convert the keys in a red-black tree into a C array. This allows 251 | * the tree to be used as an ordered set. 252 | * 253 | * @param tree The tree. 254 | * @return A newly allocated C array containing all the keys 255 | * in the tree, in order. The length of the array 256 | * is equal to the number of entries in the tree 257 | * (see @ref rb_tree_num_entries). 258 | */ 259 | 260 | RBTreeValue *rb_tree_to_array(RBTree *tree); 261 | 262 | /** 263 | * Retrieve the number of entries in the tree. 264 | * 265 | * @param tree The tree. 266 | * @return The number of key-value pairs stored in the tree. 267 | */ 268 | 269 | int rb_tree_num_entries(RBTree *tree); 270 | 271 | #ifdef __cplusplus 272 | } 273 | #endif 274 | 275 | #endif /* #ifndef ALGORITHM_RB_TREE_H */ 276 | 277 | -------------------------------------------------------------------------------- /algorithms/bloom-filter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "bloom-filter.h" 5 | 6 | /* malloc() / free() testing */ 7 | 8 | #ifdef ALLOC_TESTING 9 | #include "alloc-testing.h" 10 | #endif 11 | 12 | struct _BloomFilter { 13 | BloomFilterHashFunc hash_func; 14 | unsigned char *table; 15 | unsigned int table_size; 16 | unsigned int num_functions; 17 | }; 18 | 19 | /* Salt values. These salts are XORed with the output of the hash function to 20 | * give multiple unique hashes. 21 | * 22 | * These are "nothing up my sleeve" numbers: they are derived from the first 23 | * 256 numbers in the book "A Million Random Digits with 100,000 Normal 24 | * Deviates" published by the RAND corporation, ISBN 0-8330-3047-7. 25 | * 26 | * The numbers here were derived by taking each number from the book in turn, 27 | * then multiplying by 256 and dividing by 100,000 to give a byte range value. 28 | * Groups of four numbers were then combined to give 32-bit integers, most 29 | * significant byte first. 30 | */ 31 | 32 | static const unsigned int salts[] = { 33 | 0x1953c322, 0x588ccf17, 0x64bf600c, 0xa6be3f3d, 34 | 0x341a02ea, 0x15b03217, 0x3b062858, 0x5956fd06, 35 | 0x18b5624f, 0xe3be0b46, 0x20ffcd5c, 0xa35dfd2b, 36 | 0x1fc4a9bf, 0x57c45d5c, 0xa8661c4a, 0x4f1b74d2, 37 | 0x5a6dde13, 0x3b18dac6, 0x05a8afbf, 0xbbda2fe2, 38 | 0xa2520d78, 0xe7934849, 0xd541bc75, 0x09a55b57, 39 | 0x9b345ae2, 0xfc2d26af, 0x38679cef, 0x81bd1e0d, 40 | 0x654681ae, 0x4b3d87ad, 0xd5ff10fb, 0x23b32f67, 41 | 0xafc7e366, 0xdd955ead, 0xe7c34b1c, 0xfeace0a6, 42 | 0xeb16f09d, 0x3c57a72d, 0x2c8294c5, 0xba92662a, 43 | 0xcd5b2d14, 0x743936c8, 0x2489beff, 0xc6c56e00, 44 | 0x74a4f606, 0xb244a94a, 0x5edfc423, 0xf1901934, 45 | 0x24af7691, 0xf6c98b25, 0xea25af46, 0x76d5f2e6, 46 | 0x5e33cdf2, 0x445eb357, 0x88556bd2, 0x70d1da7a, 47 | 0x54449368, 0x381020bc, 0x1c0520bf, 0xf7e44942, 48 | 0xa27e2a58, 0x66866fc5, 0x12519ce7, 0x437a8456, 49 | }; 50 | 51 | BloomFilter *bloom_filter_new(unsigned int table_size, 52 | BloomFilterHashFunc hash_func, 53 | unsigned int num_functions) { 54 | BloomFilter *filter; 55 | 56 | /* There is a limit on the number of functions which can be 57 | * applied, due to the table size */ 58 | 59 | if (num_functions > sizeof(salts) / sizeof(*salts)) { 60 | return NULL; 61 | } 62 | 63 | /* Allocate bloom filter structure */ 64 | 65 | filter = malloc(sizeof(BloomFilter)); 66 | 67 | if (filter == NULL) { 68 | return NULL; 69 | } 70 | 71 | /* Allocate table, each entry is one bit; these are packed into 72 | * bytes. When allocating we must round the length up to the nearest 73 | * byte. */ 74 | 75 | filter->table = calloc((table_size + 7) / 8, 1); 76 | 77 | if (filter->table == NULL) { 78 | free(filter); 79 | return NULL; 80 | } 81 | 82 | filter->hash_func = hash_func; 83 | filter->num_functions = num_functions; 84 | filter->table_size = table_size; 85 | 86 | return filter; 87 | } 88 | 89 | void bloom_filter_free(BloomFilter *bloomfilter) { 90 | free(bloomfilter->table); 91 | free(bloomfilter); 92 | } 93 | 94 | void bloom_filter_insert(BloomFilter *bloomfilter, BloomFilterValue value) { 95 | unsigned int hash; 96 | unsigned int subhash; 97 | unsigned int index; 98 | unsigned int i; 99 | unsigned char b; 100 | 101 | /* Generate hash of the value to insert */ 102 | 103 | hash = bloomfilter->hash_func(value); 104 | 105 | /* Generate multiple unique hashes by XORing with values in the 106 | * salt table. */ 107 | 108 | for (i = 0; i < bloomfilter->num_functions; ++i) { 109 | 110 | /* Generate a unique hash */ 111 | 112 | subhash = hash ^ salts[i]; 113 | 114 | /* Find the index into the table */ 115 | 116 | index = subhash % bloomfilter->table_size; 117 | 118 | /* Insert into the table. 119 | * index / 8 finds the byte index of the table, 120 | * index % 8 gives the bit index within that byte to set. */ 121 | 122 | b = (unsigned char) (1 << (index % 8)); 123 | bloomfilter->table[index / 8] |= b; 124 | } 125 | } 126 | 127 | int bloom_filter_query(BloomFilter *bloomfilter, BloomFilterValue value) { 128 | unsigned int hash; 129 | unsigned int subhash; 130 | unsigned int index; 131 | unsigned int i; 132 | unsigned char b; 133 | int bit; 134 | 135 | /* Generate hash of the value to lookup */ 136 | 137 | hash = bloomfilter->hash_func(value); 138 | 139 | /* Generate multiple unique hashes by XORing with values in the 140 | * salt table. */ 141 | 142 | for (i = 0; i < bloomfilter->num_functions; ++i) { 143 | 144 | /* Generate a unique hash */ 145 | 146 | subhash = hash ^ salts[i]; 147 | 148 | /* Find the index into the table to test */ 149 | 150 | index = subhash % bloomfilter->table_size; 151 | 152 | /* The byte at index / 8 holds the value to test */ 153 | 154 | b = bloomfilter->table[index / 8]; 155 | bit = 1 << (index % 8); 156 | 157 | /* Test if the particular bit is set; if it is not set, 158 | * this value can not have been inserted. */ 159 | 160 | if ((b & bit) == 0) { 161 | return 0; 162 | } 163 | } 164 | 165 | /* All necessary bits were set. This may indicate that the value 166 | * was inserted, or the values could have been set through other 167 | * insertions. */ 168 | 169 | return 1; 170 | } 171 | 172 | void bloom_filter_read(BloomFilter *bloomfilter, unsigned char *array) { 173 | unsigned int array_size; 174 | 175 | /* The table is an array of bits, packed into bytes. Round up 176 | * to the nearest byte. */ 177 | 178 | array_size = (bloomfilter->table_size + 7) / 8; 179 | 180 | /* Copy into the buffer of the calling routine. */ 181 | 182 | memcpy(array, bloomfilter->table, array_size); 183 | } 184 | 185 | void bloom_filter_load(BloomFilter *bloomfilter, unsigned char *array) { 186 | unsigned int array_size; 187 | 188 | /* The table is an array of bits, packed into bytes. Round up 189 | * to the nearest byte. */ 190 | 191 | array_size = (bloomfilter->table_size + 7) / 8; 192 | 193 | /* Copy from the buffer of the calling routine. */ 194 | 195 | memcpy(bloomfilter->table, array, array_size); 196 | } 197 | 198 | BloomFilter *bloom_filter_union(BloomFilter *filter1, BloomFilter *filter2) { 199 | BloomFilter *result; 200 | unsigned int i; 201 | unsigned int array_size; 202 | 203 | /* To perform this operation, both filters must be created with 204 | * the same values. */ 205 | 206 | if (filter1->table_size != filter2->table_size 207 | || filter1->num_functions != filter2->num_functions 208 | || filter1->hash_func != filter2->hash_func) { 209 | return NULL; 210 | } 211 | 212 | /* Create a new bloom filter for the result */ 213 | 214 | result = bloom_filter_new(filter1->table_size, 215 | filter1->hash_func, 216 | filter1->num_functions); 217 | 218 | if (result == NULL) { 219 | return NULL; 220 | } 221 | 222 | /* The table is an array of bits, packed into bytes. Round up 223 | * to the nearest byte. */ 224 | 225 | array_size = (filter1->table_size + 7) / 8; 226 | 227 | /* Populate the table of the new filter */ 228 | 229 | for (i = 0; i < array_size; ++i) { 230 | result->table[i] = filter1->table[i] | filter2->table[i]; 231 | } 232 | 233 | return result; 234 | } 235 | 236 | BloomFilter *bloom_filter_intersection(BloomFilter *filter1, 237 | BloomFilter *filter2) { 238 | BloomFilter *result; 239 | unsigned int i; 240 | unsigned int array_size; 241 | 242 | /* To perform this operation, both filters must be created with 243 | * the same values. */ 244 | 245 | if (filter1->table_size != filter2->table_size 246 | || filter1->num_functions != filter2->num_functions 247 | || filter1->hash_func != filter2->hash_func) { 248 | return NULL; 249 | } 250 | 251 | /* Create a new bloom filter for the result */ 252 | 253 | result = bloom_filter_new(filter1->table_size, 254 | filter1->hash_func, 255 | filter1->num_functions); 256 | 257 | if (result == NULL) { 258 | return NULL; 259 | } 260 | 261 | /* The table is an array of bits, packed into bytes. Round up 262 | * to the nearest byte. */ 263 | 264 | array_size = (filter1->table_size + 7) / 8; 265 | 266 | /* Populate the table of the new filter */ 267 | 268 | for (i = 0; i < array_size; ++i) { 269 | result->table[i] = filter1->table[i] & filter2->table[i]; 270 | } 271 | 272 | return result; 273 | } 274 | -------------------------------------------------------------------------------- /algorithms/list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file list.h 3 | * 4 | * @brief Doubly-linked list. 5 | * 6 | * A doubly-linked list stores a collection of values. Each entry in 7 | * the list (represented by a pointer a @ref ListEntry structure) 8 | * contains a link to the next entry and the previous entry. 9 | * It is therefore possible to iterate over entries in the list in either 10 | * direction. 11 | * 12 | * To create an empty list, create a new variable which is a pointer to 13 | * a @ref ListEntry structure, and initialise it to NULL. 14 | * To destroy an entire list, use @ref list_free. 15 | * 16 | * To add a value to a list, use @ref list_append or @ref list_prepend. 17 | * 18 | * To remove a value from a list, use @ref list_remove_entry or 19 | * @ref list_remove_data. 20 | * 21 | * To iterate over entries in a list, use @ref list_iterate to initialise 22 | * a @ref ListIterator structure, with @ref list_iter_next and 23 | * @ref list_iter_has_more to retrieve each value in turn. 24 | * @ref list_iter_remove can be used to remove the current entry. 25 | * 26 | * To access an entry in the list by index, use @ref list_nth_entry or 27 | * @ref list_nth_data. 28 | * 29 | * To sort a list, use @ref list_sort. 30 | * 31 | */ 32 | 33 | #ifndef ALGORITHM_LIST_H 34 | #define ALGORITHM_LIST_H 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** 41 | * Represents an entry in a doubly-linked list. The empty list is 42 | * represented by a NULL pointer. To initialise a new doubly linked 43 | * list, simply create a variable of this type 44 | * containing a pointer to NULL. 45 | */ 46 | 47 | typedef struct _ListEntry ListEntry; 48 | 49 | /** 50 | * Structure used to iterate over a list. 51 | */ 52 | 53 | typedef struct _ListIterator ListIterator; 54 | 55 | /** 56 | * A value stored in a list. 57 | */ 58 | 59 | typedef void *ListValue; 60 | 61 | /** 62 | * Definition of a @ref ListIterator. 63 | */ 64 | 65 | struct _ListIterator { 66 | ListEntry **prev_next; 67 | ListEntry *current; 68 | }; 69 | 70 | /** 71 | * A null @ref ListValue. 72 | */ 73 | 74 | #define LIST_NULL ((void *) 0) 75 | 76 | /** 77 | * Callback function used to compare values in a list when sorting. 78 | * 79 | * @param value1 The first value to compare. 80 | * @param value2 The second value to compare. 81 | * @return A negative value if value1 should be sorted before 82 | * value2, a positive value if value1 should be sorted 83 | * after value2, zero if value1 and value2 are equal. 84 | */ 85 | 86 | typedef int (*ListCompareFunc)(ListValue value1, ListValue value2); 87 | 88 | /** 89 | * Callback function used to determine of two values in a list are 90 | * equal. 91 | * 92 | * @param value1 The first value to compare. 93 | * @param value2 The second value to compare. 94 | * @return A non-zero value if value1 and value2 are equal, zero 95 | * if they are not equal. 96 | */ 97 | 98 | typedef int (*ListEqualFunc)(ListValue value1, ListValue value2); 99 | 100 | /** 101 | * Free an entire list. 102 | * 103 | * @param list The list to free. 104 | */ 105 | 106 | void list_free(ListEntry *list); 107 | 108 | /** 109 | * Prepend a value to the start of a list. 110 | * 111 | * @param list Pointer to the list to prepend to. 112 | * @param data The value to prepend. 113 | * @return The new entry in the list, or NULL if it was not 114 | * possible to allocate the memory for the new entry. 115 | */ 116 | 117 | ListEntry *list_prepend(ListEntry **list, ListValue data); 118 | 119 | /** 120 | * Append a value to the end of a list. 121 | * 122 | * @param list Pointer to the list to append to. 123 | * @param data The value to append. 124 | * @return The new entry in the list, or NULL if it was not 125 | * possible to allocate the memory for the new entry. 126 | */ 127 | 128 | ListEntry *list_append(ListEntry **list, ListValue data); 129 | 130 | /** 131 | * Retrieve the previous entry in a list. 132 | * 133 | * @param listentry Pointer to the list entry. 134 | * @return The previous entry in the list, or NULL if this 135 | * was the first entry in the list. 136 | */ 137 | 138 | ListEntry *list_prev(ListEntry *listentry); 139 | 140 | /** 141 | * Retrieve the next entry in a list. 142 | * 143 | * @param listentry Pointer to the list entry. 144 | * @return The next entry in the list, or NULL if this was the 145 | * last entry in the list. 146 | */ 147 | 148 | ListEntry *list_next(ListEntry *listentry); 149 | 150 | /** 151 | * Retrieve the value at a list entry. 152 | * 153 | * @param listentry Pointer to the list entry. 154 | * @return The value stored at the list entry. 155 | */ 156 | 157 | ListValue list_data(ListEntry *listentry); 158 | 159 | /** 160 | * Retrieve the entry at a specified index in a list. 161 | * 162 | * @param list The list. 163 | * @param n The index into the list . 164 | * @return The entry at the specified index, or NULL if out of range. 165 | */ 166 | 167 | ListEntry *list_nth_entry(ListEntry *list, unsigned int n); 168 | 169 | /** 170 | * Retrieve the value at a specified index in the list. 171 | * 172 | * @param list The list. 173 | * @param n The index into the list. 174 | * @return The value at the specified index, or @ref LIST_NULL if 175 | * unsuccessful. 176 | */ 177 | 178 | ListValue list_nth_data(ListEntry *list, unsigned int n); 179 | 180 | /** 181 | * Find the length of a list. 182 | * 183 | * @param list The list. 184 | * @return The number of entries in the list. 185 | */ 186 | 187 | unsigned int list_length(ListEntry *list); 188 | 189 | /** 190 | * Create a C array containing the contents of a list. 191 | * 192 | * @param list The list. 193 | * @return A newly-allocated C array containing all values in the 194 | * list, or NULL if it was not possible to allocate the 195 | * memory. The length of the array is equal to the length 196 | * of the list (see @ref list_length). 197 | */ 198 | 199 | ListValue *list_to_array(ListEntry *list); 200 | 201 | /** 202 | * Remove an entry from a list. 203 | * 204 | * @param list Pointer to the list. 205 | * @param entry The list entry to remove . 206 | * @return If the entry is not found in the list, returns zero, 207 | * else returns non-zero. 208 | */ 209 | 210 | int list_remove_entry(ListEntry **list, ListEntry *entry); 211 | 212 | /** 213 | * Remove all occurrences of a particular value from a list. 214 | * 215 | * @param list Pointer to the list. 216 | * @param callback Function to invoke to compare values in the list 217 | * with the value to be removed. 218 | * @param data The value to remove from the list. 219 | * @return The number of entries removed from the list. 220 | */ 221 | 222 | unsigned int list_remove_data(ListEntry **list, ListEqualFunc callback, 223 | ListValue data); 224 | 225 | /** 226 | * Sort a list. 227 | * 228 | * @param list Pointer to the list to sort. 229 | * @param compare_func Function used to compare values in the list. 230 | */ 231 | 232 | void list_sort(ListEntry **list, ListCompareFunc compare_func); 233 | 234 | /** 235 | * Find the entry for a particular value in a list. 236 | * 237 | * @param list The list to search. 238 | * @param callback Function to invoke to compare values in the list 239 | * with the value to be searched for. 240 | * @param data The value to search for. 241 | * @return The list entry of the item being searched for, or 242 | * NULL if not found. 243 | */ 244 | 245 | ListEntry *list_find_data(ListEntry *list, 246 | ListEqualFunc callback, 247 | ListValue data); 248 | 249 | /** 250 | * Initialise a @ref ListIterator structure to iterate over a list. 251 | * 252 | * @param list A pointer to the list to iterate over. 253 | * @param iter A pointer to an iterator structure to initialise. 254 | */ 255 | 256 | void list_iterate(ListEntry **list, ListIterator *iter); 257 | 258 | /** 259 | * Determine if there are more values in the list to iterate over. 260 | * 261 | * @param iterator The list iterator. 262 | * @return Zero if there are no more values in the list to 263 | * iterate over, non-zero if there are more values to 264 | * read. 265 | */ 266 | 267 | int list_iter_has_more(ListIterator *iterator); 268 | 269 | /** 270 | * Using a list iterator, retrieve the next value from the list. 271 | * 272 | * @param iterator The list iterator. 273 | * @return The next value from the list, or @ref LIST_NULL if 274 | * there are no more values in the list. 275 | */ 276 | 277 | ListValue list_iter_next(ListIterator *iterator); 278 | 279 | /** 280 | * Delete the current entry in the list (the value last returned from 281 | * list_iter_next) 282 | * 283 | * @param iterator The list iterator. 284 | */ 285 | 286 | void list_iter_remove(ListIterator *iterator); 287 | 288 | #ifdef __cplusplus 289 | } 290 | #endif 291 | 292 | #endif /* #ifndef ALGORITHM_LIST_H */ 293 | -------------------------------------------------------------------------------- /algorithms/slist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file slist.h 3 | * 4 | * Singly-linked list. 5 | * 6 | * A singly-linked list stores a collection of values. Each 7 | * entry in the list (represented by a pointer to a @ref SListEntry 8 | * structure) contains a link to the next entry. It is only 9 | * possible to iterate over entries in a singly linked list in one 10 | * direction. 11 | * 12 | * To create a new singly-linked list, create a variable which is 13 | * a pointer to a @ref SListEntry, and initialise it to NULL. 14 | * 15 | * To destroy a singly linked list, use @ref slist_free. 16 | * 17 | * To add a new value at the start of a list, use @ref slist_prepend. 18 | * To add a new value at the end of a list, use @ref slist_append. 19 | * 20 | * To find the length of a list, use @ref slist_length. 21 | * 22 | * To access a value in a list by its index in the list, use 23 | * @ref slist_nth_data. 24 | * 25 | * To search a list for a value, use @ref slist_find_data. 26 | * 27 | * To sort a list into an order, use @ref slist_sort. 28 | * 29 | * To find a particular entry in a list by its index, use 30 | * @ref slist_nth_entry. 31 | * 32 | * To iterate over each value in a list, use @ref slist_iterate to 33 | * initialise a @ref SListIterator structure, with @ref slist_iter_next 34 | * and @ref slist_iter_has_more to retrieve each value in turn. 35 | * @ref slist_iter_remove can be used to efficiently remove the 36 | * current entry from the list. 37 | * 38 | * Given a particular entry in a list (@ref SListEntry): 39 | * 40 | * @li To find the next entry, use @ref slist_next. 41 | * @li To access the value stored at the entry, use @ref slist_data. 42 | * @li To remove the entry, use @ref slist_remove_entry. 43 | * 44 | */ 45 | 46 | #ifndef ALGORITHM_SLIST_H 47 | #define ALGORITHM_SLIST_H 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | /** 54 | * Represents an entry in a singly-linked list. The empty list is 55 | * represented by a NULL pointer. To initialise a new singly linked 56 | * list, simply create a variable of this type 57 | * containing a pointer to NULL. 58 | */ 59 | 60 | typedef struct _SListEntry SListEntry; 61 | 62 | /** 63 | * Structure used to iterate over a list. 64 | */ 65 | 66 | typedef struct _SListIterator SListIterator; 67 | 68 | /** 69 | * Value stored in a list. 70 | */ 71 | 72 | typedef void *SListValue; 73 | 74 | /** 75 | * Definition of a @ref SListIterator. 76 | */ 77 | 78 | struct _SListIterator { 79 | SListEntry **prev_next; 80 | SListEntry *current; 81 | }; 82 | 83 | /** 84 | * A null @ref SListValue. 85 | */ 86 | 87 | #define SLIST_NULL ((void *) 0) 88 | 89 | /** 90 | * Callback function used to compare values in a list when sorting. 91 | * 92 | * @return A negative value if value1 should be sorted before value2, 93 | * a positive value if value1 should be sorted after value2, 94 | * zero if value1 and value2 are equal. 95 | */ 96 | 97 | typedef int (*SListCompareFunc)(SListValue value1, SListValue value2); 98 | 99 | /** 100 | * Callback function used to determine of two values in a list are 101 | * equal. 102 | * 103 | * @return A non-zero value if value1 and value2 are equal, zero if they 104 | * are not equal. 105 | */ 106 | 107 | typedef int (*SListEqualFunc)(SListValue value1, SListValue value2); 108 | 109 | /** 110 | * Free an entire list. 111 | * 112 | * @param list The list to free. 113 | */ 114 | 115 | void slist_free(SListEntry *list); 116 | 117 | /** 118 | * Prepend a value to the start of a list. 119 | * 120 | * @param list Pointer to the list to prepend to. 121 | * @param data The value to prepend. 122 | * @return The new entry in the list, or NULL if it was not possible 123 | * to allocate a new entry. 124 | */ 125 | 126 | SListEntry *slist_prepend(SListEntry **list, SListValue data); 127 | 128 | /** 129 | * Append a value to the end of a list. 130 | * 131 | * @param list Pointer to the list to append to. 132 | * @param data The value to append. 133 | * @return The new entry in the list, or NULL if it was not possible 134 | * to allocate a new entry. 135 | */ 136 | 137 | SListEntry *slist_append(SListEntry **list, SListValue data); 138 | 139 | /** 140 | * Retrieve the next entry in a list. 141 | * 142 | * @param listentry Pointer to the list entry. 143 | * @return The next entry in the list. 144 | */ 145 | 146 | SListEntry *slist_next(SListEntry *listentry); 147 | 148 | /** 149 | * Retrieve the value stored at a list entry. 150 | * 151 | * @param listentry Pointer to the list entry. 152 | * @return The value at the list entry. 153 | */ 154 | 155 | SListValue slist_data(SListEntry *listentry); 156 | 157 | /** 158 | * Retrieve the entry at a specified index in a list. 159 | * 160 | * @param list The list. 161 | * @param n The index into the list . 162 | * @return The entry at the specified index, or NULL if out of range. 163 | */ 164 | 165 | SListEntry *slist_nth_entry(SListEntry *list, unsigned int n); 166 | 167 | /** 168 | * Retrieve the value stored at a specified index in the list. 169 | * 170 | * @param list The list. 171 | * @param n The index into the list. 172 | * @return The value stored at the specified index, or 173 | * @ref SLIST_NULL if unsuccessful. 174 | */ 175 | 176 | SListValue slist_nth_data(SListEntry *list, unsigned int n); 177 | 178 | /** 179 | * Find the length of a list. 180 | * 181 | * @param list The list. 182 | * @return The number of entries in the list. 183 | */ 184 | 185 | unsigned int slist_length(SListEntry *list); 186 | 187 | /** 188 | * Create a C array containing the contents of a list. 189 | * 190 | * @param list The list. 191 | * @return A newly-allocated C array containing all values in the 192 | * list, or NULL if it was not possible to allocate the 193 | * memory for the array. The length of the array is 194 | * equal to the length of the list (see @ref slist_length). 195 | */ 196 | 197 | SListValue *slist_to_array(SListEntry *list); 198 | 199 | /** 200 | * Remove an entry from a list. 201 | * 202 | * @param list Pointer to the list. 203 | * @param entry The list entry to remove. 204 | * @return If the entry is not found in the list, returns zero, 205 | * else returns non-zero. 206 | */ 207 | 208 | int slist_remove_entry(SListEntry **list, SListEntry *entry); 209 | 210 | /** 211 | * Remove all occurrences of a particular value from a list. 212 | * 213 | * @param list Pointer to the list. 214 | * @param callback Callback function to invoke to compare values in the 215 | * list with the value to remove. 216 | * @param data The value to remove from the list. 217 | * @return The number of entries removed from the list. 218 | */ 219 | 220 | unsigned int slist_remove_data(SListEntry **list, 221 | SListEqualFunc callback, 222 | SListValue data); 223 | 224 | /** 225 | * Sort a list. 226 | * 227 | * @param list Pointer to the list to sort. 228 | * @param compare_func Function used to compare values in the list. 229 | */ 230 | 231 | void slist_sort(SListEntry **list, SListCompareFunc compare_func); 232 | 233 | /** 234 | * Find the entry for a particular value in a list. 235 | * 236 | * @param list The list to search. 237 | * @param callback Callback function to be invoked to determine if 238 | * values in the list are equal to the value to be 239 | * searched for. 240 | * @param data The value to search for. 241 | * @return The list entry of the value being searched for, or 242 | * NULL if not found. 243 | */ 244 | 245 | SListEntry *slist_find_data(SListEntry *list, 246 | SListEqualFunc callback, 247 | SListValue data); 248 | 249 | /** 250 | * Initialise a @ref SListIterator structure to iterate over a list. 251 | * 252 | * @param list Pointer to the list to iterate over. 253 | * @param iter Pointer to a @ref SListIterator structure to 254 | * initialise. 255 | */ 256 | 257 | void slist_iterate(SListEntry **list, SListIterator *iter); 258 | 259 | /** 260 | * Determine if there are more values in the list to iterate over. 261 | * 262 | * @param iterator The list iterator. 263 | * @return Zero if there are no more values in the list to 264 | * iterate over, non-zero if there are more values to 265 | * read. 266 | */ 267 | 268 | int slist_iter_has_more(SListIterator *iterator); 269 | 270 | /** 271 | * Using a list iterator, retrieve the next value from the list. 272 | * 273 | * @param iterator The list iterator. 274 | * @return The next value from the list, or SLIST_NULL if 275 | * there are no more values in the list. 276 | */ 277 | 278 | SListValue slist_iter_next(SListIterator *iterator); 279 | 280 | /** 281 | * Delete the current entry in the list (the value last returned from 282 | * @ref slist_iter_next) 283 | * 284 | * @param iterator The list iterator. 285 | */ 286 | 287 | void slist_iter_remove(SListIterator *iterator); 288 | 289 | #ifdef __cplusplus 290 | } 291 | #endif 292 | 293 | #endif /* #ifndef ALGORITHM_SLIST_H */ 294 | 295 | -------------------------------------------------------------------------------- /algorithms/slist.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "slist.h" 4 | 5 | /* malloc() / free() testing */ 6 | 7 | #ifdef ALLOC_TESTING 8 | #include "alloc-testing.h" 9 | #endif 10 | 11 | /* A singly-linked list */ 12 | 13 | struct _SListEntry { 14 | SListValue data; 15 | SListEntry *next; 16 | }; 17 | 18 | void slist_free(SListEntry *list) { 19 | SListEntry *entry; 20 | 21 | /* Iterate over each entry, freeing each list entry, until the 22 | * end is reached */ 23 | 24 | entry = list; 25 | 26 | while (entry != NULL) { 27 | SListEntry *next; 28 | 29 | next = entry->next; 30 | 31 | free(entry); 32 | 33 | entry = next; 34 | } 35 | } 36 | 37 | SListEntry *slist_prepend(SListEntry **list, SListValue data) { 38 | SListEntry *newentry; 39 | 40 | /* Create new entry */ 41 | 42 | newentry = malloc(sizeof(SListEntry)); 43 | 44 | if (newentry == NULL) { 45 | return NULL; 46 | } 47 | 48 | newentry->data = data; 49 | 50 | /* Hook into the list start */ 51 | 52 | newentry->next = *list; 53 | *list = newentry; 54 | 55 | return newentry; 56 | } 57 | 58 | SListEntry *slist_append(SListEntry **list, SListValue data) { 59 | SListEntry *rover; 60 | SListEntry *newentry; 61 | 62 | /* Create new list entry */ 63 | 64 | newentry = malloc(sizeof(SListEntry)); 65 | 66 | if (newentry == NULL) { 67 | return NULL; 68 | } 69 | 70 | newentry->data = data; 71 | newentry->next = NULL; 72 | 73 | /* Hooking into the list is different if the list is empty */ 74 | 75 | if (*list == NULL) { 76 | 77 | /* Create the start of the list */ 78 | 79 | *list = newentry; 80 | 81 | } else { 82 | 83 | /* Find the end of list */ 84 | 85 | for (rover = *list; rover->next != NULL; rover = rover->next); 86 | 87 | /* Add to the end of list */ 88 | 89 | rover->next = newentry; 90 | } 91 | 92 | return newentry; 93 | } 94 | 95 | SListValue slist_data(SListEntry *listentry) { 96 | return listentry->data; 97 | } 98 | 99 | SListEntry *slist_next(SListEntry *listentry) { 100 | return listentry->next; 101 | } 102 | 103 | SListEntry *slist_nth_entry(SListEntry *list, unsigned int n) { 104 | SListEntry *entry; 105 | unsigned int i; 106 | 107 | /* Iterate through n list entries to reach the desired entry. 108 | * Make sure we do not reach the end of the list. */ 109 | 110 | entry = list; 111 | 112 | for (i = 0; i < n; ++i) { 113 | 114 | if (entry == NULL) { 115 | return NULL; 116 | } 117 | entry = entry->next; 118 | } 119 | 120 | return entry; 121 | } 122 | 123 | SListValue slist_nth_data(SListEntry *list, unsigned int n) { 124 | SListEntry *entry; 125 | 126 | /* Find the specified entry */ 127 | 128 | entry = slist_nth_entry(list, n); 129 | 130 | /* If out of range, return NULL, otherwise return the data */ 131 | 132 | if (entry == NULL) { 133 | return SLIST_NULL; 134 | } else { 135 | return entry->data; 136 | } 137 | } 138 | 139 | unsigned int slist_length(SListEntry *list) { 140 | SListEntry *entry; 141 | unsigned int length; 142 | 143 | length = 0; 144 | entry = list; 145 | 146 | while (entry != NULL) { 147 | 148 | /* Count the number of entries */ 149 | 150 | ++length; 151 | 152 | entry = entry->next; 153 | } 154 | 155 | return length; 156 | } 157 | 158 | SListValue *slist_to_array(SListEntry *list) { 159 | SListEntry *rover; 160 | SListValue *array; 161 | unsigned int length; 162 | unsigned int i; 163 | 164 | /* Allocate an array equal in size to the list length */ 165 | 166 | length = slist_length(list); 167 | 168 | array = malloc(sizeof(SListValue) * length); 169 | 170 | if (array == NULL) { 171 | return NULL; 172 | } 173 | 174 | /* Add all entries to the array */ 175 | 176 | rover = list; 177 | 178 | for (i = 0; i < length; ++i) { 179 | 180 | /* Add this node's data */ 181 | 182 | array[i] = rover->data; 183 | 184 | /* Jump to the next list node */ 185 | 186 | rover = rover->next; 187 | } 188 | 189 | return array; 190 | } 191 | 192 | int slist_remove_entry(SListEntry **list, SListEntry *entry) { 193 | SListEntry *rover; 194 | 195 | /* If the list is empty, or entry is NULL, always fail */ 196 | 197 | if (*list == NULL || entry == NULL) { 198 | return 0; 199 | } 200 | 201 | /* Action to take is different if the entry is the first in the list */ 202 | 203 | if (*list == entry) { 204 | 205 | /* Unlink the first entry and update the starting pointer */ 206 | 207 | *list = entry->next; 208 | 209 | } else { 210 | 211 | /* Search through the list to find the preceding entry */ 212 | 213 | rover = *list; 214 | 215 | while (rover != NULL && rover->next != entry) { 216 | rover = rover->next; 217 | } 218 | 219 | if (rover == NULL) { 220 | 221 | /* Not found in list */ 222 | 223 | return 0; 224 | 225 | } else { 226 | 227 | /* rover->next now points at entry, so rover is the 228 | * preceding entry. Unlink the entry from the list. */ 229 | 230 | rover->next = entry->next; 231 | } 232 | } 233 | 234 | /* Free the list entry */ 235 | 236 | free(entry); 237 | 238 | /* Operation successful */ 239 | 240 | return 1; 241 | } 242 | 243 | unsigned int slist_remove_data(SListEntry **list, SListEqualFunc callback, 244 | SListValue data) { 245 | SListEntry **rover; 246 | SListEntry *next; 247 | unsigned int entries_removed; 248 | 249 | entries_removed = 0; 250 | 251 | /* Iterate over the list. 'rover' points at the entrypoint into the 252 | * current entry, ie. the list variable for the first entry in the 253 | * list, or the "next" field of the preceding entry. */ 254 | 255 | rover = list; 256 | 257 | while (*rover != NULL) { 258 | 259 | /* Should this entry be removed? */ 260 | 261 | if (callback((*rover)->data, data) != 0) { 262 | 263 | /* Data found, so remove this entry and free */ 264 | 265 | next = (*rover)->next; 266 | free(*rover); 267 | *rover = next; 268 | 269 | /* Count the number of entries removed */ 270 | 271 | ++entries_removed; 272 | } else { 273 | 274 | /* Advance to the next entry */ 275 | 276 | rover = &((*rover)->next); 277 | } 278 | } 279 | 280 | return entries_removed; 281 | } 282 | 283 | /* Function used internally for sorting. Returns the last entry in the 284 | * new sorted list */ 285 | 286 | static SListEntry *slist_sort_internal(SListEntry **list, 287 | SListCompareFunc compare_func) { 288 | SListEntry *pivot; 289 | SListEntry *rover; 290 | SListEntry *less_list, *more_list; 291 | SListEntry *less_list_end, *more_list_end; 292 | 293 | /* If there are less than two entries in this list, it is 294 | * already sorted */ 295 | 296 | if (*list == NULL || (*list)->next == NULL) { 297 | return *list; 298 | } 299 | 300 | /* The first entry is the pivot */ 301 | 302 | pivot = *list; 303 | 304 | /* Iterate over the list, starting from the second entry. Sort 305 | * all entries into the less and more lists based on comparisons 306 | * with the pivot */ 307 | 308 | less_list = NULL; 309 | more_list = NULL; 310 | rover = (*list)->next; 311 | 312 | while (rover != NULL) { 313 | SListEntry *next = rover->next; 314 | 315 | if (compare_func(rover->data, pivot->data) < 0) { 316 | 317 | /* Place this in the less list */ 318 | 319 | rover->next = less_list; 320 | less_list = rover; 321 | 322 | } else { 323 | 324 | /* Place this in the more list */ 325 | 326 | rover->next = more_list; 327 | more_list = rover; 328 | 329 | } 330 | 331 | rover = next; 332 | } 333 | 334 | /* Sort the sublists recursively */ 335 | 336 | less_list_end = slist_sort_internal(&less_list, compare_func); 337 | more_list_end = slist_sort_internal(&more_list, compare_func); 338 | 339 | /* Create the new list starting from the less list */ 340 | 341 | *list = less_list; 342 | 343 | /* Append the pivot to the end of the less list. If the less list 344 | * was empty, start from the pivot */ 345 | 346 | if (less_list == NULL) { 347 | *list = pivot; 348 | } else { 349 | less_list_end->next = pivot; 350 | } 351 | 352 | /* Append the more list after the pivot */ 353 | 354 | pivot->next = more_list; 355 | 356 | /* Work out what the last entry in the list is. If the more list was 357 | * empty, the pivot was the last entry. Otherwise, the end of the 358 | * more list is the end of the total list. */ 359 | 360 | if (more_list == NULL) { 361 | return pivot; 362 | } else { 363 | return more_list_end; 364 | } 365 | } 366 | 367 | void slist_sort(SListEntry **list, SListCompareFunc compare_func) { 368 | slist_sort_internal(list, compare_func); 369 | } 370 | 371 | SListEntry *slist_find_data(SListEntry *list, 372 | SListEqualFunc callback, 373 | SListValue data) { 374 | SListEntry *rover; 375 | 376 | /* Iterate over entries in the list until the data is found */ 377 | 378 | for (rover = list; rover != NULL; rover = rover->next) { 379 | if (callback(rover->data, data) != 0) { 380 | return rover; 381 | } 382 | } 383 | 384 | /* Not found */ 385 | 386 | return NULL; 387 | } 388 | 389 | void slist_iterate(SListEntry **list, SListIterator *iter) { 390 | /* Start iterating from the beginning of the list. */ 391 | 392 | iter->prev_next = list; 393 | 394 | /* We have not yet read the first item. */ 395 | 396 | iter->current = NULL; 397 | } 398 | 399 | int slist_iter_has_more(SListIterator *iter) { 400 | if (iter->current == NULL || iter->current != *iter->prev_next) { 401 | 402 | /* Either we have not read the first entry, the current 403 | * item was removed or we have reached the end of the 404 | * list. Use prev_next to determine if we have a next 405 | * value to iterate over. */ 406 | 407 | return *iter->prev_next != NULL; 408 | 409 | } else { 410 | 411 | /* The current entry has not been deleted. There 412 | * is a next entry if current->next is not NULL. */ 413 | 414 | return iter->current->next != NULL; 415 | } 416 | } 417 | 418 | SListValue slist_iter_next(SListIterator *iter) { 419 | if (iter->current == NULL || iter->current != *iter->prev_next) { 420 | 421 | /* Either we are reading the first entry, we have reached 422 | * the end of the list, or the previous entry was removed. 423 | * Get the next entry with iter->prev_next. */ 424 | 425 | iter->current = *iter->prev_next; 426 | 427 | } else { 428 | 429 | /* Last value returned from slist_iter_next was not 430 | * deleted. Advance to the next entry. */ 431 | 432 | iter->prev_next = &iter->current->next; 433 | iter->current = iter->current->next; 434 | } 435 | 436 | /* Have we reached the end of the list? */ 437 | 438 | if (iter->current == NULL) { 439 | return SLIST_NULL; 440 | } else { 441 | return iter->current->data; 442 | } 443 | } 444 | 445 | void slist_iter_remove(SListIterator *iter) { 446 | if (iter->current == NULL || iter->current != *iter->prev_next) { 447 | 448 | /* Either we have not yet read the first item, we have 449 | * reached the end of the list, or we have already removed 450 | * the current value. Either way, do nothing. */ 451 | 452 | } else { 453 | 454 | /* Remove the current entry */ 455 | 456 | *iter->prev_next = iter->current->next; 457 | free(iter->current); 458 | iter->current = NULL; 459 | } 460 | } 461 | 462 | -------------------------------------------------------------------------------- /algorithms/bits.c: -------------------------------------------------------------------------------- 1 | #include "btest.h" 2 | #include 3 | 4 | // Team Information Block 5 | team_struct team = 6 | { 7 | /* Team name: Replace with either: 8 | Your login ID if working as a one person team 9 | or, ID1+ID2 where ID1 is the login ID of the first team member 10 | and ID2 is the login ID of the second team member */ 11 | "cburkhar+kraudoni", 12 | /* Student name 1: Replace with the full name of first team member */ 13 | "Casey Burkhardt", 14 | /* Login ID 1: Replace with the login ID of first team member */ 15 | "cburkhar", 16 | 17 | /* The following should only be changed if there are two team members */ 18 | /* Student name 2: Full name of the second team member */ 19 | "Kristin Raudonis", 20 | /* Login ID 2: Login ID of the second team member */ 21 | "kraudoni" 22 | }; 23 | 24 | // Problem / Solution Set 25 | /* 26 | * bitNor - ~(x|y) using only ~ and & 27 | * Example: bitNor(0x6, 0x5) = 0xFFFFFFF8 28 | * Legal ops: ~ & 29 | * Max ops: 8 30 | * Rating: 1 31 | */ 32 | int bitNor(int x, int y) 33 | { 34 | // Applied DeMorgan's Law to expression: 35 | // ~(x|y) 36 | 37 | return (~x & ~y); 38 | } 39 | 40 | /* 41 | * bitXor - x^y using only ~ and & 42 | * Example: bitXor(4, 5) = 1 43 | * Legal ops: ~ & 44 | * Max ops: 14 45 | * Rating: 2 46 | */ 47 | int bitXor(int x, int y) 48 | { 49 | // Applied DeMorgan's Law to expression: 50 | // (~x & y) | (x & ~y) 51 | // which resulted from expression: 52 | // x^y 53 | 54 | return (~(~(~x & y) & ~(x & ~y))); 55 | } 56 | 57 | /* 58 | * isNotEqual - return 0 if x == y, and 1 otherwise 59 | * Examples: isNotEqual(5,5) = 0, isNotEqual(4,5) = 1 60 | * Legal ops: ! ~ & ^ | + << >> 61 | * Max ops: 6 62 | * Rating: 2 63 | */ 64 | int isNotEqual(int x, int y) 65 | { 66 | // XOR operation can be used for equality evaluation 67 | // Double negation operation simplifies result from bit string to boolean value 68 | return(!!(x ^ y)); 69 | } 70 | 71 | /* 72 | * getByte - Extract byte n from word x 73 | * Bytes numbered from 0 (LSB) to 3 (MSB) 74 | * Examples: getByte(0x12345678,1) = 0x56 75 | * Legal ops: ! ~ & ^ | + << >> 76 | * Max ops: 6 77 | * Rating: 2 78 | */ 79 | int getByte(int x, int n) 80 | { 81 | // n << 3 adjusts n so its value is represented in bit form. 82 | // x is arithmetically shifted right to n*(2^3) bits. 83 | // The mask 0xFF is applied to return only the least significant byte, byte n 84 | return (0xFF & (x >> (n << 3))); 85 | } 86 | 87 | /* 88 | * copyLSB - set all bits of result to least significant bit of x 89 | * Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000 90 | * Legal ops: ! ~ & ^ | + << >> 91 | * Max ops: 5 92 | * Rating: 2 93 | */ 94 | int copyLSB(int x) 95 | { 96 | // x is first shifted left 31 bits to remove all but least significant bit. 97 | // x is then arithmetically shifted right 31 bits to copy the least significant bit to all positions. 98 | return ((x << 31) >> 31); 99 | } 100 | 101 | /* 102 | * logicalShift - shift x to the right by n, using a logical shift 103 | * Can assume that 1 <= n <= 31 104 | * Examples: logicalShift(0x87654321,4) = 0x08765432 105 | * Legal ops: ~ & ^ | + << >> 106 | * Max ops: 16 107 | * Rating: 3 108 | */ 109 | int logicalShift(int x, int n) 110 | { 111 | // (x >> n) computes the arithmetic right shift of x by n. 112 | // ((1 << ((~n + 1) + 32)) + ~0) computes a dynamic mask that allows for arithmetically shifted bits to be converted to logical when necessary. 113 | return ((x >> n) & ((1 << ((~n + 1) + 32)) + ~0)); 114 | } 115 | 116 | /* 117 | * bitCount - returns count of number of 1's in word 118 | * Examples: bitCount(5) = 2, bitCount(7) = 3 119 | * Legal ops: ! ~ & ^ | + << >> 120 | * Max ops: 40 121 | * Rating: 4 122 | */ 123 | int bitCount(int x) 124 | { 125 | // Mask 1 encompasses the 2 least significant bytes 126 | int mask1 = 0x11 | (0x11 << 8); 127 | 128 | // Mask 2 encompasses the final bytes 129 | int mask2 = mask1 | (mask1 << 16); 130 | 131 | // Sum will hold the number of 1 bits in the bit string 132 | // Computes the number of 1 bits within the first four bits 133 | int sum = x & mask2; 134 | sum = sum + ((x >> 1) & mask2); 135 | sum = sum + ((x >> 2) & mask2); 136 | sum = sum + ((x >> 3) & mask2); 137 | 138 | // At this point, sum represents the number of 1 bits within the first 4 bits. 139 | // in addition to extraneous bits beyond the first four bits. 140 | // As the binary position of these values do not represent their appropriate value in relation to the sum, they must be stripped. 141 | 142 | // Adjusts for overestimated sum value due to addition of 1 bits beyond first four bits. 143 | sum = sum + (sum >> 16); 144 | 145 | // Used to preserve current sum, and continue to mask 1 bits in the next byte. 146 | mask1 = 0xF | (0xF << 8); 147 | 148 | // Alternates the preserved bits of sum and adds alternating 4 bits together. 149 | sum = (sum & mask1) + ((sum >> 4) & mask1); 150 | 151 | // Shift sum value 1 byte and implement mask to limit resulting sum to 6 bits 152 | // Maximum representation of 6 bits, or a decimal value of 32, the word size for this problem set. 153 | return((sum + (sum >> 8)) & 0x3F); 154 | 155 | /* Funny Solution 156 | int mask = 0x01; 157 | int sum = 0; 158 | 159 | sum = sum + (x & mask); 160 | sum = sum + (x >> 1 & mask); 161 | sum = sum + (x >> 2 & mask); 162 | sum = sum + (x >> 3 & mask); 163 | sum = sum + (x >> 4 & mask); 164 | sum = sum + (x >> 5 & mask); 165 | sum = sum + (x >> 6 & mask); 166 | sum = sum + (x >> 7 & mask); 167 | sum = sum + (x >> 8 & mask); 168 | sum = sum + (x >> 9 & mask); 169 | sum = sum + (x >> 10 & mask); 170 | sum = sum + (x >> 11 & mask); 171 | sum = sum + (x >> 12 & mask); 172 | sum = sum + (x >> 13 & mask); 173 | sum = sum + (x >> 14 & mask); 174 | sum = sum + (x >> 15 & mask); 175 | sum = sum + (x >> 16 & mask); 176 | sum = sum + (x >> 17 & mask); 177 | sum = sum + (x >> 18 & mask); 178 | sum = sum + (x >> 19 & mask); 179 | sum = sum + (x >> 20 & mask); 180 | sum = sum + (x >> 21 & mask); 181 | sum = sum + (x >> 22 & mask); 182 | sum = sum + (x >> 23 & mask); 183 | sum = sum + (x >> 24 & mask); 184 | sum = sum + (x >> 25 & mask); 185 | sum = sum + (x >> 26 & mask); 186 | sum = sum + (x >> 27 & mask); 187 | sum = sum + (x >> 28 & mask); 188 | sum = sum + (x >> 29 & mask); 189 | sum = sum + (x >> 30 & mask); 190 | sum = sum + (x >> 31 & mask); 191 | return(sum); 192 | */ 193 | } 194 | 195 | /* 196 | * bang - Compute !x without using ! 197 | * Examples: bang(3) = 0, bang(0) = 1 198 | * Legal ops: ~ & ^ | + << >> 199 | * Max ops: 12 200 | * Rating: 4 201 | */ 202 | int bang(int x) 203 | { 204 | // The logical negative value of x. 205 | int negative_x = ~x + 1; 206 | 207 | // If (x != 0), then the most significant bit (or sign bit) of either x or -x will be 1. 208 | // XOR the sign bit of x or -x with the mask 0x01 to reproduce functionality of ! 209 | return((((x >> 31) & 0x01) | ((negative_x >> 31) & 0x01)) ^ 0x01); 210 | } 211 | 212 | /* 213 | * leastBitPos - return a mask that marks the position of the 214 | * least significant 1 bit. If x == 0, return 0 215 | * Example: leastBitPos(96) = 0x20 216 | * Legal ops: ! ~ & ^ | + << >> 217 | * Max ops: 6 218 | * Rating: 4 219 | */ 220 | int leastBitPos(int x) 221 | { 222 | // The logical negative value of x. 223 | int negative_x = ~x + 1; 224 | 225 | // x and the logical negative value of x combined with the & operator properly produce the desired mask. 226 | return(x & negative_x); 227 | } 228 | 229 | /* 230 | * TMax - return maximum two's complement integer 231 | * Legal ops: ! ~ & ^ | + << >> 232 | * Max ops: 4 233 | * Rating: 1 234 | */ 235 | int tmax(void) 236 | { 237 | // Constant representing binary value: 1000 0000 238 | int x = 0x80; 239 | 240 | // The compliment of the binary value 1000 0000 shifted 24 bits to the left produces the following binary value: 241 | // 0111 1111 1111 1111 1111 1111 1111 1111 242 | // This is the largest 32-bit two's compliment integer 243 | return(~(x << 24)); 244 | } 245 | 246 | /* 247 | * isNonNegative - return 1 if x >= 0, return 0 otherwise 248 | * Example: isNonNegative(-1) = 0. isNonNegative(0) = 1. 249 | * Legal ops: ! ~ & ^ | + << >> 250 | * Max ops: 6 251 | * Rating: 3 252 | */ 253 | int isNonNegative(int x) 254 | { 255 | 256 | // Boolean value indicating sign of x 257 | // 1 = Negative 258 | // 0 = Non-Negative 259 | int sign_x = x >> 31; 260 | 261 | // The negation of the sign bit of value x computes the appropriate boolean return value. 262 | return (!(sign_x)); 263 | } 264 | 265 | /* 266 | * isGreater - if x > y then return 1, else return 0 267 | * Example: isGreater(4,5) = 0, isGreater(5,4) = 1 268 | * Legal ops: ! ~ & ^ | + << >> 269 | * Max ops: 24 270 | * Rating: 3 271 | */ 272 | int isGreater(int x, int y) 273 | { 274 | // Boolean value indicating sign of x 275 | // 1 = Negative 276 | // 0 = Non-Negative 277 | int sign_x = x >> 31; 278 | 279 | // Boolean value indicating sign of y 280 | // 1 = Negative 281 | // 0 = Non-Negative 282 | int sign_y = y >> 31; 283 | 284 | // if the signs are equal, then 285 | // if x is larger, sign bit of (~y + x) is 0 286 | // if y is larger, sign bit of (~y + x) is 1 287 | int equal = !(sign_x ^ sign_y) & ((~y + x) >> 31); 288 | 289 | // if signs are not equal, these principles are reversed. 290 | int notEqual = sign_x & !sign_y; 291 | 292 | // this | returns 0 when it is x is greater, so you have to negate it. 293 | return !( equal | notEqual); 294 | } 295 | 296 | /* 297 | * divpwr2 - Compute x/(2^n), for 0 <= n <= 30 298 | * Round toward zero 299 | * Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2 300 | * Legal ops: ! ~ & ^ | + << >> * Max ops: 15 301 | * Rating: 2 302 | */ 303 | int divpwr2(int x, int n) 304 | { 305 | // Something is needed to account for x >> n if positive and x >> n + 1 if negative 306 | 307 | // Subtract 1 from 2^n 308 | // This accounts for the need to + 1 309 | int mask = (1 << n) + ~0; 310 | 311 | // Use & operator on mask and sign bit of x 312 | int equalizer = (x >> 31) & mask; 313 | 314 | // Adds 1 if x was originally negative 315 | // Adds 0 if x was originally positive 316 | return (x + equalizer) >> n; 317 | } 318 | 319 | /* 320 | * abs - absolute value of x (except returns TMin for TMin) 321 | * Example: abs(-1) = 1. 322 | * Legal ops: ! ~ & ^ | + << >> 323 | * Max ops: 10 324 | * Rating: 4 325 | */ 326 | int abs(int x) 327 | { 328 | // Boolean value indicating sign of x 329 | // 1 = Negative 330 | // 0 = Non-Negative 331 | int sign_x = x >> 31; 332 | 333 | // XOR of value x and the sign bit of value x plus 1 plus the compliment of the sign bit of x returns the absolute value of x. 334 | return((x ^ (sign_x)) + (1 + ( ~(sign_x)))); 335 | } 336 | 337 | /* 338 | * addOK - Determine if can compute x+y without overflow 339 | * Example: addOK(0x80000000,0x80000000) = 0, 340 | * addOK(0x80000000,0x70000000) = 1, 341 | * Legal ops: ! ~ & ^ | + << >> 342 | * Max ops: 20 343 | * Rating: 3 344 | */ 345 | int addOK(int x, int y) 346 | { 347 | // The sum of x and y 348 | int xy_sum = x + y; 349 | 350 | // Boolean value indicating sign of x 351 | // 1 = Negative 352 | // 0 = Non-Negative 353 | int sign_x = x >> 31; 354 | 355 | // Boolean value indicating sign of y 356 | // 1 = Negative 357 | // 0 = Non-Negative 358 | int sign_y = y >> 31; 359 | 360 | // Boolean value indicating sign of the sum of x and y 361 | // 1 = Negative 362 | // 0 = Non-Negative 363 | int sign_sum_xy = xy_sum >> 31; 364 | 365 | // An overflow occurs when the sign of x and y are the same, but the sign of the sum of x and y is different 366 | return !(~(sign_x ^ sign_y) & (sign_x ^ sign_sum_xy)); 367 | } 368 | -------------------------------------------------------------------------------- /algorithms/rb-tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "rb-tree.h" 4 | 5 | /* malloc() / free() testing */ 6 | 7 | #ifdef ALLOC_TESTING 8 | #include "alloc-testing.h" 9 | #endif 10 | 11 | struct _RBTreeNode { 12 | RBTreeNodeColor color; 13 | RBTreeKey key; 14 | RBTreeValue value; 15 | RBTreeNode *parent; 16 | RBTreeNode *children[2]; 17 | }; 18 | 19 | struct _RBTree { 20 | RBTreeNode *root_node; 21 | RBTreeCompareFunc compare_func; 22 | int num_nodes; 23 | }; 24 | 25 | static RBTreeNodeSide rb_tree_node_side(RBTreeNode *node) { 26 | if (node->parent->children[RB_TREE_NODE_LEFT] == node) { 27 | return RB_TREE_NODE_LEFT; 28 | } else { 29 | return RB_TREE_NODE_RIGHT; 30 | } 31 | } 32 | 33 | static RBTreeNode *rb_tree_node_sibling(RBTreeNode *node) { 34 | RBTreeNodeSide side; 35 | 36 | side = rb_tree_node_side(node); 37 | 38 | return node->parent->children[1 - side]; 39 | } 40 | 41 | RBTreeNode *rb_tree_node_uncle(RBTreeNode *node) { 42 | return rb_tree_node_sibling(node->parent); 43 | } 44 | 45 | /* Replace node1 with node2 at its parent. */ 46 | 47 | static void rb_tree_node_replace(RBTree *tree, RBTreeNode *node1, 48 | RBTreeNode *node2) { 49 | int side; 50 | 51 | /* Set the node's parent pointer. */ 52 | 53 | if (node2 != NULL) { 54 | node2->parent = node1->parent; 55 | } 56 | 57 | /* The root node? */ 58 | 59 | if (node1->parent == NULL) { 60 | tree->root_node = node2; 61 | } else { 62 | side = rb_tree_node_side(node1); 63 | node1->parent->children[side] = node2; 64 | } 65 | } 66 | 67 | /* Rotate a section of the tree. 'node' is the node at the top 68 | * of the section to be rotated. 'direction' is the direction in 69 | * which to rotate the tree: left or right, as shown in the following 70 | * diagram: 71 | * 72 | * Left rotation: Right rotation: 73 | * 74 | * B D 75 | * / \ / \ 76 | * A D B E 77 | * / \ / \ 78 | * C E A C 79 | 80 | * is rotated to: is rotated to: 81 | * 82 | * D B 83 | * / \ / \ 84 | * B E A D 85 | * / \ / \ 86 | * A C C E 87 | */ 88 | 89 | static RBTreeNode *rb_tree_rotate(RBTree *tree, RBTreeNode *node, 90 | RBTreeNodeSide direction) { 91 | RBTreeNode *new_root; 92 | 93 | /* The child of this node will take its place: 94 | for a left rotation, it is the right child, and vice versa. */ 95 | 96 | new_root = node->children[1 - direction]; 97 | 98 | /* Make new_root the root, update parent pointers. */ 99 | 100 | rb_tree_node_replace(tree, node, new_root); 101 | 102 | /* Rearrange pointers */ 103 | 104 | node->children[1 - direction] = new_root->children[direction]; 105 | new_root->children[direction] = node; 106 | 107 | /* Update parent references */ 108 | 109 | node->parent = new_root; 110 | 111 | if (node->children[1 - direction] != NULL) { 112 | node->children[1 - direction]->parent = node; 113 | } 114 | 115 | return new_root; 116 | } 117 | 118 | 119 | RBTree *rb_tree_new(RBTreeCompareFunc compare_func) { 120 | RBTree *new_tree; 121 | 122 | new_tree = malloc(sizeof(RBTree)); 123 | 124 | if (new_tree == NULL) { 125 | return NULL; 126 | } 127 | 128 | new_tree->root_node = NULL; 129 | new_tree->num_nodes = 0; 130 | new_tree->compare_func = compare_func; 131 | 132 | return new_tree; 133 | } 134 | 135 | static void rb_tree_free_subtree(RBTreeNode *node) { 136 | if (node != NULL) { 137 | /* Recurse to subnodes */ 138 | 139 | rb_tree_free_subtree(node->children[RB_TREE_NODE_LEFT]); 140 | rb_tree_free_subtree(node->children[RB_TREE_NODE_RIGHT]); 141 | 142 | /* Free this node */ 143 | 144 | free(node); 145 | } 146 | } 147 | 148 | void rb_tree_free(RBTree *tree) { 149 | /* Free all nodes in the tree */ 150 | 151 | rb_tree_free_subtree(tree->root_node); 152 | 153 | /* Free back the main tree structure */ 154 | 155 | free(tree); 156 | } 157 | 158 | static void rb_tree_insert_case1(RBTree *tree, RBTreeNode *node); 159 | 160 | static void rb_tree_insert_case2(RBTree *tree, RBTreeNode *node); 161 | 162 | static void rb_tree_insert_case3(RBTree *tree, RBTreeNode *node); 163 | 164 | static void rb_tree_insert_case4(RBTree *tree, RBTreeNode *node); 165 | 166 | static void rb_tree_insert_case5(RBTree *tree, RBTreeNode *node); 167 | 168 | /* Insert case 1: If the new node is at the root of the tree, it must 169 | * be recolored black, as the root is always black. */ 170 | 171 | static void rb_tree_insert_case1(RBTree *tree, RBTreeNode *node) { 172 | if (node->parent == NULL) { 173 | 174 | /* The root node is black */ 175 | 176 | node->color = RB_TREE_NODE_BLACK; 177 | 178 | } else { 179 | 180 | /* Not root */ 181 | 182 | rb_tree_insert_case2(tree, node); 183 | } 184 | } 185 | 186 | /* Insert case 2: If the parent of the new node is red, this 187 | * conflicts with the red-black tree conditions, as both children 188 | * of every red node are black. */ 189 | 190 | static void rb_tree_insert_case2(RBTree *tree, RBTreeNode *node) { 191 | /* Note that if this function is being called, we already know 192 | * the node has a parent, as it is not the root node. */ 193 | 194 | if (node->parent->color != RB_TREE_NODE_BLACK) { 195 | rb_tree_insert_case3(tree, node); 196 | } 197 | } 198 | 199 | /* Insert case 3: If the parent and uncle are both red, repaint them 200 | * both black and repaint the grandparent red. */ 201 | 202 | static void rb_tree_insert_case3(RBTree *tree, RBTreeNode *node) { 203 | RBTreeNode *grandparent; 204 | RBTreeNode *uncle; 205 | 206 | /* Note that the node must have a grandparent, as the parent 207 | * is red, and the root node is always black. */ 208 | 209 | grandparent = node->parent->parent; 210 | uncle = rb_tree_node_uncle(node); 211 | 212 | if (uncle != NULL && uncle->color == RB_TREE_NODE_RED) { 213 | 214 | node->parent->color = RB_TREE_NODE_BLACK; 215 | uncle->color = RB_TREE_NODE_BLACK; 216 | grandparent->color = RB_TREE_NODE_RED; 217 | 218 | /* Recurse to grandparent */ 219 | 220 | rb_tree_insert_case1(tree, grandparent); 221 | 222 | } else { 223 | rb_tree_insert_case4(tree, node); 224 | } 225 | } 226 | 227 | /* Case 4: If the parent is red, but the uncle is black, we need to do 228 | * some rotations to keep the tree balanced and complying with the tree 229 | * conditions. If the node is on the opposite side relative to its parent 230 | * as the parent is relative to its grandparent, rotate around the 231 | * parent. Either way, we will continue to case 5. 232 | * 233 | * eg. 234 | * 235 | * B B 236 | * / \ / \ 237 | * R B -> node -> R B 238 | * \ / 239 | * R <- node R 240 | * 241 | */ 242 | 243 | void rb_tree_insert_case4(RBTree *tree, RBTreeNode *node) { 244 | RBTreeNode *next_node; 245 | RBTreeNodeSide side; 246 | 247 | /* Note that at this point, by implication from case 3, we know 248 | * that the parent is red, but the uncle is black. We therefore 249 | * only need to examine what side the node is on relative 250 | * to its parent, and the side the parent is on relative to 251 | * the grandparent. */ 252 | 253 | side = rb_tree_node_side(node); 254 | 255 | if (side != rb_tree_node_side(node->parent)) { 256 | 257 | /* After the rotation, we will continue to case 5, but 258 | * the parent node will be at the bottom. */ 259 | 260 | next_node = node->parent; 261 | 262 | /* Rotate around the parent in the opposite direction 263 | * to side. */ 264 | 265 | rb_tree_rotate(tree, node->parent, 1 - side); 266 | } else { 267 | next_node = node; 268 | } 269 | 270 | rb_tree_insert_case5(tree, next_node); 271 | } 272 | 273 | /* Case 5: The node is on the same side relative to its parent as the 274 | * parent is relative to its grandparent. The node and its parent are 275 | * red, but the uncle is black. 276 | * 277 | * Now, rotate at the grandparent and recolor the parent and grandparent 278 | * to black and red respectively. 279 | * 280 | * G/B P/B 281 | * / \ / \ 282 | * P/R U/B -> N/R G/R 283 | * / \ / \ 284 | * N/R ? ? U/B 285 | * 286 | */ 287 | 288 | void rb_tree_insert_case5(RBTree *tree, RBTreeNode *node) { 289 | RBTreeNode *parent; 290 | RBTreeNode *grandparent; 291 | RBTreeNodeSide side; 292 | 293 | parent = node->parent; 294 | grandparent = parent->parent; 295 | 296 | /* What side are we, relative to the parent? This will determine 297 | * the direction that we rotate. */ 298 | 299 | side = rb_tree_node_side(node); 300 | 301 | /* Rotate at the grandparent, in the opposite direction to side. */ 302 | 303 | rb_tree_rotate(tree, grandparent, 1 - side); 304 | 305 | /* Recolor the (old) parent and grandparent. */ 306 | 307 | parent->color = RB_TREE_NODE_BLACK; 308 | grandparent->color = RB_TREE_NODE_RED; 309 | } 310 | 311 | RBTreeNode *rb_tree_insert(RBTree *tree, RBTreeKey key, RBTreeValue value) { 312 | RBTreeNode *node; 313 | RBTreeNode **rover; 314 | RBTreeNode *parent; 315 | RBTreeNodeSide side; 316 | 317 | /* Allocate a new node */ 318 | 319 | node = malloc(sizeof(RBTreeNode)); 320 | 321 | if (node == NULL) { 322 | return NULL; 323 | } 324 | 325 | /* Set up structure. Initially, the node is red. */ 326 | 327 | node->key = key; 328 | node->value = value; 329 | node->color = RB_TREE_NODE_RED; 330 | node->children[RB_TREE_NODE_LEFT] = NULL; 331 | node->children[RB_TREE_NODE_RIGHT] = NULL; 332 | 333 | /* First, perform a normal binary tree-style insert. */ 334 | 335 | parent = NULL; 336 | rover = &tree->root_node; 337 | 338 | while (*rover != NULL) { 339 | 340 | /* Update parent */ 341 | 342 | parent = *rover; 343 | 344 | /* Choose which path to go down, left or right child */ 345 | 346 | if (tree->compare_func(value, (*rover)->value) < 0) { 347 | side = RB_TREE_NODE_LEFT; 348 | } else { 349 | side = RB_TREE_NODE_RIGHT; 350 | } 351 | 352 | rover = &(*rover)->children[side]; 353 | } 354 | 355 | /* Insert at the position we have reached */ 356 | 357 | *rover = node; 358 | node->parent = parent; 359 | 360 | /* Possibly reorder the tree. */ 361 | 362 | rb_tree_insert_case1(tree, node); 363 | 364 | /* Update the node count */ 365 | 366 | ++tree->num_nodes; 367 | 368 | return node; 369 | } 370 | 371 | RBTreeNode *rb_tree_lookup_node(RBTree *tree, RBTreeKey key) { 372 | RBTreeNode *node; 373 | RBTreeNodeSide side; 374 | int diff; 375 | 376 | node = tree->root_node; 377 | 378 | /* Search down the tree. */ 379 | 380 | while (node != NULL) { 381 | diff = tree->compare_func(key, node->key); 382 | 383 | if (diff == 0) { 384 | return node; 385 | } else if (diff < 0) { 386 | side = RB_TREE_NODE_LEFT; 387 | } else { 388 | side = RB_TREE_NODE_RIGHT; 389 | } 390 | 391 | node = node->children[side]; 392 | } 393 | 394 | /* Not found. */ 395 | 396 | return NULL; 397 | } 398 | 399 | RBTreeValue rb_tree_lookup(RBTree *tree, RBTreeKey key) { 400 | RBTreeNode *node; 401 | 402 | /* Find the node for this key. */ 403 | 404 | node = rb_tree_lookup_node(tree, key); 405 | 406 | if (node == NULL) { 407 | return RB_TREE_NULL; 408 | } else { 409 | return node->value; 410 | } 411 | } 412 | 413 | void rb_tree_remove_node(RBTree *tree, RBTreeNode *node) { 414 | /* TODO */ 415 | } 416 | 417 | int rb_tree_remove(RBTree *tree, RBTreeKey key) { 418 | RBTreeNode *node; 419 | 420 | /* Find the node to remove. */ 421 | 422 | node = rb_tree_lookup_node(tree, key); 423 | 424 | if (node == NULL) { 425 | return 0; 426 | } 427 | 428 | rb_tree_remove_node(tree, node); 429 | 430 | return 1; 431 | } 432 | 433 | RBTreeNode *rb_tree_root_node(RBTree *tree) { 434 | return tree->root_node; 435 | } 436 | 437 | RBTreeKey rb_tree_node_key(RBTreeNode *node) { 438 | return node->key; 439 | } 440 | 441 | RBTreeValue rb_tree_node_value(RBTreeNode *node) { 442 | return node->value; 443 | } 444 | 445 | RBTreeNode *rb_tree_node_child(RBTreeNode *node, RBTreeNodeSide side) { 446 | if (side == RB_TREE_NODE_LEFT || side == RB_TREE_NODE_RIGHT) { 447 | return node->children[side]; 448 | } else { 449 | return NULL; 450 | } 451 | } 452 | 453 | RBTreeNode *rb_tree_node_parent(RBTreeNode *node) { 454 | return node->parent; 455 | } 456 | 457 | RBTreeValue *rb_tree_to_array(RBTree *tree) { 458 | /* TODO */ 459 | return NULL; 460 | } 461 | 462 | int rb_tree_num_entries(RBTree *tree) { 463 | return tree->num_nodes; 464 | } 465 | -------------------------------------------------------------------------------- /algorithms/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "list.h" 4 | 5 | /* malloc() / free() testing */ 6 | 7 | #ifdef ALLOC_TESTING 8 | #include "alloc-testing.h" 9 | #endif 10 | 11 | /* A doubly-linked list */ 12 | 13 | struct _ListEntry { 14 | ListValue data; 15 | ListEntry *prev; 16 | ListEntry *next; 17 | }; 18 | 19 | void list_free(ListEntry *list) { 20 | ListEntry *entry; 21 | 22 | /* Iterate over each entry, freeing each list entry, until the 23 | * end is reached */ 24 | 25 | entry = list; 26 | 27 | while (entry != NULL) { 28 | ListEntry *next; 29 | 30 | next = entry->next; 31 | 32 | free(entry); 33 | 34 | entry = next; 35 | } 36 | } 37 | 38 | ListEntry *list_prepend(ListEntry **list, ListValue data) { 39 | ListEntry *newentry; 40 | 41 | if (list == NULL) { 42 | 43 | /* not a valid list */ 44 | 45 | return NULL; 46 | } 47 | 48 | /* Create new entry */ 49 | 50 | newentry = malloc(sizeof(ListEntry)); 51 | 52 | if (newentry == NULL) { 53 | return NULL; 54 | } 55 | 56 | newentry->data = data; 57 | 58 | /* Hook into the list start */ 59 | 60 | if (*list != NULL) { 61 | (*list)->prev = newentry; 62 | } 63 | newentry->prev = NULL; 64 | newentry->next = *list; 65 | *list = newentry; 66 | 67 | return newentry; 68 | } 69 | 70 | ListEntry *list_append(ListEntry **list, ListValue data) { 71 | ListEntry *rover; 72 | ListEntry *newentry; 73 | 74 | if (list == NULL) { 75 | return NULL; 76 | } 77 | 78 | /* Create new list entry */ 79 | 80 | newentry = malloc(sizeof(ListEntry)); 81 | 82 | if (newentry == NULL) { 83 | return NULL; 84 | } 85 | 86 | newentry->data = data; 87 | newentry->next = NULL; 88 | 89 | /* Hooking into the list is different if the list is empty */ 90 | 91 | if (*list == NULL) { 92 | 93 | /* Create the start of the list */ 94 | 95 | *list = newentry; 96 | newentry->prev = NULL; 97 | 98 | } else { 99 | 100 | /* Find the end of list */ 101 | 102 | for (rover = *list; rover->next != NULL; rover = rover->next); 103 | 104 | /* Add to the end of list */ 105 | 106 | newentry->prev = rover; 107 | rover->next = newentry; 108 | } 109 | 110 | return newentry; 111 | } 112 | 113 | ListValue list_data(ListEntry *listentry) { 114 | if (listentry == NULL) { 115 | return LIST_NULL; 116 | } 117 | 118 | return listentry->data; 119 | } 120 | 121 | ListEntry *list_prev(ListEntry *listentry) { 122 | if (listentry == NULL) { 123 | return NULL; 124 | } 125 | 126 | return listentry->prev; 127 | } 128 | 129 | ListEntry *list_next(ListEntry *listentry) { 130 | if (listentry == NULL) { 131 | return NULL; 132 | } 133 | 134 | return listentry->next; 135 | } 136 | 137 | ListEntry *list_nth_entry(ListEntry *list, unsigned int n) { 138 | ListEntry *entry; 139 | unsigned int i; 140 | 141 | /* Iterate through n list entries to reach the desired entry. 142 | * Make sure we do not reach the end of the list. */ 143 | 144 | entry = list; 145 | 146 | for (i = 0; i < n; ++i) { 147 | 148 | if (entry == NULL) { 149 | return NULL; 150 | } 151 | entry = entry->next; 152 | } 153 | 154 | return entry; 155 | } 156 | 157 | ListValue list_nth_data(ListEntry *list, unsigned int n) { 158 | ListEntry *entry; 159 | 160 | /* Find the specified entry */ 161 | 162 | entry = list_nth_entry(list, n); 163 | 164 | /* If out of range, return NULL, otherwise return the data */ 165 | 166 | if (entry == NULL) { 167 | return LIST_NULL; 168 | } else { 169 | return entry->data; 170 | } 171 | } 172 | 173 | unsigned int list_length(ListEntry *list) { 174 | ListEntry *entry; 175 | unsigned int length; 176 | 177 | length = 0; 178 | entry = list; 179 | 180 | while (entry != NULL) { 181 | 182 | /* Count the number of entries */ 183 | 184 | ++length; 185 | 186 | entry = entry->next; 187 | } 188 | 189 | return length; 190 | } 191 | 192 | ListValue *list_to_array(ListEntry *list) { 193 | ListEntry *rover; 194 | ListValue *array; 195 | unsigned int length; 196 | unsigned int i; 197 | 198 | /* Allocate an array equal in size to the list length */ 199 | 200 | length = list_length(list); 201 | 202 | array = malloc(sizeof(ListValue) * length); 203 | 204 | if (array == NULL) { 205 | return NULL; 206 | } 207 | 208 | /* Add all entries to the array */ 209 | 210 | rover = list; 211 | 212 | for (i = 0; i < length; ++i) { 213 | 214 | /* Add this node's data */ 215 | 216 | array[i] = rover->data; 217 | 218 | /* Jump to the next list node */ 219 | 220 | rover = rover->next; 221 | } 222 | 223 | return array; 224 | } 225 | 226 | int list_remove_entry(ListEntry **list, ListEntry *entry) { 227 | /* If the list is empty, or entry is NULL, always fail */ 228 | 229 | if (list == NULL || *list == NULL || entry == NULL) { 230 | return 0; 231 | } 232 | 233 | /* Action to take is different if the entry is the first in the list */ 234 | 235 | if (entry->prev == NULL) { 236 | 237 | /* Unlink the first entry and update the starting pointer */ 238 | 239 | *list = entry->next; 240 | 241 | /* Update the second entry's prev pointer, if there is a second 242 | * entry */ 243 | 244 | if (entry->next != NULL) { 245 | entry->next->prev = NULL; 246 | } 247 | 248 | } else { 249 | 250 | /* This is not the first in the list, so we must have a 251 | * previous entry. Update its 'next' pointer to the new 252 | * value */ 253 | 254 | entry->prev->next = entry->next; 255 | 256 | /* If there is an entry following this one, update its 'prev' 257 | * pointer to the new value */ 258 | 259 | if (entry->next != NULL) { 260 | entry->next->prev = entry->prev; 261 | } 262 | } 263 | 264 | /* Free the list entry */ 265 | 266 | free(entry); 267 | 268 | /* Operation successful */ 269 | 270 | return 1; 271 | } 272 | 273 | unsigned int list_remove_data(ListEntry **list, ListEqualFunc callback, 274 | ListValue data) { 275 | unsigned int entries_removed; 276 | ListEntry *rover; 277 | ListEntry *next; 278 | 279 | if (list == NULL || callback == NULL) { 280 | return 0; 281 | } 282 | 283 | entries_removed = 0; 284 | 285 | /* Iterate over the entries in the list */ 286 | 287 | rover = *list; 288 | 289 | while (rover != NULL) { 290 | 291 | next = rover->next; 292 | 293 | if (callback(rover->data, data)) { 294 | 295 | /* This data needs to be removed. Unlink this entry 296 | * from the list. */ 297 | 298 | if (rover->prev == NULL) { 299 | 300 | /* This is the first entry in the list */ 301 | 302 | *list = rover->next; 303 | } else { 304 | 305 | /* Point the previous entry at its new 306 | * location */ 307 | 308 | rover->prev->next = rover->next; 309 | } 310 | 311 | if (rover->next != NULL) { 312 | rover->next->prev = rover->prev; 313 | } 314 | 315 | /* Free the entry */ 316 | 317 | free(rover); 318 | 319 | ++entries_removed; 320 | } 321 | 322 | /* Advance to the next list entry */ 323 | 324 | rover = next; 325 | } 326 | 327 | return entries_removed; 328 | } 329 | 330 | /* Function used internally for sorting. Returns the last entry in the 331 | * new sorted list */ 332 | 333 | static ListEntry *list_sort_internal(ListEntry **list, 334 | ListCompareFunc compare_func) { 335 | ListEntry *pivot; 336 | ListEntry *rover; 337 | ListEntry *less_list, *more_list; 338 | ListEntry *less_list_end, *more_list_end; 339 | 340 | if (list == NULL || compare_func == NULL) { 341 | return NULL; 342 | } 343 | 344 | /* If there are less than two entries in this list, it is 345 | * already sorted */ 346 | 347 | if (*list == NULL || (*list)->next == NULL) { 348 | return *list; 349 | } 350 | 351 | /* The first entry is the pivot */ 352 | 353 | pivot = *list; 354 | 355 | /* Iterate over the list, starting from the second entry. Sort 356 | * all entries into the less and more lists based on comparisons 357 | * with the pivot */ 358 | 359 | less_list = NULL; 360 | more_list = NULL; 361 | rover = (*list)->next; 362 | 363 | while (rover != NULL) { 364 | ListEntry *next = rover->next; 365 | 366 | if (compare_func(rover->data, pivot->data) < 0) { 367 | 368 | /* Place this in the less list */ 369 | 370 | rover->prev = NULL; 371 | rover->next = less_list; 372 | if (less_list != NULL) { 373 | less_list->prev = rover; 374 | } 375 | less_list = rover; 376 | 377 | } else { 378 | 379 | /* Place this in the more list */ 380 | 381 | rover->prev = NULL; 382 | rover->next = more_list; 383 | if (more_list != NULL) { 384 | more_list->prev = rover; 385 | } 386 | more_list = rover; 387 | } 388 | 389 | rover = next; 390 | } 391 | 392 | /* Sort the sublists recursively */ 393 | 394 | less_list_end = list_sort_internal(&less_list, compare_func); 395 | more_list_end = list_sort_internal(&more_list, compare_func); 396 | 397 | /* Create the new list starting from the less list */ 398 | 399 | *list = less_list; 400 | 401 | /* Append the pivot to the end of the less list. If the less list 402 | * was empty, start from the pivot */ 403 | 404 | if (less_list == NULL) { 405 | pivot->prev = NULL; 406 | *list = pivot; 407 | } else { 408 | pivot->prev = less_list_end; 409 | less_list_end->next = pivot; 410 | } 411 | 412 | /* Append the more list after the pivot */ 413 | 414 | pivot->next = more_list; 415 | if (more_list != NULL) { 416 | more_list->prev = pivot; 417 | } 418 | 419 | /* Work out what the last entry in the list is. If the more list was 420 | * empty, the pivot was the last entry. Otherwise, the end of the 421 | * more list is the end of the total list. */ 422 | 423 | if (more_list == NULL) { 424 | return pivot; 425 | } else { 426 | return more_list_end; 427 | } 428 | } 429 | 430 | void list_sort(ListEntry **list, ListCompareFunc compare_func) { 431 | list_sort_internal(list, compare_func); 432 | } 433 | 434 | ListEntry *list_find_data(ListEntry *list, 435 | ListEqualFunc callback, 436 | ListValue data) { 437 | ListEntry *rover; 438 | 439 | /* Iterate over entries in the list until the data is found */ 440 | 441 | for (rover = list; rover != NULL; rover = rover->next) { 442 | if (callback(rover->data, data) != 0) { 443 | return rover; 444 | } 445 | } 446 | 447 | /* Not found */ 448 | 449 | return NULL; 450 | } 451 | 452 | void list_iterate(ListEntry **list, ListIterator *iter) { 453 | /* Start iterating from the beginning of the list. */ 454 | 455 | iter->prev_next = list; 456 | 457 | /* We have not yet read the first item. */ 458 | 459 | iter->current = NULL; 460 | } 461 | 462 | int list_iter_has_more(ListIterator *iter) { 463 | if (iter->current == NULL || iter->current != *iter->prev_next) { 464 | 465 | /* Either we have not read the first entry, the current 466 | * item was removed or we have reached the end of the 467 | * list. Use prev_next to determine if we have a next 468 | * value to iterate over. */ 469 | 470 | return *iter->prev_next != NULL; 471 | 472 | } else { 473 | /* The current entry as not been deleted since the last 474 | * call to list_iter_next: there is a next entry if 475 | * current->next is not NULL */ 476 | 477 | return iter->current->next != NULL; 478 | } 479 | } 480 | 481 | ListValue list_iter_next(ListIterator *iter) { 482 | if (iter->current == NULL || iter->current != *iter->prev_next) { 483 | 484 | /* Either we are reading the first entry, we have reached 485 | * the end of the list, or the previous entry was removed. 486 | * Get the next entry with iter->prev_next. */ 487 | 488 | iter->current = *iter->prev_next; 489 | 490 | } else { 491 | 492 | /* Last value returned from list_iter_next was not deleted. 493 | * Advance to the next entry. */ 494 | 495 | iter->prev_next = &iter->current->next; 496 | iter->current = iter->current->next; 497 | } 498 | 499 | /* Have we reached the end of the list? */ 500 | 501 | if (iter->current == NULL) { 502 | return LIST_NULL; 503 | } else { 504 | return iter->current->data; 505 | } 506 | } 507 | 508 | void list_iter_remove(ListIterator *iter) { 509 | if (iter->current == NULL || iter->current != *iter->prev_next) { 510 | 511 | /* Either we have not yet read the first item, we have 512 | * reached the end of the list, or we have already removed 513 | * the current value. Either way, do nothing. */ 514 | 515 | } else { 516 | 517 | /* Remove the current entry */ 518 | 519 | *iter->prev_next = iter->current->next; 520 | 521 | if (iter->current->next != NULL) { 522 | iter->current->next->prev = iter->current->prev; 523 | } 524 | 525 | free(iter->current); 526 | iter->current = NULL; 527 | } 528 | } 529 | 530 | -------------------------------------------------------------------------------- /algorithms/hash-table.c: -------------------------------------------------------------------------------- 1 | /* Hash table implementation */ 2 | 3 | #include 4 | #include 5 | 6 | #include "hash-table.h" 7 | 8 | /* malloc() / free() testing */ 9 | 10 | #ifdef ALLOC_TESTING 11 | #include "alloc-testing.h" 12 | #endif 13 | 14 | struct _HashTableEntry { 15 | HashTablePair pair; 16 | HashTableEntry *next; 17 | }; 18 | 19 | struct _HashTable { 20 | HashTableEntry **table; 21 | unsigned int table_size; 22 | HashTableHashFunc hash_func; 23 | HashTableEqualFunc equal_func; 24 | HashTableKeyFreeFunc key_free_func; 25 | HashTableValueFreeFunc value_free_func; 26 | unsigned int entries; 27 | unsigned int prime_index; 28 | }; 29 | 30 | /* This is a set of good hash table prime numbers, from: 31 | * http://planetmath.org/encyclopedia/GoodHashTablePrimes.html 32 | * Each prime is roughly double the previous value, and as far as 33 | * possible from the nearest powers of two. */ 34 | 35 | static const unsigned int hash_table_primes[] = { 36 | 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 37 | 196613, 393241, 786433, 1572869, 3145739, 6291469, 38 | 12582917, 25165843, 50331653, 100663319, 201326611, 39 | 402653189, 805306457, 1610612741, 40 | }; 41 | 42 | static const unsigned int hash_table_num_primes 43 | = sizeof(hash_table_primes) / sizeof(int); 44 | 45 | /* Internal function used to allocate the table on hash table creation 46 | * and when enlarging the table */ 47 | 48 | static int hash_table_allocate_table(HashTable *hash_table) { 49 | unsigned int new_table_size; 50 | 51 | /* Determine the table size based on the current prime index. 52 | * An attempt is made here to ensure sensible behavior if the 53 | * maximum prime is exceeded, but in practice other things are 54 | * likely to break long before that happens. */ 55 | 56 | if (hash_table->prime_index < hash_table_num_primes) { 57 | new_table_size = hash_table_primes[hash_table->prime_index]; 58 | } else { 59 | new_table_size = hash_table->entries * 10; 60 | } 61 | 62 | hash_table->table_size = new_table_size; 63 | 64 | /* Allocate the table and initialise to NULL for all entries */ 65 | 66 | hash_table->table = calloc(hash_table->table_size, 67 | sizeof(HashTableEntry *)); 68 | 69 | return hash_table->table != NULL; 70 | } 71 | 72 | /* Free an entry, calling the free functions if there are any registered */ 73 | 74 | static void hash_table_free_entry(HashTable *hash_table, HashTableEntry *entry) { 75 | HashTablePair *pair; 76 | 77 | pair = &(entry->pair); 78 | 79 | /* If there is a function registered for freeing keys, use it to free 80 | * the key */ 81 | 82 | if (hash_table->key_free_func != NULL) { 83 | hash_table->key_free_func(pair->key); 84 | } 85 | 86 | /* Likewise with the value */ 87 | 88 | if (hash_table->value_free_func != NULL) { 89 | hash_table->value_free_func(pair->value); 90 | } 91 | 92 | /* Free the data structure */ 93 | 94 | free(entry); 95 | } 96 | 97 | HashTable *hash_table_new(HashTableHashFunc hash_func, 98 | HashTableEqualFunc equal_func) { 99 | HashTable *hash_table; 100 | 101 | /* Allocate a new hash table structure */ 102 | 103 | hash_table = (HashTable *) malloc(sizeof(HashTable)); 104 | 105 | if (hash_table == NULL) { 106 | return NULL; 107 | } 108 | 109 | hash_table->hash_func = hash_func; 110 | hash_table->equal_func = equal_func; 111 | hash_table->key_free_func = NULL; 112 | hash_table->value_free_func = NULL; 113 | hash_table->entries = 0; 114 | hash_table->prime_index = 0; 115 | 116 | /* Allocate the table */ 117 | 118 | if (!hash_table_allocate_table(hash_table)) { 119 | free(hash_table); 120 | 121 | return NULL; 122 | } 123 | 124 | return hash_table; 125 | } 126 | 127 | void hash_table_free(HashTable *hash_table) { 128 | HashTableEntry *rover; 129 | HashTableEntry *next; 130 | unsigned int i; 131 | 132 | /* Free all entries in all chains */ 133 | 134 | for (i = 0; i < hash_table->table_size; ++i) { 135 | rover = hash_table->table[i]; 136 | while (rover != NULL) { 137 | next = rover->next; 138 | hash_table_free_entry(hash_table, rover); 139 | rover = next; 140 | } 141 | } 142 | 143 | /* Free the table */ 144 | 145 | free(hash_table->table); 146 | 147 | /* Free the hash table structure */ 148 | 149 | free(hash_table); 150 | } 151 | 152 | void hash_table_register_free_functions(HashTable *hash_table, 153 | HashTableKeyFreeFunc key_free_func, 154 | HashTableValueFreeFunc value_free_func) { 155 | hash_table->key_free_func = key_free_func; 156 | hash_table->value_free_func = value_free_func; 157 | } 158 | 159 | 160 | static int hash_table_enlarge(HashTable *hash_table) { 161 | HashTableEntry **old_table; 162 | unsigned int old_table_size; 163 | unsigned int old_prime_index; 164 | HashTableEntry *rover; 165 | HashTablePair *pair; 166 | HashTableEntry *next; 167 | unsigned int index; 168 | unsigned int i; 169 | 170 | /* Store a copy of the old table */ 171 | 172 | old_table = hash_table->table; 173 | old_table_size = hash_table->table_size; 174 | old_prime_index = hash_table->prime_index; 175 | 176 | /* Allocate a new, larger table */ 177 | 178 | ++hash_table->prime_index; 179 | 180 | if (!hash_table_allocate_table(hash_table)) { 181 | 182 | /* Failed to allocate the new table */ 183 | 184 | hash_table->table = old_table; 185 | hash_table->table_size = old_table_size; 186 | hash_table->prime_index = old_prime_index; 187 | 188 | return 0; 189 | } 190 | 191 | /* Link all entries from all chains into the new table */ 192 | 193 | for (i = 0; i < old_table_size; ++i) { 194 | rover = old_table[i]; 195 | 196 | while (rover != NULL) { 197 | next = rover->next; 198 | 199 | /* Fetch rover HashTablePair */ 200 | 201 | pair = &(rover->pair); 202 | 203 | /* Find the index into the new table */ 204 | 205 | index = hash_table->hash_func(pair->key) % hash_table->table_size; 206 | 207 | /* Link this entry into the chain */ 208 | 209 | rover->next = hash_table->table[index]; 210 | hash_table->table[index] = rover; 211 | 212 | /* Advance to next in the chain */ 213 | 214 | rover = next; 215 | } 216 | } 217 | 218 | /* Free the old table */ 219 | 220 | free(old_table); 221 | 222 | return 1; 223 | } 224 | 225 | int hash_table_insert(HashTable *hash_table, HashTableKey key, 226 | HashTableValue value) { 227 | HashTableEntry *rover; 228 | HashTablePair *pair; 229 | HashTableEntry *newentry; 230 | unsigned int index; 231 | 232 | /* If there are too many items in the table with respect to the table 233 | * size, the number of hash collisions increases and performance 234 | * decreases. Enlarge the table size to prevent this happening */ 235 | 236 | if ((hash_table->entries * 3) / hash_table->table_size > 0) { 237 | 238 | /* Table is more than 1/3 full */ 239 | 240 | if (!hash_table_enlarge(hash_table)) { 241 | 242 | /* Failed to enlarge the table */ 243 | 244 | return 0; 245 | } 246 | } 247 | 248 | /* Generate the hash of the key and hence the index into the table */ 249 | 250 | index = hash_table->hash_func(key) % hash_table->table_size; 251 | 252 | /* Traverse the chain at this location and look for an existing 253 | * entry with the same key */ 254 | 255 | rover = hash_table->table[index]; 256 | 257 | while (rover != NULL) { 258 | 259 | /* Fetch rover's HashTablePair entry */ 260 | 261 | pair = &(rover->pair); 262 | 263 | if (hash_table->equal_func(pair->key, key) != 0) { 264 | 265 | /* Same key: overwrite this entry with new data */ 266 | 267 | /* If there is a value free function, free the old data 268 | * before adding in the new data */ 269 | 270 | if (hash_table->value_free_func != NULL) { 271 | hash_table->value_free_func(pair->value); 272 | } 273 | 274 | /* Same with the key: use the new key value and free 275 | * the old one */ 276 | 277 | if (hash_table->key_free_func != NULL) { 278 | hash_table->key_free_func(pair->key); 279 | } 280 | 281 | pair->key = key; 282 | pair->value = value; 283 | 284 | /* Finished */ 285 | 286 | return 1; 287 | } 288 | 289 | rover = rover->next; 290 | } 291 | 292 | /* Not in the hash table yet. Create a new entry */ 293 | 294 | newentry = (HashTableEntry *) malloc(sizeof(HashTableEntry)); 295 | 296 | if (newentry == NULL) { 297 | return 0; 298 | } 299 | 300 | newentry->pair.key = key; 301 | newentry->pair.value = value; 302 | 303 | /* Link into the list */ 304 | 305 | newentry->next = hash_table->table[index]; 306 | hash_table->table[index] = newentry; 307 | 308 | /* Maintain the count of the number of entries */ 309 | 310 | ++hash_table->entries; 311 | 312 | /* Added successfully */ 313 | 314 | return 1; 315 | } 316 | 317 | HashTableValue hash_table_lookup(HashTable *hash_table, HashTableKey key) { 318 | HashTableEntry *rover; 319 | HashTablePair *pair; 320 | unsigned int index; 321 | 322 | /* Generate the hash of the key and hence the index into the table */ 323 | 324 | index = hash_table->hash_func(key) % hash_table->table_size; 325 | 326 | /* Walk the chain at this index until the corresponding entry is 327 | * found */ 328 | 329 | rover = hash_table->table[index]; 330 | 331 | while (rover != NULL) { 332 | pair = &(rover->pair); 333 | 334 | if (hash_table->equal_func(key, pair->key) != 0) { 335 | 336 | /* Found the entry. Return the data. */ 337 | 338 | return pair->value; 339 | } 340 | 341 | rover = rover->next; 342 | } 343 | 344 | /* Not found */ 345 | 346 | return HASH_TABLE_NULL; 347 | } 348 | 349 | int hash_table_remove(HashTable *hash_table, HashTableKey key) { 350 | HashTableEntry **rover; 351 | HashTableEntry *entry; 352 | HashTablePair *pair; 353 | unsigned int index; 354 | int result; 355 | 356 | /* Generate the hash of the key and hence the index into the table */ 357 | 358 | index = hash_table->hash_func(key) % hash_table->table_size; 359 | 360 | /* Rover points at the pointer which points at the current entry 361 | * in the chain being inspected. ie. the entry in the table, or 362 | * the "next" pointer of the previous entry in the chain. This 363 | * allows us to unlink the entry when we find it. */ 364 | 365 | result = 0; 366 | rover = &hash_table->table[index]; 367 | 368 | while (*rover != NULL) { 369 | 370 | pair = &((*rover)->pair); 371 | 372 | if (hash_table->equal_func(key, pair->key) != 0) { 373 | 374 | /* This is the entry to remove */ 375 | 376 | entry = *rover; 377 | 378 | /* Unlink from the list */ 379 | 380 | *rover = entry->next; 381 | 382 | /* Destroy the entry structure */ 383 | 384 | hash_table_free_entry(hash_table, entry); 385 | 386 | /* Track count of entries */ 387 | 388 | --hash_table->entries; 389 | 390 | result = 1; 391 | 392 | break; 393 | } 394 | 395 | /* Advance to the next entry */ 396 | 397 | rover = &((*rover)->next); 398 | } 399 | 400 | return result; 401 | } 402 | 403 | unsigned int hash_table_num_entries(HashTable *hash_table) { 404 | return hash_table->entries; 405 | } 406 | 407 | void hash_table_iterate(HashTable *hash_table, HashTableIterator *iterator) { 408 | unsigned int chain; 409 | 410 | iterator->hash_table = hash_table; 411 | 412 | /* Default value of next if no entries are found. */ 413 | 414 | iterator->next_entry = NULL; 415 | 416 | /* Find the first entry */ 417 | 418 | for (chain = 0; chain < hash_table->table_size; ++chain) { 419 | 420 | if (hash_table->table[chain] != NULL) { 421 | iterator->next_entry = hash_table->table[chain]; 422 | iterator->next_chain = chain; 423 | break; 424 | } 425 | } 426 | } 427 | 428 | int hash_table_iter_has_more(HashTableIterator *iterator) { 429 | return iterator->next_entry != NULL; 430 | } 431 | 432 | HashTablePair hash_table_iter_next(HashTableIterator *iterator) { 433 | HashTableEntry *current_entry; 434 | HashTable *hash_table; 435 | HashTablePair pair = {NULL, NULL}; 436 | unsigned int chain; 437 | 438 | hash_table = iterator->hash_table; 439 | 440 | if (iterator->next_entry == NULL) { 441 | return pair; 442 | } 443 | 444 | /* Result is immediately available */ 445 | 446 | current_entry = iterator->next_entry; 447 | pair = current_entry->pair; 448 | 449 | /* Find the next entry */ 450 | 451 | if (current_entry->next != NULL) { 452 | 453 | /* Next entry in current chain */ 454 | 455 | iterator->next_entry = current_entry->next; 456 | 457 | } else { 458 | 459 | /* None left in this chain, so advance to the next chain */ 460 | 461 | chain = iterator->next_chain + 1; 462 | 463 | /* Default value if no next chain found */ 464 | 465 | iterator->next_entry = NULL; 466 | 467 | while (chain < hash_table->table_size) { 468 | 469 | /* Is there anything in this chain? */ 470 | 471 | if (hash_table->table[chain] != NULL) { 472 | iterator->next_entry = hash_table->table[chain]; 473 | break; 474 | } 475 | 476 | /* Try the next chain */ 477 | 478 | ++chain; 479 | } 480 | 481 | iterator->next_chain = chain; 482 | } 483 | 484 | return pair; 485 | } 486 | 487 | 488 | -------------------------------------------------------------------------------- /algorithms/trie.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "trie.h" 5 | 6 | /* malloc() / free() testing */ 7 | 8 | #ifdef ALLOC_TESTING 9 | #include "alloc-testing.h" 10 | #endif 11 | 12 | typedef struct _TrieNode TrieNode; 13 | 14 | struct _TrieNode { 15 | TrieValue data; 16 | unsigned int use_count; 17 | TrieNode *next[256]; 18 | }; 19 | 20 | struct _Trie { 21 | TrieNode *root_node; 22 | }; 23 | 24 | Trie *trie_new(void) { 25 | Trie *new_trie; 26 | 27 | new_trie = (Trie *) malloc(sizeof(Trie)); 28 | 29 | if (new_trie == NULL) { 30 | return NULL; 31 | } 32 | 33 | new_trie->root_node = NULL; 34 | 35 | return new_trie; 36 | } 37 | 38 | static void trie_free_list_push(TrieNode **list, TrieNode *node) { 39 | node->data = *list; 40 | *list = node; 41 | } 42 | 43 | static TrieNode *trie_free_list_pop(TrieNode **list) { 44 | TrieNode *result; 45 | 46 | result = *list; 47 | *list = result->data; 48 | 49 | return result; 50 | } 51 | 52 | void trie_free(Trie *trie) { 53 | TrieNode *free_list; 54 | TrieNode *node; 55 | int i; 56 | 57 | free_list = NULL; 58 | 59 | /* Start with the root node */ 60 | 61 | if (trie->root_node != NULL) { 62 | trie_free_list_push(&free_list, trie->root_node); 63 | } 64 | 65 | /* Go through the free list, freeing nodes. We add new nodes as 66 | * we encounter them; in this way, all the nodes are freed 67 | * non-recursively. */ 68 | 69 | while (free_list != NULL) { 70 | node = trie_free_list_pop(&free_list); 71 | 72 | /* Add all children of this node to the free list */ 73 | 74 | for (i = 0; i < 256; ++i) { 75 | if (node->next[i] != NULL) { 76 | trie_free_list_push(&free_list, node->next[i]); 77 | } 78 | } 79 | 80 | /* Free the node */ 81 | 82 | free(node); 83 | } 84 | 85 | /* Free the trie */ 86 | 87 | free(trie); 88 | } 89 | 90 | static TrieNode *trie_find_end(Trie *trie, char *key) { 91 | TrieNode *node; 92 | char *p; 93 | 94 | /* Search down the trie until the end of string is reached */ 95 | 96 | node = trie->root_node; 97 | 98 | for (p = key; *p != '\0'; ++p) { 99 | 100 | if (node == NULL) { 101 | /* Not found in the tree. Return. */ 102 | 103 | return NULL; 104 | } 105 | 106 | /* Jump to the next node */ 107 | 108 | node = node->next[(unsigned char) *p]; 109 | } 110 | 111 | /* This key is present if the value at the last node is not NULL */ 112 | 113 | return node; 114 | } 115 | 116 | static TrieNode *trie_find_end_binary(Trie *trie, unsigned char *key, 117 | int key_length) { 118 | TrieNode *node; 119 | int j; 120 | int c; 121 | 122 | /* Search down the trie until the end of string is reached */ 123 | 124 | node = trie->root_node; 125 | 126 | for (j = 0; j < key_length; j++) { 127 | 128 | if (node == NULL) { 129 | /* Not found in the tree. Return. */ 130 | return NULL; 131 | } 132 | 133 | c = (unsigned char) key[j]; 134 | 135 | /* Jump to the next node */ 136 | 137 | node = node->next[c]; 138 | } 139 | 140 | /* This key is present if the value at the last node is not NULL */ 141 | 142 | return node; 143 | } 144 | 145 | /* Roll back an insert operation after a failed malloc() call. */ 146 | 147 | static void trie_insert_rollback(Trie *trie, unsigned char *key) { 148 | TrieNode *node; 149 | TrieNode **prev_ptr; 150 | TrieNode *next_node; 151 | TrieNode **next_prev_ptr; 152 | unsigned char *p; 153 | 154 | /* Follow the chain along. We know that we will never reach the 155 | * end of the string because trie_insert never got that far. As a 156 | * result, it is not necessary to check for the end of string 157 | * delimiter (NUL) */ 158 | 159 | node = trie->root_node; 160 | prev_ptr = &trie->root_node; 161 | p = key; 162 | 163 | while (node != NULL) { 164 | 165 | /* Find the next node now. We might free this node. */ 166 | 167 | next_prev_ptr = &node->next[(unsigned char) *p]; 168 | next_node = *next_prev_ptr; 169 | ++p; 170 | 171 | /* Decrease the use count and free the node if it 172 | * reaches zero. */ 173 | 174 | --node->use_count; 175 | 176 | if (node->use_count == 0) { 177 | free(node); 178 | 179 | if (prev_ptr != NULL) { 180 | *prev_ptr = NULL; 181 | } 182 | 183 | next_prev_ptr = NULL; 184 | } 185 | 186 | /* Update pointers */ 187 | 188 | node = next_node; 189 | prev_ptr = next_prev_ptr; 190 | } 191 | } 192 | 193 | int trie_insert(Trie *trie, char *key, TrieValue value) { 194 | TrieNode **rover; 195 | TrieNode *node; 196 | char *p; 197 | int c; 198 | 199 | /* Cannot insert NULL values */ 200 | 201 | if (value == TRIE_NULL) { 202 | return 0; 203 | } 204 | 205 | /* Search to see if this is already in the tree */ 206 | 207 | node = trie_find_end(trie, key); 208 | 209 | /* Already in the tree? If so, replace the existing value and 210 | * return success. */ 211 | 212 | if (node != NULL && node->data != TRIE_NULL) { 213 | node->data = value; 214 | return 1; 215 | } 216 | 217 | /* Search down the trie until we reach the end of string, 218 | * creating nodes as necessary */ 219 | 220 | rover = &trie->root_node; 221 | p = key; 222 | 223 | for (; ;) { 224 | 225 | node = *rover; 226 | 227 | if (node == NULL) { 228 | 229 | /* Node does not exist, so create it */ 230 | 231 | node = (TrieNode *) calloc(1, sizeof(TrieNode)); 232 | 233 | if (node == NULL) { 234 | 235 | /* Allocation failed. Go back and undo 236 | * what we have done so far. */ 237 | 238 | trie_insert_rollback(trie, 239 | (unsigned char *) key); 240 | 241 | return 0; 242 | } 243 | 244 | node->data = TRIE_NULL; 245 | 246 | /* Link in to the trie */ 247 | 248 | *rover = node; 249 | } 250 | 251 | /* Increase the node use count */ 252 | 253 | ++node->use_count; 254 | 255 | /* Current character */ 256 | 257 | c = (unsigned char) *p; 258 | 259 | /* Reached the end of string? If so, we're finished. */ 260 | 261 | if (c == '\0') { 262 | 263 | /* Set the data at the node we have reached */ 264 | 265 | node->data = value; 266 | 267 | break; 268 | } 269 | 270 | /* Advance to the next node in the chain */ 271 | 272 | rover = &node->next[c]; 273 | ++p; 274 | } 275 | 276 | return 1; 277 | } 278 | 279 | 280 | int trie_insert_binary(Trie *trie, unsigned char *key, int key_length, 281 | TrieValue value) { 282 | TrieNode **rover; 283 | TrieNode *node; 284 | int p, c; 285 | 286 | /* Cannot insert NULL values */ 287 | 288 | if (value == TRIE_NULL) { 289 | return 0; 290 | } 291 | 292 | /* Search to see if this is already in the tree */ 293 | 294 | node = trie_find_end_binary(trie, key, key_length); 295 | 296 | /* Already in the tree? If so, replace the existing value and 297 | * return success. */ 298 | 299 | if (node != NULL && node->data != TRIE_NULL) { 300 | node->data = value; 301 | return 1; 302 | } 303 | 304 | /* Search down the trie until we reach the end of string, 305 | * creating nodes as necessary */ 306 | 307 | rover = &trie->root_node; 308 | p = 0; 309 | 310 | for (; ;) { 311 | 312 | node = *rover; 313 | 314 | if (node == NULL) { 315 | 316 | /* Node does not exist, so create it */ 317 | 318 | node = (TrieNode *) calloc(1, sizeof(TrieNode)); 319 | 320 | if (node == NULL) { 321 | 322 | /* Allocation failed. Go back and undo 323 | * what we have done so far. */ 324 | 325 | trie_insert_rollback(trie, key); 326 | 327 | return 0; 328 | } 329 | 330 | node->data = TRIE_NULL; 331 | 332 | /* Link in to the trie */ 333 | 334 | *rover = node; 335 | } 336 | 337 | /* Increase the node use count */ 338 | 339 | ++node->use_count; 340 | 341 | /* Current character */ 342 | 343 | c = (unsigned char) key[p]; 344 | 345 | /* Reached the end of string? If so, we're finished. */ 346 | 347 | if (p == key_length) { 348 | 349 | /* Set the data at the node we have reached */ 350 | 351 | node->data = value; 352 | 353 | break; 354 | } 355 | 356 | /* Advance to the next node in the chain */ 357 | 358 | rover = &node->next[c]; 359 | ++p; 360 | } 361 | 362 | return 1; 363 | } 364 | 365 | int trie_remove_binary(Trie *trie, unsigned char *key, int key_length) { 366 | TrieNode *node; 367 | TrieNode *next; 368 | TrieNode **last_next_ptr; 369 | int p, c; 370 | 371 | /* Find the end node and remove the value */ 372 | 373 | node = trie_find_end_binary(trie, key, key_length); 374 | 375 | if (node != NULL && node->data != TRIE_NULL) { 376 | node->data = TRIE_NULL; 377 | } else { 378 | return 0; 379 | } 380 | 381 | /* Now traverse the tree again as before, decrementing the use 382 | * count of each node. Free back nodes as necessary. */ 383 | 384 | node = trie->root_node; 385 | last_next_ptr = &trie->root_node; 386 | p = 0; 387 | 388 | for (; ;) { 389 | 390 | /* Find the next node */ 391 | c = (unsigned char) key[p]; 392 | next = node->next[c]; 393 | 394 | /* Free this node if necessary */ 395 | 396 | --node->use_count; 397 | 398 | if (node->use_count <= 0) { 399 | free(node); 400 | 401 | /* Set the "next" pointer on the previous node to NULL, 402 | * to unlink the freed node from the tree. This only 403 | * needs to be done once in a remove. After the first 404 | * unlink, all further nodes are also going to be 405 | * free'd. */ 406 | 407 | if (last_next_ptr != NULL) { 408 | *last_next_ptr = NULL; 409 | last_next_ptr = NULL; 410 | } 411 | } 412 | 413 | /* Go to the next character or finish */ 414 | if (p == key_length) { 415 | break; 416 | } else { 417 | ++p; 418 | } 419 | 420 | /* If necessary, save the location of the "next" pointer 421 | * so that it may be set to NULL on the next iteration if 422 | * the next node visited is freed. */ 423 | 424 | if (last_next_ptr != NULL) { 425 | last_next_ptr = &node->next[c]; 426 | } 427 | 428 | /* Jump to the next node */ 429 | 430 | node = next; 431 | } 432 | 433 | /* Removed successfully */ 434 | 435 | return 1; 436 | } 437 | 438 | int trie_remove(Trie *trie, char *key) { 439 | TrieNode *node; 440 | TrieNode *next; 441 | TrieNode **last_next_ptr; 442 | char *p; 443 | int c; 444 | 445 | /* Find the end node and remove the value */ 446 | 447 | node = trie_find_end(trie, key); 448 | 449 | if (node != NULL && node->data != TRIE_NULL) { 450 | node->data = TRIE_NULL; 451 | } else { 452 | return 0; 453 | } 454 | 455 | /* Now traverse the tree again as before, decrementing the use 456 | * count of each node. Free back nodes as necessary. */ 457 | 458 | node = trie->root_node; 459 | last_next_ptr = &trie->root_node; 460 | p = key; 461 | 462 | for (; ;) { 463 | 464 | /* Find the next node */ 465 | 466 | c = (unsigned char) *p; 467 | next = node->next[c]; 468 | 469 | /* Free this node if necessary */ 470 | 471 | --node->use_count; 472 | 473 | if (node->use_count <= 0) { 474 | free(node); 475 | 476 | /* Set the "next" pointer on the previous node to NULL, 477 | * to unlink the freed node from the tree. This only 478 | * needs to be done once in a remove. After the first 479 | * unlink, all further nodes are also going to be 480 | * free'd. */ 481 | 482 | if (last_next_ptr != NULL) { 483 | *last_next_ptr = NULL; 484 | last_next_ptr = NULL; 485 | } 486 | } 487 | 488 | /* Go to the next character or finish */ 489 | 490 | if (c == '\0') { 491 | break; 492 | } else { 493 | ++p; 494 | } 495 | 496 | /* If necessary, save the location of the "next" pointer 497 | * so that it may be set to NULL on the next iteration if 498 | * the next node visited is freed. */ 499 | 500 | if (last_next_ptr != NULL) { 501 | last_next_ptr = &node->next[c]; 502 | } 503 | 504 | /* Jump to the next node */ 505 | 506 | node = next; 507 | } 508 | 509 | /* Removed successfully */ 510 | 511 | return 1; 512 | } 513 | 514 | TrieValue trie_lookup(Trie *trie, char *key) { 515 | TrieNode *node; 516 | 517 | node = trie_find_end(trie, key); 518 | 519 | if (node != NULL) { 520 | return node->data; 521 | } else { 522 | return TRIE_NULL; 523 | } 524 | } 525 | 526 | TrieValue trie_lookup_binary(Trie *trie, unsigned char *key, int key_length) { 527 | TrieNode *node; 528 | 529 | node = trie_find_end_binary(trie, key, key_length); 530 | 531 | if (node != NULL) { 532 | return node->data; 533 | } else { 534 | return TRIE_NULL; 535 | } 536 | } 537 | 538 | unsigned int trie_num_entries(Trie *trie) { 539 | /* To find the number of entries, simply look at the use count 540 | * of the root node. */ 541 | 542 | if (trie->root_node == NULL) { 543 | return 0; 544 | } else { 545 | return trie->root_node->use_count; 546 | } 547 | } 548 | 549 | --------------------------------------------------------------------------------