├── README.md ├── algorithm ├── compress │ ├── bit.c │ ├── bit.h │ ├── compress.h │ └── huffman.c ├── nummeths │ ├── interpol.c │ ├── lsqe.c │ ├── nummeths.h │ └── root.c └── sort │ ├── bisearch.c │ ├── bisearch.h │ ├── ctsort.c │ ├── directls.c │ ├── directls.h │ ├── issort.c │ ├── mgsort.c │ ├── qksort.c │ ├── rxsort.c │ ├── sort.h │ ├── spell.c │ └── spell.h └── data_structure ├── bfs.c ├── bfs.h ├── bistree.c ├── bistree.h ├── bitree.c ├── bitree.h ├── chtbl.c ├── chtbl.h ├── clist.c ├── clist.h ├── cover.c ├── cover.h ├── dfs.c ├── dfs.h ├── dlist.c ├── dlist.h ├── fact.c ├── graph.c ├── graph.h ├── heap.c ├── heap.h ├── list.c ├── list.h ├── ohtbl.c ├── ohtbl.h ├── parcel.h ├── parcels.c ├── parcels.h ├── pqueue.h ├── queue.c ├── queue.h ├── set.c ├── set.h ├── stack.c └── stack.h /README.md: -------------------------------------------------------------------------------- 1 | # 算法精解-C语言描述 2 | 3 | 该项目是《算法精解-C语言描述》这本书上的一些代码。 4 | 在我一边看书的时候,一边将书中的代码敲了一遍,并添加了一些自己的理解。 5 | 同时给书中的代码添加了索引,方便以后复习和查找。 6 | 7 | ## 数据结构 8 | 9 | - [递归与尾递归](./data_structure/fact.c) 10 | - [单链表](./data_structure/list.c) 11 | - [单向循环链表](./data_structure/clist.c) 12 | - [双向循环链表](./data_structure/dlist.c) 13 | - [栈](./data_structure/stack.c) 14 | - [队列](./data_structure/queue.c) 15 | - [集合](./data_structure/set.c) 16 | - [集合应用:集合覆盖](./data_structure/cover.c) 17 | - [链式哈希表](./data_structure/chtbl.c) 18 | - [开地址哈希表](./data_structure/ohtbl.c) 19 | - [二叉树](./data_structure/bitree.c) 20 | - [二叉搜索树、平衡二叉树](./data_structure/bistree.c) 21 | - [堆](./data_structure/heap.c) 22 | - [优先队列](./data_structure/pqueue.h) 23 | - [优先队列应用:包裹分拣](./data_structure/parcels.c) 24 | - [图](./data_structure/graph.c) 25 | - [图的广度优先搜索](./data_structure/bfs.c) 26 | - [图的深度优先搜索](./data_structure/bfs.c) 27 | 28 | ## 算法 29 | 30 | ### 排序 31 | 32 | - [插入排序](./algorithm/sort/issort.c) 33 | - [快速排序](./algorithm/sort/qksort.c) 34 | - [归并排序](./algorithm/sort/mgsort.c) 35 | - [计数排序](./algorithm/sort/ctsort.c) 36 | - [归并排序](./algorithm/sort/rxsort.c) 37 | - [二分查找](./algorithm/sort/bisearch.c) 38 | 39 | ### 数值计算 40 | 41 | - [多项式插值的实现](./algorithm/nummeths/interpol.c) 42 | - [最小二乘估计](./algorithm/nummeths/lsqe.c) 43 | - [方程求解](./algorithm/nummeths/root.c) 44 | 45 | ### 数据压缩 46 | 47 | -------------------------------------------------------------------------------- /algorithm/compress/bit.c: -------------------------------------------------------------------------------- 1 | // bit.c,位操作 2 | 3 | #include "bit.h" 4 | 5 | /** 6 | * 获取某一位的值 7 | * @param bits 字符数组 8 | * @param pos 位置,从高位开始计算 9 | * @return 返回该位置的值 10 | */ 11 | int bit_get(const unsigned char *bits, int pos) 12 | { 13 | unsigned char mask; 14 | int i; 15 | 16 | mask = 0x80; 17 | 18 | for (i = 0; i < (pos % 8); i++) 19 | mask = mask >> 1; 20 | 21 | return (mask & bits[pos / 8]) == mask ? 1 : 0; 22 | } 23 | // int bit_get(const unsigned char *bits, int pos) 24 | // { 25 | // unsigned char mask; 26 | // int i; 27 | 28 | // mask = 0x01; 29 | 30 | // for (i = 0; i < (pos % 8); i++) 31 | // mask = mask << 1; 32 | 33 | // return (mask & bits[pos / 8]) == mask ? 1 : 0; 34 | // } 35 | 36 | /** 37 | * 设置某一位的值 38 | * @param bits 字符数组 39 | * @param pos 位置 40 | * @param state 要设置的值 41 | */ 42 | void bit_set(unsigned char *bits, int pos, int state) 43 | { 44 | unsigned char mask; 45 | int i; 46 | 47 | mask = 0x80; 48 | 49 | for (i = 0; i < pos % 8; i++) 50 | mask = mask >> 1; 51 | 52 | if (state) 53 | bits[pos / 8] = bits[pos / 8] | mask; 54 | else 55 | bits[pos / 8] = bits[pos / 8] & (~mask); 56 | } 57 | 58 | /** 59 | * 对bits1和bits2进行异或,结果放在bitsx中,size表示要异或的数据大小。 60 | * @param bits1 [description] 61 | * @param bits2 [description] 62 | * @param bitsx [description] 63 | * @param size [description] 64 | */ 65 | void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned 66 | char *bitsx, int size) 67 | { 68 | int i; 69 | for (i = 0; i < size; i++) { 70 | if (bit_get(bits1, i) != bit_get(bits2, i)) 71 | bit_set(bitsx, i, 1); 72 | else 73 | bit_set(bitsx, i, 0); 74 | } 75 | } 76 | 77 | /** 78 | * 将缓冲区中指定数量的位向左轮转。 79 | * @param bits [description] 80 | * @param size [description] 81 | * @param count [description] 82 | */ 83 | void bit_rot_left(unsigned char *bits, int size, int count) 84 | { 85 | int fbit, lbit, i, j; 86 | 87 | if (size > 0) { 88 | for (j = 0; j < count; j++) { 89 | for (i = 0; i <= ((size - 1) / 8); i++) { 90 | lbit = bit_get(&bits[i], 0); 91 | if (i == 0) { 92 | fbit = lbit; 93 | } else { 94 | bit_set(&bits[i - 1], 7, lbit); 95 | } 96 | bits[i] = bits[i] << 1; 97 | } 98 | 99 | bit_set(bits, size - 1, fbit); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /algorithm/compress/bit.h: -------------------------------------------------------------------------------- 1 | // bit.h 2 | #ifndef BIT_H 3 | #define BIT_H 4 | 5 | int bit_get(const unsigned char *bits, int pos); 6 | 7 | void bit_set(unsigned char *bits, int pos, int state); 8 | 9 | void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned 10 | char *bitsx, int size); 11 | 12 | void bit_rot_left(unsigned char *bits, int size, int count); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /algorithm/compress/compress.h: -------------------------------------------------------------------------------- 1 | // compress.h,数据压缩头文件 2 | #ifndef COMPRESS_H 3 | #define COMPRESS_H 4 | 5 | #include "../../data_structure/bitree.h" 6 | 7 | 8 | typedef struct HuffNode_ { 9 | unsigned char symbol; 10 | int freq; 11 | } HuffNode; 12 | 13 | typedef struct HuffCode_ { 14 | unsigned char used; 15 | unsigned short code; 16 | unsigned char size; 17 | } HuffCode; 18 | 19 | #define LZ77_TYPE_BITS 1 20 | #define LZ77_WINOFF_BITS 12 21 | #define LZ77_BUFLEN_BITS 5 22 | #define LZ77_NEXT_BITS 8 23 | 24 | #define LZ77_WINDOW_SIZE 4096 25 | #define LZ77_BUFFER_SIZE 32 26 | 27 | #define LZ77_PHRASE_BITS (LZ77_TYPE_BITS+LZ77_WINOFF_BITS\ 28 | +LZ77_NEXT_BITS+LZ77_BUFLEN_BITS) 29 | #define LZ77_SYMBOL_BITS (LZ77_TYPE_BITS+LZ77_NEXT_BITS) 30 | 31 | 32 | /** 33 | * 霍夫曼压缩 34 | * @param original 原始数据 35 | * @param compressed 用于存放压缩后的数据 36 | * @param size 原始数据的大小 37 | * @return 成功,返回压缩后数据的字节数;否则,返回-1 38 | */ 39 | int huffman_compress(const unsigned char *original, unsigned char 40 | **compressed, int size); 41 | 42 | /** 43 | * 霍夫曼解压缩 44 | * @param compressed 压缩后的数据 45 | * @param original 解压后的原始数据 46 | * @return 成功:返回恢复后数据的字节数;失败:-1 47 | */ 48 | int huffman_uncompress(const unsigned char *compressed, unsigned char 49 | **original); 50 | 51 | int lz77_compress(const unsigned char *original, unsigned char **compressed, 52 | int size); 53 | 54 | int lz77_uncompress(const unsigned char *compressed, unsigned char 55 | **original); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /algorithm/compress/huffman.c: -------------------------------------------------------------------------------- 1 | // huffman.c 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "bit.h" 8 | #include "compress.h" 9 | #include "../../data_structure/pqueue.h" 10 | 11 | static int compare_freq(const void *tree1, const void *tree2) 12 | { 13 | HuffNode *root1, *root2; 14 | 15 | root1 = (HuffNode *)bitree_data(bitree_root((const BiTree *)tree1)); 16 | root2 = (HuffNode *)bitree_data(bitree_root((const BiTree *)tree2)); 17 | 18 | if (root1->freq < root2->freq) 19 | return 1; 20 | else if (root1->freq > root2->freq) 21 | return -1; 22 | else 23 | return 0; 24 | } 25 | 26 | static void destroy_tree(void *tree) 27 | { 28 | bittree_destroy(tree); 29 | free(tree); 30 | } 31 | 32 | static int build_tree(int *freqs, BiTree **tree) 33 | { 34 | BiTree *init, *merge, *left, *right; 35 | PQueue pqueue; 36 | HuffNode *data; 37 | int size, c; 38 | 39 | *tree = NULL; 40 | 41 | for (c = 0; c <= UCHAR_MAX; c++) { 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /algorithm/nummeths/interpol.c: -------------------------------------------------------------------------------- 1 | // interpol.c,多项式插值的实现 2 | #include 3 | #include 4 | 5 | #include "nummeths.h" 6 | 7 | /** 8 | * 采用多项式插值法求得函数在某些特定点上的值 9 | * @param x 函数已知的点集 10 | * @param fx 每个已知点集对应的函数值 11 | * @param n 已知点集的个数 12 | * @param z 待求得点集 13 | * @param pz 待求点集得到的值 14 | * @param m 待求点集个数 15 | * @return 成功返回0;失败返回-1 16 | */ 17 | int interpol(const double *x, const double *fx, int n, double *z, 18 | double *pz, int m) 19 | { 20 | // coeff用来保存系数 21 | double term, *table, *coeff; 22 | int i, j, k; 23 | 24 | if ((table = (double *)malloc(sizeof(double) * n)) == NULL) 25 | return -1; 26 | 27 | if ((coeff = (double *)malloc(sizeof(double) * n)) == NULL) { 28 | free(table); 29 | return -1; 30 | } 31 | 32 | // 给第一行赋值 33 | memcpy(table, fx, sizeof(double) * n); 34 | coeff[0] = table[0]; 35 | 36 | // 计算每一层的系数 37 | for (k = 1; k < n; k++) { 38 | for (i = 0; i < n - k; i++) { 39 | j = i + k; 40 | table[i] = (table[i + 1] - table[i]) / (x[j] - x[i]); 41 | } 42 | coeff[k] = table[0]; 43 | } 44 | free(table); 45 | 46 | // 计算指定的z点的值 47 | for (k = 0; k < m; k++) { 48 | pz[k] = coeff[0]; 49 | for (j = 1; j < n; j++) { 50 | term = coeff[j]; 51 | for (i = 0; i < j; i++) 52 | term = term * (z[k] - x[i]); 53 | 54 | pz[k] = pz[k] + term; 55 | } 56 | } 57 | 58 | free(coeff); 59 | return 0; 60 | } 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /algorithm/nummeths/lsqe.c: -------------------------------------------------------------------------------- 1 | // lsqe.c,最小二乘估计 2 | #include 3 | 4 | #include "nummeths.h" 5 | 6 | void lsqe(const double *x, const double *y, 7 | int n, double *b1, double *b0) 8 | { 9 | double sumx, sumy, sumx2, sumxy; 10 | int i; 11 | 12 | sumx = 0.0; 13 | sumy = 0.0; 14 | sumx2 = 0.0; 15 | sumxy = 0.0; 16 | 17 | for (i = 0; i < n; i++) { 18 | sumx = sumx + x[i]; 19 | sumy = sumy + y[i]; 20 | sumx2 = sumx2 + pow(x[i], 2.0); 21 | sumxy = sumxy + (x[i] * y[i]); 22 | } 23 | 24 | *b1 = (sumxy - ((sumx * sumy) / (double)n)) / 25 | (sumx2 - (pow(sumx, 2.0) / (double)n)); 26 | *b0 = (sumy - ((*b1) * sumx)) / (double)n; 27 | } -------------------------------------------------------------------------------- /algorithm/nummeths/nummeths.h: -------------------------------------------------------------------------------- 1 | #ifndef NUMMETHS_H 2 | #define NUMMETHS_H 3 | 4 | int interpol(const double *x, const double *fx, int n, double *z, double *pz, 5 | int m); 6 | 7 | void lsqe(const double *x, const double *y, int n, double *b1, double *b0); 8 | 9 | int root(double (*f)(double x), double (*g)(double x), double *x, int *n, 10 | double delta); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /algorithm/nummeths/root.c: -------------------------------------------------------------------------------- 1 | // root.c,方程求解 2 | #include 3 | #include "nummeths.h" 4 | 5 | /** 6 | * f:函数f 7 | * g:函数f的导数 8 | * x:初始值为x[0],迭代过程中计算出的近似值也都保存在数组x中 9 | * n:代表迭代的最大次数 10 | * delta:表示一个可接受的差值 11 | */ 12 | int root(double (*f)(double x), double (*g)(double x), double *x, int *n, 13 | double delta) 14 | { 15 | int satisfied, i; 16 | 17 | i = 0; 18 | satisfied = 0; 19 | 20 | while (!satisfied && i + 1 < *n) { 21 | // 这是在干什么?? 22 | x[i + 1] = x[i] - (f(x[i]) / g(x[i])); 23 | 24 | if (fabs(x[i + 1] - x[i]) < delta) 25 | satisfied = 1; 26 | 27 | i++; 28 | } 29 | 30 | if (i == 0) 31 | *n = 1; 32 | else 33 | *n = i + 1; 34 | 35 | if (satisfied) 36 | return 0; 37 | else 38 | return -1; 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /algorithm/sort/bisearch.c: -------------------------------------------------------------------------------- 1 | // bisearch.c,二分查找 2 | #include 3 | #include 4 | 5 | #include "search.h" 6 | 7 | /** 8 | * sorted:排好序的数组 9 | * target:要查找的元素 10 | * size:数组中元素个数 11 | * esize:数组中单个元素大小 12 | * compare:用于比较两个元素大小的函数 13 | */ 14 | int bisearch(void *sorted, const void *target, int size, int esize, int 15 | (*compare)(const void *key1, const void *key2)) 16 | { 17 | int left, middle, right; 18 | 19 | left = 0; 20 | right = size - 1; 21 | 22 | while (left <= right) { 23 | middle = (left + right) / 2; 24 | 25 | switch (compare((char *)sorted + (esize * middle), target)) { 26 | case -1: 27 | left = middle + 1; 28 | break; 29 | case 1: 30 | right = middle - 1; 31 | break; 32 | case 0: 33 | return middle; 34 | } 35 | } 36 | 37 | return -1; 38 | } 39 | -------------------------------------------------------------------------------- /algorithm/sort/bisearch.h: -------------------------------------------------------------------------------- 1 | // bisearch.h,二分查找 2 | #ifndef BISEARCH_H 3 | #define BISEARCH_H 4 | 5 | int bisearch(void *sorted, const void *target, int size, int esize, int 6 | (*compare)(const void *key1, const void *key2)); 7 | 8 | #endif -------------------------------------------------------------------------------- /algorithm/sort/ctsort.c: -------------------------------------------------------------------------------- 1 | // ctsort.c 2 | #include 3 | #include 4 | #include "sort.h" 5 | 6 | /** 7 | * 计数排序 8 | * @param data 用于排序的数据,函数返回后,保存排序后的数据 9 | * @param size 数据个数 10 | * @param k 数据中的最大值 11 | * @return 成功返回0;失败返回-1 12 | */ 13 | int ctsort(int *data, int size, int k) 14 | { 15 | int *counts, *temp; 16 | int i, j; 17 | 18 | if ((counts = (int *)malloc(k * sizeof(int))) == NULL) 19 | return -1; 20 | 21 | if ((temp = (int *)malloc(size * sizeof(int))) == NULL) { 22 | free(counts); 23 | return -1; 24 | } 25 | 26 | // 初始化计数 27 | for (i = 0; i < k; i++) 28 | counts[i] = 0; 29 | 30 | // 开始计数 31 | for (j = 0; j < size; j++) 32 | counts[data[j]] = counts[data[j]] + 1; 33 | 34 | // 调整计数,使后一个计数包含前面的计数, 35 | // 这样就确定了每个数的位置 36 | for (i = 1; i < k; i++) 37 | counts[i] = counts[i] + counts[i - 1]; 38 | 39 | // 将每个数放到对应的位置 40 | for (j = size - 1; j >= 0; j--) { 41 | temp[counts[data[j]] - 1] = data[j]; 42 | counts[data[j]] = counts[data[j]] - 1; 43 | } 44 | 45 | memcpy(data, temp, size * sizeof(int)); 46 | 47 | free(counts); 48 | free(temp); 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /algorithm/sort/directls.c: -------------------------------------------------------------------------------- 1 | // directls.c,快速排序的例子,目录列表 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "directls.h" 8 | #include "sort.h" 9 | 10 | static int compare_dir(const void *key1, const void *key2) 11 | { 12 | int retval; 13 | 14 | if ((retval = strcmp(((const Directory *)key1)->name, 15 | ((const Directory *)key2)->name)) > 0) 16 | return 1; 17 | else if (retval < 0) 18 | return -1; 19 | else 20 | return 0; 21 | } 22 | 23 | int directory(const char *path, Directory **dir) 24 | { 25 | DIR *dirptr; 26 | Directory *temp; 27 | struct dirent *curdir; 28 | int count; 29 | 30 | if ((dirptr = opendir(path)) == NULL) 31 | return -1; 32 | 33 | *dir = NULL; 34 | count = 0; 35 | 36 | while ((curdir = readdir(dirptr)) != NULL) { 37 | count++; 38 | if ((temp = (Directory *)realloc(*dir, count * sizeof(Directory))) == NULL) { 39 | free(*dir); 40 | return -1; 41 | } else { 42 | *dir = temp; 43 | } 44 | 45 | strcpy(((*dir)[count - 1]).name, curdir->d_name); 46 | } 47 | closedir(dirptr); 48 | 49 | if (qksort(*dir, count, sizeof(Directory), 0, count - 1, compare_dir) != 0) 50 | return -1; 51 | 52 | return count; 53 | } 54 | -------------------------------------------------------------------------------- /algorithm/sort/directls.h: -------------------------------------------------------------------------------- 1 | // directls.h,快速排序的例子,目录列表 2 | #ifndef DIRECTLS_H 3 | #define DIRECTLS_H 4 | 5 | #include 6 | 7 | typedef struct Directory_ { 8 | char name[MAXNAMELEN + 1]; 9 | } Directory; 10 | 11 | int directory(const char *path, Directory **dir); 12 | 13 | #endif -------------------------------------------------------------------------------- /algorithm/sort/issort.c: -------------------------------------------------------------------------------- 1 | // issort.c,插入排序,时间复杂度O(n*n) 2 | #include 3 | #include 4 | #include "sort.h" 5 | 6 | /** 7 | * 取出一个结点,与已经排序好的结点对比,然后插入空位中。 8 | * data:保存已经排好序的元素 9 | * size: 元素个数 10 | * esize:每个元素的大小 11 | * compare:比较函数;在增序中,如果key1>key2,函数返回1; 12 | * 如果key1=key2,函数返回0; 13 | * 如果key1= 0 && compare(&a[i * esize], key) > 0) { 30 | memcpy(&a[(i + 1) * esize], &a[i * esize], esize); 31 | i--; 32 | } 33 | memcpy(&a[(i + 1) * esize], key, esize); 34 | } 35 | 36 | free(key); 37 | return 0; 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /algorithm/sort/mgsort.c: -------------------------------------------------------------------------------- 1 | // mgsort.c,归并排序实现 2 | 3 | #include 4 | #include 5 | #include "sort.h" 6 | 7 | /** 8 | * 将两个有序集合并为一个 9 | * data:有序集 10 | * esize:单个元素大小 11 | * i:左边集合的开始位置 12 | * j:中间位置 13 | * k:右边集合的最后位置 14 | * compare:用户传入得用于比较两个数据大小的函数 15 | */ 16 | static int merge(void *data, int esize, int i, int j, int k, 17 | int (*compare)(const void *key1, const void *key2)) 18 | { 19 | char *a = data, *m; 20 | int ipos, jpos, mpos; 21 | 22 | ipos = i;// 指向左边集合 23 | jpos = j + 1;// 指向右边集合 24 | mpos = 0;// 记录现在已经排序好的元素的位置 25 | 26 | if ((m = (char *)malloc(esize * ((k - i) + 1))) == NULL) 27 | return -1; 28 | 29 | while (ipos <= j || jpos <= k) { 30 | if (ipos > j) { 31 | // 左边的已经全部被和并了,现在开始把右边的全部合并 32 | while (jpos <= k) { 33 | memcpy(&m[mpos * esize], &a[jpos * esize], esize); 34 | jpos++; 35 | mpos++; 36 | } 37 | break; 38 | } else if (jpos > k) { 39 | // 右边的已经全部被和并了,现在开始把左边的全部合并 40 | while (ipos <= j) { 41 | memcpy(&m[mpos * esize], &a[ipos * esize], esize); 42 | ipos++; 43 | mpos++; 44 | } 45 | break; 46 | } 47 | 48 | if (compare(&a[ipos * esize], &a[jpos * esize]) < 0) { 49 | memcpy(&m[mpos * esize], &a[ipos * esize], esize); 50 | ipos++; 51 | mpos++; 52 | } else { 53 | memcpy(&m[mpos * esize], &a[jpos * esize], esize); 54 | jpos++; 55 | mpos++; 56 | } 57 | } 58 | 59 | memcpy(&a[i * esize], m, esize * ((k - i) + 1)); 60 | 61 | free(m); 62 | 63 | return 0; 64 | } 65 | 66 | /** 67 | * data:data最初包含size个无序元素 68 | * size:元素个数 69 | * esize:单个元素的大小 70 | * i:开始时i设置为0 71 | * k:开始时k设置为size-1 72 | * compare:用户传入得用于比较两个数据大小的函数 73 | */ 74 | int mgsort(void *data, int size, int esize, int i, int k, int (*compare) 75 | (const void *key1, const void *key2)) 76 | { 77 | int j; 78 | if (i < k) { 79 | j = (int)(((i + k - 1)) / 2); 80 | 81 | if (mgsort(data, size, esize, i, j, compare) < 0) 82 | return -1; 83 | 84 | if (mgsort(data, size, esize, j + 1, k, compare) < 0) 85 | return -1; 86 | 87 | if (merge(data, esize, i, j, k, compare) < 0) 88 | return -1; 89 | } 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /algorithm/sort/qksort.c: -------------------------------------------------------------------------------- 1 | // qksort.c,快速排序 2 | #include 3 | #include 4 | 5 | #include "sort.h" 6 | 7 | /** 8 | * 比较两个整数的大小 9 | * @param int1 整数1 10 | * @param int2 整数2 11 | * @return int1>int2返回1,int1 *(const int *)int2) 16 | return 1; 17 | else if (*(const int *)int1 < *(const int *)int2) 18 | return -1; 19 | else 20 | return 0; 21 | } 22 | 23 | /** 24 | * data: 用于排序的数据集合 25 | * esize:元素大小 26 | * i:左边开始位置 27 | * k:右边末尾位置 28 | * compare:比较函数 29 | * return:返回中间位置 30 | */ 31 | static int partition(void *data, int esize, int i, int k, 32 | int (*compare)(const void *key1, const void *key2)) 33 | { 34 | char *a = data; 35 | void *pval, *temp; 36 | int r[3]; 37 | 38 | if ((pval = malloc(esize)) == NULL) 39 | return -1; 40 | 41 | if ((temp = malloc(esize)) == NULL) { 42 | free(pval); 43 | return -1; 44 | } 45 | // 随机计算一个中位数 46 | r[0] = (rand() % (k - i + 1)) + i; 47 | r[1] = (rand() % (k - i + 1)) + i; 48 | r[2] = (rand() % (k - i + 1)) + i; 49 | issort(r, 3, sizeof(int), compare_int); 50 | memcpy(pval, &a[r[1] * esize], esize); 51 | 52 | i--; 53 | k++; 54 | 55 | // 开始对比交换左右两边的数据 56 | while (1) { 57 | do { 58 | k--; 59 | } while (compare(&a[k * esize], pval) > 0); 60 | 61 | do { 62 | i++; 63 | } while (compare(&a[i * esize], pval) < 0); 64 | 65 | if (i >= k) { 66 | break; 67 | } else { 68 | memcpy(temp, &a[i * esize], esize); 69 | memcpy(&a[i * esize], &a[k * esize], esize); 70 | memcpy(&a[k * esize], temp, esize); 71 | } 72 | } 73 | 74 | free(pval); 75 | free(temp); 76 | 77 | return k; 78 | } 79 | 80 | /** 81 | * i:开始时为0 82 | * k:开始时为size-1 83 | */ 84 | int qksort(void *data, int size, int esize, int i, int k, int (*compare) 85 | (const void *key1, const void *key2)) 86 | { 87 | int j; 88 | while (i < k) { 89 | if ((j = partition(data, esize, i, k, compare)) < 0) 90 | return -1; 91 | // 排序左边部分 92 | if (qksort(data, size, esize, i, j, compare) < 0) 93 | return -1; 94 | // 排序右边部分 95 | i = j + 1; 96 | } 97 | return 0; 98 | } -------------------------------------------------------------------------------- /algorithm/sort/rxsort.c: -------------------------------------------------------------------------------- 1 | // rxsort.c 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "sort.h" 8 | 9 | /** 10 | * 基数排序。实质是在元素每一位上应用计数排序来对数据集合排序。 11 | * @param data 用于排序的数据,函数返回后,里面保存的是排好序的内容。 12 | * @param size 元素个数 13 | * @param p 每个整数包含的位数??每个数位数必须一样吗? 14 | * @param k 指定的基数 15 | * @return 成功返回0;失败返回-1 16 | */ 17 | int rxsort(int *data, int size, int p, int k) 18 | { 19 | int *counts, *temp; 20 | int index, pval, i, j, n; 21 | 22 | if ((counts = (int *)malloc(k * sizeof(int))) == NULL) 23 | return -1; 24 | 25 | if ((temp = (int *)malloc(size * sizeof(int))) == NULL) { 26 | free(counts); 27 | return -1; 28 | } 29 | 30 | for (n = 0; n < p; n++) { 31 | for (i = 0; i < k; i++) 32 | counts[i] = 0; 33 | // 计算取哪一个位置的数,k的n次方,比如10,100... 34 | pval = (int)pow((double)k, (double)n); 35 | 36 | // 开始计数 37 | for (j = 0; j < size; j++) { 38 | index = (int)(data[j] / pval) % k; 39 | counts[index] = counts[index] + 1; 40 | } 41 | // 开始计算每个元素的偏移量 42 | for (i = 1; i < k; i++) 43 | counts[i] = counts[i] + counts[i - 1]; 44 | 45 | // 开始排序 46 | for (j = size - 1; j >= 0; j--) { 47 | index = (int)(data[j] / pval) % k; 48 | temp[counts[index] - 1] = data[j]; 49 | counts[index] = counts[index] - 1; 50 | } 51 | 52 | memcpy(data, temp, size * sizeof(int)); 53 | } 54 | 55 | free(counts); 56 | free(temp); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /algorithm/sort/sort.h: -------------------------------------------------------------------------------- 1 | #ifndef SORT_H 2 | #define SORT_H 3 | 4 | // 插入排序 5 | int issort(void *data, int size, int esize, int (*compare)(const void *key1, 6 | const void *key2)); 7 | 8 | // 快速排序 9 | int qksort(void *data, int size, int esize, int i, int k, int (*compare) 10 | (const void *key1, const void *key2)); 11 | 12 | // 归并排序 13 | int mgsort(void *data, int size, int esize, int i, int k, int (*compare) 14 | (const void *key1, const void *key2)); 15 | 16 | // 计数排序 17 | int ctsort(int *data, int size, int k); 18 | 19 | // 基数排序 20 | int rxsort(int *data, int size, int p, int k); 21 | 22 | #endif -------------------------------------------------------------------------------- /algorithm/sort/spell.c: -------------------------------------------------------------------------------- 1 | // spell.c 2 | #include 3 | 4 | #include "bisearch.h" 5 | #include "spell.h" 6 | 7 | static int compare_str(const void *str1, const void *str2) 8 | { 9 | int retval; 10 | 11 | if ((retval = strcmp((const char *)str1, (const char *)str2)) > 0) 12 | return 1; 13 | else if (retval < 0) 14 | return -1; 15 | else 16 | return 0; 17 | } 18 | 19 | // int main(int argc, char const *argv[]) 20 | // { 21 | // char a[2][3] = {{'1','2','3'},{'4','5','6'}}; 22 | // char (*p)[3] = a; 23 | // char b[2][32] = {"hello", "word"}; 24 | // char (*p1)[32] = b; 25 | // int i, j; 26 | 27 | // for (i = 0; i < 2; i++) 28 | // for (j = 0; j < 3; j++) 29 | // printf("%c\n", p[i][j]); 30 | 31 | 32 | // for (i = 0; i < 2; i++) 33 | // printf("%s\n", p1[i]); 34 | 35 | // return 0; 36 | // } 37 | 38 | /** 39 | * dictionary:指向一维数组类型的指针,每个一维数组大小为SPELL_SIZE 40 | * size:dictionary中单词个数 41 | * word:要搜索的单词 42 | */ 43 | int spell(char (*dictionary)[SPELL_SIZE], int size, const char *word) 44 | { 45 | if (bisearch(dictionary, word, size, SPELL_SIZE, compare_str) >= 0) 46 | return 1; 47 | else 48 | return 0; 49 | } -------------------------------------------------------------------------------- /algorithm/sort/spell.h: -------------------------------------------------------------------------------- 1 | // spell.h,使用二分查找实现拼写检查器 2 | #ifndef SPELL_H 3 | #define SPELL_H 4 | 5 | #define SPELL_SIZE 31 6 | 7 | int spell(char (*dictionary)[SPELL_SIZE], int size, const char *word); 8 | 9 | #endif -------------------------------------------------------------------------------- /data_structure/bfs.c: -------------------------------------------------------------------------------- 1 | // bfs.c 2 | #include 3 | #include "bfs.h" 4 | #include "graph.h" 5 | #include "list.h" 6 | #include "queue.h" 7 | 8 | /** 9 | * 图应用举例,计算网络跳数。计算从一个结点到另外一个结点的最佳路径 10 | * 使用广度优先搜索 11 | * @param graph 代表整个网络 12 | * @param start 代表起始顶点 13 | * @param hops 从起始顶点可到达的顶点的链表 14 | * @return 成功返回0;失败非0 15 | */ 16 | int bfs(Graph *graph, BfsVertex *start, List *hops) 17 | { 18 | Queue queue; 19 | AdjList *adjlist, *clr_adjlist; 20 | BfsVertex *clr_vertex, *adj_vertex; 21 | ListElmt *element, *member; 22 | 23 | // 初始化图中所有顶点 24 | for (element = list_head(&graph_adjlists(graph)); element != NULL; 25 | element = list_next(element)) { 26 | clr_vertex = ((AdjList *)list_data(element))->vertex; 27 | // 起始点涂为灰色,其它都涂为白色 28 | if (graph->match(clr_vertex, start)) { 29 | clr_vertex->color = gray; 30 | clr_vertex->hops = 0; 31 | } else { 32 | clr_vertex->color = white; 33 | clr_vertex->hops = -1; 34 | } 35 | } 36 | 37 | // 初始化队列,并将起始邻接表放入队列中 38 | queue_init(&queue, NULL); 39 | if (graph_adjlist(graph, start, &clr_adjlist) != 0) { 40 | queue_destroy(&queue); 41 | return -1; 42 | } 43 | if (queue_enqueue(&queue, clr_adjlist) != 0) { 44 | queue_destroy(&queue); 45 | return -1; 46 | } 47 | 48 | // 开始广度优先搜索 49 | while (queue_size(&queue) > 0) { 50 | adjlist = queue_peek(&queue); 51 | // 遍历当前邻接表中的每一个顶点 52 | for (member = list_head(&adjlist->adjacent); member != NULL; 53 | member = list_next(member)) { 54 | adj_vertex = list_data(member); 55 | // 取出一个邻接表,并修改其顶点的颜色 56 | if (graph_adjlist(graph, adj_vertex, &clr_adjlist) != 0) { 57 | queue_destroy(&queue); 58 | return -1; 59 | } 60 | clr_vertex = clr_adjlist->vertex; 61 | 62 | if (clr_vertex->color == white) { 63 | clr_vertex->color = gray; 64 | clr_vertex->hops = ((BfsVertex *)adjlist->vertex)->hops + 1; 65 | // 将这个邻接表加入队列中 66 | if (queue_enqueue(&queue, clr_adjlist) != 0) { 67 | queue_destroy(&queue); 68 | return -1; 69 | } 70 | } 71 | } 72 | // 将当前邻接表移除队列,并将其颜色涂为黑色 73 | if (queue_dequeue(&queue, (void **)&adjlist) == 0) { 74 | ((BfsVertex *)adjlist->vertex)->color = black; 75 | } else { 76 | queue_destroy(&queue); 77 | return -1; 78 | } 79 | } 80 | 81 | queue_destroy(&queue); 82 | 83 | list_init(hops, NULL); 84 | 85 | for (element = list_head(&graph_adjlists(graph)); element != NULL; 86 | element = list_next(element)) { 87 | clr_vertex = ((AdjList *)list_data(element))->vertex; 88 | if (clr_vertex->hops != -1) { 89 | if (list_ins_next(hops, list_tail(hops), clr_vertex) != 0) { 90 | list_destroy(hops); 91 | return -1; 92 | } 93 | } 94 | } 95 | 96 | return 0; 97 | } -------------------------------------------------------------------------------- /data_structure/bfs.h: -------------------------------------------------------------------------------- 1 | // bfs.h 2 | #ifndef BFS_H 3 | #define BFS_H 4 | 5 | #include "graph.h" 6 | #include "list.h" 7 | 8 | typedef struct BfsVertex_ 9 | { 10 | void *data;//数据域指针 11 | VertexColor color;//搜索过程中维护顶点的颜色 12 | int hops;//维护从起始结点开始到顶点的跳数统计 13 | } BfsVertex; 14 | 15 | int bfs(Graph *graph, BfsVertex *start, List *hops); 16 | 17 | #endif -------------------------------------------------------------------------------- /data_structure/bistree.c: -------------------------------------------------------------------------------- 1 | // bistree.c 2 | #include 3 | #include 4 | #include "bistree.h" 5 | 6 | static void destroy_right(BisTree *tree, BiTreeNode *node); 7 | 8 | static void rotate_left(BiTreeNode **node) 9 | { 10 | BiTreeNode *left, *grandchild; 11 | 12 | left = bitree_left(*node); 13 | if (((AvlNode *)bitree_data(left))->factor == AVL_LFT_HEAVY) { 14 | bitree_left(*node) = bitree_right(left); 15 | bitree_right(left) = *node; 16 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 17 | ((AvlNode *)bitree_data(left))->factor = AVL_BALANCED; 18 | *node = left; 19 | } else { 20 | grandchild = bitree_right(left); 21 | bitree_right(left) = bitree_left(grandchild); 22 | bitree_left(grandchild) = left; 23 | bitree_left(*node) = bitree_right(grandchild); 24 | bitree_right(grandchild) = *node; 25 | 26 | switch (((AvlNode *)bitree_data(grandchild))->factor) { 27 | case AVL_LFT_HEAVY: 28 | ((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY; 29 | ((AvlNode *)bitree_data(left))->factor = AVL_BALANCED; 30 | break; 31 | case AVL_BALANCED: 32 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 33 | ((AvlNode *)bitree_data(left))->factor = AVL_BALANCED; 34 | break; 35 | case AVL_RGT_HEAVY: 36 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 37 | ((AvlNode *)bitree_data(left))->factor = AVL_LFT_HEAVY; 38 | break; 39 | } 40 | ((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED; 41 | *node = grandchild; 42 | } 43 | } 44 | 45 | static void rotate_right(BiTreeNode **node) 46 | { 47 | BiTreeNode *right, *grandchild; 48 | 49 | right = bitree_left(*node); 50 | if (((AvlNode *)bitree_data(right))->factor == AVL_RGT_HEAVY) { 51 | bitree_right(*node) = bitree_left(right); 52 | bitree_left(right) = *node; 53 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 54 | ((AvlNode *)bitree_data(right))->factor = AVL_BALANCED; 55 | *node = right; 56 | } else { 57 | grandchild = bitree_left(right); 58 | bitree_left(right) = bitree_right(grandchild); 59 | bitree_right(grandchild) = right; 60 | bitree_right(*node) = bitree_left(grandchild); 61 | bitree_left(grandchild) = *node; 62 | 63 | switch (((AvlNode *)bitree_data(grandchild))->factor) { 64 | case AVL_LFT_HEAVY: 65 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 66 | ((AvlNode *)bitree_data(right))->factor = AVL_RGT_HEAVY; 67 | break; 68 | case AVL_BALANCED: 69 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 70 | ((AvlNode *)bitree_data(right))->factor = AVL_BALANCED; 71 | break; 72 | case AVL_RGT_HEAVY: 73 | ((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY; 74 | ((AvlNode *)bitree_data(right))->factor = AVL_BALANCED; 75 | break; 76 | } 77 | ((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED; 78 | *node = grandchild; 79 | } 80 | } 81 | 82 | static void destory_left(BisTree *tree, BiTreeNode *node) 83 | { 84 | BiTreeNode **position; 85 | 86 | if (bitree_size(tree) == 0) 87 | return; 88 | 89 | if (node == NULL) 90 | position = &tree->root; 91 | else 92 | position = &node->left; 93 | 94 | if (*position != NULL) { 95 | destory_left(tree, *position); 96 | destroy_right(tree, *position); 97 | 98 | if (tree->destroy != NULL) 99 | tree->destroy(((AvlNode *)(*position)->data)->data); 100 | 101 | free((*position)->data); 102 | free(*position); 103 | *position = NULL; 104 | 105 | tree->size--; 106 | } 107 | } 108 | 109 | static void destroy_right(BisTree *tree, BiTreeNode *node) 110 | { 111 | BiTreeNode **position; 112 | 113 | if (bitree_size(tree) == 0) 114 | return; 115 | 116 | if (node == NULL) 117 | position = &tree->root; 118 | else 119 | position = &node->right; 120 | 121 | if (*position != NULL) { 122 | destory_left(tree, *position); 123 | destroy_right(tree, *position); 124 | 125 | if (tree->destroy != NULL) 126 | tree->destroy(((AvlNode *)(*position)->data)->data); 127 | 128 | free((*position)->data); 129 | free(*position); 130 | *position = NULL; 131 | 132 | tree->size--; 133 | } 134 | } 135 | 136 | /** 137 | * 插入结点。插入一个结点后,更新结点的平衡因子。如果有任何一个结点的平衡因子变成了 138 | * ±2,就必须从这个结点开始往下重新平衡这棵树,这个重新平衡的过程就称为旋转。 139 | * @param tree [description] 140 | * @param node [description] 141 | * @param data [description] 142 | * @param balanced [description] 143 | * @return [description] 144 | */ 145 | static int insert(BisTree *tree, BiTreeNode **node, 146 | const void *data, int *balanced) 147 | { 148 | AvlNode *avl_data; 149 | int cmpval, retval; 150 | 151 | // 是否为空树 152 | if (bitree_is_eob(*node)) { 153 | if ((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) 154 | return -1; 155 | 156 | avl_data->factor = AVL_BALANCED; 157 | avl_data->hidden = 0; 158 | avl_data->data = (void *)data; 159 | 160 | return bitree_ins_left(tree, *node, avl_data); 161 | } else { 162 | cmpval = tree->compare(data, ((AvlNode *)bitree_data(*node))->data); 163 | if (cmpval < 0) { 164 | // 找到了要插入的位置 165 | if (bitree_is_eob(bitree_left(*node))) { 166 | if ((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) 167 | return -1; 168 | 169 | avl_data->factor = AVL_BALANCED; 170 | avl_data->hidden = 0; 171 | avl_data->data = (void *)data; 172 | 173 | if (bitree_ins_left(tree, *node, avl_data) != 0) 174 | return -1; 175 | 176 | *balanced = 0; 177 | } else { 178 | if ((retval = insert(tree, &bitree_left(*node), data, balanced)) != 0) 179 | return retval; 180 | } 181 | 182 | // 保持平衡 183 | if (!(*balanced)) { 184 | switch (((AvlNode *)bitree_data(*node))->factor) { 185 | case AVL_LFT_HEAVY: 186 | rotate_left(node); 187 | *balanced = 1; 188 | break; 189 | case AVL_BALANCED: 190 | ((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY; 191 | break; 192 | case AVL_RGT_HEAVY: 193 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 194 | *balanced = 1; 195 | break; 196 | } 197 | } 198 | } else if (cmpval > 0) { 199 | if (bitree_is_eob(bitree_right(*node))) { 200 | if ((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) 201 | return -1; 202 | 203 | avl_data->factor = AVL_BALANCED; 204 | avl_data->hidden = 0; 205 | avl_data->data = (void *)data; 206 | 207 | if (bitree_ins_right(tree, *node, avl_data) != 0) 208 | return -1; 209 | 210 | *balanced = 0; 211 | } else { 212 | if ((retval = insert(tree, &bitree_right(*node), data, balanced)) != 0) 213 | return retval; 214 | } 215 | 216 | if (!(*balanced)) { 217 | switch (((AvlNode *)bitree_data(*node))->factor) { 218 | case AVL_LFT_HEAVY: 219 | ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; 220 | *balanced = 1; 221 | break; 222 | case AVL_BALANCED: 223 | ((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY; 224 | break; 225 | case AVL_RGT_HEAVY: 226 | rotate_right(node); 227 | *balanced = 1; 228 | break; 229 | } 230 | } 231 | } else { 232 | // 已经有这个数据了 233 | if (!((AvlNode *)bitree_data(*node))->hidden) { 234 | return 1; 235 | } // 覆盖以前的数据 236 | else { 237 | if (tree->destroy != NULL) { 238 | tree->destroy(((AvlNode *)bitree_data(*node))->data); 239 | } 240 | ((AvlNode *)bitree_data(*node))->data = (void *)data; 241 | ((AvlNode *)bitree_data(*node))->hidden = 0; 242 | 243 | *balanced = 1; 244 | } 245 | } 246 | } 247 | 248 | return 0; 249 | } 250 | 251 | static int hide(BisTree *tree, BiTreeNode *node, const void *data) 252 | { 253 | int cmpval, retval; 254 | 255 | if (bitree_is_eob(node)) { 256 | return -1; 257 | } 258 | 259 | cmpval = tree->compare(data, ((AvlNode *)bitree_data(node))->data); 260 | if (cmpval < 0) { 261 | retval = hide(tree, bitree_left(node), data); 262 | } else { 263 | ((AvlNode *)bitree_data(node))->hidden = 1; 264 | retval = 0; 265 | } 266 | return retval; 267 | } 268 | 269 | static int lookup(BisTree *tree, BiTreeNode *node, void **data) 270 | { 271 | int cmpval, retval; 272 | 273 | if (bitree_is_eob(node)) { 274 | return -1; 275 | } 276 | 277 | cmpval = tree->compare(*data, ((AvlNode *)bitree_data(node))->data); 278 | if (cmpval < 0) { 279 | retval = lookup(tree, bitree_left(node), data); 280 | } else if (cmpval > 0) { 281 | retval = lookup(tree, bitree_right(node), data); 282 | } else { 283 | if (!((AvlNode *)bitree_data(node))->hidden) { 284 | *data = ((AvlNode *)bitree_data(node))->data; 285 | retval = 0; 286 | } else { 287 | return -1; 288 | } 289 | } 290 | 291 | return retval; 292 | } 293 | 294 | void bistree_init(BisTree *tree, int (*compare)(const void *key1, const void *key2), 295 | void (*destroy)(void *data)) 296 | { 297 | bitree_init(tree, destroy); 298 | tree->compare = compare; 299 | } 300 | 301 | void bistree_destroy(BisTree *tree) 302 | { 303 | destory_left(tree, NULL); 304 | memset(tree, 0, sizeof(BisTree)); 305 | } 306 | 307 | /** 308 | * 309 | * @param tree 树 310 | * @param data 待插入的结点 311 | * @return 如果插入成功,返回0;如果待插入的结点已经在树中存在,返回1;否则返回-1; 312 | */ 313 | int bistree_insert(BisTree *tree, const void *data) 314 | { 315 | int balanced = 0; 316 | return insert(tree, &bitree_root(tree), data, &balanced); 317 | } 318 | 319 | /** 320 | * 该操作仅仅只执行一种惰性移除,即该结点只是简单地标记为隐藏。 321 | * @param tree [description] 322 | * @param data [description] 323 | * @return 成功0;否则-1。 324 | */ 325 | int bistree_remove(BisTree *tree, const void *data) 326 | { 327 | return hide(tree, bitree_root(tree), data); 328 | } 329 | 330 | int bitree_lookup(BisTree *tree, void **data) 331 | { 332 | return lookup(tree, bitree_root(tree), data); 333 | } 334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /data_structure/bistree.h: -------------------------------------------------------------------------------- 1 | // bistree.h,二叉搜索树 2 | // 这是一种专门用于查找操作的二叉树。 3 | // 保持一棵树的平衡是指对于给定数量的结点,要使得树的高度尽可能短。 4 | #ifndef BISTREE_H 5 | #define BISTREE_H 6 | 7 | #include "bitree.h" 8 | 9 | // 平衡因子定义 10 | #define AVL_LFT_HEAVY 1 11 | #define AVL_BALANCED 0 12 | #define AVL_RGT_HEAVY -1 13 | 14 | typedef struct AvlNode_ 15 | { 16 | void *data; 17 | int hidden;//标志该节点已经移除 18 | int factor;//平衡因子 19 | } AvlNode; 20 | 21 | typedef BiTree BisTree; 22 | 23 | // public interface 24 | void bistree_init(BisTree *tree, int (*compare)(const void *key1, const void *key2), 25 | void (*destroy)(void *data)); 26 | void bistree_destroy(BisTree *tree); 27 | int bistree_insert(BisTree *tree, const void *data); 28 | int bistree_remove(BisTree *tree, const void *data); 29 | int bitree_lookup(BisTree *tree, void **data); 30 | #define bistree_size(tree) ((tree)->size) 31 | 32 | #endif -------------------------------------------------------------------------------- /data_structure/bitree.c: -------------------------------------------------------------------------------- 1 | // bitree.c 2 | #include 3 | #include 4 | #include "bitree.h" 5 | 6 | void bitree_init(BiTree *tree, void (*destroy)(void *data)) 7 | { 8 | tree->size = 0; 9 | tree->destroy = destroy; 10 | tree->root = NULL; 11 | } 12 | 13 | void bittree_destroy(BiTree *tree) 14 | { 15 | bitree_rem_left(tree, NULL); 16 | memset(tree, 0, sizeof(BiTree)); 17 | } 18 | 19 | /** 20 | * 在指定节点的左边插入一个结点,如果指定的结点为NULL并且树的大小为0,则在根结点插入 21 | * 22 | * @param tree 树 23 | * @param node 指定的结点 24 | * @param data 要插入的数据 25 | * @return 成功返回0,失败返回-1 26 | */ 27 | int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data) 28 | { 29 | BiTreeNode *new_node, **position; 30 | 31 | if (node == NULL) { 32 | if (bitree_size(tree) > 0) 33 | return -1; 34 | position = &tree->root; 35 | } else { 36 | if (bitree_left(node) != NULL) 37 | return -1; 38 | position = &node->left; 39 | } 40 | if ((new_node = (BiTreeNode *)malloc(sizeof(BiTreeNode))) == NULL) 41 | return -1; 42 | 43 | new_node->data = (void *)data; 44 | new_node->left = NULL; 45 | new_node->right = NULL; 46 | *position = new_node; 47 | 48 | tree->size++; 49 | 50 | return 0; 51 | } 52 | 53 | /** 54 | * 在指定节点的右边插入一个结点,如果指定的结点为NULL并且树的大小为0,则在根结点插入 55 | * 56 | * @param tree 树 57 | * @param node 指定的结点 58 | * @param data 要插入的数据 59 | * @return 成功返回0,失败返回-1 60 | */ 61 | int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data) 62 | { 63 | BiTreeNode *new_node, **position; 64 | 65 | if (node == NULL) { 66 | if (bitree_size(tree) > 0) 67 | return -1; 68 | position = &tree->root; 69 | } else { 70 | if (bitree_left(node) != NULL) 71 | return -1; 72 | position = &node->right; 73 | } 74 | if ((new_node = (BiTreeNode *)malloc(sizeof(BiTreeNode))) == NULL) 75 | return -1; 76 | 77 | new_node->data = (void *)data; 78 | new_node->left = NULL; 79 | new_node->right = NULL; 80 | *position = new_node; 81 | 82 | tree->size++; 83 | 84 | return 0; 85 | } 86 | 87 | /** 88 | * 移除某个结点左边所有的结点 89 | * @param tree 树 90 | * @param node 指定的结点 91 | */ 92 | void bitree_rem_left(BiTree *tree, BiTreeNode *node) 93 | { 94 | BiTreeNode **position; 95 | 96 | if (bitree_size(tree) == 0) 97 | return; 98 | 99 | if (node == NULL) 100 | position = &tree->root; 101 | else 102 | position = &node->left; 103 | 104 | if (*position != NULL) { 105 | bitree_rem_left(tree, *position); 106 | bitree_rem_right(tree, *position); 107 | 108 | if (tree->destroy != NULL) { 109 | tree->destroy((*position)->data); 110 | } 111 | 112 | free(*position); 113 | *position = NULL; 114 | 115 | tree->size--; 116 | } 117 | } 118 | 119 | /** 120 | * 移除某个结点右边所有的结点 121 | * @param tree 树 122 | * @param node 指定的结点 123 | */ 124 | void bitree_rem_right(BiTree *tree, BiTreeNode *node) 125 | { 126 | BiTreeNode **position; 127 | 128 | if (bitree_size(tree) == 0) 129 | return; 130 | 131 | if (node == NULL) 132 | position = &tree->root; 133 | else 134 | position = &node->right; 135 | 136 | if (*position != NULL) { 137 | bitree_rem_left(tree, *position); 138 | bitree_rem_right(tree, *position); 139 | 140 | if (tree->destroy != NULL) { 141 | tree->destroy((*position)->data); 142 | } 143 | 144 | free(*position); 145 | *position = NULL; 146 | 147 | tree->size--; 148 | } 149 | } 150 | 151 | /** 152 | * 合并两棵树 153 | * @param merge 合并后的树 154 | * @param left 合并前的左子树 155 | * @param right 合并前的又子树 156 | * @param data 新的树的跟结点的数据 157 | * @return 成功返回0,失败-1 158 | */ 159 | int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data) 160 | { 161 | bitree_init(merge, left->destroy); 162 | 163 | if (bitree_ins_left(merge, NULL, data) != 0) { 164 | bittree_destroy(merge); 165 | return -1; 166 | } 167 | 168 | bitree_root(merge)->left = bitree_root(left); 169 | bitree_root(merge)->right = bitree_root(right); 170 | // 调整树的大小 171 | merge->size = merge->size + bitree_size(left) + bitree_size(right); 172 | 173 | // 不允许原来的树访问合并后的结点 174 | left->root = NULL; 175 | left->size = 0; 176 | right->root = NULL; 177 | right->size = 0; 178 | 179 | return 0; 180 | } -------------------------------------------------------------------------------- /data_structure/bitree.h: -------------------------------------------------------------------------------- 1 | // bitree.h 2 | #ifndef BITREE_H 3 | #define BITREE_H 4 | #include 5 | 6 | typedef struct BiTreeNode_ 7 | { 8 | void *data; 9 | struct BiTreeNode_ *left; 10 | struct BiTreeNode_ *right; 11 | } BiTreeNode; 12 | 13 | typedef struct BiTree_ 14 | { 15 | int size; 16 | int (*compare)(const void *key1, const void *key2); 17 | void (*destroy)(void *data); 18 | BiTreeNode *root; 19 | } BiTree; 20 | 21 | // public interface 22 | void bitree_init(BiTree *tree, void (*destroy)(void *data)); 23 | void bittree_destroy(BiTree *tree); 24 | int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data); 25 | int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data); 26 | void bitree_rem_left(BiTree *tree, BiTreeNode *node); 27 | void bitree_rem_right(BiTree *tree, BiTreeNode *node); 28 | int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data); 29 | 30 | #define bitree_size(tree) ((tree)->size) 31 | #define bitree_root(tree) ((tree)->root) 32 | #define bitree_is_eob(node) ((node) == NULL) 33 | #define bitree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL) 34 | #define bitree_data(node) ((node)->data) 35 | #define bitree_left(node) ((node)->left) 36 | #define bitree_right(node) ((node)->right) 37 | 38 | #endif -------------------------------------------------------------------------------- /data_structure/chtbl.c: -------------------------------------------------------------------------------- 1 | // chtbl.c,链式哈希表 2 | #include 3 | #include 4 | 5 | #include "chtbl.h" 6 | 7 | int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), 8 | int (*match)(const void *key1, const void *key2), void (*destroy)(void *data)) 9 | { 10 | int i; 11 | if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL) 12 | return -1; 13 | 14 | htbl->buckets = buckets; 15 | for (i = 0; i < htbl->buckets; i++) 16 | list_init(&htbl->table[i], destroy); 17 | 18 | htbl->h = h; 19 | htbl->match = match; 20 | htbl->destroy = destroy; 21 | htbl->size = 0; 22 | 23 | return 0; 24 | } 25 | 26 | void chtbl_destroy(CHTbl *htbl) 27 | { 28 | int i; 29 | for (i = 0; i < htbl->buckets; i++) { 30 | list_destroy(&htbl->table[i]); 31 | } 32 | free(htbl->table); 33 | memset(htbl, 0, sizeof(CHTbl)); 34 | } 35 | 36 | /** 37 | * 向哈希表中插入元素 38 | * @param htbl 哈希表 39 | * @param data 要插入的元素 40 | * @return 成功返回0,如果元素已经存在返回1,其它情况返回-1 41 | */ 42 | int chtbl_insert(CHTbl *htbl, const void *data) 43 | { 44 | void *temp; 45 | int bucket, retval; 46 | 47 | temp = (void *)data; 48 | if (chtbl_lookup(htbl, &temp) == 0) 49 | return 1; 50 | 51 | // hash the key 52 | bucket = htbl->h(data) % htbl->buckets; 53 | 54 | if ((retval = list_ins_next(&htbl->table[bucket], NULL, data)) == 0) 55 | htbl->size++; 56 | 57 | return retval; 58 | } 59 | 60 | int chtbl_remove(CHTbl *htbl, void **data) 61 | { 62 | ListElmt *element, *prev; 63 | int bucket; 64 | 65 | bucket = htbl->h(*data) * htbl->buckets; 66 | prev = NULL; 67 | 68 | for (element = list_head(&htbl->table[bucket]); element != NULL; 69 | element = list_next(element)) { 70 | if (htbl->match(*data, list_data(element))) { 71 | if (list_rem_next(&htbl->table[bucket], prev, data) == 0) { 72 | htbl->size--; 73 | return 0; 74 | } else { 75 | return -1; 76 | } 77 | } 78 | prev = element; 79 | } 80 | 81 | return -1; 82 | } 83 | 84 | /** 85 | * 在哈希表中查找元素 86 | * @param htbl 哈希表 87 | * @param data 要找的元素 88 | * @return 成功返回0;失败返回-1 89 | */ 90 | int chtbl_lookup(const CHTbl *htbl, void **data) 91 | { 92 | ListElmt *element; 93 | int bucket; 94 | 95 | bucket = htbl->h(*data) % htbl->buckets; 96 | 97 | for (element = list_head(&htbl->table[bucket]); element != NULL; 98 | element = list_next(element)) { 99 | if (htbl->match(*data, list_data(element))) { 100 | *data = list_data(element); 101 | return 0; 102 | } 103 | } 104 | 105 | return -1; 106 | } 107 | -------------------------------------------------------------------------------- /data_structure/chtbl.h: -------------------------------------------------------------------------------- 1 | // chtbl.h 链式哈希表 2 | #ifndef CHTBL_H 3 | #define CHTBL_H 4 | 5 | #include 6 | #include "list.h" 7 | 8 | // define for chained hash tables 9 | typedef struct CHTbl_ 10 | { 11 | int buckets;// 桶的个数 12 | int (*h)(const void *key);// 用户定义的哈希函数 13 | int (*match)(const void *key1, const void *key2); 14 | void (*destroy)(void *data); 15 | 16 | int size;// 表中现有元素的个数 17 | List *table;// 保存桶的链表 18 | } CHTbl; 19 | 20 | // public interface 21 | int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), 22 | int (*match)(const void *key1, const void *key2), void (*destroy)(void *data)); 23 | void chtbl_destroy(CHTbl *htbl); 24 | int chtbl_insert(CHTbl *htbl, const void *data); 25 | int chtbl_remove(CHTbl *htbl, void **data); 26 | int chtbl_lookup(const CHTbl *htbl, void **data); 27 | #define chtbl_size(htbl) ((htbl)->size) 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /data_structure/clist.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 单向循环链表,clist.c 3 | */ 4 | #include 5 | #include 6 | 7 | #include "clist.h" 8 | 9 | void clist_init(CList *list, void (*destroy)(void *data)) 10 | { 11 | list->size = 0; 12 | list->destroy = destroy; 13 | list->head = NULL; 14 | } 15 | 16 | void clist_destroy(CList *list) 17 | { 18 | void *data; 19 | 20 | while (clist_size(list) > 0) { 21 | if (clist_rem_next(list, list->head, (void **)&data) == 0 22 | && list->destroy != NULL) { 23 | list->destroy(data); 24 | } 25 | } 26 | 27 | memset(list, 0, sizeof(CList)); 28 | } 29 | 30 | /** 31 | * 插入元素到链表list的节点element后面。 32 | * @param list 链表 33 | * @param element 节点 34 | * @param data 数据 35 | * @return 成功返回0,失败-1 36 | */ 37 | int clist_ins_next(CList *list, CListElmt *element, const void *data) 38 | { 39 | CListElmt *new_element; 40 | 41 | if ((new_element = (CListElmt *)malloc(sizeof(CListElmt))) == NULL) 42 | return -1; 43 | 44 | new_element->data = (void *)data; 45 | if (clist_size(list) == 0) { 46 | new_element->next = new_element; 47 | list->head = new_element; 48 | } else { 49 | new_element->next = element->next; 50 | element->next = new_element; 51 | } 52 | 53 | list->size++; 54 | return 0; 55 | } 56 | 57 | /** 58 | * 从链表list中删除element节点。 59 | * @param list 链表 60 | * @param element 节点 61 | * @param data 被删除节点中的数据 62 | * @return 成功返回0,失败返回-1 63 | */ 64 | int clist_rem_next(CList *list, CListElmt *element, void **data) 65 | { 66 | CListElmt *old_element; 67 | 68 | if (clist_size(list) == 0) 69 | return -1; 70 | 71 | *data = element->next->data; 72 | if (element->next == element) { 73 | old_element = element->next; 74 | list->head = NULL; 75 | } else { 76 | old_element = element->next; 77 | element->next = element->next->next; 78 | if (old_element == clist_head(list)) 79 | list->head = old_element->next; 80 | } 81 | 82 | free(old_element); 83 | list->size--; 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /data_structure/clist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 单向循环链表,clist.h 3 | */ 4 | #ifndef CLIST_H 5 | #define CLIST_H 6 | 7 | #include 8 | 9 | typedef struct CListElmt_ 10 | { 11 | void *data; 12 | struct CListElmt_ *next; 13 | } CListElmt; 14 | 15 | typedef struct CList_ 16 | { 17 | int size; 18 | int (*match)(const void *key1, const void *key2); 19 | void (*destroy)(void *data); 20 | CListElmt *head; 21 | } CList; 22 | 23 | /* public interface */ 24 | void clist_init(CList *list, void (*destroy)(void *data)); 25 | void clist_destroy(CList *list); 26 | int clist_ins_next(CList *list, CListElmt *element, const void *data); 27 | int clist_rem_next(CList *list, CListElmt *element, void **data); 28 | 29 | #define clist_size(list) ((list)->size) 30 | #define clist_head(list) ((list)->head) 31 | #define clist_data(element) ((element)->data) 32 | #define clist_next(element) ((element)->next) 33 | 34 | #endif -------------------------------------------------------------------------------- /data_structure/cover.c: -------------------------------------------------------------------------------- 1 | // cover.c 2 | #include 3 | #include "cover.h" 4 | 5 | /** 6 | * 集合覆盖问题的实现。 7 | * @param members 待覆盖的集合 8 | * @param subsets 用来覆盖的子集 9 | * @param covering 用来保存覆盖集 10 | * @return 成功返回0;不可能完全覆盖返回1;其它返回-1 11 | */ 12 | int cover(Set *members, Set *subsets, Set *covering) 13 | { 14 | Set intersection; 15 | KSet *subset; 16 | ListElmt *member, *max_member; 17 | void *data; 18 | int max_size; 19 | 20 | set_init(covering, subsets->match, NULL); 21 | 22 | while (set_size(members) > 0 && set_size(subsets) > 0) { 23 | max_size = 0; 24 | // 寻找一个拥有最大交集的子集 25 | for (member = list_head(subsets); member != NULL; 26 | member = list_next(member)) { 27 | if (set_intersection(&intersection, 28 | &((KSet *)list_data(member))->set, members) != 0) { 29 | return -1; 30 | } 31 | 32 | if (set_size(&intersection) > max_size) { 33 | max_member = member; 34 | max_size = set_size(&intersection); 35 | } 36 | // 清空这个集合 37 | set_destroy(&intersection); 38 | } 39 | 40 | // 没有找到交集 41 | if (max_size == 0) 42 | return 1; 43 | 44 | // 把找到的子集放在结果的集合中 45 | subset = (KSet *)list_data(max_member); 46 | if (set_insert(covering, subset) != 0) 47 | return -1; 48 | 49 | // 将选中的子集中的元素从members中移除 50 | for (member = list_head(&((KSet *)list_data(max_member))->set); 51 | member != NULL; member = list_next(member)) { 52 | data = list_data(member); 53 | if (set_remove(members, (void**)&data) == 0 && members->destroy) 54 | members->destroy(data); 55 | } 56 | 57 | // 将选中的子集从集合中移除 58 | if (set_remove(subsets, (void**)&subset) != 0) 59 | return -1; 60 | } 61 | 62 | // 如果待覆盖的集合中还有元素,则表示不能完全覆盖 63 | if (set_size(members) > 0) 64 | return -1; 65 | 66 | return 0; 67 | } -------------------------------------------------------------------------------- /data_structure/cover.h: -------------------------------------------------------------------------------- 1 | // cover.h 2 | #ifndef COVER_H 3 | #define COVER_H 4 | 5 | #include "set.h" 6 | 7 | typedef struct KSet_ 8 | { 9 | void *key; 10 | Set set; 11 | } KSet; 12 | 13 | int cover(Set *members, Set *subsets, Set *covering); 14 | 15 | #endif -------------------------------------------------------------------------------- /data_structure/dfs.c: -------------------------------------------------------------------------------- 1 | // dfs.c,深度优先搜索的实现 2 | #include 3 | #include "dfs.h" 4 | #include "graph.h" 5 | #include "list.h" 6 | 7 | static int dfs_main(Graph *graph, AdjList *adjlist, List *ordered) 8 | { 9 | AdjList *clr_adjlist; 10 | DfsVertex *clr_vertex, *adj_vertex; 11 | ListElmt *member; 12 | 13 | ((DfsVertex *)adjlist->vertex)->color = gray; 14 | 15 | for (member = list_head(&adjlist->adjacent); member != NULL; 16 | member = list_next(member)) { 17 | adj_vertex = list_data(member); 18 | if (graph_adjlist(graph, adj_vertex, &clr_adjlist) != 0) 19 | return -1; 20 | 21 | clr_vertex = clr_adjlist->vertex; 22 | // 如果当前邻接顶点的颜色是白色,就继续往下一级遍历 23 | if (clr_vertex->color == white) { 24 | if (dfs_main(graph, clr_adjlist, ordered) != 0) 25 | return -1; 26 | } 27 | } 28 | 29 | ((DfsVertex *)adjlist->vertex)->color = black; 30 | if (list_ins_next(ordered, NULL, (DfsVertex *)adjlist->vertex) != 0) 31 | return -1; 32 | 33 | return 0; 34 | } 35 | 36 | int dfs(Graph *graph, List *ordered) 37 | { 38 | DfsVertex *vertex; 39 | ListElmt *element; 40 | 41 | // 初始化所有的顶点,全部涂为白色 42 | for (element = list_head(&graph_adjlists(graph)); element != NULL; 43 | element = list_next(element)) { 44 | vertex = ((AdjList *)list_data(element))->vertex; 45 | vertex->color = white; 46 | } 47 | 48 | list_init(ordered, NULL); 49 | for (element = list_head(&graph_adjlists(graph)); element != NULL; 50 | element = list_next(element)) { 51 | vertex = ((AdjList *)list_data(element))->vertex; 52 | 53 | if (vertex->color == white) { 54 | if (dfs_main(graph, (AdjList *)list_data(element), ordered) != 0) { 55 | list_destroy(ordered); 56 | return -1; 57 | } 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /data_structure/dfs.h: -------------------------------------------------------------------------------- 1 | // dfs.h,深度优先例子,拓扑排序 2 | #ifndef DFS_H 3 | #define DFS_H 4 | 5 | #include "graph.h" 6 | #include "list.h" 7 | 8 | typedef struct DfsVertex_ { 9 | void *data; 10 | VertexColor color; 11 | } DfsVertex; 12 | 13 | int dfs(Graph *graph, List *ordered); 14 | 15 | #endif -------------------------------------------------------------------------------- /data_structure/dlist.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 双向链表,dlist.c 3 | */ 4 | #include 5 | #include 6 | 7 | #include "dlist.h" 8 | 9 | /** 10 | * 初始化链表 11 | * @param list 要初始化的链表 12 | * @param destory 指定一个销毁数据的函数,该函数会在dlist_destroy中调用。 13 | */ 14 | void dlist_init(DList *list, void (*destroy)(void *data)) 15 | { 16 | list->size = 0; 17 | list->destroy = destroy; 18 | list->head = NULL; 19 | list->tail = NULL; 20 | } 21 | 22 | /** 23 | * 销毁链表 24 | * @param list 要销毁的链表 25 | */ 26 | void dlist_destroy(DList *list) 27 | { 28 | void *data; 29 | while (dlist_size(list) > 0) { 30 | if (dlist_remove(list, dlist_tail(list), (void **)&data) == 0 31 | && list->destroy != NULL) { 32 | list->destroy(data); 33 | } 34 | } 35 | memset(list, 0, sizeof(DList)); 36 | } 37 | 38 | /** 39 | * 将元素插入由list指定的双向链表中element元素之后。如果element为NULL。 40 | * 则将元素插入到链表的开始位置。新的元素包含一个指向data的指针,因此只要 41 | * 该元素仍在链表中,data所引用的内存空间就应该保持合法。由调用者负责管理 42 | * data所引用的存储空间。 43 | * @param list 要操作的链表 44 | * @param element 指定的节点 45 | * @param data 要插入的元素 46 | * @return 成功返回0,失败返回-1 47 | */ 48 | int dlist_ins_next(DList *list, DListElmt *element, const void *data) 49 | { 50 | DListElmt *new_element; 51 | 52 | if ((new_element = (DListElmt *)malloc(sizeof(DListElmt))) == NULL) 53 | return -1; 54 | 55 | new_element->data = (void *)data; 56 | if (element == NULL) { 57 | if (dlist_size(list) == 0) { 58 | new_element->next = NULL; 59 | new_element->prev = NULL; 60 | list->head = new_element; 61 | list->tail = new_element; 62 | } else { 63 | new_element->next = list->head; 64 | new_element->prev = NULL; 65 | list->head->prev = new_element; 66 | list->head = new_element; 67 | } 68 | } else { 69 | new_element->next = element->next; 70 | new_element->prev = element; 71 | 72 | if (element->next == NULL) 73 | list->tail = new_element; 74 | else 75 | element->next->prev = new_element; 76 | 77 | element->next = new_element; 78 | } 79 | list->size++; 80 | 81 | return 0; 82 | } 83 | 84 | /** 85 | * 将元素插入由list指定的双向链表中element元素之前。如果element为NULL。 86 | * 则将元素插入到链表的开始位置。新的元素包含一个指向data的指针,因此只要 87 | * 该元素仍在链表中,data所引用的内存空间就应该保持合法。由调用者负责管理 88 | * data所引用的存储空间。 89 | * @param list 要操作的链表 90 | * @param element 指定的节点 91 | * @param data 要插入的元素 92 | * @return 成功返回0,失败返回-1 93 | */ 94 | int dlist_ins_prev(DList *list, DListElmt *element, const void *data) 95 | { 96 | DListElmt *new_element; 97 | 98 | if ((new_element = (DListElmt *)malloc(sizeof(DListElmt))) == NULL) 99 | return -1; 100 | 101 | if (element == NULL) { 102 | if (dlist_size(list) == 0) { 103 | list->head = new_element; 104 | list->tail = new_element; 105 | new_element->next = NULL; 106 | new_element->prev = NULL; 107 | } else { 108 | new_element->next = list->head; 109 | new_element->prev = NULL; 110 | list->head->prev = new_element; 111 | list->head = new_element; 112 | } 113 | } else { 114 | new_element->next = element; 115 | new_element->prev = element->prev; 116 | if (element->prev == NULL) 117 | list->head = new_element; 118 | else 119 | element->prev->next = new_element; 120 | element->prev = new_element; 121 | } 122 | 123 | return 0; 124 | } 125 | 126 | /** 127 | * 将元素element从链表中移除 128 | * @param list 要操作的链表 129 | * @param element 要从链表中移除的节点 130 | * @param data 移除的节点中的数据 131 | * @return 成功返回0;失败返回-1。 132 | */ 133 | int dlist_remove(DList *list, DListElmt *element, void **data) 134 | { 135 | if (element == NULL || dlist_size(list) == 0) 136 | return -1; 137 | 138 | *data = element->data; 139 | if (element == list->head) { 140 | list->head = element->next; 141 | 142 | if (list->head == NULL) 143 | list->tail = NULL; 144 | else 145 | element->next->prev = NULL; 146 | } else { 147 | // 将前一个节点的next指向当前节点的下一个节点 148 | element->prev->next = element->next; 149 | // 如果这个节点是最后一个节点,删除后,将尾指针指向当前节点的前一个节点; 150 | // 如果不是最后一个节点,则将后一个节点的prev指向当前节点的前一个节点。 151 | if (element->next == NULL) 152 | list->tail = element->prev; 153 | else 154 | element->next->prev = element->prev; 155 | } 156 | 157 | free(element); 158 | 159 | list->size--; 160 | 161 | return 0; 162 | } 163 | -------------------------------------------------------------------------------- /data_structure/dlist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 双向链表,dlist.h 3 | */ 4 | #ifndef DLIST_H 5 | #define DLIST_H 6 | 7 | #include 8 | 9 | typedef struct DListElmt_ 10 | { 11 | void *data; 12 | struct DListElmt_ *prev; 13 | struct DListElmt_ *next; 14 | } DListElmt; 15 | 16 | typedef struct DList_ 17 | { 18 | int size; 19 | int (*match)(const void *key1, const void *key2); 20 | void (*destroy)(void *data); 21 | DListElmt *head; 22 | DListElmt *tail; 23 | } DList; 24 | 25 | /* public interface */ 26 | void dlist_init(DList *list, void (*destroy)(void *data)); 27 | void dlist_destroy(DList *list); 28 | int dlist_ins_next(DList *list, DListElmt *element, const void *data); 29 | int dlist_ins_prev(DList *list, DListElmt *element, const void *data); 30 | int dlist_remove(DList *list, DListElmt *element, void **data); 31 | 32 | #define dlist_size(list) ((list)->size) 33 | #define dlist_head(list) ((list)->head) 34 | #define dlist_tail(list) ((list)->tail) 35 | #define dlist_is_head(list, element) ((element) == (list)->head ? 1 : 0) 36 | #define dlist_is_tail(element) ((element)->next == NULL ? 1 : 0) 37 | #define dlist_data(element) ((element)->data) 38 | #define dlist_next(element) ((element)->next) 39 | #define dlist_prev(element) ((element)->prev) 40 | 41 | #endif -------------------------------------------------------------------------------- /data_structure/fact.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 普通递归方式求阶乘 4 | int fact(int n) 5 | { 6 | if (n < 0) { 7 | return 0; 8 | } else if (n == 0 || n == 1) { 9 | return 1; 10 | } else { 11 | return n * fact(n - 1); 12 | } 13 | } 14 | 15 | // 尾递归的方式求阶乘 16 | int facttail(int n, int a) 17 | { 18 | if (n < 0) { 19 | return 0; 20 | } else if (n == 0 || n == 1) { 21 | return a; 22 | } else { 23 | return facttail(n - 1, n * a); 24 | } 25 | } 26 | 27 | int main(int argc, char const *argv[]) 28 | { 29 | printf("result = %d\n", fact(5)); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /data_structure/graph.c: -------------------------------------------------------------------------------- 1 | // graph.c 2 | 3 | #include 4 | #include 5 | 6 | #include "graph.h" 7 | #include "list.h" 8 | #include "set.h" 9 | 10 | void graph_init(Graph *graph, int (*match)(const void *key1, const void *key2), 11 | void (*destroy)(void *data)) 12 | { 13 | graph->vcount = 0; 14 | graph->ecount = 0; 15 | graph->match = match; 16 | graph->destroy = destroy; 17 | 18 | list_init(&graph->adjlists, NULL); 19 | } 20 | 21 | void graph_destroy(Graph *graph) 22 | { 23 | AdjList *adjlist; 24 | 25 | while (list_size(&graph->adjlists) > 0) { 26 | if (list_rem_next(&graph->adjlists, NULL, (void **)&adjlist) == 0) { 27 | set_destroy(&adjlist->adjacent); 28 | 29 | if (graph->destroy != NULL) { 30 | graph->destroy(adjlist->vertex); 31 | } 32 | 33 | free(adjlist); 34 | } 35 | } 36 | 37 | list_destroy(&graph->adjlists); 38 | memset(graph, 0, sizeof(Graph)); 39 | } 40 | 41 | // 将一个顶点插入图中 42 | int graph_ins_vertex(Graph *graph, const void *data) 43 | { 44 | ListElmt *element; 45 | AdjList *adjlist; 46 | int retval; 47 | 48 | // 不允许插入相同的顶点 49 | for (element = list_head(&graph->adjlists); element != NULL; 50 | element = list_next(element)) { 51 | if (graph->match(data, ((AdjList *)list_data(element))->vertex)) 52 | return 1; 53 | } 54 | 55 | if ((adjlist = (AdjList *)malloc(sizeof(AdjList))) == NULL) 56 | return -1; 57 | 58 | adjlist->vertex = (void *)data; 59 | set_init(&adjlist->adjacent, graph->match, NULL); 60 | 61 | if ((retval = list_ins_next(&graph->adjlists, list_tail(&graph->adjlists), 62 | adjlist)) != 0) { 63 | return retval; 64 | } 65 | 66 | graph->vcount++; 67 | return 0; 68 | } 69 | 70 | //将一条边插入图中 71 | int graph_ins_edge(Graph *graph, const void *data1, const void *data2) 72 | { 73 | ListElmt *element; 74 | int retval; 75 | 76 | // 确保两个顶点都在图中 77 | for (element = list_head(&graph->adjlists); element != NULL; 78 | element = list_next(element)) { 79 | if (graph->match(data2, ((AdjList *)list_data(element))->vertex)) 80 | break; 81 | } 82 | 83 | if (element == NULL) 84 | return -1; 85 | 86 | for (element = list_head(&graph->adjlists); element != NULL; 87 | element = list_next(element)) { 88 | if (graph->match(data1, ((AdjList *)list_data(element))->vertex)) 89 | break; 90 | } 91 | 92 | if (element == NULL) 93 | return -1; 94 | 95 | // 把data2放到data1的集合中去,即插入一条边 96 | if ((retval = set_insert(&((AdjList *)list_data(element))->adjacent, data2)) != 0) 97 | return retval; 98 | 99 | graph->ecount++; 100 | return 0; 101 | } 102 | 103 | // 移除一个顶点 104 | int graph_rem_vertex(Graph *graph, void **data) 105 | { 106 | ListElmt *element, *temp, *prev; 107 | AdjList *adjlist; 108 | int found; 109 | 110 | prev = NULL; 111 | found = 0; 112 | 113 | // 为什么这个循环里面没有break,一定要轮询完吗?? 114 | for (element = list_head(&graph->adjlists); element != NULL; 115 | element = list_next(element)) { 116 | if (set_is_member(&((AdjList *)list_data(element))->adjacent, *data)) 117 | return -1; 118 | 119 | if (graph->match(*data, ((AdjList *)list_data(element))->vertex)) { 120 | temp = element; 121 | found = 1; 122 | } 123 | 124 | if (!found) 125 | prev = element; 126 | } 127 | 128 | // 未找到该顶点 129 | if (!found) 130 | return -1; 131 | 132 | // 如果这个顶点的邻接表不是空,则不允许移除这个顶点 133 | if (set_size(&((AdjList *)list_data(temp))->adjacent) > 0) 134 | return -1; 135 | 136 | // 移除顶点 137 | if (list_rem_next(&graph->adjlists, prev, (void **)&adjlist) != 0) 138 | return -1; 139 | 140 | *data = adjlist->vertex; 141 | free(adjlist); 142 | 143 | graph->vcount--; 144 | return 0; 145 | } 146 | 147 | // 移除一条边 148 | int graph_rem_edge(Graph *graph, void *data1, void **data2) 149 | { 150 | ListElmt *element; 151 | 152 | for (element = list_head(&graph->adjlists); element != NULL; 153 | element = list_next(element)) { 154 | if (graph->match(data1, ((AdjList *)list_data(element))->vertex)) 155 | break; 156 | } 157 | 158 | if (element == NULL) 159 | return -1; 160 | 161 | // 把data1到data2的那条边移除 162 | if (set_remove(&((AdjList *)list_data(element))->adjacent, data2) != 0) 163 | return -1; 164 | 165 | graph->ecount--; 166 | return 0; 167 | } 168 | 169 | // 获取图中的某个邻接表 170 | int graph_adjlist(const Graph *graph, const void *data, AdjList **adjlist) 171 | { 172 | // prev这个指针有卵用? 173 | ListElmt *element, *prev; 174 | 175 | prev = NULL; 176 | for (element = list_head(&graph->adjlists); element != NULL; 177 | element = list_next(element)) { 178 | if (graph->match(data, ((AdjList *)list_data(element))->vertex)) 179 | break; 180 | 181 | prev = element; 182 | } 183 | 184 | if (element == NULL) 185 | return -1; 186 | 187 | *adjlist = list_data(element); 188 | return 0; 189 | } 190 | 191 | // 判断指定的两个顶点是否邻接 192 | int graph_is_adjacent(const Graph *graph, const void *data1, 193 | const void *data2) 194 | { 195 | // prev这个指针有卵用? 196 | ListElmt *element, *prev; 197 | 198 | prev = NULL; 199 | for (element = list_head(&graph->adjlists); element != NULL; 200 | element = list_next(element)) { 201 | if (graph->match(data1, ((AdjList *)list_data(element))->vertex)) 202 | break; 203 | 204 | prev = element; 205 | } 206 | 207 | if (element == NULL) 208 | return -1; 209 | 210 | return set_is_member(&((AdjList *)list_data(element))->adjacent, data2); 211 | } 212 | -------------------------------------------------------------------------------- /data_structure/graph.h: -------------------------------------------------------------------------------- 1 | // graph.h 2 | #ifndef GRAPH_H 3 | #define GRAPH_H 4 | 5 | #include 6 | #include "list.h" 7 | #include "set.h" 8 | 9 | // 邻接表的定义 10 | typedef struct AdjList_ { 11 | void *vertex;//顶点 12 | Set adjacent;//与该顶点相邻接的顶点的集合 13 | } AdjList; 14 | 15 | typedef struct Graph_ { 16 | int vcount;// 顶点计数 17 | int ecount;// 边计数 18 | 19 | int (*match)(const void *key1, const void *key2); 20 | void (*destroy)(void *data); 21 | 22 | List adjlists; 23 | } Graph; 24 | 25 | typedef enum VertexColor_ {white, gray, black} VertexColor; 26 | 27 | void graph_init(Graph *graph, int (*match)(const void *key1, const void *key2), 28 | void (*destroy)(void *data)); 29 | void graph_destroy(Graph *graph); 30 | // 将一个顶点插入图中 31 | int graph_ins_vertex(Graph *graph, const void *data); 32 | //将一条边插入图中 33 | int graph_ins_edge(Graph *graph, const void *data1, const void *data2); 34 | // 移除一个顶点 35 | int graph_rem_vertex(Graph *graph, void **data); 36 | // 移除一条边 37 | int graph_rem_edge(Graph *graph, void *data1, void **data2); 38 | // 获取指定顶点的邻接表 39 | int graph_adjlist(const Graph *graph, const void *data, AdjList **adjlist); 40 | // 判断指定的两个顶点是否有邻接关系 41 | int graph_is_adjacent(const Graph *graph, const void *data1, const void *data2); 42 | #define graph_adjlists(graph) ((graph)->adjlists) 43 | #define graph_vcount(graph) ((graph)->vcount) 44 | #define graph_ecount(graph) ((graph)->ecount) 45 | 46 | 47 | #endif -------------------------------------------------------------------------------- /data_structure/heap.c: -------------------------------------------------------------------------------- 1 | //heap.c,最大值堆 2 | #include 3 | #include 4 | 5 | #include "heap.h" 6 | 7 | #define heap_parent(npos) ((int)(((npos) - 1) / 2)) 8 | #define heap_left(npos) (((npos) * 2) +1) 9 | #define heap_right(npos) (((npos) * 2) + 2) 10 | 11 | void heap_init(Heap *heap, int (*compare)(const void *key1, const void *key2), 12 | void (*destroy)(void *data)) 13 | { 14 | heap->size = 0; 15 | heap->compare = compare; 16 | heap->destroy = destroy; 17 | heap->tree = NULL; 18 | } 19 | 20 | void heap_destroy(Heap *heap) 21 | { 22 | int i; 23 | if (heap->destroy != NULL) { 24 | for (i = 0; i < heap_size(heap); i++) { 25 | heap->destroy(heap->tree[i]); 26 | } 27 | } 28 | 29 | free(heap->tree); 30 | 31 | memset(heap, 0, sizeof(Heap)); 32 | } 33 | 34 | int heap_insert(Heap *heap, const void *data) 35 | { 36 | void *temp; 37 | int ipos, ppos; 38 | 39 | if ((temp = (void **)realloc(heap->tree, 40 | (heap_size(heap) + 1) * sizeof(void *))) == NULL) { 41 | return -1; 42 | } else { 43 | heap->tree = temp; 44 | } 45 | 46 | // 将结点插入到末尾 47 | heap->tree[heap_size(heap)] = (void *)data; 48 | ipos = heap_size(heap); 49 | ppos = heap_parent(ipos); 50 | 51 | // 调整数据 52 | while (ipos > 0 && heap->compare(heap->tree[ppos], heap->tree[ipos]) < 0) { 53 | temp = heap->tree[ppos]; 54 | heap->tree[ppos] = heap->tree[ipos]; 55 | heap->tree[ipos] = temp; 56 | 57 | ipos = ppos; 58 | ppos = heap_parent(ipos); 59 | } 60 | 61 | heap->size++; 62 | 63 | return 0; 64 | } 65 | 66 | /** 67 | * 从堆heap中释放堆顶部的结点。返回时,data指向被释放结点中存储的数据。 68 | * 与data相关的内存将有函数的调用者来管理。 69 | * @param heap [description] 70 | * @param data [description] 71 | * @return [description] 72 | */ 73 | int heap_extract(Heap *heap, void **data) 74 | { 75 | void *save, *temp; 76 | int ipos, lpos, rpos, mpos; 77 | 78 | if (heap_size(heap) == 0) { 79 | return -1; 80 | } 81 | *data = heap->tree[0]; 82 | save = heap->tree[heap_size(heap) - 1]; 83 | 84 | if (heap_size(heap) - 1 > 0) { 85 | if ((temp = (void **)realloc(heap->tree, 86 | (heap_size(heap) - 1) * sizeof(void *))) == NULL) { 87 | return -1; 88 | } else { 89 | heap->tree = temp; 90 | } 91 | heap->size--; 92 | } else { 93 | free(heap->tree); 94 | heap->tree = NULL; 95 | heap->size = 0; 96 | return 0; 97 | } 98 | 99 | // 把最后一个结点放到顶点 100 | heap->tree[0] = save; 101 | ipos = 0; 102 | lpos = heap_left(ipos); 103 | rpos = heap_right(ipos); 104 | 105 | while (1) { 106 | lpos = heap_left(ipos); 107 | rpos = heap_right(ipos); 108 | // 如果左边结点比右边结点大 109 | if (lpos < heap_size(heap) && heap->compare(heap->tree[lpos], 110 | heap->tree[ipos]) > 0) { 111 | mpos = lpos; 112 | } else { 113 | mpos = ipos; 114 | } 115 | 116 | if (rpos < heap_size(heap) && heap->compare(heap->tree[rpos], 117 | heap->tree[mpos]) > 0) { 118 | mpos = rpos; 119 | } 120 | 121 | if (mpos == ipos) { 122 | break; 123 | } else { 124 | temp = heap->tree[mpos]; 125 | heap->tree[mpos] = heap->tree[ipos]; 126 | heap->tree[ipos] = temp; 127 | // 继续遍历下面一层 128 | ipos = mpos; 129 | } 130 | } 131 | return 0; 132 | } 133 | 134 | 135 | -------------------------------------------------------------------------------- /data_structure/heap.h: -------------------------------------------------------------------------------- 1 | //heap.h,最大值堆 2 | #ifndef HEAP_H 3 | #define HEAP_H 4 | 5 | typedef struct Heap_ { 6 | int size; 7 | int (*compare)(const void *key1, const void *key2); 8 | void (*destroy)(void *data); 9 | void **tree; 10 | } Heap; 11 | 12 | void heap_init(Heap *heap, int (*compare)(const void *key1, const void *key2), 13 | void (*destroy)(void *data)); 14 | void heap_destroy(Heap *heap); 15 | int heap_insert(Heap *heap, const void *data); 16 | int heap_extract(Heap *heap, void **data); 17 | #define heap_size(heap) ((heap)->size) 18 | 19 | 20 | #endif -------------------------------------------------------------------------------- /data_structure/list.c: -------------------------------------------------------------------------------- 1 | //list.c 2 | #include 3 | #include 4 | 5 | #include "list.h" 6 | 7 | /** 8 | * 初始化链表 9 | * @param list 要初始化的链表 10 | * @param destory 如果节点中的数据需要destroy,则提供destroy函数,该函数 11 | * 在list_destroy中被调用,用于销毁节点中的数据。如果节点中的数据不需要销毁, 12 | * 则该参数传NULL。 13 | */ 14 | void list_init(List *list, void (*destroy)(void *data)) 15 | { 16 | list->size = 0; 17 | list->destroy = destroy; 18 | list->head = NULL; 19 | list->tail = NULL; 20 | } 21 | 22 | /** 23 | * 销毁链表 24 | * @param list 要销毁的链表 25 | */ 26 | void list_destroy(List *list) 27 | { 28 | void *data; 29 | while (list_size(list) > 0) { 30 | if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destroy != NULL) { 31 | list->destroy(data); 32 | } 33 | } 34 | memset(list, 0, sizeof(List)); 35 | } 36 | 37 | /** 38 | * 将元素data插入到链表list的element节点后面。如果element为NULL, 39 | * 则新的节点插入到链表的开始。 40 | * @param list 要操作的链表 41 | * @param element 指定的节点 42 | * @param data 要插入的数据 43 | * @return 成功返回0;失败返回-1; 44 | */ 45 | int list_ins_next(List *list, ListElmt *element, const void *data) 46 | { 47 | ListElmt *new_element; 48 | 49 | if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) 50 | return -1; 51 | 52 | new_element->data = (void*)data; 53 | if (element == NULL) { 54 | /* 当链表中没有节点时 */ 55 | if (list_size(list) == 0) 56 | list->tail = new_element; 57 | 58 | new_element->next = list->head; 59 | list->head = new_element; 60 | } else { 61 | /* 当指定的元素为最后一个节点时 */ 62 | if (element->next == NULL) 63 | list->tail = new_element; 64 | 65 | new_element->next = element->next; 66 | element->next = new_element; 67 | } 68 | 69 | list->size++; 70 | 71 | return 0; 72 | } 73 | 74 | /** 75 | * 将节点element后面的那个节点从链表list中删除 76 | * @param list 要操作的链表 77 | * @param element 指定的节点 78 | * @param data 用于保存被删除的节点中的数据 79 | * @return 成功返回0;失败返回-1; 80 | */ 81 | int list_rem_next(List *list, ListElmt *element, void **data) 82 | { 83 | ListElmt *old_element; 84 | 85 | if (list_size(list) == 0) 86 | return -1; 87 | 88 | if (element == NULL) { 89 | *data = list->head->data; 90 | old_element = list->head; 91 | list->head = list->head->next; 92 | 93 | if (list_size(list) == 1) 94 | list->tail = NULL; 95 | } else { 96 | if (element->next == NULL) 97 | return -1; 98 | 99 | *data = element->next->data; 100 | old_element = element->next; 101 | element->next = element->next->next; 102 | 103 | /* 如果移除的是尾节点,调整尾节点 */ 104 | if (element->next == NULL) 105 | list->tail = element; 106 | } 107 | 108 | free(old_element); 109 | list->size--; 110 | 111 | return 0; 112 | } -------------------------------------------------------------------------------- /data_structure/list.h: -------------------------------------------------------------------------------- 1 | //list.h 2 | #ifndef LIST_H 3 | #define LIST_H 4 | 5 | #include 6 | 7 | typedef struct ListElmt_ 8 | { 9 | void *data; 10 | struct ListElmt_ *next; 11 | } ListElmt; 12 | 13 | typedef struct List_ 14 | { 15 | int size; 16 | int (*match)(const void *key1, const void *key2); 17 | void (*destroy)(void *data); 18 | ListElmt *head; 19 | ListElmt *tail; 20 | } List; 21 | 22 | /* public interface */ 23 | void list_init(List *list, void (*destroy)(void *data)); 24 | void list_destroy(List *list); 25 | int list_ins_next(List *list, ListElmt *element, const void *data); 26 | int list_rem_next(List *list, ListElmt *element, void **data); 27 | 28 | #define list_size(list) ((list)->size) 29 | #define list_head(list) ((list)->head) 30 | #define list_tail(list) ((list)->tail) 31 | #define list_is_head(list, element) ((element) == (list)->head ? 1 : 0) 32 | #define list_is_tail(element) ((element)->next == NULL ? 1 : 0) 33 | #define list_data(element) ((element)->data) 34 | #define list_next(element) ((element)->next) 35 | 36 | #endif -------------------------------------------------------------------------------- /data_structure/ohtbl.c: -------------------------------------------------------------------------------- 1 | // ohtbl.c,开地址哈希表 2 | #include 3 | #include 4 | 5 | #include "ohtbl.h" 6 | 7 | static char vacated; 8 | 9 | int ohtbl_init(OHTbl *htbl, int positions, int (*h1)(const void *key), 10 | int (*h2)(const void *key), int (*match)(const void *key1, const void *key2), 11 | void (*destroy)(void *data)) 12 | { 13 | int i; 14 | if ((htbl->table = (void **)malloc(positions * sizeof(void *))) == NULL) { 15 | return -1; 16 | } 17 | 18 | htbl->positions = positions; 19 | for (i = 0; i < htbl->positions; i++) 20 | htbl->table[i] = NULL; 21 | 22 | htbl->vacated = &vacated; 23 | 24 | htbl->h1 = h1; 25 | htbl->h2 = h2; 26 | htbl->match = match; 27 | htbl->destroy = destroy; 28 | 29 | htbl->size = 0; 30 | 31 | return 0; 32 | } 33 | 34 | void ohtbl_destroy(OHTbl *htbl) 35 | { 36 | int i; 37 | if (htbl->destroy != NULL) { 38 | for (i = 0; i < htbl->positions; i++) { 39 | if (htbl->table[i] != NULL && htbl->table[i] != htbl->vacated) 40 | htbl->destroy(htbl->table[i]); 41 | } 42 | } 43 | 44 | free(htbl->table); 45 | memset(htbl, 0, sizeof(OHTbl)); 46 | } 47 | 48 | /** 49 | * 将数据data插入htbl中 50 | * 51 | * @param htbl 哈希表 52 | * @param data 要插入的数据 53 | * @return 成功返回0,已经存在该数据返回1,其它情况返回-1 54 | */ 55 | int ohtbl_insert(OHTbl *htbl, const void *data) 56 | { 57 | void *temp; 58 | int position, i; 59 | 60 | // 没有空间了 61 | if (htbl->size == htbl->positions) 62 | return -1; 63 | 64 | temp = (void *)data; 65 | // 如果已经存在该元素,直接返回 66 | if (ohtbl_lookup(htbl, &temp) == 0) 67 | return 1; 68 | 69 | for (i = 0; i < htbl->positions; i++) { 70 | position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->positions; 71 | 72 | if (htbl->table[position] == NULL 73 | || htbl->table[position] == htbl->vacated) { 74 | htbl->table[position] = (void *)data; 75 | htbl->size++; 76 | return 0; 77 | } 78 | } 79 | 80 | return -1; 81 | } 82 | 83 | /** 84 | * 将数据data从哈希表htbl中移除 85 | * @param htbl 哈希表 86 | * @param data 要移除的数据 87 | * @return 成功返回0,失败返回-1 88 | */ 89 | int ohtbl_remove(OHTbl *htbl, void **data) 90 | { 91 | int position, i; 92 | 93 | for (i = 0; i < htbl->positions; i++) { 94 | position = (htbl->h1(data) + (i * htbl->h2(*data))) % htbl->positions; 95 | 96 | if (htbl->table[position] == NULL) { 97 | return -1; 98 | } // 该位置的数据已经被删除了,但是仍然需要遍历完才能知道是否还有其它位置有数据 99 | else if (htbl->table[position] == htbl->vacated) { 100 | continue; 101 | } else if (htbl->match(htbl->table[position], *data)) { 102 | *data = htbl->table[position]; 103 | htbl->table[position] = htbl->vacated; 104 | htbl->size--; 105 | return 0; 106 | } 107 | } 108 | 109 | return -1; 110 | } 111 | 112 | int ohtbl_lookup(const OHTbl *htbl, void **data) 113 | { 114 | int position, i; 115 | 116 | for (i = 0; i < htbl->positions; i++) { 117 | position = (htbl->h1(data) + (i * htbl->h2(*data))) % htbl->positions; 118 | 119 | if (htbl->table[position] == NULL) { 120 | return -1; 121 | } else if (htbl->match(htbl->table[position], *data)) { 122 | // 为什么要给data再赋值 123 | *data = htbl->table[position]; 124 | return 0; 125 | } 126 | } 127 | return -1; 128 | } 129 | 130 | 131 | -------------------------------------------------------------------------------- /data_structure/ohtbl.h: -------------------------------------------------------------------------------- 1 | // ohtbl.h 2 | #ifndef OHTBL_H 3 | #define OHTBL_H 4 | 5 | #include 6 | 7 | typedef struct OHTbl_ 8 | { 9 | int positions;// 槽位数目 10 | void *vacated; 11 | 12 | int (*h1)(const void *key);// 双散列函数 13 | int (*h2)(const void *key);// 双散列函数 14 | int (*match)(const void *key1, const void *key2); 15 | void (*destroy)(void *data); 16 | 17 | int size;// 表中现有元素的数量 18 | void **table;// 存储元素的数组 19 | } OHTbl; 20 | 21 | /* public interface */ 22 | int ohtbl_init(OHTbl *htbl, int positions, int (*h1)(const void *key), 23 | int (*h2)(const void *key), int (*match)(const void *key1, const void *key2), 24 | void (*destroy)(void *data)); 25 | 26 | void ohtbl_destroy(OHTbl *htbl); 27 | int ohtbl_insert(OHTbl *htbl, const void *data); 28 | int ohtbl_remove(OHTbl *htbl, void **data); 29 | int ohtbl_lookup(const OHTbl *htbl, void **data); 30 | #define ohtbl_size(htbl) ((htbl)->size) 31 | 32 | #endif -------------------------------------------------------------------------------- /data_structure/parcel.h: -------------------------------------------------------------------------------- 1 | #ifndef PARCEL_H 2 | #define PARCEL_H 3 | 4 | typedef struct Parcel_ { 5 | int priority; 6 | } Parcel; 7 | 8 | #endif -------------------------------------------------------------------------------- /data_structure/parcels.c: -------------------------------------------------------------------------------- 1 | // parcels.c,包裹分拣,使用优先级队列的例子 2 | #include 3 | #include 4 | 5 | #include "parcel.h" 6 | #include "parcels.h" 7 | #include "pqueue.h" 8 | 9 | int get_parcel(PQueue *parcels, Parcel *parcel) 10 | { 11 | Parcel *data; 12 | if (pqueue_size(parcels) == 0) { 13 | return -1; 14 | } else { 15 | if (pqueue_extract(parcels, (void **)&data) != 0) { 16 | return -1; 17 | } 18 | memcpy(parcel, data, sizeof(Parcel)); 19 | free(data); 20 | } 21 | return 0; 22 | } 23 | 24 | int put_parcel(PQueue *parcels, const Parcel *parcel) 25 | { 26 | Parcel *data; 27 | if ((data = (Parcel *)malloc(sizeof(Parcel))) == NULL) { 28 | return -1; 29 | } 30 | 31 | memcpy(data, parcel, sizeof(Parcel)); 32 | 33 | if (pqueue_insert(parcels, data) != 0) 34 | return -1; 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /data_structure/parcels.h: -------------------------------------------------------------------------------- 1 | #ifndef PARCELS_H 2 | #define PARCELS_H 3 | 4 | #include "parcel.h" 5 | #include "pqueue.h" 6 | 7 | int get_parcel(PQueue *parcels, Parcel *parcel); 8 | 9 | int put_parcel(PQueue *parcels, const Parcel *parcel); 10 | 11 | #endif -------------------------------------------------------------------------------- /data_structure/pqueue.h: -------------------------------------------------------------------------------- 1 | // pqueue.h,优先队列 2 | #ifndef PQUEUE_H 3 | #define PQUEUE_H 4 | 5 | #include "heap.h" 6 | 7 | typedef Heap PQueue; 8 | 9 | #define pqueue_init heap_init 10 | #define pqueue_destroy heap_destroy 11 | #define pqueue_insert heap_insert 12 | #define pqueue_extract heap_extract 13 | #define pqueue_peek(pqueue) ((pqueue)->tree == NULL ? NULL : (pqueue)->tree[0]) 14 | #define pqueue_size heap_size 15 | 16 | #endif -------------------------------------------------------------------------------- /data_structure/queue.c: -------------------------------------------------------------------------------- 1 | // queue.c 2 | #include 3 | 4 | #include "queue.h" 5 | 6 | /** 7 | * 入队 8 | * @param queue [description] 9 | * @param data [description] 10 | * @return [description] 11 | */ 12 | int queue_enqueue(Queue *queue, const void *data) 13 | { 14 | return list_ins_next(queue, list_tail(queue), data); 15 | } 16 | 17 | /** 18 | * 出队 19 | * @param queue [description] 20 | * @param data [description] 21 | * @return [description] 22 | */ 23 | int queue_dequeue(Queue *queue, void **data) 24 | { 25 | return list_rem_next(queue, NULL, data); 26 | } 27 | -------------------------------------------------------------------------------- /data_structure/queue.h: -------------------------------------------------------------------------------- 1 | // queue 2 | #ifndef QUEUE_H 3 | #define QUEUE_H 4 | 5 | #include "list.h" 6 | 7 | typedef List Queue; 8 | 9 | #define queue_init list_init 10 | #define queue_destroy list_destroy 11 | int queue_enqueue(Queue *queue, const void *data); 12 | int queue_dequeue(Queue *queue, void **data); 13 | // 获取队列头元素的信息,但是不出队 14 | #define queue_peek(queue) ((queue)->head == NULL ? NULL : (queue)->head->data) 15 | #define queue_size list_size 16 | 17 | #endif -------------------------------------------------------------------------------- /data_structure/set.c: -------------------------------------------------------------------------------- 1 | // set.c 2 | #include 3 | #include 4 | #include "set.h" 5 | 6 | void set_init(Set *set, int (*match)(const void *key1, const void *key2), 7 | void (*destroy)(void *data)) 8 | { 9 | list_init(set, destroy); 10 | set->match = match; 11 | } 12 | 13 | int set_insert(Set *set, const void *data) 14 | { 15 | if (set_is_member(set, data)) 16 | return 1; 17 | return list_ins_next(set, list_tail(set), data); 18 | } 19 | 20 | int set_remove(Set *set, void **data) 21 | { 22 | ListElmt *member, *prev; 23 | 24 | prev = NULL; 25 | for (member = list_head(set); member != NULL; member = list_next(member)) { 26 | if (set->match(*data, list_data(member))) 27 | break; 28 | prev = member; 29 | } 30 | 31 | if (member == NULL) 32 | return -1; 33 | 34 | return list_rem_next(set, prev, data); 35 | } 36 | 37 | /** 38 | * 计算两个集合的并集 39 | * @param setu 合并后的集合 40 | * @param set1 用于合并的集合1 41 | * @param set2 用于合并的集合2 42 | * @return 成功返回0;失败返回-1 43 | */ 44 | int set_union(Set *setu, const Set *set1, const Set *set2) 45 | { 46 | ListElmt *member; 47 | void *data; 48 | 49 | set_init(setu, set1->match, NULL); 50 | 51 | for (member = list_head(set1); member != NULL; member = list_next(member)) { 52 | data = list_data(member); 53 | if (list_ins_next(setu, list_tail(setu), data) != 0) 54 | return -1; 55 | } 56 | 57 | for (member = list_head(set2); member != NULL; member = list_next(member)) { 58 | if (set_is_member(set1, list_data(member))) { 59 | continue; 60 | } else { 61 | data = list_data(member); 62 | if (list_ins_next(setu, list_tail(setu), data) != 0) { 63 | set_destroy(setu); 64 | return -1; 65 | } 66 | } 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | /** 73 | * 求两个集合的交集 74 | * @param seti 交集 75 | * @param set1 集合1 76 | * @param set2 集合2 77 | * @return 成功返回0;失败返回-1 78 | */ 79 | int set_intersection(Set *seti, const Set *set1, const Set *set2) 80 | { 81 | ListElmt *member; 82 | void *data; 83 | 84 | set_init(seti, set1->match, NULL); 85 | 86 | for (member = list_head(set1); member != NULL; member = list_next(member)) { 87 | if (set_is_member(set2, list_data(member))) { 88 | data = list_data(member); 89 | if (list_ins_next(seti, list_tail(seti), data) != 0) { 90 | set_destroy(seti); 91 | return -1; 92 | } 93 | } 94 | } 95 | return 0; 96 | } 97 | 98 | /** 99 | * 求两个集合的差集 100 | * @param setd 差集 101 | * @param set1 集合1 102 | * @param set2 集合2 103 | * @return 成功返回0;失败返回-1 104 | */ 105 | int set_difference(Set *setd, const Set *set1, const Set *set2) 106 | { 107 | ListElmt *member; 108 | void *data; 109 | 110 | set_init(setd, set1->match, NULL); 111 | for (member = list_head(set1); member != NULL; member = list_next(member)) { 112 | if (!set_is_member(set2, list_data(member))) { 113 | data = list_data(member); 114 | if (list_ins_next(setd, list_tail(setd), data) != 0) { 115 | set_destroy(setd); 116 | return -1; 117 | } 118 | } 119 | } 120 | return 0; 121 | } 122 | 123 | /** 124 | * 判断某个元素是否在集合中 125 | * @param set [description] 126 | * @param data [description] 127 | * @return 成功返回1;失败0 128 | */ 129 | int set_is_member(const Set *set, const void *data) 130 | { 131 | ListElmt *member; 132 | 133 | for (member = list_head(set); member != NULL; member = list_next(member)) { 134 | if (set->match(data, list_data(member))) 135 | return 1; 136 | } 137 | return 0; 138 | } 139 | 140 | /** 141 | * set1是否是set2的子集 142 | * @param set1 [description] 143 | * @param set2 [description] 144 | * @return 成功返回1;失败0 145 | */ 146 | int set_is_subset(const Set *set1, const Set *set2) 147 | { 148 | ListElmt *member; 149 | 150 | if (set_size(set1) > set_size(set2)) 151 | return 0; 152 | 153 | for (member = list_head(set1); member != NULL; member = list_next(member)) { 154 | if (!set_is_member(set2, list_data(member))) 155 | return 0; 156 | } 157 | return 1; 158 | } 159 | 160 | /** 161 | * 判断两个集合是否相等 162 | * @param set1 [description] 163 | * @param set2 [description] 164 | * @return 成功返回1;失败返回0 165 | */ 166 | int set_is_equal(const Set *set1, const Set *set2) 167 | { 168 | if (set_size(set1) != set_size(set2)) 169 | return 0; 170 | 171 | return set_is_subset(set1, set2); 172 | } 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /data_structure/set.h: -------------------------------------------------------------------------------- 1 | // set.h 2 | #ifndef SET_H 3 | #define SET_H 4 | 5 | #include 6 | #include "list.h" 7 | 8 | typedef List Set; 9 | 10 | // public interface 11 | void set_init(Set *set, int (*match)(const void *key1, const void *key2), 12 | void (*destroy)(void *data)); 13 | #define set_destroy list_destroy 14 | int set_insert(Set *set, const void *data); 15 | int set_remove(Set *set, void **data); 16 | 17 | /** 18 | * 计算两个集合的并集 19 | * @param setu 合并后的集合 20 | * @param set1 用于合并的集合1 21 | * @param set2 用于合并的集合2 22 | * @return 成功返回0;失败返回-1 23 | */ 24 | int set_union(Set *setu, const Set *set1, const Set *set2); 25 | 26 | /** 27 | * 求两个集合的交集 28 | * @param seti 交集 29 | * @param set1 集合1 30 | * @param set2 集合2 31 | * @return 成功返回0;失败返回-1 32 | */ 33 | int set_intersection(Set *seti, const Set *set1, const Set *set2); 34 | 35 | /** 36 | * 求两个集合的差集 37 | * @param setd 差集 38 | * @param set1 集合1 39 | * @param set2 集合2 40 | * @return 成功返回0;失败返回-1 41 | */ 42 | int set_difference(Set *setd, const Set *set1, const Set *set2); 43 | 44 | int set_is_member(const Set *set, const void *data); 45 | int set_is_subset(const Set *set1, const Set *set2); 46 | int set_is_equal(const Set *set1, const Set *set2); 47 | #define set_size(set) ((set)->size) 48 | 49 | #endif -------------------------------------------------------------------------------- /data_structure/stack.c: -------------------------------------------------------------------------------- 1 | // stack.c 2 | #include 3 | #include "stack.h" 4 | 5 | int stack_push(Stack *stack, const void *data) 6 | { 7 | return list_ins_next(stack, NULL, data); 8 | } 9 | 10 | int stack_pop(Stack *stack, void **data) 11 | { 12 | return list_rem_next(stack, NULL, data); 13 | } -------------------------------------------------------------------------------- /data_structure/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef STACK_H 2 | #define STACK_H 3 | 4 | #include 5 | #include "list.h" 6 | 7 | typedef List Stack; 8 | 9 | #define stack_init lisg_init 10 | #define stack_destroy list_destroy 11 | 12 | int stack_push(Stack *stack, const void *data); 13 | int stack_pop(Stack *stack, void **data); 14 | #define stack_peek(stack) ((stack)->head == NULL ? NULL : (stack)->head->data) 15 | #define stack_size list_size 16 | 17 | #endif --------------------------------------------------------------------------------