├── ScreenShot.png ├── Algorithms.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── Algorithms.xcscheme ├── MasteringAlgorithms.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── C07-Set.xcscheme │ ├── C14-Bit.xcscheme │ ├── C05-List.xcscheme │ ├── C05-Page.xcscheme │ ├── C10-Heap.xcscheme │ ├── C12-Sort.xcscheme │ ├── C05-CList.xcscheme │ ├── C05-DList.xcscheme │ ├── C06-Queue.xcscheme │ ├── C06-Stack.xcscheme │ ├── C07-Cover.xcscheme │ ├── C11-Graph.xcscheme │ ├── C12-Spell.xcscheme │ ├── C09-BiTree.xcscheme │ └── C10-PQueue.xcscheme ├── run ├── include ├── parcel.h ├── hashpjw.h ├── lex.h ├── page.h ├── spell.h ├── symbol.h ├── frames.h ├── geodist.h ├── directls.h ├── search.h ├── cover.h ├── route.h ├── dfs.h ├── parcels.h ├── bfs.h ├── events.h ├── transfer.h ├── traverse.h ├── cbc.h ├── nummeths.h ├── bit.h ├── stack.h ├── queue.h ├── pqueue.h ├── heap.h ├── geometry.h ├── encrypt.h ├── bistree.h ├── chtbl.h ├── ohtbl.h ├── clist.h ├── graphalg.h ├── compress.h ├── sort.h ├── set.h ├── list.h ├── dlist.h ├── graph.h └── bitree.h ├── source ├── queue.c ├── stack.c ├── page.c ├── spell.c ├── hashpjw.c ├── lsqe.c ├── geodist.c ├── root.c ├── arclen.c ├── issort.c ├── parcels.c ├── events.c ├── bisearch.c ├── frames.c ├── rsa.c ├── ctsort.c ├── cbc.c ├── lex.c ├── interpol.c ├── route.c ├── transfer.c ├── rxsort.c ├── directls.c ├── traverse.c ├── lint.c ├── cover.c ├── bit.c ├── dfs.c ├── clist.c ├── cvxhull.c ├── tsp.c ├── list.c ├── mgsort.c ├── qksort.c ├── bfs.c ├── chtbl.c ├── mst.c └── shortest.c ├── LICENSE ├── .gitignore ├── Example ├── directls │ └── main.c ├── geodist │ └── main.c ├── cbc │ └── main.c ├── page │ └── main.c ├── spell │ └── main.c ├── bissearch │ └── main.c ├── clist │ └── main.c ├── heap │ └── main.c ├── queue │ └── main.c ├── stack │ └── main.c ├── pqueue │ └── main.c └── list │ └── main.c ├── .travis.yml └── README.md /ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yourtion/LearningMasteringAlgorithms-C/HEAD/ScreenShot.png -------------------------------------------------------------------------------- /Algorithms.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -d "build" ];then 4 | mkdir build 5 | fi 6 | 7 | if [ -d "Example/$1" ] 8 | then 9 | cc source/*.c Example/$1/main.c -I ./include -lm -o build/$1 10 | cd build 11 | ./$1 12 | else 13 | echo "Example does not exists." 14 | echo "Example list :" 15 | echo `ls Example` 16 | fi 17 | -------------------------------------------------------------------------------- /include/parcel.h: -------------------------------------------------------------------------------- 1 | // 2 | // parcel.h 3 | // Algorithms - Parcel 4 | // 5 | // Created by YourtionGuo on 05/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef PARCEL_H 10 | #define PARCEL_H 11 | 12 | 13 | /** 14 | 包裹 15 | */ 16 | typedef struct Parcel_ 17 | { 18 | int priority; 19 | 20 | } Parcel; 21 | 22 | #endif /* PARCEL_H */ 23 | -------------------------------------------------------------------------------- /include/hashpjw.h: -------------------------------------------------------------------------------- 1 | // 2 | // hashpjw.h 3 | // Algorithms - hash function 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef HASHPJW_H 10 | #define HASHPJW_H 11 | 12 | /// 定义桶数量(表大小) 13 | #define PRIME_TBLSIZ 1699 14 | 15 | 16 | /** 17 | 处理字符串的哈希函数 18 | 19 | @param key 待处理键 20 | @return 哈希 21 | */ 22 | int hashpjw(const void *key); 23 | 24 | #endif /* HASHPJW_H */ 25 | -------------------------------------------------------------------------------- /include/lex.h: -------------------------------------------------------------------------------- 1 | // 2 | // lex.h 3 | // Algorithms - lex 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef LEX_H 10 | #define LEX_H 11 | 12 | #include "chtbl.h" 13 | 14 | typedef enum Token_ {lexit, error, digit, other} Token; 15 | 16 | 17 | /** 18 | 根据输入流生成符号表 19 | 20 | @param istream 输入流 21 | @param symtbl 符号表 22 | @return 类型 23 | */ 24 | Token lex(const char *istream, CHTbl *symtbl); 25 | 26 | #endif /* LEX_H */ 27 | -------------------------------------------------------------------------------- /source/queue.c: -------------------------------------------------------------------------------- 1 | // 2 | // queue.c 3 | // Algorithms - queue 4 | // 5 | // Created by YourtionGuo on 25/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "list.h" 10 | #include "queue.h" 11 | 12 | #pragma mark - Public 13 | 14 | 15 | int queue_enqueue(Queue *queue, const void *data) 16 | { 17 | /// 入队 18 | return list_ins_next(queue, list_tail(queue), data); 19 | } 20 | 21 | 22 | int queue_dequeue(Queue *queue, void **data) 23 | { 24 | /// 出队 25 | return list_rem_next(queue, NULL, data); 26 | } 27 | -------------------------------------------------------------------------------- /include/page.h: -------------------------------------------------------------------------------- 1 | // 2 | // page.h 3 | // Algorithms - second-chance page 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef PAGE_H 10 | #define PAGE_H 11 | 12 | #include "clist.h" 13 | 14 | /** 15 | 页 16 | */ 17 | typedef struct Page_ 18 | { 19 | int number; 20 | int reference; 21 | 22 | } Page; 23 | 24 | 25 | /** 26 | 第二次机会置换法(时钟算法)LRU 27 | 28 | @param current 当前元素 29 | @return 页位置 30 | */ 31 | int replace_page(CListElmt **current); 32 | 33 | #endif /* PAGE_H */ 34 | -------------------------------------------------------------------------------- /include/spell.h: -------------------------------------------------------------------------------- 1 | // 2 | // spell.h 3 | // Algorithms - Spell checking 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef SPELL_H 10 | #define SPELL_H 11 | 12 | /// 设置单词最大长度 13 | #define SPELL_SIZE 31 14 | 15 | 16 | /** 17 | 单词拼写检查 - O(lgn) 18 | 19 | @param dictionary 有序字符串数组 20 | @param size 字典中字符串的个数 21 | @param word 被检查的单词 22 | @return 找到返回 1;否则返回 0 23 | */ 24 | int spell(char (*dictionary)[SPELL_SIZE], int size, const char *word); 25 | 26 | #endif /* SPELL_H */ 27 | -------------------------------------------------------------------------------- /source/stack.c: -------------------------------------------------------------------------------- 1 | // 2 | // stack.c 3 | // Algorithms - stack 4 | // 5 | // Created by YourtionGuo on 25/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "list.h" 12 | #include "stack.h" 13 | 14 | #pragma mark - Public 15 | 16 | 17 | int stack_push(Stack *stack, const void *data) 18 | { 19 | /// 将数据压入栈 20 | return list_ins_next(stack, NULL, data); 21 | } 22 | 23 | 24 | int stack_pop(Stack *stack, void **data) 25 | { 26 | /// 弹出栈顶元素 27 | return list_rem_next(stack, NULL, data); 28 | } 29 | -------------------------------------------------------------------------------- /include/symbol.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol.h 3 | // Algorithms - lex Symbol 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef SYMBOL_H 10 | #define SYMBOL_H 11 | 12 | 13 | /** 14 | 模拟输入流拆分函数 15 | 16 | @param istream 输入流 17 | @return 标记( NULL 表示结束) 18 | */ 19 | static char *next_token(const char *istream) 20 | { 21 | return NULL; 22 | } 23 | 24 | 25 | /** 26 | 符号标记 27 | */ 28 | typedef struct 29 | { 30 | char *lexeme; 31 | Token token; 32 | 33 | } Symbol; 34 | 35 | #endif /* SYMBOL_H */ 36 | -------------------------------------------------------------------------------- /source/page.c: -------------------------------------------------------------------------------- 1 | // 2 | // page.c 3 | // Algorithms - second-chance page 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "clist.h" 10 | #include "page.h" 11 | 12 | #pragma mark - Public 13 | 14 | 15 | int replace_page(CListElmt **current) 16 | { 17 | /// 循环整个链表直至找到结果 18 | 19 | while (((Page *)(*current)->data)->reference != 0) { 20 | 21 | ((Page *)(*current)->data)->reference = 0; 22 | *current = clist_next(*current); 23 | 24 | } 25 | 26 | return ((Page *)(*current)->data)->number; 27 | } 28 | -------------------------------------------------------------------------------- /include/frames.h: -------------------------------------------------------------------------------- 1 | // 2 | // frames.h 3 | // Algorithms - frame 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef FRAMES_H 10 | #define FRAMES_H 11 | 12 | #include "list.h" 13 | 14 | 15 | /** 16 | 从空闲页帧链表中获取空闲页帧号 17 | 18 | @param frames 帧链表 19 | @return 页帧号 20 | */ 21 | int alloc_frame(List *frames); 22 | 23 | 24 | 25 | /** 26 | 释放之前获取的页帧号 27 | 28 | @param frames 帧链表 29 | @param frame_number 页帧号 30 | @return 成功返回 0,否则返回 -1 31 | */ 32 | int free_frame(List *frames, int frame_number); 33 | 34 | #endif /* FRAMES_H */ 35 | -------------------------------------------------------------------------------- /include/geodist.h: -------------------------------------------------------------------------------- 1 | // 2 | // geodist.h 3 | // Algorithms - Geo dist 4 | // 5 | // Created by YourtionGuo on 25/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef GEODIST_H 10 | #define GEODIST_H 11 | 12 | /// 地球半径 13 | #define EARTH_RADIUS 3440.065 14 | 15 | /** 16 | 计算地球上两点间近似距离 - O(1) 17 | 18 | @param lat1 地点 1 经度 19 | @param lon1 地点 1 纬度 20 | @param lat2 地点 2 经度 21 | @param lon2 地点 2 纬度 22 | @param d 近似距离结果 23 | @return 计算成功返回0;否则,返回-1 24 | */ 25 | int geodist(double lat1, double lon1, double lat2, double lon2, double *d); 26 | 27 | #endif /* GEODIST_H */ 28 | -------------------------------------------------------------------------------- /include/directls.h: -------------------------------------------------------------------------------- 1 | // 2 | // directls.h 3 | // Algorithms - Sorting a directory listing 4 | // 5 | // Created by YourtionGuo on 10/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef DIRECTLS_H 10 | #define DIRECTLS_H 11 | 12 | #include 13 | 14 | 15 | /** 16 | 目录结构 17 | */ 18 | typedef struct Directory_ 19 | { 20 | char name[MAXNAMLEN + 1]; 21 | 22 | } Directory; 23 | 24 | 25 | /** 26 | 列出 path 路径中指定的目录列表 27 | 28 | @param path 路径 29 | @param dir 目录列表 30 | @return 成功返回 0;否则返回 -1 31 | */ 32 | int directls(const char *path, Directory **dir); 33 | 34 | #endif /* DIRECTLS_H */ 35 | -------------------------------------------------------------------------------- /include/search.h: -------------------------------------------------------------------------------- 1 | // 2 | // search.h 3 | // Algorithms - Search 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef SEARCH_H 10 | #define SEARCH_H 11 | 12 | 13 | /** 14 | 二分查找 - O(lg n) 15 | 16 | @param sorted 已排序数据 17 | @param target 查找目标 18 | @param size 元素个数 19 | @param esize 每个元素的大小 20 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 21 | @return 查找成功返回目标的索引值;否则,返回-1 22 | */ 23 | int bisearch(void *sorted, const void *target, int size, int esize, 24 | int(*compare)(const void *key1, const void *key2)); 25 | 26 | #endif /* SEARCH_H */ 27 | -------------------------------------------------------------------------------- /include/cover.h: -------------------------------------------------------------------------------- 1 | // 2 | // cover.h 3 | // Algorithms - set covering 4 | // 5 | // Created by YourtionGuo on 26/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef COVER_H 10 | #define COVER_H 11 | 12 | #include "set.h" 13 | 14 | 15 | /** 16 | 带 key 的集合 17 | */ 18 | typedef struct KSet_ 19 | { 20 | void *key; 21 | Set set; 22 | 23 | } KSet; 24 | 25 | 26 | /** 27 | 计算集合覆盖 28 | 29 | @param members 待覆盖集合成员 30 | @param subsets 候选人集合 31 | @param covering 覆盖集合C结果 32 | @return 找到覆盖返回0; 不可能实现完全覆盖返回1;其他情况返回-1 33 | */ 34 | int cover(Set *members, Set *subsets, Set *covering); 35 | 36 | #endif /* COVER_H */ 37 | -------------------------------------------------------------------------------- /include/route.h: -------------------------------------------------------------------------------- 1 | // 2 | // route.h 3 | // Algorithms - Route SPF 4 | // 5 | // Created by YourtionGuo on 24/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef ROUTE_H 10 | #define ROUTE_H 11 | 12 | #include "graphalg.h" 13 | #include "list.h" 14 | 15 | 16 | /** 17 | 计算路由下一个结点 18 | 19 | @param paths 路径信息列表(通过 shortest 计算) 20 | @param destination 目的地址 21 | @param next 指向下一结点顶点指针 22 | @param match 函数指针,用于判断两个成员是否相匹配(等于返回 1,否则返回 0) 23 | @return 计算成功返回0;否则,返回-1 24 | */ 25 | int route(List *paths, PathVertex *destination, PathVertex **next, 26 | int(*match)(const void *key1, const void *key2)); 27 | 28 | #endif /* ROUTE_H */ 29 | -------------------------------------------------------------------------------- /include/dfs.h: -------------------------------------------------------------------------------- 1 | // 2 | // dfs.h 3 | // Algorithms - Graph depth-first search 4 | // 5 | // Created by YourtionGuo on 08/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef DFS_H 10 | #define DFS_H 11 | 12 | #include "graph.h" 13 | #include "list.h" 14 | 15 | 16 | /** 17 | 深度优先搜索 18 | */ 19 | typedef struct DfsVertex_ { 20 | 21 | void *data; 22 | 23 | VertexColor color; 24 | 25 | } DfsVertex; 26 | 27 | 28 | /** 29 | 在 graph 指定的图执行深度优先搜索 - O(V+E) V是图中顶点的个数,E是边的个数 30 | 31 | @param graph 图 32 | @param ordered 顶点链表 33 | @return 成功返回0;否则返回-1 34 | */ 35 | int dfs(Graph *graph, List *ordered); 36 | 37 | #endif /* DFS_H */ 38 | -------------------------------------------------------------------------------- /include/parcels.h: -------------------------------------------------------------------------------- 1 | // 2 | // parcels.h 3 | // Algorithms - Parcels 4 | // 5 | // Created by YourtionGuo on 05/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef PARCELS_H 10 | #define PARCELS_H 11 | 12 | #include "parcel.h" 13 | #include "pqueue.h" 14 | 15 | 16 | /** 17 | 在优先队列 parcels 获取下一个包裹 18 | 19 | @param parcels 包裹优先队列 20 | @param parcel 包裹 21 | @return 成功返回0;否则返回-1 22 | */ 23 | int get_parcel(PQueue *parcels, Parcel *parcel); 24 | 25 | 26 | /** 27 | 将一个包裹 parcel 插入一个优先队列 parcels 28 | 29 | @param parcels 包裹优先队列 30 | @param parcel 包裹 31 | @return 成功,返回0;否则返回-1 32 | */ 33 | int put_parcel(PQueue *parcels, const Parcel *parcel); 34 | 35 | #endif /* PARCELS_H */ 36 | -------------------------------------------------------------------------------- /include/bfs.h: -------------------------------------------------------------------------------- 1 | // 2 | // bfs.h 3 | // Algorithms - Graph breadth-first search 4 | // 5 | // Created by YourtionGuo on 08/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef BFS_H 10 | #define BFS_H 11 | 12 | #include "graph.h" 13 | #include "list.h" 14 | 15 | 16 | /** 17 | 广度优先搜索 18 | */ 19 | typedef struct BfsVertex_ 20 | { 21 | void *data; 22 | 23 | VertexColor color; 24 | int hops; 25 | 26 | } BfsVertex; 27 | 28 | 29 | /** 30 | 在 graph 指定的图执行广度优先搜索 - O(V+E) V是图中顶点的个数,E是边的个数 31 | 32 | @param graph 图 33 | @param start 起始的顶点 34 | @param hops 跳数链表 35 | @return 成功返回0;否则返回-1 36 | */ 37 | int bfs(Graph *graph, BfsVertex *start, List *hops); 38 | 39 | #endif /* BFS_H */ 40 | -------------------------------------------------------------------------------- /source/spell.c: -------------------------------------------------------------------------------- 1 | // 2 | // spell.c 3 | // Algorithms - Spell checking 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "search.h" 12 | #include "spell.h" 13 | 14 | #pragma mark - Private 15 | 16 | static int compare_str(const void *str1, const void *str2) 17 | { 18 | int retval; 19 | 20 | /// 比较两个字符 21 | if ((retval = strcmp((const char *)str1, (const char *)str2)) > 0) return 1; 22 | if (retval < 0) return -1; 23 | return 0; 24 | } 25 | 26 | #pragma mark - Public 27 | 28 | int spell(char (*dictionary)[SPELL_SIZE], int size, const char *word) 29 | { 30 | /// 查找单词 31 | if (bisearch(dictionary, word, size, SPELL_SIZE, compare_str) >= 0) return 1; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /source/hashpjw.c: -------------------------------------------------------------------------------- 1 | // 2 | // hashpjw.c 3 | // Algorithms - hash function 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "hashpjw.h" 10 | 11 | #pragma mark - Public 12 | 13 | 14 | int hashpjw(const void *key) 15 | { 16 | const char *ptr; 17 | int val; 18 | 19 | /// 通过一系列位操作对提供的 key 进行 hash 20 | 21 | val = 0; 22 | ptr = key; 23 | 24 | while (*ptr != '\0') { 25 | 26 | int tmp; 27 | val = (val << 4) + (*ptr); 28 | 29 | if ((tmp = (val & 0xf0000000))) { 30 | 31 | val = val ^ (tmp >> 24); 32 | val = val ^ tmp; 33 | 34 | } 35 | 36 | ptr++; 37 | } 38 | 39 | /// 根据实际情况将 PRIME_TBLSIZ 替换为需要的表大小 40 | return val % PRIME_TBLSIZ; 41 | } 42 | -------------------------------------------------------------------------------- /include/events.h: -------------------------------------------------------------------------------- 1 | // 2 | // events.h 3 | // Algorithms - events 4 | // 5 | // Created by YourtionGuo on 25/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef EVENTS_H 10 | #define EVENTS_H 11 | 12 | #include 13 | 14 | #include "queue.h" 15 | 16 | /** 17 | 事件 18 | */ 19 | typedef struct Event_ 20 | { 21 | int type; 22 | 23 | } Event; 24 | 25 | 26 | /** 27 | 将要处理的事件入队 - O(1) 28 | 29 | @param events 事件队列 30 | @param event 事件 31 | @return 成功返回 0,否则返回 -1 32 | */ 33 | int receive_event(Queue *events, const Event *event); 34 | 35 | 36 | /** 37 | 事件从队列中出队 - O(1) 38 | 39 | @param events 事件队列 40 | @param dispatch 调度函数 41 | @return 成功返回 0,否则返回 -1 42 | */ 43 | int process_event(Queue *events, int (*dispatch)(Event *event)); 44 | 45 | #endif /* EVENTS_H */ 46 | -------------------------------------------------------------------------------- /include/transfer.h: -------------------------------------------------------------------------------- 1 | // 2 | // transfer.h 3 | // Algorithms - Network transfer 4 | // 5 | // Created by YourtionGuo on 18/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef TRANSFER_H 10 | #define TRANSFER_H 11 | 12 | 13 | /** 14 | 首先压缩数据,然后调用标准套接字函数 send 15 | 16 | @param s 已经建立连接的套接字描述符 17 | @param data 要发送数据的缓冲区 18 | @param size 缓冲区大小 19 | @param flags 传入 send 的正常 flags 参数 20 | @return 成功返回0;否则返回-1 21 | */ 22 | int send_comp(int s, const unsigned char *data, int size, int flags); 23 | 24 | 25 | /** 26 | 使用标准套接字函数 recv 接收从 send_comp 发送过来的数据 27 | 28 | @param s 已经建立连接的套接字描述符 29 | @param data 指向解压缩数据的指针 30 | @param size data 的大小(由recv_comp的返回值决定) 31 | @param flags 传入 recv 的正常 flags 参数 32 | @return 成功返回0;否则返回-1 33 | */ 34 | int recv_comp(int s, unsigned char **data, int *size, int flags); 35 | 36 | #endif /* TRANSFER_H */ 37 | -------------------------------------------------------------------------------- /include/traverse.h: -------------------------------------------------------------------------------- 1 | // 2 | // traverse.h 3 | // Algorithms - bitree traverse 4 | // 5 | // Created by YourtionGuo on 03/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef TRAVERSE_H 10 | #define TRAVERSE_H 11 | 12 | #include "bitree.h" 13 | #include "list.h" 14 | 15 | 16 | /** 17 | 前序方式来遍历表达式树 18 | 19 | @param node 根结点 20 | @param list 链表 21 | @return 操作成功返回0;否则返回-1 22 | */ 23 | int bitree_preorder(const BiTreeNode *node, List *list); 24 | 25 | 26 | /** 27 | 中序式来遍历表达式树 28 | 29 | @param node 根结点 30 | @param list 链表 31 | @return 操作成功返回0;否则返回-1 32 | */ 33 | int bitree_inorder(const BiTreeNode *node, List *list); 34 | 35 | 36 | /** 37 | 后序方式来遍历表达式树 38 | 39 | @param node 根结点 40 | @param list 链表 41 | @return 操作成功返回0;否则返回-1 42 | */ 43 | int bitree_postorder(const BiTreeNode *node, List *list); 44 | 45 | #endif /* TRAVERSE_H */ 46 | -------------------------------------------------------------------------------- /include/cbc.h: -------------------------------------------------------------------------------- 1 | // 2 | // cbc.h 3 | // Algorithms - DES in CBC mode 4 | // 5 | // Created by YourtionGuo on 22/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef CBC_H 10 | #define CBC_H 11 | 12 | 13 | /** 14 | 采用 DES 算法中的 CBC 模式来对缓冲区中的数据做加密操作 - O(n) n 为加密或解密的分组数量 15 | 16 | @param plaintext 明文缓冲区 17 | @param ciphertext 加密后数据 18 | @param key 密钥 19 | @param size 缓冲区字节大小 20 | */ 21 | void cbc_encipher(const unsigned char *plaintext, unsigned char *ciphertext, 22 | const unsigned char *key, int size); 23 | 24 | 25 | /** 26 | 采用 DES 算法中的 CBC 模式来对缓冲区中的数据做解密操作 - O(n) 27 | 28 | @param ciphertext 密文缓冲区 29 | @param plaintext 解密后数据 30 | @param key 密钥 31 | @param size 缓冲区字节大小 32 | */ 33 | void cbc_decipher(const unsigned char *ciphertext, unsigned char *plaintext, 34 | const unsigned char *key, int size); 35 | 36 | #endif /* CBC_H */ 37 | -------------------------------------------------------------------------------- /source/lsqe.c: -------------------------------------------------------------------------------- 1 | // 2 | // lsqe.c 3 | // Algorithms 4 | // 5 | // Created by YourtionGuo on 16/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | 10 | #include 11 | 12 | #include "nummeths.h" 13 | 14 | #pragma mark - Public 15 | 16 | 17 | void lsqe(const double *x, const double *y, int n, double *b1, double *b0) 18 | { 19 | double sumx, sumy, sumx2, sumxy; 20 | int i; 21 | 22 | /// 计算合计结果 23 | 24 | sumx = 0.0; 25 | sumy = 0.0; 26 | sumx2 = 0.0; 27 | sumxy = 0.0; 28 | 29 | for (i = 0; i < n; i++) { 30 | 31 | sumx = sumx + x[i]; 32 | sumy = sumy + y[i]; 33 | sumx2 = sumx2 + pow(x[i], 2.0); 34 | sumxy = sumxy + (x[i] * y[i]); 35 | 36 | } 37 | 38 | /// 计算最小二乘估计 39 | 40 | *b1 = (sumxy - ((sumx * sumy)/(double)n)) / (sumx2-(pow(sumx,2.0)/(double)n)); 41 | *b0 = (sumy - ((*b1) * sumx)) / (double)n; 42 | 43 | return; 44 | } 45 | -------------------------------------------------------------------------------- /source/geodist.c: -------------------------------------------------------------------------------- 1 | // 2 | // geodist.c 3 | // Algorithms - Geo dist 4 | // 5 | // Created by YourtionGuo on 25/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "geodist.h" 10 | #include "geometry.h" 11 | 12 | #pragma mark - Public 13 | 14 | 15 | int geodist(double lat1, double lon1, double lat2, double lon2, double *d) 16 | { 17 | 18 | SPoint p1, p2; 19 | 20 | /// 检验坐标是否合法 21 | if (lat1 < -90.0 || lat1 > 90.0 || lat2 < -90.0 || lat2 > 90.0) return -1; 22 | if (lon1 < -180.0 || lon1 > 180.0 || lon2 < -180.0 || lon2 > 180.0) return -1; 23 | 24 | /// 将经纬度转换为球坐标 25 | 26 | p1.rho = EARTH_RADIUS; 27 | p1.theta = -1.0 * DEGTORAD(lon1); 28 | p1.phi = (DEGTORAD(-1.0 * lat1)) + DEGTORAD(90.0); 29 | 30 | p2.rho = EARTH_RADIUS; 31 | p2.theta = -1.0 * DEGTORAD(lon2); 32 | p2.phi = (DEGTORAD(-1.0 * lat2)) + DEGTORAD(90.0); 33 | 34 | /// 计算两个点的距离 35 | arclen(p1, p2, d); 36 | 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /source/root.c: -------------------------------------------------------------------------------- 1 | // 2 | // root.c 3 | // Algorithms - Find the roots 4 | // 5 | // Created by YourtionGuo on 16/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "nummeths.h" 12 | 13 | #pragma mark - Public 14 | 15 | 16 | int root(double (*f)(double x), double (*g)(double x), double *x, int *n, double delta) 17 | { 18 | int satisfied, i; 19 | 20 | /// 使用牛顿迭代法找方程的根 21 | 22 | i = 0; 23 | satisfied = 0; 24 | 25 | while (!satisfied && i + 1 < *n) { 26 | 27 | /// 确定下一个迭代的 x 28 | x[i + 1] = x[i] - (f(x[i]) / g(x[i])); 29 | 30 | /// 确定是否找到想要的近似值 31 | if (fabs(x[i + 1] - x[i]) < delta) { 32 | satisfied = 1; 33 | } 34 | 35 | /// 准备下一次迭代 36 | i++; 37 | } 38 | 39 | /// 即使没有迭代,表明一个值已被存入 x 40 | 41 | if (i == 0) { 42 | *n = 1; 43 | } else { 44 | *n = i + 1; 45 | } 46 | 47 | /// 返回找到根或者到达最大迭代次数 48 | 49 | if (satisfied) return 0; 50 | return -1; 51 | } 52 | -------------------------------------------------------------------------------- /source/arclen.c: -------------------------------------------------------------------------------- 1 | // 2 | // arclen.c 3 | // Algorithms - Lengths on spherical surfaces 4 | // 5 | // Created by YourtionGuo on 25/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "geometry.h" 12 | 13 | #pragma mark - Public 14 | 15 | 16 | void arclen(SPoint p1, SPoint p2, double *length) 17 | { 18 | Point p1_rct, p2_rct; 19 | double alpha, dot; 20 | 21 | /// 将球面坐标系转换为直角坐标系 22 | p1_rct.x = p1.rho * sin(p1.phi) * cos(p1.theta); 23 | p1_rct.y = p1.rho * sin(p1.phi) * sin(p1.theta); 24 | p1_rct.z = p1.rho * cos(p1.phi); 25 | 26 | p2_rct.x = p2.rho * sin(p2.phi) * cos(p2.theta); 27 | p2_rct.y = p2.rho * sin(p2.phi) * sin(p2.theta); 28 | p2_rct.z = p2.rho * cos(p2.phi); 29 | 30 | 31 | /// 计算出从原点到点P1和P2这两条线段之间的夹角 32 | dot = (p1_rct.x * p2_rct.x) + (p1_rct.y * p2_rct.y) + (p1_rct.z * p2_rct.z); 33 | alpha = acos(dot / pow(p1.rho, 2.0)); 34 | 35 | /// 通过计算该夹角与球体的半径之间的乘积来得到两点之间的弧长 36 | *length = alpha * p1.rho; 37 | 38 | return; 39 | } 40 | -------------------------------------------------------------------------------- /source/issort.c: -------------------------------------------------------------------------------- 1 | // 2 | // issort.c 3 | // Algorithms - Insertion sort 4 | // 5 | // Created by YourtionGuo on 10/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "sort.h" 13 | 14 | #pragma mark - Public 15 | 16 | 17 | int issort(void *data, int size, int esize, 18 | int (*compare)(const void *key1, const void *key2)) 19 | { 20 | char *a = data; 21 | void *key; 22 | int i, j; 23 | 24 | /// 创建存储当前元素空间 25 | if ((key = (char *)malloc(esize)) == NULL) return -1; 26 | 27 | /// 循环插入当前元素到已排序数组 28 | 29 | for (j = 1; j < size; j++) { 30 | 31 | memcpy(key, &a[j * esize], esize); 32 | i = j - 1; 33 | 34 | /// 确定当前元素插入位置 35 | while (i >= 0 && compare(&a[i * esize], key) > 0) { 36 | 37 | memcpy(&a[(i + 1) * esize], &a[i * esize], esize); 38 | i--; 39 | } 40 | 41 | memcpy(&a[(i + 1) * esize], key, esize); 42 | } 43 | 44 | /// 销毁排序所需空间 45 | free(key); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /source/parcels.c: -------------------------------------------------------------------------------- 1 | // 2 | // parcels.c 3 | // Algorithms - Parcels 4 | // 5 | // Created by YourtionGuo on 05/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "parcel.h" 13 | #include "parcels.h" 14 | #include "pqueue.h" 15 | 16 | 17 | int get_parcel(PQueue *parcels, Parcel *parcel) 18 | { 19 | Parcel *data; 20 | 21 | /// 如果没有包裹返回 -1 22 | if (pqueue_size(parcels) == 0) return -1; 23 | 24 | /// 无法获取包裹返回 -1 25 | if (pqueue_extract(parcels, (void **)&data) != 0) return -1; 26 | 27 | memcpy(parcel, data, sizeof(Parcel)); 28 | free(data); 29 | 30 | return 0; 31 | } 32 | 33 | 34 | int put_parcel(PQueue *parcels, const Parcel *parcel) 35 | { 36 | Parcel *data; 37 | 38 | /// 初始化包裹内存空间 39 | if ((data = (Parcel *)malloc(sizeof(Parcel))) == NULL) return -1; 40 | 41 | /// 将包裹插入到优先队列 42 | 43 | memcpy(data, parcel, sizeof(Parcel)); 44 | 45 | if (pqueue_insert(parcels, data) != 0) return -1; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /source/events.c: -------------------------------------------------------------------------------- 1 | // 2 | // events.c 3 | // Algorithms - events 4 | // 5 | // Created by YourtionGuo on 25/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "events.h" 13 | #include "queue.h" 14 | 15 | #pragma mark - Public 16 | 17 | 18 | int receive_event(Queue *events, const Event *event) 19 | { 20 | Event *new_event; 21 | 22 | /// 创建事件对应存储空间 23 | if ((new_event = (Event *)malloc(sizeof(Event))) == NULL) return -1; 24 | 25 | /// 拷贝事件并入列 26 | memcpy(new_event, event, sizeof(Event)); 27 | 28 | if (queue_enqueue(events, new_event) != 0) return -1; 29 | 30 | return 0; 31 | } 32 | 33 | 34 | int process_event(Queue *events, int (*dispatch)(Event *event)) 35 | { 36 | Event *event; 37 | 38 | /// 如果没有事件待处理,返回 -1 39 | if (queue_size(events) == 0) return -1; 40 | 41 | /// 如果无法获取事件,返回 -1 42 | if (queue_dequeue(events, (void **)&event) != 0) return -1; 43 | 44 | dispatch(event); 45 | free(event); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /source/bisearch.c: -------------------------------------------------------------------------------- 1 | // 2 | // bisearch.c 3 | // Algorithms - Binary search 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "search.h" 13 | 14 | #pragma mark - Public 15 | 16 | int bisearch(void *sorted, const void *target, int size, int esize, 17 | int(*compare)(const void *key1, const void *key2)) 18 | { 19 | int left, middle, right; 20 | 21 | /// 持续执行搜索,直到 left 和 right 相交 22 | left = 0; 23 | right = size - 1; 24 | 25 | while (left <= right) { 26 | 27 | middle = (left + right) / 2; 28 | 29 | switch (compare(((char *)sorted + (esize * middle)), target)) { 30 | 31 | case -1: 32 | 33 | /// 准备向中间元素右方执行搜索 34 | left = middle + 1; 35 | break; 36 | 37 | case 1: 38 | 39 | /// 准备向中间元素左方执行搜索 40 | right = middle - 1; 41 | break; 42 | 43 | case 0: 44 | 45 | /// 将找到的元素索引返回 46 | return middle; 47 | 48 | } 49 | } 50 | 51 | /// 没找到元素返回 -1 52 | return -1; 53 | } 54 | -------------------------------------------------------------------------------- /source/frames.c: -------------------------------------------------------------------------------- 1 | // 2 | // frames.c 3 | // Algorithms - frame 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "frames.h" 11 | #include "list.h" 12 | 13 | #pragma mark - Public 14 | 15 | 16 | int alloc_frame(List *frames) 17 | { 18 | int frame_number, *data; 19 | if (list_size(frames) == 0) { 20 | /// 如果 frames 没有空间,返回错误 21 | return -1; 22 | } else { 23 | if (list_rem_next(frames, NULL, (void **)&data) != 0) { 24 | /// 如果找不到空闲的 frame,返回错误 25 | return -1; 26 | } else { 27 | /// 从 frames 中获取一个空闲的帧号 28 | frame_number = *data; 29 | free(data); 30 | } 31 | } 32 | return frame_number; 33 | } 34 | 35 | 36 | int free_frame(List *frames, int frame_number) 37 | { 38 | int *data; 39 | 40 | /// 获取存储页帧号的空间 41 | if ((data = (int *) malloc(sizeof(int))) == NULL) { 42 | return -1; 43 | } 44 | 45 | /// 将对应的页帧放回帧链表 46 | *data = frame_number; 47 | if (list_ins_next(frames, NULL, data) != 0) { 48 | return -1; 49 | } 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 郭宇翔 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | # Prerequisites 26 | *.d 27 | 28 | # Object files 29 | *.o 30 | *.ko 31 | *.obj 32 | *.elf 33 | 34 | # Linker output 35 | *.ilk 36 | *.map 37 | *.exp 38 | 39 | # Precompiled Headers 40 | *.gch 41 | *.pch 42 | 43 | # Libraries 44 | *.lib 45 | *.a 46 | *.la 47 | *.lo 48 | 49 | # Shared objects (inc. Windows DLLs) 50 | *.dll 51 | *.so 52 | *.so.* 53 | *.dylib 54 | 55 | # Executables 56 | *.exe 57 | *.out 58 | *.app 59 | *.i*86 60 | *.x86_64 61 | *.hex 62 | 63 | # Debug files 64 | *.dSYM/ 65 | *.su 66 | *.idb 67 | *.pdb 68 | 69 | # Kernel Module Compile Results 70 | *.mod* 71 | *.cmd 72 | modules.order 73 | Module.symvers 74 | Mkfile.old 75 | dkms.conf 76 | 77 | -------------------------------------------------------------------------------- /Example/directls/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Description: Illustrates sorting a directory listing (see Chapter 12). 5 | // 6 | // Created by YourtionGuo on 10/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "directls.h" 16 | 17 | 18 | int main(int argc, char **argv) 19 | { 20 | Directory *dir; 21 | char buffer[MAXPATHLEN]; 22 | int count, i; 23 | 24 | /// 获取目录列表 25 | 26 | if (argc > 1) { 27 | 28 | if ((count = directls(argv[1], &dir)) < 0) { 29 | 30 | fprintf(stdout, "Could not read directory\n"); 31 | exit(1); 32 | 33 | } 34 | 35 | } else { 36 | 37 | if ((count = directls(getcwd(buffer, MAXPATHLEN), &dir)) < 0) { 38 | 39 | fprintf(stdout, "Could not read directory\n"); 40 | exit(1); 41 | 42 | } 43 | } 44 | 45 | /// 列出目录 46 | 47 | for (i = 0; i < count; i++) { 48 | fprintf(stdout, "%s\n", dir[i].name); 49 | } 50 | 51 | fprintf(stdout, "%d found\n", count); 52 | free(dir); 53 | 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /source/rsa.c: -------------------------------------------------------------------------------- 1 | // 2 | // rsa.c 3 | // Algorithms - RSA 4 | // 5 | // Created by YourtionGuo on 22/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "encrypt.h" 10 | 11 | #pragma mark - Private 12 | 13 | 14 | /** 15 | 计算幂模 - 使用称为二进制平方-乘的算法 16 | 17 | @param a 明文分组 18 | @param b 公钥的 e 或 私钥的d 19 | @param n 公钥的 n 或 私钥的n 20 | @return 幂模结果 21 | */ 22 | static Huge modexp(Huge a, Huge b, Huge n) 23 | { 24 | Huge y; 25 | 26 | /// 使用二进制平方-乘的算法计算 a 的 b 次幂 27 | 28 | /// 寄存器 y 初始值为1 29 | y = 1; 30 | 31 | while (b != 0) { 32 | 33 | /// 每当遇到 b 中为 1 的位时,就将当前的 a 值乘上另一个寄存器 y 34 | if (b & 1) { 35 | y = (y * a) % n; 36 | } 37 | 38 | /// 对b的每个位执行平方操作 39 | a = (a * a) % n; 40 | 41 | /// 准备b的下一个位 42 | b = b >> 1; 43 | } 44 | 45 | return y; 46 | } 47 | 48 | #pragma mark - Public 49 | 50 | void rsa_encipher(Huge plaintext, Huge *ciphertext, RsaPubKey pubkey) 51 | { 52 | *ciphertext = modexp(plaintext, pubkey.e, pubkey.n); 53 | return; 54 | } 55 | 56 | void rsa_decipher(Huge ciphertext, Huge *plaintext, RsaPriKey prikey) 57 | { 58 | *plaintext = modexp(ciphertext, prikey.d, prikey.n); 59 | return; 60 | } 61 | -------------------------------------------------------------------------------- /include/nummeths.h: -------------------------------------------------------------------------------- 1 | // 2 | // nummeths.h 3 | // Algorithms - Number methods 4 | // 5 | // Created by YourtionGuo on 16/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef NUMMETHS_H 10 | #define NUMMETHS_H 11 | 12 | /** 13 | 采用多项式插值法来求得函数在某些特定点上的值 - O(mn2) m代表待求值的个数,n代表已知点的个数 14 | 15 | @param x 指定函数值已知的点集 16 | @param fx 每个已知点所对应的函数值 17 | @param n x 和 fx 中的元素个数 18 | @param z 待求的点 19 | @param pz 待求点返回值 20 | @param m 待求点的个数 21 | @return 插值成功返回0;否则返回-1 22 | */ 23 | int interpol(const double *x, const double *fx, int n, double *z, double *pz, int m); 24 | 25 | 26 | /** 27 | 采用最小二乘估计法来计算出函数 y(x)=b1x+b0 中的系数 b1 和 b0 - O(n) 28 | 29 | @param x 点集的横坐标 30 | @param y 点集的纵坐标 31 | @param n 代表点的个数 32 | @param b1 合适的 b1 33 | @param b0 合适的 b0 34 | */ 35 | void lsqe(const double *x, const double *y, int n, double *b1, double *b0); 36 | 37 | 38 | /** 39 | 采用牛顿迭代法根据给定的初始值来计算方程 f 的根 - O(n) 40 | 41 | @param f 计算方程 42 | @param g 函数 f 的导数 43 | @param x 计算出的近似值数组 44 | @param n x 中的元素个数 45 | @param delta 逐次逼近的差值 46 | @return 找到根返回0;否则返回-1 47 | */ 48 | int root(double (*f)(double x), double (*g)(double x), double *x, int *n, double delta); 49 | 50 | #endif /* NUMMETHS_H */ 51 | -------------------------------------------------------------------------------- /include/bit.h: -------------------------------------------------------------------------------- 1 | // 2 | // bit.h 3 | // Algorithms - Bit operations 4 | // 5 | // Created by YourtionGuo on 17/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef BIT_H 10 | #define BIT_H 11 | 12 | 13 | /** 14 | 获取缓冲区 bits 中处于位置 pos 的位的状态 - O(1) 15 | 16 | @param bits 缓冲区 17 | @param pos 位置(缓冲区最左边的位置为 0 ) 18 | @return 状态值为 0 或 1 19 | */ 20 | int bit_get(const unsigned char *bits, int pos); 21 | 22 | 23 | /** 24 | 设置缓冲区 bits 中处于位置 pos 的位的状态为 state - O(1) 25 | 26 | @param bits 缓冲区 27 | @param pos 位置 (缓冲区最左边的位置为 0 ) 28 | @param state 状态值(必须为 0 或 1 ) 29 | */ 30 | void bit_set(unsigned char *bits, int pos, int state); 31 | 32 | 33 | /** 34 | 按位计算两个缓冲区 bits1 与 bits2 的异或值 - O(β) β 为每个缓冲区中位的个数 35 | 36 | @param bits1 缓冲区 1 37 | @param bits2 缓冲区 2 38 | @param bitsx 计算结果 39 | @param size 每个缓冲区位个位 40 | */ 41 | void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx, int size); 42 | 43 | 44 | /** 45 | 轮转缓冲区 bits(含 size 位),将位值向左移 count 位 - O(nβ) β 为每个缓冲区中位的个数,n 为要轮转到左边的位数 46 | 47 | @param bits 缓冲区 48 | @param size 缓冲区位个位 49 | @param count 左移位数 50 | */ 51 | void bit_rot_left(unsigned char *bits, int size, int count); 52 | 53 | #endif /* BIT_H */ 54 | -------------------------------------------------------------------------------- /source/ctsort.c: -------------------------------------------------------------------------------- 1 | // 2 | // ctsort.c 3 | // Algorithms - Counting sort 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "sort.h" 13 | 14 | #pragma mark - Public 15 | 16 | int ctsort(int *data, int size, int k) 17 | { 18 | int *counts, *temp; 19 | int i, j; 20 | 21 | /// 初始化 counts 数组空间 22 | if ((counts = (int *)malloc(k * sizeof(int))) == NULL)return -1; 23 | 24 | /// 初始化空间用于排序结果 25 | if ((temp = (int *)malloc(size * sizeof(int))) == NULL) return -1; 26 | 27 | /// 初始化 counts 28 | for (i = 0; i < k; i++) { 29 | counts[i] = 0; 30 | } 31 | 32 | /// 计算元素出现个数 33 | for (j = 0; j < size; j++) 34 | counts[data[j]] = counts[data[j]] + 1; 35 | 36 | /// 调整计数值,加上前一个元素出现次数 37 | for (i = 1; i < k; i++) { 38 | counts[i] = counts[i] + counts[i - 1]; 39 | } 40 | 41 | /// 使用 counts 将元素放到对应位置 42 | for (j = size - 1; j >= 0; j--) { 43 | 44 | temp[counts[data[j]] - 1] = data[j]; 45 | counts[data[j]] = counts[data[j]] - 1; 46 | } 47 | 48 | /// 将已排序数据放回 49 | memcpy(data, temp, size * sizeof(int)); 50 | 51 | /// 销毁用于排序的临时空间 52 | free(counts); 53 | free(temp); 54 | 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /include/stack.h: -------------------------------------------------------------------------------- 1 | // 2 | // stack.h 3 | // Algorithms - stack 4 | // 5 | // Created by YourtionGuo on 25/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef STACK_H 10 | #define STACK_H 11 | 12 | #include 13 | 14 | #include "list.h" 15 | 16 | /** 17 | 栈 18 | */ 19 | typedef List Stack; 20 | 21 | 22 | /** 23 | 初始化 stack 指定的栈 - O(1) 24 | 25 | @param stack 栈 26 | @param destroy 成员析构函数(free...) 27 | */ 28 | #define stack_init list_init 29 | 30 | 31 | /** 32 | 销毁 stack 指定的栈 - O(n) 33 | 34 | @param stack 栈 35 | */ 36 | #define stack_destroy list_destroy 37 | 38 | 39 | /** 40 | 向 stack 指定的栈中压入一个元素 - O(1) 41 | 42 | @param stack 栈 43 | @param data 被压入数据 44 | @return 成功返回 0,否则返回 -1 45 | */ 46 | int stack_push(Stack *stack, const void *data); 47 | 48 | 49 | /** 50 | 从 stack 指定的栈中弹出一个元素 - O(1) 51 | 52 | @param stack 栈 53 | @param data 已弹出元素中存储的数据 54 | @return 成功返回 0,否则返回 -1 55 | */ 56 | int stack_pop(Stack *stack, void **data); 57 | 58 | 59 | /** 60 | 获取 stack 指定的栈顶部元素中存储的数据 - O(1) 61 | 62 | @param stack 栈 63 | @return 栈顶存储的数据 64 | */ 65 | #define stack_peek(stack) ((stack)->head == NULL ? NULL : (stack)->head->data) 66 | 67 | 68 | /** 69 | 栈中元素的个数 - O(1) 70 | 71 | @return 栈中元素的个数 72 | */ 73 | #define stack_size list_size 74 | 75 | #endif /* STACK_H */ 76 | -------------------------------------------------------------------------------- /include/queue.h: -------------------------------------------------------------------------------- 1 | // 2 | // queue.h 3 | // Algorithms - queue 4 | // 5 | // Created by YourtionGuo on 25/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef QUEUE_H 10 | #define QUEUE_H 11 | 12 | #include 13 | 14 | #include "list.h" 15 | 16 | /** 17 | 队列 18 | */ 19 | typedef List Queue; 20 | 21 | /** 22 | 初始化 queue 指定的队列 - O(1) 23 | 24 | @param queue 队列 25 | @param destroy 成员析构函数(free...) 26 | */ 27 | #define queue_init list_init 28 | 29 | 30 | /** 31 | 销毁 queue 指定的队列 - O(n) 32 | 33 | @param queue 队列 34 | */ 35 | #define queue_destroy list_destroy 36 | 37 | 38 | /** 39 | 向 queue 指定的队列末尾中插入一个元素 - O(1) 40 | 41 | @param queue 队列 42 | @param data 待插入元素 43 | @return 成功返回 0,否则返回 -1 44 | */ 45 | int queue_enqueue(Queue *queue, const void *data); 46 | 47 | 48 | /** 49 | 从 queue 指定的队列头部删除一个元素 - O(1) 50 | 51 | @param queue 队列 52 | @param data 出队元素中存储的数据 53 | @return 成功返回 0,否则返回 -1 54 | */ 55 | int queue_dequeue(Queue *queue, void **data); 56 | 57 | 58 | /** 59 | 获取由 queue 指定的队列头部元素中存储数据 - O(1) 60 | 61 | @param queue 队列 62 | @return 队列头部元素中存储的数据 63 | */ 64 | #define queue_peek(queue) ((queue)->head == NULL ? NULL : (queue)->head->data) 65 | 66 | 67 | /** 68 | 获取由 queue 指定的队列元素个数 - O(1) 69 | 70 | @return 队列元素个数 71 | */ 72 | #define queue_size list_size 73 | 74 | #endif /* QUEUE_H */ 75 | -------------------------------------------------------------------------------- /Example/geodist/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates computing great-circle distances (see Chapter 17). 5 | // 6 | // Created by YourtionGuo on 26/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | 12 | #include "geodist.h" 13 | 14 | int main(int argc, char **argv) 15 | { 16 | double lat1, lon1, lat2, lon2, distance; 17 | 18 | /// 计算地球上两点的距离 19 | 20 | fprintf(stdout, "Computing distances between points on Earth\n"); 21 | 22 | /* SFO (San Francisco) */ 23 | lat1 = 37.62; 24 | lon1 = 122.38; 25 | 26 | /* LAX (Los Angeles) */ 27 | lat2 = 33.94; 28 | lon2 = 118.41; 29 | 30 | if (geodist(lat1, lon1, lat2, lon2, &distance) != 0) return 1; 31 | 32 | fprintf(stdout, "SFO: (%+07.2lf,%+07.2lf)\n", lat1, lon1); 33 | fprintf(stdout, "LAX: (%+07.2lf,%+07.2lf)\n", lat2, lon2); 34 | fprintf(stdout, "distance=%d\n", (int)distance); 35 | 36 | /* CDG (Paris) */ 37 | lat1 = 49.01; 38 | lon1 = -2.55; 39 | 40 | /* PER (Perth) */ 41 | lat2 = -31.94; 42 | lon2 = -115.97; 43 | 44 | if (geodist(lat1, lon1, lat2, lon2, &distance) != 0) return 1; 45 | 46 | fprintf(stdout, "CDG: (%+07.2lf,%+07.2lf)\n", lat1, lon1); 47 | fprintf(stdout, "PER: (%+07.2lf,%+07.2lf)\n", lat2, lon2); 48 | fprintf(stdout, "distance=%d\n", (int)distance); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /source/cbc.c: -------------------------------------------------------------------------------- 1 | // 2 | // cbc.c 3 | // Algorithms - DES in CBC mode 4 | // 5 | // Created by YourtionGuo on 22/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "bit.h" 12 | #include "cbc.h" 13 | #include "encrypt.h" 14 | 15 | #pragma mark - Public 16 | 17 | void cbc_encipher(const unsigned char *plaintext, unsigned char *ciphertext, 18 | const unsigned char *key, int size) 19 | { 20 | unsigned char temp[8]; 21 | int i; 22 | 23 | /// 加密初始向量 24 | des_encipher(&plaintext[0], &ciphertext[0], key); 25 | 26 | /// 使用 CBC 模式执行 DES 加密 27 | i = 8; 28 | 29 | while (i < size) { 30 | 31 | bit_xor(&plaintext[i], &ciphertext[i - 8], temp, 64); 32 | des_encipher(temp, &ciphertext[i], NULL); 33 | i = i + 8; 34 | } 35 | 36 | return; 37 | } 38 | 39 | 40 | void cbc_decipher(const unsigned char *ciphertext, unsigned char *plaintext, 41 | const unsigned char *key, int size) 42 | { 43 | unsigned char temp[8]; 44 | int i; 45 | 46 | /// 解密初始向量 47 | des_decipher(&ciphertext[0], &plaintext[0], key); 48 | 49 | /// 使用 CBC 模式执行 DES 解密 50 | i = 8; 51 | 52 | while (i < size) { 53 | 54 | des_decipher(&ciphertext[i], temp, NULL); 55 | bit_xor(&ciphertext[i - 8], temp, &plaintext[i], 64); 56 | i = i + 8; 57 | } 58 | 59 | return; 60 | } 61 | -------------------------------------------------------------------------------- /include/pqueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // pqueue.h 3 | // Algorithms - priority queue 4 | // 5 | // Created by YourtionGuo on 05/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef PQUEUE_H 10 | #define PQUEUE_H 11 | 12 | #include "heap.h" 13 | 14 | /** 15 | 优先队列 16 | */ 17 | typedef Heap PQueue; 18 | 19 | 20 | /** 21 | 初始化由参数 pqueue 所指定优先队列 - O(1) 22 | 23 | @param pqueue 优先队列 24 | @param compare 函数指针,用于比较两个成员优先级(高于返回 1,低于返回 -1,等于返回 0) 25 | @param destroy 成员析构函数(free...) 26 | */ 27 | #define pqueue_init heap_init 28 | 29 | 30 | /** 31 | 销毁由参数 pqueue 所指定优先队列 - O(n) 32 | 33 | @param pqueue 优先队列 34 | */ 35 | #define pqueue_destroy heap_destroy 36 | 37 | 38 | /** 39 | 在 pqueue 所指定的优先队列中插入一个元素 - O(lg n) 40 | 41 | @param pqueue 优先队列 42 | @param data 新成员 43 | @return 插入成功返回0; 已经存在返回1;否则返回-1 44 | */ 45 | #define pqueue_insert heap_insert 46 | 47 | 48 | /** 49 | 从优先队列 pqueue 中提取优先队列顶部的元素 - O(lg n) 50 | 51 | @param pqueue 优先队列 52 | @param data 已释放结点的存储数据 53 | @return 释放成功,返回0;否则返回-1 54 | */ 55 | #define pqueue_extract heap_extract 56 | 57 | 58 | /** 59 | 获取优先队列 pqueue 中优先级最高元素 - O(1) 60 | 61 | @param pqueue 优先队列 62 | @return 优先级最高的元素;如果队列为空,那么返回NULL 63 | */ 64 | #define pqueue_peek(pqueue) ((pqueue)->tree == NULL ? NULL : (pqueue)->tree[0]) 65 | 66 | 67 | /** 68 | 优先队列中的元素个数 - O(1) 69 | 70 | @return 元素个数 71 | */ 72 | #define pqueue_size heap_size 73 | 74 | #endif /* PQUEUE_H */ 75 | -------------------------------------------------------------------------------- /include/heap.h: -------------------------------------------------------------------------------- 1 | // 2 | // heap.h 3 | // Algorithms - Heap 4 | // 5 | // Created by YourtionGuo on 05/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef HEAP_H 10 | #define HEAP_H 11 | 12 | 13 | /** 14 | 堆 15 | */ 16 | typedef struct Heap_ 17 | { 18 | int size; 19 | 20 | int (*compare)(const void *key1, const void *key2); 21 | void (*destroy)(void *data); 22 | 23 | void **tree; 24 | 25 | } Heap; 26 | 27 | 28 | /** 29 | 初始化由参数 heap 所指定堆 - O(1) 30 | 31 | @param heap 堆 32 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 33 | @param destroy 成员析构函数(free...) 34 | */ 35 | void heap_init(Heap *heap, 36 | int (*compare)(const void *key1, const void *key2), 37 | void (*destroy)(void *data)); 38 | 39 | 40 | /** 41 | 销毁由参数 heap 所指定堆 - O(n) 42 | 43 | @param heap 堆 44 | */ 45 | void heap_destroy(Heap *heap); 46 | 47 | 48 | /** 49 | 向堆 heap 中插入一个结点 - O(lg n) 50 | 51 | @param heap 堆 52 | @param data 结点数据 53 | @return 插入成功,返回0;否则返回-1 54 | */ 55 | int heap_insert(Heap *heap, const void *data); 56 | 57 | 58 | /** 59 | 从堆 heap 中释放堆顶部的结点 - O(lg n) 60 | 61 | @param heap 堆 62 | @param data 已释放结点的存储数据 63 | @return 释放成功,返回0;否则返回-1 64 | */ 65 | int heap_extract(Heap *heap, void **data); 66 | 67 | 68 | /** 69 | 由参数 heap 所指定堆中的结点个数 - O(1) 70 | 71 | @param heap 堆 72 | @return 结点个数 73 | */ 74 | #define heap_size(heap) ((heap)->size) 75 | 76 | #endif /* HEAP_H */ 77 | -------------------------------------------------------------------------------- /source/lex.c: -------------------------------------------------------------------------------- 1 | // 2 | // lex.c 3 | // Algorithms - lex 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "chtbl.h" 14 | #include "lex.h" 15 | #include "symbol.h" 16 | 17 | #pragma mark - Public 18 | 19 | 20 | Token lex(const char *istream, CHTbl *symtbl) 21 | { 22 | 23 | Token token; 24 | Symbol *symbol; 25 | int length, retval, i; 26 | 27 | /// 创建符号表的空间 28 | if ((symbol = (Symbol *)malloc(sizeof(Symbol))) == NULL) return error; 29 | 30 | /// 对输入流进行分割 31 | if ((symbol->lexeme = next_token(istream)) == NULL) { 32 | 33 | /// 如果没有更多数据则返回 34 | free(symbol); 35 | return lexit; 36 | 37 | } else { 38 | 39 | /// 判断符号类型 40 | symbol->token = digit; 41 | length = (int)strlen(symbol->lexeme); 42 | 43 | for (i = 0; i < length; i++) { 44 | 45 | if (!isdigit(symbol->lexeme[i])) { 46 | symbol->token = other; 47 | } 48 | } 49 | 50 | memcpy(&token, &symbol->token, sizeof(Token)); 51 | 52 | /// 插入到符号表 53 | if ((retval = chtbl_insert(symtbl, symbol)) < 0) { 54 | 55 | free(symbol); 56 | return error; 57 | 58 | } else if (retval == 1) { 59 | 60 | /// 符号已经存在 61 | free(symbol); 62 | } 63 | } 64 | 65 | /// 返回结果 66 | return token; 67 | } 68 | -------------------------------------------------------------------------------- /source/interpol.c: -------------------------------------------------------------------------------- 1 | // 2 | // interpol.c 3 | // Algorithms - Interpolate 4 | // 5 | // Created by YourtionGuo on 16/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "nummeths.h" 13 | 14 | #pragma mark - Public 15 | 16 | 17 | int interpol(const double *x, const double *fx, int n, double *z, double *pz, int m) 18 | { 19 | double term, *table, *coeff; 20 | int i, j, k; 21 | 22 | /// 为差商以及待确定的系数分配存储空间 23 | 24 | if ((table = (double *)malloc(sizeof(double) * n)) == NULL) return -1; 25 | 26 | if ((coeff = (double *)malloc(sizeof(double) * n)) == NULL) { 27 | 28 | free(table); 29 | return -1; 30 | } 31 | 32 | /// 初始化系数 33 | memcpy(table, fx, sizeof(double) * n); 34 | 35 | /// 确定插值多项式的系数 36 | 37 | coeff[0] = table[0]; 38 | 39 | for (k = 1; k < n; k++) { 40 | 41 | for (i = 0; i < n - k; i++) { 42 | 43 | j = i + k; 44 | table[i] = (table[i + 1] - table[i]) / (x[j] - x[i]); 45 | } 46 | 47 | coeff[k] = table[0]; 48 | } 49 | 50 | free(table); 51 | 52 | /// 计算插值多项式在特定点的值 53 | 54 | for (k = 0; k < m; k++) { 55 | 56 | pz[k] = coeff[0]; 57 | 58 | for (j = 1; j < n; j++) { 59 | 60 | term = coeff[j]; 61 | 62 | for (i = 0; i < j; i++) { 63 | term = term * (z[k] - x[i]); 64 | } 65 | 66 | pz[k] = pz[k] + term; 67 | 68 | } 69 | } 70 | 71 | free(coeff); 72 | 73 | return 0; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /source/route.c: -------------------------------------------------------------------------------- 1 | // 2 | // route.c 3 | // Algorithms - Route SPF 4 | // 5 | // Created by YourtionGuo on 24/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "graphalg.h" 12 | #include "list.h" 13 | #include "route.h" 14 | 15 | #pragma mark - Public 16 | 17 | int route(List *paths, PathVertex *destination, PathVertex **next, 18 | int(*match)(const void *key1, const void *key2)) 19 | { 20 | PathVertex *temp = NULL, *parent = NULL; 21 | ListElmt *element; 22 | int found; 23 | 24 | /// 在网关列表中找到目的结点 25 | 26 | found = 0; 27 | 28 | for (element = list_head(paths); element != NULL; element = list_next(element)) { 29 | 30 | if (match(list_data(element), destination)) { 31 | 32 | temp = list_data(element); 33 | parent = ((PathVertex *)list_data(element))->parent; 34 | found = 1; 35 | break; 36 | } 37 | } 38 | 39 | /// 如果找不到目标结点返回 -1 40 | if (!found) return -1; 41 | 42 | /// 计算到目标结点最短路径的下一网关 43 | 44 | while (parent != NULL) { 45 | 46 | temp = list_data(element); 47 | found = 0; 48 | 49 | for (element = list_head(paths); element != NULL; element = list_next(element)) { 50 | 51 | if (match(list_data(element), parent)) { 52 | 53 | parent = ((PathVertex *)list_data(element))->parent; 54 | found = 1; 55 | break; 56 | } 57 | } 58 | 59 | /// 结点不可达返回 -1 60 | if (!found) return -1; 61 | 62 | } 63 | 64 | *next = temp; 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /source/transfer.c: -------------------------------------------------------------------------------- 1 | // 2 | // transfer.c 3 | // Algorithms - Network transfer 4 | // 5 | // Created by YourtionGuo on 18/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "compress.h" 13 | #include "transfer.h" 14 | 15 | #pragma mark - Public 16 | 17 | 18 | int send_comp(int s, const unsigned char *data, int size, int flags) 19 | { 20 | unsigned char *compressed; 21 | int size_comp; 22 | 23 | /// 压缩数据 24 | if ((size_comp = huffman_compress(data, &compressed, size)) < 0) return -1; 25 | 26 | /// 发送压缩数据及大小 27 | 28 | if (send(s, (char *)&size_comp, sizeof(int), flags) != sizeof(int)) return -1; 29 | 30 | if (send(s, (char *)compressed, size_comp, flags) != size_comp) return -1; 31 | 32 | /// 释放已压缩数据 33 | free(compressed); 34 | 35 | return 0; 36 | } 37 | 38 | 39 | int recv_comp(int s, unsigned char **data, int *size, int flags) 40 | { 41 | unsigned char *compressed; 42 | int size_comp; 43 | 44 | /// 根据数据大小接收压缩数据 45 | 46 | if (recv(s, (char *)&size_comp, sizeof(int), flags) != sizeof(int)) return -1; 47 | 48 | if ((compressed = (unsigned char *)malloc(size_comp)) == NULL) return -1; 49 | 50 | if (recv(s, (char *)compressed, size_comp, flags) != size_comp) { 51 | 52 | free(compressed); 53 | return -1; 54 | } 55 | 56 | /// 解压数据 57 | if ((*size = huffman_uncompress(compressed, data)) < 0) return -1; 58 | 59 | /// 释放收到的压缩数据 60 | free(compressed); 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /include/geometry.h: -------------------------------------------------------------------------------- 1 | // 2 | // geometry.h 3 | // Algorithms - Geometry 4 | // 5 | // Created by YourtionGuo on 25/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef GEOMETRY_H 10 | #define GEOMETRY_H 11 | 12 | #include "list.h" 13 | 14 | /// 定义 PI 15 | #ifndef PI 16 | #define PI 3.14159 17 | #endif 18 | 19 | /// 定义大小比较宏 20 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 21 | #define MAX(x, y) (((x) > (y)) ? (x) : (y)) 22 | 23 | /// 计算角度与弧度转换宏 24 | #define DEGTORAD(deg) (((deg) * 2.0 * PI) / 360.0) 25 | #define RADTODEG(rad) (((rad) * 360.0) / (2.0 * PI)) 26 | 27 | /** 28 | 直角坐标系中的点 29 | */ 30 | typedef struct Point_ 31 | { 32 | double x, y, z; 33 | 34 | } Point; 35 | 36 | 37 | /** 38 | 球坐标系中的点 39 | */ 40 | typedef struct SPoint_ 41 | { 42 | double rho, theta, phi; 43 | 44 | } SPoint; 45 | 46 | 47 | /** 48 | 检测两条线段是否相交 - O(1) 49 | 50 | @param p1 线段 1 起点 51 | @param p2 线段 1 终点 52 | @param p3 线段 2 起点 53 | @param p4 线段 2 终点 54 | @return 两条线段相交返回1;否则返回0 55 | */ 56 | int lint(Point p1, Point p2, Point p3, Point p4); 57 | 58 | 59 | /** 60 | 函数计算出由 P 所指定的点集的凸包 - O(nh) n表示点集中总的元素个数,h表示凸包中点的个数 61 | 62 | @param P 点集 63 | @param polygon 计算结果链表 64 | @return 成功计算出凸包返回0;否则返回-1 65 | */ 66 | int cvxhull(const List *P, List *polygon); 67 | 68 | 69 | /** 70 | 计算球面上的点 P1 和 P2 之间的弧长 - O(1) 71 | 72 | @param p1 球坐标系中的点 1 73 | @param p2 球坐标系中的点 2 74 | @param length 弧长 75 | */ 76 | void arclen(SPoint p1, SPoint p2, double *length); 77 | 78 | #endif /* GEOMETRY_H */ 79 | -------------------------------------------------------------------------------- /source/rxsort.c: -------------------------------------------------------------------------------- 1 | // 2 | // rxsort.c 3 | // Algorithms - Radix sort 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "sort.h" 15 | 16 | #pragma mark - Public 17 | 18 | int rxsort(int *data, int size, int p, int k) 19 | { 20 | int *counts, *temp; 21 | int index, pval, i, j, n; 22 | 23 | /// 初始化 counts 空间 24 | if ((counts = (int *)malloc(k * sizeof(int))) == NULL) return -1; 25 | 26 | /// 初始化空间用于排序结果 27 | if ((temp = (int *)malloc(size * sizeof(int))) == NULL) return -1; 28 | 29 | /// 从低位到高位对数据进行排序 30 | for (n = 0; n < p; n++) { 31 | 32 | /// 初始化 counts 33 | 34 | for (i = 0; i < k; i++) { 35 | counts[i] = 0; 36 | } 37 | 38 | /// 计算当前位数值 39 | pval = (int)pow((double)k, (double)n); 40 | 41 | /// 对当前位置进行计数 42 | for (j = 0; j < size; j++) { 43 | 44 | index = (int)(data[j] / pval) % k; 45 | counts[index] = counts[index] + 1; 46 | } 47 | 48 | /// 调整计数值,加上前一个元素出现次数 49 | for (i = 1; i < k; i++) { 50 | counts[i] = counts[i] + counts[i - 1]; 51 | } 52 | 53 | /// 使用 counts 将元素放到对应位置 54 | 55 | for (j = size - 1; j >= 0; j--) { 56 | 57 | index = (int)(data[j] / pval) % k; 58 | temp[counts[index] - 1] = data[j]; 59 | counts[index] = counts[index] - 1; 60 | } 61 | 62 | /// 将当前已排序数据放回 63 | memcpy(data, temp, size * sizeof(int)); 64 | } 65 | 66 | /// 销毁用于排序的临时空间 67 | free(counts); 68 | free(temp); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /source/directls.c: -------------------------------------------------------------------------------- 1 | // 2 | // directls.c 3 | // Algorithms - Sorting a directory listing 4 | // 5 | // Created by YourtionGuo on 10/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "directls.h" 15 | #include "sort.h" 16 | 17 | #pragma mark - Private 18 | 19 | 20 | /** 21 | 比较两个目录 22 | 23 | @param key1 目录1 24 | @param key2 目录2 25 | @return 大于返回 1,小于返回 -1,等于返回 0 26 | */ 27 | static int compare_dir(const void *key1, const void *key2) 28 | { 29 | int retval = strcmp(((const Directory *)key1)->name, ((const Directory *)key2)->name); 30 | 31 | if (retval > 0) return 1; 32 | if (retval < 0) return -1; 33 | return 0; 34 | } 35 | 36 | 37 | #pragma mark - Public 38 | 39 | int directls(const char *path, Directory **dir) 40 | { 41 | DIR *dirptr; 42 | Directory *temp; 43 | struct dirent *curdir; 44 | int count; 45 | 46 | /// 打开目录 47 | if ((dirptr = opendir(path)) == NULL) return -1; 48 | 49 | /// 获得目录内容 50 | 51 | *dir = NULL; 52 | count = 0; 53 | 54 | while ((curdir = readdir(dirptr)) != NULL) { 55 | 56 | count++; 57 | 58 | if ((temp = (Directory *)realloc(*dir, count * sizeof(Directory))) == NULL) { 59 | 60 | free(*dir); 61 | return -1; 62 | 63 | } else { 64 | 65 | *dir = temp; 66 | } 67 | 68 | strcpy(((*dir)[count - 1]).name, curdir->d_name); 69 | } 70 | 71 | closedir(dirptr); 72 | 73 | /// 对目录中条目按照名字进行排序 74 | if (qksort(*dir, count, sizeof(Directory), 0, count - 1, compare_dir) != 0) return -1; 75 | 76 | /// 返回目录条目数量 77 | return count; 78 | } 79 | -------------------------------------------------------------------------------- /include/encrypt.h: -------------------------------------------------------------------------------- 1 | // 2 | // encrypt.h 3 | // Algorithms - Encrypt 4 | // 5 | // Created by YourtionGuo on 22/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef ENCRYPT_H 10 | #define ENCRYPT_H 11 | 12 | 13 | /** 14 | 采用 DES 算法将明文 plaintext 的一个 64 位的明文组加密 - O(1) 15 | 16 | @param plaintext 明文组 17 | @param ciphertext 返回的 64 位密文组 18 | @param key 指定64位的密钥 19 | */ 20 | void des_encipher(const unsigned char *plaintext, unsigned char *ciphertext, 21 | const unsigned char *key); 22 | 23 | 24 | /** 25 | 采用 DES 算法将密文 ciphertext 的一个 64 位分组 - O(1) 26 | 27 | @param ciphertext 通过 des_encipher 加密过的密文 28 | @param plaintext 返回的 64 位明文分组 29 | @param key 指定64位的密钥(NULL 表示重用 des_encipher 的子密钥) 30 | */ 31 | void des_decipher(const unsigned char *ciphertext, unsigned char *plaintext, 32 | const unsigned char *key); 33 | 34 | 35 | /// 定义大数,在实际实现中需为 400 位以上的大数,Demo 中使用 unsigned long 替代 36 | typedef unsigned long Huge; 37 | 38 | /** 39 | RSA 公钥 40 | */ 41 | typedef struct RsaPubKey_ 42 | { 43 | Huge e; 44 | Huge n; 45 | 46 | } RsaPubKey; 47 | 48 | /** 49 | RSA 私钥 50 | */ 51 | typedef struct RsaPriKey_ 52 | { 53 | Huge d; 54 | Huge n; 55 | 56 | } RsaPriKey; 57 | 58 | 59 | /** 60 | 采用 RSA 算法来加密由 plaintext 所指定的明文分组 - O(1) 61 | 62 | @param plaintext 明文组 63 | @param ciphertext 返回的密文组 64 | @param pubkey 公钥 65 | */ 66 | void rsa_encipher(Huge plaintext, Huge *ciphertext, RsaPubKey pubkey); 67 | 68 | 69 | /** 70 | 采用 RSA 算法来解密由 ciphertext 所指定的密文分组 - O(1) 71 | 72 | @param ciphertext 通过 rsa_encipher 加密过的密文 73 | @param plaintext 返回的明文分组 74 | @param prikey 私钥 75 | */ 76 | void rsa_decipher(Huge ciphertext, Huge *plaintext, RsaPriKey prikey); 77 | 78 | #endif /* ENCRYPT_H */ 79 | -------------------------------------------------------------------------------- /Example/cbc/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using DES in CBC mode (see Chapter 15). 5 | // 6 | // Created by YourtionGuo on 22/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "cbc.h" 14 | 15 | /// 定义加密字符长度 16 | #define TXTSIZ 1000 17 | 18 | int main(int argc, char **argv) 19 | { 20 | unsigned char destmp[TXTSIZ], desptx[TXTSIZ], desctx[TXTSIZ], deskey[8]; 21 | int i, error = 0; 22 | 23 | /// 使用 CBC 模式执行 DES 加解密 24 | 25 | fprintf(stdout, "Enciphering with DES in CBC mode\n"); 26 | 27 | deskey[0] = 0x01; 28 | deskey[1] = 0xf1; 29 | deskey[2] = 0x23; 30 | deskey[3] = 0x4a; 31 | deskey[4] = 0x1f; 32 | deskey[5] = 0x22; 33 | deskey[6] = 0x00; 34 | deskey[7] = 0xee; 35 | 36 | for (i = 0; i < TXTSIZ; i++) { 37 | destmp[i] = (i * 23) % 256; 38 | } 39 | 40 | cbc_encipher(destmp, desctx, deskey, TXTSIZ); 41 | cbc_decipher(desctx, desptx, deskey, TXTSIZ); 42 | 43 | fprintf(stdout, "deskey: %02x %02x %02x %02x %02x %02x %02x %02x\n", 44 | deskey[0], deskey[1], deskey[2], deskey[3], deskey[4], deskey[5], deskey[6], deskey[7]); 45 | 46 | for (i = 0; i < TXTSIZ; i++) { 47 | 48 | if (destmp[i] == desptx[i]) { 49 | fprintf(stdout, "-> destmp[%03d]=%02x, desctx[%03d]=%02x, desptx[%03d]=%02x (OK)\n", 50 | i, destmp[i], i, desctx[i], i, desptx[i]); 51 | } else { 52 | error++; 53 | fprintf(stdout, "-> destmp[%03d]=%02x, desctx[%03d]=%02x, desptx[%03d]=%02x (ERROR)\n", 54 | i, destmp[i], i, desctx[i], i, desptx[i]); 55 | } 56 | } 57 | 58 | if (error == 0) { 59 | fprintf(stdout, "Enciphering OK\n"); 60 | } else { 61 | fprintf(stdout, "Enciphering Error: %d\n", error); 62 | } 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: gcc 4 | 5 | os: 6 | # - osx 7 | - linux 8 | 9 | before_install: 10 | - mkdir -p build 11 | - cp Example/compress/sample.txt build/sample.txt 12 | 13 | branches: 14 | only: 15 | - master 16 | 17 | jobs: 18 | include: 19 | - script: ./run bfs 20 | name: bfs 21 | - script: ./run bissearch 22 | name: bissearch 23 | - script: ./run bistree 24 | name: bistree 25 | - script: ./run bit 26 | name: bit 27 | - script: ./run bitree 28 | name: bitree 29 | - script: ./run cbc 30 | name: cbc 31 | - script: ./run chtbl 32 | name: chtbl 33 | - script: ./run clist 34 | name: clist 35 | - script: ./run compress 36 | name: compress 37 | - script: ./run cover 38 | name: cover 39 | - script: ./run dfs 40 | name: dfs 41 | - script: ./run directls 42 | name: directls 43 | - script: ./run dlist 44 | name: dlist 45 | - script: ./run encryption 46 | name: encryption 47 | - script: ./run geodist 48 | name: geodist 49 | - script: ./run geometry 50 | name: geometry 51 | - script: ./run graph 52 | name: graph 53 | - script: ./run graphalg 54 | name: graphalg 55 | - script: ./run heap 56 | name: heap 57 | - script: ./run list 58 | name: list 59 | - script: ./run nummeths 60 | name: nummeths 61 | - script: ./run ohtbl 62 | name: ohtbl 63 | - script: ./run page 64 | name: page 65 | - script: ./run pqueue 66 | name: pqueue 67 | - script: ./run queue 68 | name: queue 69 | - script: ./run routing 70 | name: routing 71 | - script: ./run set 72 | name: set 73 | - script: ./run sort 74 | name: sort 75 | - script: ./run spell 76 | name: spell 77 | - script: ./run stack 78 | name: stack 79 | -------------------------------------------------------------------------------- /source/traverse.c: -------------------------------------------------------------------------------- 1 | // 2 | // traverse.c 3 | // Algorithms - bitree traverse 4 | // 5 | // Created by YourtionGuo on 03/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "list.h" 10 | #include "traverse.h" 11 | 12 | #pragma mark - Public 13 | 14 | 15 | int bitree_preorder(const BiTreeNode *node, List *list) 16 | { 17 | if (!bitree_is_eob(node)) { 18 | 19 | if (list_ins_next(list, list_tail(list), bitree_data(node)) != 0) return -1; 20 | 21 | if (!bitree_is_eob(bitree_left(node))) { 22 | if (bitree_preorder(bitree_left(node), list) != 0) return -1; 23 | } 24 | 25 | if (!bitree_is_eob(bitree_right(node))) { 26 | if (bitree_preorder(bitree_right(node), list) != 0) return -1; 27 | } 28 | 29 | } 30 | 31 | return 0; 32 | } 33 | 34 | 35 | int bitree_inorder(const BiTreeNode *node, List *list) 36 | { 37 | if (!bitree_is_eob(node)) { 38 | 39 | if (!bitree_is_eob(bitree_left(node))) { 40 | if (bitree_inorder(bitree_left(node), list) != 0) return -1; 41 | } 42 | 43 | if (list_ins_next(list, list_tail(list), bitree_data(node)) != 0) return -1; 44 | 45 | if (!bitree_is_eob(bitree_right(node))) { 46 | if (bitree_inorder(bitree_right(node), list) != 0) return -1; 47 | } 48 | 49 | } 50 | 51 | return 0; 52 | } 53 | 54 | 55 | int bitree_postorder(const BiTreeNode *node, List *list) 56 | { 57 | if (!bitree_is_eob(node)) { 58 | 59 | if (!bitree_is_eob(bitree_left(node))) { 60 | if (bitree_postorder(bitree_left(node), list) != 0) return -1; 61 | } 62 | 63 | if (!bitree_is_eob(bitree_right(node))) { 64 | if (bitree_postorder(bitree_right(node), list) != 0) return -1; 65 | } 66 | 67 | if (list_ins_next(list, list_tail(list), bitree_data(node)) != 0) return -1; 68 | 69 | } 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /source/lint.c: -------------------------------------------------------------------------------- 1 | // 2 | // lint.c 3 | // Algorithms - Two line segments intersect 4 | // 5 | // Created by YourtionGuo on 25/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include "geometry.h" 10 | 11 | #pragma mark - Public 12 | 13 | 14 | int lint(Point p1, Point p2, Point p3, Point p4) 15 | { 16 | double z1, z2, z3, z4; 17 | int s1, s2, s3, s4; 18 | 19 | /// 执行快速剔除检测 20 | if (!(MAX(p1.x, p2.x) >= MIN(p3.x, p4.x) 21 | && MAX(p3.x, p4.x) >= MIN(p1.x, p2.x) 22 | && MAX(p1.y, p2.y) >= MIN(p3.y, p4.y) 23 | && MAX(p3.y, p4.y) >= MIN(p1.y, p2.y))) { 24 | 25 | return 0; 26 | } 27 | 28 | /***************************************************************************** 29 | * * 30 | * Determine whether the line segments straddle each other. * 31 | * * 32 | *****************************************************************************/ 33 | 34 | if ((z1 = ((p3.x - p1.x)*(p2.y - p1.y)) - ((p3.y - p1.y)*(p2.x - p1.x))) < 0) { 35 | s1 = -1; 36 | } else if (z1 > 0) { 37 | s1 = 1; 38 | } else { 39 | s1 = 0; 40 | } 41 | 42 | if ((z2 = ((p4.x - p1.x)*(p2.y - p1.y)) - ((p4.y - p1.y)*(p2.x - p1.x))) < 0) { 43 | s2 = -1; 44 | } else if (z2 > 0) { 45 | s2 = 1; 46 | } else { 47 | s2 = 0; 48 | } 49 | 50 | if ((z3 = ((p1.x - p3.x)*(p4.y - p3.y)) - ((p1.y - p3.y)*(p4.x - p3.x))) < 0) { 51 | s3 = -1; 52 | } else if (z3 > 0) { 53 | s3 = 1; 54 | } else { 55 | s3 = 0; 56 | } 57 | 58 | if ((z4 = ((p2.x - p3.x)*(p4.y - p3.y)) - ((p2.y - p3.y)*(p4.x - p3.x))) < 0) { 59 | s4 = -1; 60 | } else if (z4 > 0) { 61 | s4 = 1; 62 | } else { 63 | s4 = 0; 64 | } 65 | 66 | if ((s1 * s2 <= 0) && (s3 * s4 <= 0)) return 1; 67 | 68 | /// 如果线段没有相交返回 0 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /Example/page/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates second-chance page replacement (see Chapter 5). 5 | // 6 | // Created by YourtionGuo on 24/04/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | 12 | #include "page.h" 13 | 14 | int main(int argc, char **argv) 15 | { 16 | CList list; 17 | CListElmt *current; 18 | Page *p; 19 | int i; 20 | 21 | /// 初始化链表 22 | clist_init(&list, free); 23 | 24 | /// 将页加载到链表中 25 | current = NULL; 26 | 27 | for (i = 0; i < 10; i++) { 28 | 29 | if ((p = (Page *)malloc(sizeof(Page))) == NULL) return 1; 30 | 31 | if (i < 5) { 32 | p->reference = 1; 33 | } else { 34 | p->reference = 0; 35 | } 36 | 37 | p->number = i; 38 | 39 | if (clist_ins_next(&list, current, p) != 0) return 1; 40 | 41 | if (current == NULL) { 42 | current = clist_next(clist_head(&list)); 43 | } else { 44 | current = clist_next(current); 45 | } 46 | 47 | } 48 | 49 | current = clist_head(&list); 50 | 51 | for (i = 0; i < 10; i++) { 52 | 53 | p = clist_data(current); 54 | 55 | fprintf(stdout, "p[%d].number=%d, p[%d].reference=%d\n", i, p->number, i, p->reference); 56 | 57 | current = clist_next(current); 58 | 59 | } 60 | 61 | /// 获取需要被置换的页 62 | 63 | current = clist_head(&list); 64 | i = replace_page(¤t); 65 | fprintf(stdout, "Selected %d\n", i); 66 | 67 | current = clist_head(&list); 68 | 69 | for (i = 0; i < 10; i++) { 70 | 71 | p = clist_data(current); 72 | 73 | fprintf(stdout, "p[%d].number=%d, p[%d].reference=%d\n", i, p->number, i, p->reference); 74 | 75 | current = clist_next(current); 76 | 77 | } 78 | 79 | /// 销毁链表 80 | fprintf(stdout, "Destroying the list\n"); 81 | clist_destroy(&list); 82 | 83 | return 0; 84 | 85 | } 86 | -------------------------------------------------------------------------------- /include/bistree.h: -------------------------------------------------------------------------------- 1 | // 2 | // bistree.h 3 | // Algorithms - binary search tree AVL树(Adel'son-Vel'skii and Landis) 4 | // 5 | // Created by YourtionGuo on 04/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef BISTREE_H 10 | #define BISTREE_H 11 | 12 | #include "bitree.h" 13 | 14 | /// 定义平衡参数 15 | #define AVL_LFT_HEAVY 1 16 | #define AVL_BALANCED 0 17 | #define AVL_RGT_HEAVY -1 18 | 19 | 20 | /** 21 | 自平衡二叉搜索树结点 22 | */ 23 | typedef struct AvlNode_ 24 | { 25 | void *data; 26 | int hidden; 27 | int factor; 28 | 29 | } AvlNode; 30 | 31 | 32 | /** 33 | 自平衡二叉搜索树 34 | */ 35 | typedef BiTree BisTree; 36 | 37 | 38 | /** 39 | 初始化由参数 tree 所指定二叉搜索树 - O(1) 40 | 41 | @param tree 二叉搜索树 42 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 43 | @param destroy 成员析构函数(free...) 44 | */ 45 | void bistree_init(BisTree *tree, 46 | int (*compare)(const void *key1, const void *key2), 47 | void (*destroy)(void *data)); 48 | 49 | 50 | /** 51 | 销毁由参数 tree 所指定二叉搜索树 - O(n) 52 | 53 | @param tree 二叉搜索树 54 | */ 55 | void bistree_destroy(BisTree *tree); 56 | 57 | 58 | /** 59 | 将结点插入由参数 tree 所指定二叉搜索树中 - O(lg n) 60 | 61 | @param tree 二叉搜索树 62 | @param data 结点数据 63 | @return 插入成功,返回0;已存在,返回1;否则返回-1 64 | */ 65 | int bistree_insert(BisTree *tree, const void *data); 66 | 67 | 68 | /** 69 | 在由参数 tree 所指定二叉搜索树中移除数据 data 相吻合的结点 - O(lg n) 70 | 71 | @param tree 二叉搜索树 72 | @param data 已移除结点的存储数据 73 | @return 移除成功,返回0;否则返回-1 74 | */ 75 | int bistree_remove(BisTree *tree, const void *data); 76 | 77 | 78 | /** 79 | 判断由参数 tree 所指定二叉搜索树中是否存在同参数 data 相吻合的结点 - O(lg n) 80 | 81 | @param tree 二叉搜索树 82 | @param data 结点数据 83 | @return 查找到结点,返回0;否则返回-1 84 | */ 85 | int bistree_lookup(BisTree *tree, void **data); 86 | 87 | 88 | /** 89 | 由参数 tree 所指定二叉搜索树中的结点个数 - O(1) 90 | 91 | @param tree 二叉搜索树 92 | @return 结点个数 93 | */ 94 | #define bistree_size(tree) ((tree)->size) 95 | 96 | #endif /* bistree_h */ 97 | -------------------------------------------------------------------------------- /include/chtbl.h: -------------------------------------------------------------------------------- 1 | // 2 | // chtbl.h 3 | // Algorithms - chained hash table 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef CHTBL_H 10 | #define CHTBL_H 11 | 12 | #include 13 | 14 | #include "list.h" 15 | 16 | 17 | /** 18 | 链式哈希表 19 | */ 20 | typedef struct CHTbl_ 21 | { 22 | int buckets; 23 | 24 | int (*h)(const void *key); 25 | int (*match)(const void *key1, const void *key2); 26 | void (*destroy)(void *data); 27 | 28 | int size; 29 | List *table; 30 | 31 | } CHTbl; 32 | 33 | 34 | /** 35 | 初始化 htbl 指定的链式哈希表 - O(m),m 是哈希表中“桶”的个数 36 | 37 | @param htbl 哈希表 38 | @param buckets 所分配的“桶”的个数 39 | @param h 函数指针,用户定义的哈希函数 40 | @param match 函数指针,用于判断两个成员是否相匹配 41 | @param destroy 成员析构函数(free...) 42 | @return 表初始化成功,返回0;否则返回-1 43 | */ 44 | int chtbl_init(CHTbl *htbl, int buckets, 45 | int (*h)(const void *key), 46 | int (*match)(const void *key1, const void *key2), 47 | void (*destroy)(void *data)); 48 | 49 | 50 | /** 51 | 销毁 htbl 指定的链式哈希表 - O(m) 52 | 53 | @param htbl 哈希表 54 | */ 55 | void chtbl_destroy(CHTbl *htbl); 56 | 57 | 58 | /** 59 | 向 htbl 指定的链式哈希表中插入一个元素 - O(1) 60 | 61 | @param htbl 哈希表 62 | @param data 待插入元素 63 | @return 插入成功,返回0;已包含此元素,返回1;否则,返回-1 64 | */ 65 | int chtbl_insert(CHTbl *htbl, const void *data); 66 | 67 | 68 | /** 69 | 从 htbl 指定的链式哈希表中删除与 data 匹配的元素 - O(1) 70 | 71 | @param htbl 哈希表 72 | @param data 待删除元素 73 | @return 删除成功,返回0;否则,返回-1 74 | */ 75 | int chtbl_remove(CHTbl *htbl, void **data); 76 | 77 | 78 | /** 79 | 判断由参数 htbl 指定的链式哈希表中查找是否有与 data 相匹配的元素 - O(1) 80 | 81 | @param htbl 哈希表 82 | @param data 待查找元素 83 | @return 找到元素,返回0;否则,返回-1 84 | */ 85 | int chtbl_lookup(const CHTbl *htbl, void **data); 86 | 87 | 88 | /** 89 | 返回由参数 htbl 指定的链式哈希表中元素的个数 - O(1) 90 | 91 | @param htbl 哈希表 92 | @return 哈希表中元素的个数 93 | */ 94 | #define chtbl_size(htbl) ((htbl)->size) 95 | 96 | #endif /* CHTBL_H */ 97 | -------------------------------------------------------------------------------- /source/cover.c: -------------------------------------------------------------------------------- 1 | // 2 | // cover.c 3 | // Algorithms - set covering 4 | // 5 | // Created by YourtionGuo on 26/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "cover.h" 12 | #include "list.h" 13 | #include "set.h" 14 | 15 | #pragma mark - Public 16 | 17 | 18 | int cover(Set *members, Set *subsets, Set *covering) 19 | { 20 | Set intersection; 21 | KSet *subset; 22 | ListElmt *member, *max_member = NULL; 23 | void *data; 24 | int max_size; 25 | 26 | /// 初始化覆盖集合 27 | set_init(covering, subsets->match, NULL); 28 | 29 | /// 当还有成员未覆盖同时还有候选集合成员 30 | while (set_size(members) > 0 && set_size(subsets) > 0) { 31 | 32 | ///找到覆盖最多成员的子集 33 | 34 | max_size = 0; 35 | 36 | for (member = list_head(subsets); member != NULL; member = list_next(member)) { 37 | 38 | if (set_intersection(&intersection, &((KSet *)list_data(member))->set, members) != 0) return -1; 39 | 40 | if (set_size(&intersection) > max_size) { 41 | 42 | max_member = member; 43 | max_size = set_size(&intersection); 44 | 45 | } 46 | 47 | set_destroy(&intersection); 48 | } 49 | 50 | /// 如果没有交集则不可能覆盖 51 | if (max_size == 0) return 1; 52 | 53 | 54 | /// 插入选中的子集到覆盖集合 55 | subset = (KSet *)list_data(max_member); 56 | 57 | if (set_insert(covering, subset) != 0) return -1; 58 | 59 | /// 从待覆盖集合移除已覆盖成员 60 | for (member = list_head(&((KSet *)list_data(max_member))->set); member != NULL; member = list_next(member)) { 61 | 62 | data = list_data(member); 63 | 64 | if (set_remove(members, (void**)&data) == 0 && members->destroy != NULL) members->destroy(data); 65 | 66 | } 67 | 68 | /// 从候选人集合移除已选中子集 69 | if (set_remove(subsets, (void **)&subset) != 0) return -1; 70 | } 71 | 72 | /// 如果还有未覆盖成员则不可能覆盖 73 | if (set_size(members) > 0) return -1; 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /include/ohtbl.h: -------------------------------------------------------------------------------- 1 | // 2 | // ohtbl.h 3 | // Algorithms - open-addressed hash tables. 4 | // 5 | // Created by YourtionGuo on 02/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef OHTBL_H 10 | #define OHTBL_H 11 | 12 | #include 13 | 14 | 15 | /** 16 | 开地址哈希表 17 | */ 18 | typedef struct OHTbl_ 19 | { 20 | int positions; 21 | void *vacated; 22 | 23 | int (*h1)(const void *key); 24 | int (*h2)(const void *key); 25 | int (*match)(const void *key1, const void *key2); 26 | void (*destroy)(void *data); 27 | 28 | int size; 29 | void **table; 30 | 31 | } OHTbl; 32 | 33 | 34 | /** 35 | 初始化 htbl 指定的开地址哈希表 - O(m),m 是哈希表中槽位的个数 36 | 37 | @param htbl 哈希表 38 | @param positions 槽位的个数 39 | @param h1 函数指针,用户定义的辅助哈希函数1 40 | @param h2 函数指针,用户定义的辅助哈希函数2 41 | @param match 函数指针,用于判断两个成员是否相匹配 42 | @param destroy 成员析构函数(free...) 43 | @return 初始化成功,返回0;否则返回-1 44 | */ 45 | int ohtbl_init(OHTbl *htbl, int positions, 46 | int (*h1)(const void *key), 47 | int (*h2)(const void *key), 48 | int (*match)(const void *key1, const void *key2), 49 | void (*destroy)(void *data)); 50 | 51 | 52 | /** 53 | 销毁 htbl 指定的开地址哈希表 - O(m) 54 | 55 | @param htbl 哈希表 56 | */ 57 | void ohtbl_destroy(OHTbl *htbl); 58 | 59 | 60 | /** 61 | 向 htbl 指定的开地址哈希表中插入一个元素 - O(1) 62 | 63 | @param htbl 哈希表 64 | @param data 待插入元素 65 | @return 插入成功,返回0;已包含此元素,返回1;否则,返回-1 66 | */ 67 | int ohtbl_insert(OHTbl *htbl, const void *data); 68 | 69 | 70 | /** 71 | 从 htbl 指定的开地址哈希表中删除与 data 匹配的元素 - O(1) 72 | 73 | @param htbl 哈希表 74 | @param data 待删除元素 75 | @return 删除成功,返回0;否则,返回-1 76 | */ 77 | int ohtbl_remove(OHTbl *htbl, void **data); 78 | 79 | 80 | /** 81 | 判断由参数 htbl 指定的开地址哈希表中查找是否有与 data 相匹配的元素 - O(1) 82 | 83 | @param htbl 哈希表 84 | @param data 待查找元素 85 | @return 找到元素,返回0;否则,返回-1 86 | */ 87 | int ohtbl_lookup(const OHTbl *htbl, void **data); 88 | 89 | 90 | /** 91 | 返回由参数 htbl 指定的开地址哈希表中元素的个数 - O(1) 92 | 93 | @param htbl 哈希表 94 | @return 哈希表中元素的个数 95 | */ 96 | #define ohtbl_size(htbl) ((htbl)->size) 97 | 98 | #endif /* OHTBL_H */ 99 | -------------------------------------------------------------------------------- /include/clist.h: -------------------------------------------------------------------------------- 1 | // 2 | // clist.h 3 | // Algorithms - circular list 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef CLIST_H 10 | #define CLIST_H 11 | 12 | #include 13 | 14 | /** 15 | 循环链表结点 16 | */ 17 | typedef struct CListElmt_ 18 | { 19 | 20 | void *data; 21 | struct CListElmt_ *next; 22 | 23 | } CListElmt; 24 | 25 | /** 26 | 循环链表 27 | */ 28 | typedef struct CList_ 29 | { 30 | int size; 31 | int (*match)(const void *key1, const void *key2); 32 | void (*destroy)(void *data); 33 | CListElmt *head; 34 | 35 | } CList; 36 | 37 | 38 | /** 39 | 初始化指定的循环链表 list - O(1) 40 | 41 | @param list 循环链表 42 | @param destroy 成员析构函数(free...) 43 | */ 44 | void clist_init(CList *list, void (*destroy)(void *data)); 45 | 46 | 47 | /** 48 | 销毁指定的循环链表 list - O(n) 49 | 50 | @param list 循环链表 51 | */ 52 | void clist_destroy(CList *list); 53 | 54 | 55 | /** 56 | 在指定链表 list 中 element 后面插入一个新元素 57 | 58 | @param list 指定的循环链表 59 | @param element 指定的元素 60 | @param data 元素数据 61 | @return 成功返回 0,否则返回 -1 62 | */ 63 | int clist_ins_next(CList *list, CListElmt *element, const void *data); 64 | 65 | 66 | /** 67 | 在指定链表 list 中移除 element 后的元素 - O(1) 68 | 69 | @param list 指定的循环链表 70 | @param element 待移除元素前面的元素,如果为 NULL 则移除头部 71 | @param data 已移除元素的存储数据 72 | @return 成功返回 0,否则返回 -1 73 | */ 74 | int clist_rem_next(CList *list, CListElmt *element, void **data); 75 | 76 | 77 | /** 78 | 获取指定链表 list 的长度 - O(1) 79 | 80 | @param list 指定的循环链表 81 | @return 链表中元素的个数 82 | */ 83 | #define clist_size(list) ((list)->size) 84 | 85 | 86 | /** 87 | 获取指定链表 list 的头元素指针 - O(1) 88 | 89 | @param list 指定的循环链表 90 | @return 链表的头元素指针 91 | */ 92 | #define clist_head(list) ((list)->head) 93 | 94 | 95 | /** 96 | 获取指定元素 element 中保存的数据 - O(1) 97 | 98 | @param element 指定的元素 99 | @return 结点保存的数据 100 | */ 101 | #define clist_data(element) ((element)->data) 102 | 103 | 104 | /** 105 | 获取指定元素 element 中保存的下一个节点 - O(1) 106 | 107 | @param element 指定的元素 108 | @return 结点的下一个节点 109 | */ 110 | #define clist_next(element) ((element)->next) 111 | 112 | 113 | #endif /* CLIST_H */ 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《算法精解:C语言描述》源码及Xcode工程、Linux工程 2 | 3 | Mac 下使用 Xcode 打开 `MasteringAlgorithms.xcodeproj` 即可。`Algorithms.xcodeproj` 为算法库文件工程。每个 Example 都是单独的运行文件。 4 | 5 | ## Mac 或者 Linux 命令行 6 | 7 | 只需要有简单的 c 编译环境`cc` 8 | 9 | 然后执行 `./run bfs`,其中 `bfs` 为 `Example` 中的示例目录。 10 | 11 | 也可以自己使用`cc` `gcc` 等,`gcc source/*.c Example/bfs/main.c -I ./include -o bfs && ./bfs` 12 | 13 | ![ScreenShot](ScreenShot.png) 14 | 15 | ## 数据结构 16 | 17 | ### 链表 18 | 19 | - [单链表](source/list.c) 20 | - [页帧管理](source/frames.c) 21 | - [双向链表](source/dlist.c) 22 | - [循环链表](source/clist.c) 23 | - [第二次机会页面置换](source/page.c) 24 | 25 | ### 栈和队列 26 | 27 | - [栈](source/stack.c) 28 | - [队列](source/queue.c) 29 | - [事件处理](source/events.c) 30 | 31 | ### 集合 32 | 33 | - [集合](source/set.c) 34 | - [集合覆盖](source/cover.c) 35 | 36 | ### 哈希表 37 | 38 | - [链式哈希表](source/chtbl.c) 39 | - [符号表](source/lex.c) 40 | - [开地址哈希表](source/ohtbl.c) 41 | 42 | ### 树 43 | 44 | - [二叉树](source/bitree.c) 45 | - [二叉树遍历](source/traverse.c) 46 | - [二叉搜索树](source/bistree.c) 47 | 48 | ### 堆和优先队列 49 | 50 | - [堆](source/heap.c) 51 | - [优先队列](include/pqueue.h) 52 | - [包裹分拣](source/parcels.c) 53 | 54 | ### 图 55 | 56 | - [图](source/graph.c) 57 | - [图的深度搜索](source/dfs.c) 58 | - [图的广度搜索](source/bfs.c) 59 | 60 | ## 算法 61 | 62 | ### 排序和搜索 63 | 64 | - [插入排序](source/issort.c) 65 | - [快速排序](source/qksort.c) 66 | - [目录列表](source/directls.c) 67 | - [归并排序](source/mgsort.c) 68 | - [计数排序](source/ctsort.c) 69 | - [基数排序](source/rxsort.c) 70 | - [二分查找](source/bisearch.c) 71 | - [拼写检查器](source/spell.c) 72 | 73 | ### 数值计算 74 | 75 | - [多项式插值法](source/interpol.c) 76 | - [最小二乘估计法](source/lsqe.c) 77 | - [方程求解](source/root.c) 78 | 79 | ### 数据压缩 80 | 81 | - [位操作](source/bit.c) 82 | - [霍夫曼编码](source/huffman.c) 83 | - [网络传输优化](source/transfer.c) 84 | - [LZ77](source/lz77.c) 85 | 86 | ### 数据加密 87 | 88 | - [DES算法](source/des.c) 89 | - [分组加密模式](source/cbc.c) 90 | - [RSA算法](source/rsa.c) 91 | 92 | ### 图算法 93 | 94 | - [最小生成树](source/mst.c) 95 | - [最短路径](source/shortest.c) 96 | - [最短距离路由](source/route.c) 97 | - [旅行商问题](source/tsp.c) 98 | 99 | ### 几何算法 100 | 101 | - [测试线段是否相交](source/lint.c) 102 | - [凸包计算](source/cvxhull.c) 103 | - [球面弧长](source/arclen.c) 104 | - [地球上两点之间的近似距离](source/geodist.c) 105 | 106 | 107 | -------------------------------------------------------------------------------- /source/bit.c: -------------------------------------------------------------------------------- 1 | // 2 | // bit.c 3 | // Algorithms - Bit operations 4 | // 5 | // Created by YourtionGuo on 17/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | 10 | #include 11 | 12 | #include "bit.h" 13 | 14 | #pragma mark - Public 15 | 16 | int bit_get(const unsigned char *bits, int pos) 17 | { 18 | unsigned char mask; 19 | int i; 20 | 21 | /// 设置位获取掩码 22 | mask = 0x80; 23 | 24 | for (i = 0; i < (pos % 8); i++) { 25 | mask = mask >> 1; 26 | } 27 | 28 | /// 获取位 29 | return (((mask & bits[(int)(pos / 8)]) == mask) ? 1 : 0); 30 | } 31 | 32 | 33 | void bit_set(unsigned char *bits, int pos, int state) 34 | { 35 | unsigned char mask; 36 | int i; 37 | 38 | /// 设置位获取掩码 39 | mask = 0x80; 40 | 41 | for (i = 0; i < (pos % 8); i++) { 42 | mask = mask >> 1; 43 | } 44 | 45 | /// 设置位 46 | if (state) { 47 | bits[pos / 8] = bits[pos / 8] | mask; 48 | } else { 49 | bits[pos / 8] = bits[pos / 8] & (~mask); 50 | } 51 | 52 | return; 53 | } 54 | 55 | 56 | void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx, int size) 57 | { 58 | int i; 59 | 60 | /// 按位计算两个缓存区的异或值 61 | 62 | for (i = 0; i < size; i++) { 63 | 64 | if (bit_get(bits1, i) != bit_get(bits2, i)) { 65 | bit_set(bitsx, i, 1); 66 | } else { 67 | bit_set(bitsx, i, 0); 68 | } 69 | } 70 | 71 | return; 72 | } 73 | 74 | 75 | 76 | void bit_rot_left(unsigned char *bits, int size, int count) 77 | { 78 | int fbit = 0, lbit, i, j; 79 | 80 | /// 向左轮转缓冲区特定位数 81 | 82 | if (size > 0) { 83 | 84 | for (j = 0; j < count; j++) { 85 | 86 | for (i = 0; i <= ((size - 1) / 8); i++) { 87 | 88 | /// 获取即将被替换的位的值 89 | lbit = bit_get(&bits[i], 0); 90 | 91 | if (i == 0) { 92 | 93 | /// 将第一个位保存起来 94 | fbit = lbit; 95 | 96 | } else { 97 | 98 | /// 将前一个字节最右边的位移到当前字节的最左边 99 | bit_set(&bits[i - 1], 7, lbit); 100 | } 101 | 102 | /// 将特定位向左移动 103 | bits[i] = bits[i] << 1; 104 | } 105 | 106 | /// 将其最右边的位移动到首字节的最高位上 107 | 108 | bit_set(bits, size - 1, fbit); 109 | } 110 | } 111 | 112 | return; 113 | } 114 | 115 | -------------------------------------------------------------------------------- /include/graphalg.h: -------------------------------------------------------------------------------- 1 | // 2 | // graphalg.h 3 | // Algorithms - Graph algorithms 4 | // 5 | // Created by YourtionGuo on 23/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef GRAPHALG_H 10 | #define GRAPHALG_H 11 | 12 | #include "graph.h" 13 | #include "list.h" 14 | 15 | 16 | /** 17 | 最小生成树顶点 18 | */ 19 | typedef struct MstVertex_ 20 | { 21 | void *data; // 顶点的数据 22 | double weight; // 边的权值 23 | 24 | VertexColor color; // 顶点的色值 25 | double key; // 顶点的键值 26 | 27 | struct MstVertex_ *parent; // 顶点的父结点 28 | 29 | } MstVertex; 30 | 31 | 32 | /** 33 | 最短路径顶点 34 | */ 35 | typedef struct PathVertex_ 36 | { 37 | void *data; // 顶点的数据 38 | double weight; // 边的权值 39 | 40 | VertexColor color; // 顶点的色值 41 | double d; // 顶点的最短路径估计 42 | 43 | struct PathVertex_ *parent; // 顶点的父结点 44 | 45 | } PathVertex; 46 | 47 | /** 48 | 旅行商问题顶点 49 | */ 50 | typedef struct TspVertex_ 51 | { 52 | void *data; // 顶点的数据 53 | 54 | double x, y; // 顶点的坐标 55 | 56 | VertexColor color; // 顶点的色值 57 | 58 | } TspVertex; 59 | 60 | 61 | /** 62 | 为一个无方向的带权图 graph 计算最小生成树 - O(EV^2) V是图中顶点的个数,E是边的条数 63 | 64 | @param graph 无方向的带权图 65 | @param start 顶点 66 | @param span 最小生成树的相关数据 67 | @param match 函数指针,用于判断两个成员是否相匹配(等于返回 1,否则返回 0) 68 | @return 计算最小生成树成功返回0;否则,返回-1 69 | */ 70 | int mst(Graph *graph, const MstVertex *start, List *span, 71 | int (*match)(const void *key1, const void *key2)); 72 | 73 | 74 | /** 75 | 计算顶点 start 与有向带权图 graph 中其他所有顶点之间的最短路径 - O(EV^2) V是图中顶点的个数,E是边的条数 76 | 77 | @param graph 有向带权图 78 | @param start 顶点 79 | @param paths 最短路径的相关数据 80 | @param match 函数指针,用于判断两个成员是否相匹配(等于返回 1,否则返回 0) 81 | @return 计算最短路径成功返回0;否则,返回-1 82 | */ 83 | int shortest(Graph *graph, const PathVertex *start, List *paths, 84 | int (*match)(const void *key1, const void *key2)); 85 | 86 | 87 | /** 88 | 为存储在 vertices 中的顶点计算一条近似旅行商的路线 - O(V^2) V是路线中要访问顶点的个数 89 | 90 | @param vertices 顶点列表 91 | @param start 顶点 92 | @param tour 计算得到的路线 93 | @param match 函数指针,用于判断两个成员是否相匹配(等于返回 1,否则返回 0) 94 | @return 计算近似旅行商路线成功返回0;否则,返回-1 95 | */ 96 | int tsp(List *vertices, const TspVertex *start, List *tour, 97 | int (*match)(const void *key1, const void *key2)); 98 | 99 | #endif /* GRAPHALG_H */ 100 | -------------------------------------------------------------------------------- /source/dfs.c: -------------------------------------------------------------------------------- 1 | // 2 | // dfs.c 3 | // Algorithms - Graph depth-first search 4 | // 5 | // Created by YourtionGuo on 08/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "dfs.h" 12 | #include "graph.h" 13 | #include "list.h" 14 | 15 | #pragma mark - Private 16 | 17 | 18 | /** 19 | 实际执行深度优先搜索 20 | 21 | @param graph 图 22 | @param adjlist 邻接表 23 | @param ordered 顶点链表 24 | @return 成功返回0;否则返回-1 25 | */ 26 | static int dfs_main(Graph *graph, AdjList *adjlist, List *ordered) 27 | { 28 | AdjList *clr_adjlist; 29 | DfsVertex *clr_vertex, *adj_vertex; 30 | ListElmt *member; 31 | 32 | /// 将顶点着色为灰色并遍历它的邻接表 33 | 34 | ((DfsVertex *)adjlist->vertex)->color = gray; 35 | 36 | for (member = list_head(&adjlist->adjacent); member != NULL; member = list_next(member)) { 37 | 38 | /// 确定下一个邻接顶点的颜色 39 | 40 | adj_vertex = list_data(member); 41 | 42 | if (graph_adjlist(graph, adj_vertex, &clr_adjlist) != 0) return -1; 43 | 44 | clr_vertex = clr_adjlist->vertex; 45 | 46 | /// 深入邻接顶点如果为白色 47 | 48 | if (clr_vertex->color == white) { 49 | 50 | if (dfs_main(graph, clr_adjlist, ordered) != 0)return -1; 51 | 52 | } 53 | } 54 | 55 | /// 将当前顶点着色为黑色并将它放在列表头 56 | 57 | ((DfsVertex *)adjlist->vertex)->color = black; 58 | 59 | if (list_ins_next(ordered, NULL, (DfsVertex *)adjlist->vertex) != 0) return -1; 60 | 61 | return 0; 62 | } 63 | 64 | #pragma mark - Public 65 | 66 | int dfs(Graph *graph, List *ordered) 67 | { 68 | DfsVertex *vertex; 69 | ListElmt *element; 70 | 71 | /// 初始化图的所有顶点 72 | 73 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 74 | 75 | vertex = ((AdjList *)list_data(element))->vertex; 76 | vertex->color = white; 77 | 78 | } 79 | 80 | /// 执行深度优先搜索 81 | 82 | list_init(ordered, NULL); 83 | 84 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 85 | 86 | /// 确保每个未连接顶点被搜索到 87 | 88 | vertex = ((AdjList *)list_data(element))->vertex; 89 | 90 | if (vertex->color == white) { 91 | 92 | if (dfs_main(graph, (AdjList *)list_data(element), ordered) != 0) { 93 | 94 | list_destroy(ordered); 95 | return -1; 96 | } 97 | } 98 | } 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /source/clist.c: -------------------------------------------------------------------------------- 1 | // 2 | // clist.c 3 | // Algorithms - circular list 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "clist.h" 13 | 14 | #pragma mark - Public 15 | 16 | 17 | void clist_init(CList *list, void (*destroy)(void *data)) 18 | { 19 | /// 初始化链表 20 | list->size = 0; 21 | list->destroy = destroy; 22 | list->head = NULL; 23 | 24 | return; 25 | } 26 | 27 | 28 | void clist_destroy(CList *list) 29 | { 30 | void *data; 31 | 32 | /// 删除每一个元素 33 | while (clist_size(list) > 0) { 34 | if (clist_rem_next(list, list->head, (void **)&data) == 0 && list->destroy != NULL) { 35 | /// 调用用户定义的 destroy 方法销毁动态创建的数据 36 | list->destroy(data); 37 | } 38 | } 39 | 40 | /// 清理链表结构体数据 41 | memset(list, 0, sizeof(CList)); 42 | 43 | return; 44 | } 45 | 46 | 47 | int clist_ins_next(CList *list, CListElmt *element, const void *data) 48 | { 49 | CListElmt *new_element; 50 | 51 | /// 分配元素需要的空间 52 | if ((new_element = (CListElmt *)malloc(sizeof(CListElmt))) == NULL) return -1; 53 | 54 | /// 插入元素到链表 55 | new_element->data = (void *)data; 56 | 57 | if (clist_size(list) == 0) { 58 | 59 | /// 处理插入空循环链表 60 | new_element->next = new_element; 61 | list->head = new_element; 62 | 63 | } else { 64 | 65 | /// 处理非空情况 66 | new_element->next = element->next; 67 | element->next = new_element; 68 | 69 | } 70 | 71 | /// 更新链表的 size 72 | list->size++; 73 | 74 | return 0; 75 | } 76 | 77 | 78 | int clist_rem_next(CList *list, CListElmt *element, void **data) 79 | { 80 | CListElmt *old_element; 81 | 82 | /// 禁止删除空链表的数据 83 | if (clist_size(list) == 0) return -1; 84 | 85 | /// 从链表中删除元素 86 | *data = element->next->data; 87 | if (element->next == element) { 88 | 89 | /// 处理删除最后一个元素 90 | old_element = element->next; 91 | list->head = NULL; 92 | 93 | } else { 94 | 95 | /// 处理其他情况 96 | old_element = element->next; 97 | element->next = element->next->next; 98 | 99 | if (old_element == clist_head(list)) { 100 | list->head = old_element->next; 101 | } 102 | 103 | } 104 | 105 | /// 清理旧结点元素的 106 | free(old_element); 107 | 108 | /// 更新链表的 size 109 | list->size--; 110 | 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /Example/spell/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Description: Illustrates spell checking (see Chapter 12). 5 | // 6 | // Created by YourtionGuo on 11/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "search.h" 15 | #include "sort.h" 16 | #include "spell.h" 17 | 18 | static int compare_str(const void *key1, const void *key2) 19 | { 20 | int retval; 21 | 22 | /// 比较两个字符 23 | if ((retval = strcmp((const char *)key1, (const char *)key2)) > 0) return 1; 24 | if (retval < 0) return -1; 25 | return 0; 26 | } 27 | 28 | 29 | int main(int argc, char **argv) 30 | { 31 | char dictionary[12][SPELL_SIZE], lookup[SPELL_SIZE], target[SPELL_SIZE]; 32 | int i; 33 | 34 | /// 创建已排序单词字典 35 | 36 | strcpy(dictionary[ 0], "HOP"); 37 | strcpy(dictionary[ 1], "HAT"); 38 | strcpy(dictionary[ 2], "TAP"); 39 | strcpy(dictionary[ 3], "BAT"); 40 | strcpy(dictionary[ 4], "TIP"); 41 | strcpy(dictionary[ 5], "MOP"); 42 | strcpy(dictionary[ 6], "MOM"); 43 | strcpy(dictionary[ 7], "CAT"); 44 | strcpy(dictionary[ 8], "ZOO"); 45 | strcpy(dictionary[ 9], "WAX"); 46 | strcpy(dictionary[10], "TOP"); 47 | strcpy(dictionary[11], "DIP"); 48 | 49 | if (issort(dictionary, 12, SPELL_SIZE, compare_str) != 0) return 1; 50 | 51 | /// 执行单词拼写 52 | 53 | strcpy(lookup, "hat"); 54 | memset(target, 0, SPELL_SIZE); 55 | 56 | for (i = 0; i < strlen(lookup); i++) { 57 | target[i] = toupper(lookup[i]); 58 | } 59 | 60 | if (spell(dictionary, 12, target)) { 61 | fprintf(stdout, "%s is spelled correctly\n", lookup); 62 | } else { 63 | fprintf(stdout, "%s is not spelled correctly\n", lookup); 64 | } 65 | 66 | strcpy(lookup, "dop"); 67 | memset(target, 0, SPELL_SIZE); 68 | 69 | for (i = 0; i < strlen(lookup); i++) { 70 | target[i] = toupper(lookup[i]); 71 | } 72 | 73 | if (spell(dictionary, 12, target)) { 74 | fprintf(stdout, "%s is spelled correctly\n", lookup); 75 | } else { 76 | fprintf(stdout, "%s is not spelled correctly\n", lookup); 77 | } 78 | 79 | strcpy(lookup, "dip"); 80 | memset(target, 0, SPELL_SIZE); 81 | 82 | for (i = 0; i < strlen(lookup); i++) { 83 | target[i] = toupper(lookup[i]); 84 | } 85 | 86 | if (spell(dictionary, 12, target)) { 87 | fprintf(stdout, "%s is spelled correctly\n", lookup); 88 | } else { 89 | fprintf(stdout, "%s is not spelled correctly\n", lookup); 90 | } 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /include/compress.h: -------------------------------------------------------------------------------- 1 | // 2 | // compress.h 3 | // Algorithms - Huffman and LZ77(Lempel-Ziv-1977) compress 4 | // 5 | // Created by YourtionGuo on 17/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef COMPRESS_H 10 | #define COMPRESS_H 11 | 12 | #include "bitree.h" 13 | 14 | 15 | /** 16 | 霍夫曼树结点 17 | */ 18 | typedef struct HuffNode_ 19 | { 20 | unsigned char symbol; 21 | int freq; 22 | 23 | } HuffNode; 24 | 25 | 26 | /** 27 | 霍夫曼编码表 28 | */ 29 | typedef struct HuffCode_ 30 | { 31 | unsigned char used; 32 | unsigned short code; 33 | unsigned char size; 34 | 35 | } HuffCode; 36 | 37 | 38 | /** 39 | 用霍夫曼编码的方法压缩缓冲区 original 中的数据 - O(n) n 是原始数据中符号的个数 40 | 41 | @param original 原始数据缓冲区 42 | @param compressed 压缩后的数据 43 | @param size 缓冲区包含字节 44 | @return 压缩数据成功返回压缩后数据的字节数;否则,返回-1 45 | */ 46 | int huffman_compress(const unsigned char *original, unsigned char **compressed, int size); 47 | 48 | 49 | /** 50 | 用霍夫曼编码的方法解压缩缓冲区 compressed 中的数据 - O(n) n 是原始数据中符号的个数 51 | 52 | @param compressed 压缩缓冲区 53 | @param original 恢复后数据 54 | @return 解压缩数据成功返回恢复后数据的字节数;否则,返回-1 55 | */ 56 | int huffman_uncompress(const unsigned char *compressed, unsigned char **original); 57 | 58 | 59 | /// 类型长度 60 | #define LZ77_TYPE_BITS 1 61 | /// 滑动窗口偏移量长度 62 | #define LZ77_WINOFF_BITS 12 63 | /// 短语标志长度 64 | #define LZ77_BUFLEN_BITS 5 65 | /// 下一个匹配符号长度 66 | #define LZ77_NEXT_BITS 8 67 | 68 | /// 滑动窗口的大小 69 | #define LZ77_WINDOW_SIZE 4096 70 | /// 前向缓冲区大小 71 | #define LZ77_BUFFER_SIZE 32 72 | 73 | /// LZ77短语长度 74 | #define LZ77_PHRASE_BITS (LZ77_TYPE_BITS+LZ77_WINOFF_BITS+LZ77_NEXT_BITS+LZ77_BUFLEN_BITS) 75 | 76 | /// LZ77符号长度 77 | #define LZ77_SYMBOL_BITS (LZ77_TYPE_BITS+LZ77_NEXT_BITS) 78 | #define LZ77_SYNBOL_BITS (LZ77_TYPE_BITS+LZ77_NEXT_BITS) 79 | 80 | 81 | /** 82 | 用 LZ77 算法压缩缓冲区 original 中的数据 - O(n) n 是原始数据中符号的个数 83 | 84 | @param original 原始数据缓冲区 85 | @param compressed 压缩后的数据 86 | @param size 缓冲区包含字节 87 | @return 压缩数据成功返回压缩后数据的字节数;否则,返回-1 88 | */ 89 | int lz77_compress(const unsigned char *original, unsigned char **compressed, int size); 90 | 91 | 92 | /** 93 | 用 LZ77 算法解压缩缓冲区 compressed 中的数据 - O(n) n 是原始数据中符号的个数 94 | 95 | @param compressed 压缩缓冲区 96 | @param original 恢复后数据 97 | @return 解压缩数据成功返回恢复后数据的字节数;否则,返回-1 98 | */ 99 | int lz77_uncompress(const unsigned char *compressed, unsigned char **original); 100 | 101 | #endif /* COMPRESS_H */ 102 | -------------------------------------------------------------------------------- /Example/bissearch/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Description: Illustrates searching algorithms (see Chapter 12). 5 | // 6 | // Created by YourtionGuo on 11/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "search.h" 14 | #include "sort.h" 15 | 16 | /// 定义字符串长度 17 | #define STRSIZ 6 18 | 19 | static int compare_str(const void *key1, const void *key2) 20 | { 21 | int retval; 22 | 23 | /// 比较两个字符 24 | if ((retval = strcmp((const char *)key1, (const char *)key2)) > 0) return 1; 25 | if (retval < 0) return -1; 26 | return 0; 27 | } 28 | 29 | /// 搜索词定义 30 | typedef enum Words_ {hop, hat, tap, bat, tip, mop, mom, cat, zoo, wax, top, dip} Words; 31 | 32 | 33 | int main(int argc, char **argv) 34 | { 35 | char *target; 36 | char sarray[12][STRSIZ], tarray[12][STRSIZ]; 37 | Words word; 38 | int retval; 39 | 40 | /// 初始化搜索词 41 | strcpy(sarray[hop], "hop"); 42 | strcpy(sarray[hat], "hat"); 43 | strcpy(sarray[tap], "tap"); 44 | strcpy(sarray[bat], "bat"); 45 | strcpy(sarray[tip], "tip"); 46 | strcpy(sarray[mop], "mop"); 47 | strcpy(sarray[mom], "mom"); 48 | strcpy(sarray[cat], "cat"); 49 | strcpy(sarray[zoo], "zoo"); 50 | strcpy(sarray[wax], "wax"); 51 | strcpy(sarray[top], "top"); 52 | strcpy(sarray[dip], "dip"); 53 | 54 | /// 执行二分搜索 55 | 56 | fprintf(stdout, "Performing binary search\n"); 57 | 58 | strcpy(tarray[0], "bat"); 59 | strcpy(tarray[1], "top"); 60 | strcpy(tarray[2], "xxx"); 61 | 62 | issort(sarray, 12, STRSIZ, compare_str); 63 | 64 | for (word = hop; word <= dip; word++) { 65 | fprintf(stdout, "-> sorted[%02d]=%s\n", word, (char *)sarray[word]); 66 | } 67 | 68 | target = tarray[0]; 69 | retval = bisearch(sarray, target, 12, STRSIZ, compare_str); 70 | 71 | if (retval < 0) { 72 | fprintf(stdout, "Could not find %s\n", target); 73 | } else { 74 | fprintf(stdout, "Found %s at position %d\n", target, retval); 75 | } 76 | 77 | target = tarray[1]; 78 | retval = bisearch(sarray, target, 12, STRSIZ, compare_str); 79 | 80 | if (retval < 0) { 81 | fprintf(stdout, "Could not find %s\n", target); 82 | } else { 83 | fprintf(stdout, "Found %s at position %d\n", target, retval); 84 | } 85 | 86 | target = tarray[2]; 87 | retval = bisearch(sarray, target, 12, STRSIZ, compare_str); 88 | 89 | if (retval < 0) { 90 | fprintf(stdout, "Could not find %s\n", target); 91 | } else { 92 | fprintf(stdout, "Found %s at position %d\n", target, retval); 93 | } 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /source/cvxhull.c: -------------------------------------------------------------------------------- 1 | // 2 | // cvxhull.c 3 | // Algorithms - Convex hull (Jarvis's march) 4 | // 5 | // Created by YourtionGuo on 25/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "geometry.h" 13 | #include "list.h" 14 | 15 | #pragma mark - Public 16 | 17 | 18 | int cvxhull(const List *P, List *polygon) 19 | { 20 | ListElmt *element; 21 | Point *min, *low = NULL, *p0, *pi, *pc = NULL; 22 | double z, length1, length2; 23 | int count; 24 | 25 | /// 确定点集P中的最低点 26 | 27 | min = list_data(list_head(P)); 28 | 29 | for (element = list_head(P); element != NULL; element = list_next(element)) { 30 | 31 | p0 = list_data(element); 32 | 33 | /// 继续跟踪最低点 34 | 35 | if (p0->y < min->y) { 36 | 37 | min = p0; 38 | low = list_data(element); 39 | 40 | } else { 41 | 42 | /// 如果发生冲突,使用最左点 43 | 44 | if (p0->y == min->y && p0->x < min->x) { 45 | 46 | min = p0; 47 | low = list_data(element); 48 | 49 | } 50 | } 51 | } 52 | 53 | /// 初始化凸包结果链表 54 | list_init(polygon, NULL); 55 | 56 | /// 使用 Jarvis's march 进行凸包检测 57 | 58 | p0 = low; 59 | 60 | do { 61 | 62 | /// 插入新的 p0 到凸包 63 | if (list_ins_next(polygon, list_tail(polygon), p0) != 0) { 64 | 65 | list_destroy(polygon); 66 | return -1; 67 | 68 | } 69 | 70 | /// 找到顺时针方向的其他点 71 | count = 0; 72 | 73 | for (element = list_head(P); element != NULL; element = list_next(element)) { 74 | 75 | /// 跳过列表中的 p0 76 | if ((pi = list_data(element)) == p0) continue; 77 | 78 | /// 统计已经发现点的个数 79 | count++; 80 | 81 | /// 假设第一个点就是其他点的顺时针点,除非找到多个 82 | if (count == 1) { 83 | 84 | pc = list_data(element); 85 | continue; 86 | 87 | } 88 | 89 | /// 判断 pi 是不是在 pc 的顺时针方法 90 | if ((z = ((pi->x - p0->x) * (pc->y - p0->y)) - ((pi->y - p0->y) * (pc->x - p0->x))) > 0) { 91 | 92 | /// pi 在 pc 的顺时针方法 93 | pc = pi; 94 | 95 | } else if (z == 0) { 96 | 97 | /// 如果 pi 和 pc 共线,选择距离 p0 远的点 98 | length1 = sqrt(pow(pi->x - p0->x, 2.0) + pow(pi->y - p0->y, 2.0)); 99 | length2 = sqrt(pow(pc->x - p0->x, 2.0) + pow(pc->y - p0->y, 2.0)); 100 | 101 | if (length1 > length2) { 102 | /// pi 比 pc 距离 p0 更远 103 | pc = pi; 104 | } 105 | } 106 | } 107 | 108 | /// 准备查找下一个点 109 | p0 = pc; 110 | 111 | /// 执行直到回到最低点 112 | } while (p0 != low); 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /include/sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // sort.h 3 | // Algorithms - sort algorithms 4 | // 5 | // Created by YourtionGuo on 10/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef SORT_H 10 | #define SORT_H 11 | 12 | 13 | /** 14 | 利用插入排序将数组 data 中的元素进行排序 - O(n^2) 15 | 16 | @param data 数据数组 17 | @param size 元素的个数 18 | @param esize 每个元素的大小 19 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 20 | @return 成功返回 0;否则返回 -1 21 | */ 22 | int issort(void *data, int size, int esize, 23 | int (*compare)(const void *key1, const void *key2)); 24 | 25 | 26 | /** 27 | 利用快速排序将数组 data 中的元素进行排序 - O(n lg n) 28 | 29 | @param data 数据数组 30 | @param size 元素的个数 31 | @param esize 每个元素的大小 32 | @param i 元素分区起点(默认 0 ) 33 | @param k 元素分区终点(默认 size-1 ) 34 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 35 | @return 成功返回 0;否则返回 -1 36 | */ 37 | int qksort(void *data, int size, int esize, int i, int k, 38 | int (*compare)(const void *key1, const void *key2)); 39 | 40 | 41 | 42 | /** 43 | 利用快速排序将数组 data 中的元素进行排序简化 - O(n lg n) 44 | 45 | @param data 数据数组 46 | @param size 元素的个数 47 | @param esize 每个元素的大小 48 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 49 | @return 成功返回 0;否则返回 -1 50 | */ 51 | int qsrt(void *data, int size, int esize, int (*compare)(const void *key1, const void *key2)); 52 | 53 | 54 | /** 55 | 利用归并排序将数组 data 中的元素进行排序 - O(n lg n) 56 | 57 | @param data 数据数组 58 | @param size 元素的个数 59 | @param esize 每个元素的大小 60 | @param i 元素分区起点(默认 0 ) 61 | @param k 元素分区终点(默认 size-1 ) 62 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 63 | @return 成功返回 0;否则返回 -1 64 | */ 65 | int mgsort(void *data, int size, int esize, int i, int k, 66 | int (*compare)(const void *key1, const void *key2)); 67 | 68 | /** 69 | 利用归并排序将数组 data 中的元素进行排序简化 - O(n lg n) 70 | 71 | @param data 数据数组 72 | @param size 元素的个数 73 | @param esize 每个元素的大小 74 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 75 | @return 成功返回 0;否则返回 -1 76 | */ 77 | int mgsrt(void *data, int size, int esize, int (*compare)(const void *key1, const void *key2)); 78 | 79 | 80 | /** 81 | 利用计数排序将数组 data 中的整数进行排序 - O(n+k) 82 | 83 | @param data 数据数组 84 | @param size 元素的个数 85 | @param k data 中最大的整数加1 86 | @return 成功返回 0;否则返回 -1 87 | */ 88 | int ctsort(int *data, int size, int k); 89 | 90 | 91 | /** 92 | 利用基数排序将数组 data 中的整数进行排序 - O(pn+pk) 93 | 94 | @param data 数据数组 95 | @param size 元素的个数 96 | @param p 每个整数包含的位数 97 | @param k 基数 98 | @return 成功返回 0;否则返回 -1 99 | */ 100 | int rxsort(int *data, int size, int p, int k); 101 | 102 | #endif /* SORT_H */ 103 | -------------------------------------------------------------------------------- /Example/clist/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using a circular list (see Chapter 5). 5 | // 6 | // Created by YourtionGuo on 24/04/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "clist.h" 14 | 15 | 16 | static void print_list(const CList *list) 17 | { 18 | CListElmt *element; 19 | int *data, size, i; 20 | 21 | /// 显示链表 22 | fprintf(stdout, "-> CList size is %d (circling twice)\n", clist_size(list)); 23 | 24 | size = clist_size(list); 25 | element = clist_head(list); 26 | 27 | /// 循环两次验证循环链表 28 | i = 0; 29 | 30 | while (i < size * 2) { 31 | 32 | data = clist_data(element); 33 | fprintf(stdout, "--> list[%03d]=%03d\n", (i % size), *data); 34 | element = clist_next(element); 35 | i++; 36 | 37 | } 38 | 39 | return; 40 | } 41 | 42 | 43 | int main(int argc, char **argv) 44 | { 45 | CList list; 46 | CListElmt *element; 47 | int *data, i; 48 | 49 | /// 初始化链表 50 | clist_init(&list, free); 51 | 52 | /// 执行链表操作 53 | element = clist_head(&list); 54 | 55 | for (i = 0; i < 10; i++) { 56 | 57 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 58 | 59 | *data = i + 1; 60 | 61 | if (clist_ins_next(&list, element, data) != 0) return 1; 62 | 63 | if (element == NULL) { 64 | element = clist_next(clist_head(&list)); 65 | } else { 66 | element = clist_next(element); 67 | } 68 | } 69 | 70 | print_list(&list); 71 | 72 | element = clist_head(&list); 73 | 74 | for (i = 0; i < 10; i++) { 75 | element = clist_next(element); 76 | } 77 | 78 | data = clist_data(element); 79 | fprintf(stdout, "Circling and removing an element after the one containing %03d\n",*data); 80 | 81 | if (clist_rem_next(&list, element, (void **)&data) != 0) return 1; 82 | 83 | free(data); 84 | print_list(&list); 85 | 86 | element = clist_head(&list); 87 | 88 | for (i = 0; i < 15; i++) { 89 | element = clist_next(element); 90 | } 91 | 92 | data = clist_data(element); 93 | fprintf(stdout, "Circling and inserting 011 after the element containing %03d\n", *data); 94 | 95 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 96 | 97 | *data = 11; 98 | if (clist_ins_next(&list, element, data) != 0) return 1; 99 | 100 | print_list(&list); 101 | 102 | /// 销毁链表 103 | fprintf(stdout, "Destroying the list\n"); 104 | clist_destroy(&list); 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /include/set.h: -------------------------------------------------------------------------------- 1 | // 2 | // set.h 3 | // Algorithms - set 4 | // 5 | // Created by YourtionGuo on 26/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef SET_H 10 | #define SET_H 11 | 12 | #include 13 | 14 | #include "list.h" 15 | 16 | /** 17 | 集合 18 | */ 19 | typedef List Set; 20 | 21 | 22 | /** 23 | 初始化由参数 set 所指定的集合 - O(1) 24 | 25 | @param set 集合参数 26 | @param match 函数指针,用于判断两个成员是否相匹配 27 | @param destroy 成员析构函数(free...) 28 | */ 29 | void set_init(Set *set, int (*match)(const void *key1, const void *key2), void (*destroy)(void *data)); 30 | 31 | 32 | /** 33 | 销毁 set 所指定的集合 - O(n) 34 | 35 | @param set 集合 36 | */ 37 | #define set_destroy list_destroy 38 | 39 | 40 | /** 41 | 在 set 所指定的集合中插入一个成员 - O(n) 42 | 43 | @param set 集合 44 | @param data 新成员 45 | @return 插入成功返回0; 已经存在返回1;否则返回-1 46 | */ 47 | int set_insert(Set *set, const void *data); 48 | 49 | 50 | /** 51 | 在 set 所指定的集合中移除数据域同 data 相吻合的成员 - O(n) 52 | 53 | @param set 集合 54 | @param data 被移除的成员的数据 55 | @return 移除成功返回0;否则返回-1 56 | */ 57 | int set_remove(Set *set, void **data); 58 | 59 | 60 | /** 61 | 建立一个集合,其结果为 set1 和 set2 所指定集合的并集 - O(mn) 62 | 63 | @param setu 新集合 64 | @param set1 集合1 65 | @param set2 集合2 66 | @return 成功返回0;否则返回-1 67 | */ 68 | int set_union(Set *setu, const Set *set1, const Set *set2); 69 | 70 | 71 | /** 72 | 建立一个集合,其结果为 set1 和 set2 所指定集合的交集 - O(mn) 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 | 82 | /** 83 | 建立一个集合,其结果为 set1 和 set2 所指定集合的差集 - O(mn) 84 | 85 | @param setd 集合 86 | @param set1 集合 87 | @param set2 集合 88 | @return 成功返回0;否则返回-1 89 | */ 90 | int set_difference(Set *setd, const Set *set1, const Set *set2); 91 | 92 | 93 | /** 94 | 判断由 data 所指定成员是否存在于set所指定的集合中 - O(n) 95 | 96 | @param set 集合 97 | @param data 所指定成员 98 | @return 找到成员返回1;否则返回-1 99 | */ 100 | int set_is_member(const Set *set, const void *data); 101 | 102 | 103 | /** 104 | 判断由参数 set1 所指定集合是否为参数 set2 所指定集合的子集 - O(mn) 105 | 106 | @param set1 集合1 107 | @param set2 集合2 108 | @return 子集返回1;否则返回-1 109 | */ 110 | int set_is_subset(const Set *set1, const Set *set2); 111 | 112 | 113 | /** 114 | 判断由参数 set1 所指定集合是否等于由参数 set2 所指定集合 - O(mn) 115 | 116 | @param set1 集合1 117 | @param set2 集合2 118 | @return 相等返回1;否则返回-1 119 | */ 120 | int set_is_equal(const Set *set1, const Set *set2); 121 | 122 | 123 | /** 124 | 返回由参数 set 所指定集合中的元素个数 - O(1) 125 | 126 | @param set 集合 127 | @return 集合大小 128 | */ 129 | #define set_size(set) ((set)->size) 130 | 131 | #endif /* SET_H */ 132 | -------------------------------------------------------------------------------- /Example/heap/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using a heap (see Chapter 10). 5 | // 6 | // Created by YourtionGuo on 05/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "heap.h" 14 | 15 | 16 | static void print_heap(Heap *heap) 17 | { 18 | int i; 19 | 20 | /// 打印堆结构 21 | fprintf(stdout, "-> Heap size is %d\n", heap_size(heap)); 22 | 23 | for (i = 0; i < heap_size(heap); i++) { 24 | fprintf(stdout, "--> Node=%03d\n", *(int *)heap->tree[i]); 25 | } 26 | 27 | return; 28 | } 29 | 30 | 31 | static int compare_int(const void *int1, const void *int2) 32 | { 33 | /// 比较两个整数 34 | 35 | if (*(const int *)int1 > *(const int *)int2) return 1; 36 | 37 | if (*(const int *)int1 < *(const int *)int2) return -1; 38 | 39 | return 0; 40 | } 41 | 42 | 43 | int main(int argc, char **argv) 44 | { 45 | Heap heap; 46 | void *data; 47 | int intval[30], i; 48 | 49 | /// 初始化堆 50 | heap_init(&heap, compare_int, NULL); 51 | 52 | /// 执行堆操作 53 | 54 | i = 0; 55 | 56 | intval[i] = 5; 57 | fprintf(stdout, "Inserting %03d\n", intval[i]); 58 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 59 | print_heap(&heap); 60 | i++; 61 | 62 | intval[i] = 10; 63 | fprintf(stdout, "Inserting %03d\n", intval[i]); 64 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 65 | print_heap(&heap); 66 | i++; 67 | 68 | intval[i] = 20; 69 | fprintf(stdout, "Inserting %03d\n", intval[i]); 70 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 71 | print_heap(&heap); 72 | i++; 73 | 74 | intval[i] = 1; 75 | fprintf(stdout, "Inserting %03d\n", intval[i]); 76 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 77 | print_heap(&heap); 78 | i++; 79 | 80 | intval[i] = 25; 81 | fprintf(stdout, "Inserting %03d\n", intval[i]); 82 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 83 | print_heap(&heap); 84 | i++; 85 | 86 | intval[i] = 22; 87 | fprintf(stdout, "Inserting %03d\n", intval[i]); 88 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 89 | print_heap(&heap); 90 | i++; 91 | 92 | intval[i] = 9; 93 | fprintf(stdout, "Inserting %03d\n", intval[i]); 94 | if (heap_insert(&heap, &intval[i]) != 0) return 1; 95 | print_heap(&heap); 96 | i++; 97 | 98 | while (heap_size(&heap) > 0) { 99 | 100 | if (heap_extract(&heap, (void **)&data) != 0) return 1; 101 | fprintf(stdout, "Extracting %03d\n", *(int *)data); 102 | print_heap(&heap); 103 | 104 | } 105 | 106 | /// 销毁堆 107 | 108 | fprintf(stdout, "Destroying the heap\n"); 109 | heap_destroy(&heap); 110 | 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /source/tsp.c: -------------------------------------------------------------------------------- 1 | // 2 | // tsp.c 3 | // Algorithms 4 | // 5 | // Created by YourtionGuo on 24/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "graph.h" 14 | #include "graphalg.h" 15 | #include "list.h" 16 | 17 | #pragma mark - Public 18 | 19 | 20 | int tsp(List *vertices, const TspVertex *start, List *tour, 21 | int (*match)(const void *key1, const void *key2)) 22 | { 23 | TspVertex *tsp_vertex, *tsp_start, *selection = NULL; 24 | ListElmt *element; 25 | double minimum, distance, x = 0.0, y = 0.0; 26 | int found, i; 27 | 28 | /// 初始化旅途结果列表 29 | list_init(tour, NULL); 30 | 31 | /// 初始化图的所有顶点 32 | 33 | found = 0; 34 | 35 | for (element = list_head(vertices); element != NULL; element = list_next(element)) { 36 | 37 | tsp_vertex = list_data(element); 38 | 39 | if (match(tsp_vertex, start)) { 40 | 41 | /// 从起点开始旅行 42 | 43 | if (list_ins_next(tour, list_tail(tour), tsp_vertex) != 0) { 44 | 45 | list_destroy(tour); 46 | return -1; 47 | } 48 | 49 | /// 保存其他及其坐标 50 | tsp_start = tsp_vertex; 51 | x = tsp_vertex->x; 52 | y = tsp_vertex->y; 53 | 54 | /// 将选中的顶点涂为黑色 55 | tsp_vertex->color = black; 56 | found = 1; 57 | 58 | } else { 59 | 60 | /// 将其它点涂为白色 61 | tsp_vertex->color = white; 62 | 63 | } 64 | } 65 | 66 | /// 如果找不到起点返回 -1 67 | if (!found) { 68 | 69 | list_destroy(tour); 70 | return -1; 71 | } 72 | 73 | /// 使用最近邻点法计算旅行路径 74 | 75 | i = 0; 76 | 77 | while (i < list_size(vertices) - 1) { 78 | 79 | /// 选择距离上一结点最近的白色顶点 80 | 81 | minimum = DBL_MAX; 82 | 83 | for (element = list_head(vertices); element != NULL; element = list_next(element)) { 84 | 85 | tsp_vertex = list_data(element); 86 | 87 | if (tsp_vertex->color == white) { 88 | 89 | distance = sqrt(pow(tsp_vertex->x-x,2.0) + pow(tsp_vertex->y-y,2.0)); 90 | 91 | if (distance < minimum) { 92 | 93 | minimum = distance; 94 | selection = tsp_vertex; 95 | } 96 | } 97 | } 98 | 99 | /// 保存选中顶点的坐标 100 | x = selection->x; 101 | y = selection->y; 102 | 103 | /// 将选中的顶点涂为黑色 104 | selection->color = black; 105 | 106 | /// 插入选中顶点到旅途列表 107 | if (list_ins_next(tour, list_tail(tour), selection) != 0) { 108 | 109 | list_destroy(tour); 110 | return -1; 111 | } 112 | 113 | /// 准备选择下一个顶点 114 | i++; 115 | } 116 | 117 | /// 将起点插入旅途完成旅行 118 | if (list_ins_next(tour, list_tail(tour), tsp_start) != 0) { 119 | 120 | list_destroy(tour); 121 | return -1; 122 | } 123 | 124 | return 0; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /source/list.c: -------------------------------------------------------------------------------- 1 | // 2 | // list.c 3 | // Algorithms - linked list 4 | // 5 | // Created by YourtionGuo on 05/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "list.h" 13 | 14 | #pragma mark - Public 15 | 16 | 17 | void list_init(List *list, void (*destroy)(void *data)) 18 | { 19 | /// 初始化链表 20 | list->size = 0; 21 | list->destroy = destroy; 22 | list->head = NULL; 23 | list->tail = NULL; 24 | 25 | return; 26 | } 27 | 28 | 29 | void list_destroy(List *list) 30 | { 31 | void *data; 32 | 33 | /// 删除每一个元素 34 | while (list_size(list) > 0) { 35 | if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destroy != NULL) { 36 | /// 调用用户定义的 destroy 方法销毁动态创建的数据 37 | list->destroy(data); 38 | } 39 | } 40 | 41 | /// 清理链表结构体数据 42 | memset(list, 0, sizeof(List)); 43 | 44 | return; 45 | } 46 | 47 | 48 | int list_ins_next(List *list, ListElmt *element, const void *data) 49 | { 50 | ListElmt *new_element; 51 | 52 | /// 分配元素需要的空间 53 | if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) return -1; 54 | 55 | /// 插入元素到链表 56 | new_element->data = (void *)data; 57 | 58 | if (element == NULL) { 59 | 60 | /// 处理插入到头部的情况 61 | 62 | if (list_size(list) == 0) { 63 | list->tail = new_element; 64 | } 65 | 66 | new_element->next = list->head; 67 | list->head = new_element; 68 | 69 | } else { 70 | 71 | /// 处理其他情况 72 | 73 | if (element->next == NULL) { 74 | list->tail = new_element; 75 | } 76 | 77 | new_element->next = element->next; 78 | element->next = new_element; 79 | 80 | } 81 | 82 | /// 更新链表的 size 83 | list->size++; 84 | 85 | return 0; 86 | } 87 | 88 | 89 | int list_rem_next(List *list, ListElmt *element, void **data) 90 | { 91 | ListElmt *old_element; 92 | 93 | /// 禁止删除空链表的数据 94 | if (list_size(list) == 0) return -1; 95 | 96 | /// 从链表中删除元素 97 | if (element == NULL) { 98 | 99 | /// 处理删除头部元素 100 | 101 | *data = list->head->data; 102 | old_element = list->head; 103 | list->head = list->head->next; 104 | 105 | if (list_size(list) == 1) { 106 | list->tail = NULL; 107 | } 108 | 109 | } else { 110 | 111 | /// 处理其他情况 112 | 113 | if (element->next == NULL) return -1; 114 | 115 | *data = element->next->data; 116 | old_element = element->next; 117 | element->next = element->next->next; 118 | 119 | if (element->next == NULL) { 120 | list->tail = element; 121 | } 122 | 123 | } 124 | 125 | /// 清理旧结点元素的 126 | free(old_element); 127 | 128 | /// 更新链表的 size 129 | list->size--; 130 | 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /include/list.h: -------------------------------------------------------------------------------- 1 | // 2 | // list.h 3 | // Algorithms - linked list 4 | // 5 | // Created by YourtionGuo on 05/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef LIST_H 10 | #define LIST_H 11 | 12 | #include 13 | 14 | /** 15 | 链表结点 16 | */ 17 | typedef struct ListElmt_ 18 | { 19 | void *data; 20 | struct ListElmt_ *next; 21 | 22 | } ListElmt; 23 | 24 | 25 | /** 26 | 链表 27 | */ 28 | typedef struct List_ 29 | { 30 | int size; 31 | int (*match)(const void *key1, const void *key2); 32 | void (*destroy)(void *data); 33 | ListElmt *head; 34 | ListElmt *tail; 35 | 36 | } List; 37 | 38 | 39 | /** 40 | 初始化指定的链表 list - O(1) 41 | 42 | @param list 链表 43 | @param destroy 成员析构函数(free...) 44 | */ 45 | void list_init(List *list, void (*destroy)(void *data)); 46 | 47 | 48 | /** 49 | 销毁指定的链表 list - O(n) 50 | 51 | @param list 链表 52 | */ 53 | void list_destroy(List *list); 54 | 55 | 56 | /** 57 | 在指定链表 list 中 element 后面插入一个新元素 - O(1) 58 | 59 | @param list 指定的链表 60 | @param element 新元素,如果为 NULL 则插入头部 61 | @param data 元素数据 62 | @return 成功返回 1,否则返回 -1 63 | */ 64 | int list_ins_next(List *list, ListElmt *element, const void *data); 65 | 66 | 67 | /** 68 | 在指定链表 list 中移除 element 后的元素 - O(1) 69 | 70 | @param list 指定的链表 71 | @param element 待移除元素前的元素,如果为 NULL 则移除头部 72 | @param data 已移除元素的存储数据 73 | @return 成功返回 0,否则返回 -1 74 | */ 75 | int list_rem_next(List *list, ListElmt *element, void **data); 76 | 77 | 78 | /** 79 | 获取指定链表 list 的长度 - O(1) 80 | 81 | @param list 指定的链表 82 | @return 链表中元素的个数 83 | */ 84 | #define list_size(list) ((list)->size) 85 | 86 | 87 | /** 88 | 获取指定链表 list 的头元素指针 - O(1) 89 | 90 | @param list 指定的链表 91 | @return 链表的头元素指针 92 | */ 93 | #define list_head(list) ((list)->head) 94 | 95 | 96 | /** 97 | 获取指定链表 list 的尾元素指针 - O(1) 98 | 99 | @param list 指定的链表 100 | @return 链表的尾元素指针 101 | */ 102 | #define list_tail(list) ((list)->tail) 103 | 104 | 105 | 106 | /** 107 | 判断元素 element 是否为指定链表 list 的头节点 - O(1) 108 | 109 | @param list 指定的链表 110 | @param element 待判断的元素 111 | @return 是返回 1,否则返回 0 112 | */ 113 | #define list_is_head(list, element) ((element) == (list)->head ? 1 : 0) 114 | 115 | 116 | /** 117 | 判断元素 element 是否为指定链表 list 的尾节点 - O(1) 118 | 119 | @param list 指定的链表 120 | @param element 待判断的元素 121 | @return 是返回 1,否则返回 0 122 | */ 123 | #define list_is_tail(element) ((element)->next == NULL ? 1 : 0) 124 | 125 | 126 | /** 127 | 获取指定元素 element 中保存的数据 - O(1) 128 | 129 | @param element 指定的元素 130 | @return 结点保存的数据 131 | */ 132 | #define list_data(element) ((element)->data) 133 | 134 | 135 | /** 136 | 获取指定元素 element 中保存的下一个节点 - O(1) 137 | 138 | @param element 指定的元素 139 | @return 结点的下一个节点 140 | */ 141 | #define list_next(element) ((element)->next) 142 | 143 | #endif /* LIST_H */ 144 | -------------------------------------------------------------------------------- /source/mgsort.c: -------------------------------------------------------------------------------- 1 | // 2 | // mgsort.c 3 | // Algorithms - Merge sort 4 | // 5 | // Created by YourtionGuo on 11/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "sort.h" 13 | 14 | #pragma mark - Private 15 | 16 | 17 | /** 18 | 将两个有序集合并成一个有序集 19 | 20 | @param data 数据数组 21 | @param esize 每个元素的大小 22 | @param i 元素分区起点 23 | @param j 元素中间元素位置 24 | @param k 元素分区终点 25 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 26 | @return 成功返回 0;否则返回 -1 27 | */ 28 | static int merge(void *data, int esize, int i, int j, int k, 29 | int (*compare)(const void *key1, const void *key2)) 30 | { 31 | char *a = data, *m; 32 | int ipos, jpos, mpos; 33 | 34 | /// 初始化合并过程使用的计数器 35 | ipos = i; 36 | jpos = j + 1; 37 | mpos = 0; 38 | 39 | /// 创建用于合并数组的空间 40 | if ((m = (char *)malloc(esize * ((k - i) + 1))) == NULL) return -1; 41 | 42 | /// 执行合并直到没有数据 43 | 44 | while (ipos <= j || jpos <= k) { 45 | 46 | if (ipos > j) { 47 | 48 | /// 左半部分还有元素 49 | while (jpos <= k) { 50 | 51 | memcpy(&m[mpos * esize], &a[jpos * esize], esize); 52 | jpos++; 53 | mpos++; 54 | } 55 | 56 | continue; 57 | 58 | } else if (jpos > k) { 59 | 60 | /// 右半部分还有元素 61 | while (ipos <= j) { 62 | 63 | memcpy(&m[mpos * esize], &a[ipos * esize], esize); 64 | ipos++; 65 | mpos++; 66 | 67 | } 68 | 69 | continue; 70 | } 71 | 72 | /// 添加下一个元素到已排序数组 73 | 74 | if (compare(&a[ipos * esize], &a[jpos * esize]) < 0) { 75 | 76 | memcpy(&m[mpos * esize], &a[ipos * esize], esize); 77 | ipos++; 78 | mpos++; 79 | 80 | } else { 81 | 82 | memcpy(&m[mpos * esize], &a[jpos * esize], esize); 83 | jpos++; 84 | mpos++; 85 | 86 | } 87 | } 88 | 89 | /// 将已排序数据放回 90 | memcpy(&a[i * esize], m, esize * ((k - i) + 1)); 91 | 92 | /// 销毁用于排序的临时空间 93 | free(m); 94 | 95 | return 0; 96 | } 97 | 98 | #pragma mark - Public 99 | 100 | 101 | int mgsort(void *data, int size, int esize, int i, int k, 102 | int (*compare)(const void *key1, const void *key2)) 103 | { 104 | int j; 105 | 106 | /// 当没有元素可以分割则停止递归 107 | if (i < k) { 108 | 109 | /// 确定元素分割点 110 | j = (int)(((i + k - 1)) / 2); 111 | 112 | /// 递归对两部分执行归并排序 113 | if (mgsort(data, size, esize, i, j, compare) < 0) return -1; 114 | if (mgsort(data, size, esize, j + 1, k, compare) < 0) return -1; 115 | 116 | /// 合并两个已排序白部分 117 | if (merge(data, esize, i, j, k, compare) < 0) return -1; 118 | 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | int mgsrt(void *data, int size, int esize, int (*compare)(const void *key1, const void *key2)) { 125 | return mgsort(data, size, esize, 0, size - 1, compare); 126 | } 127 | 128 | -------------------------------------------------------------------------------- /Example/queue/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using a queue (see Chapter 6). 5 | // 6 | // Created by YourtionGuo on 25/04/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "list.h" 14 | #include "queue.h" 15 | 16 | static void print_queue(const Queue *queue) 17 | { 18 | ListElmt *element; 19 | int *data, size, i; 20 | 21 | /// 打印队列 22 | fprintf(stdout, "-> Queue size is %d\n", size = queue_size(queue)); 23 | 24 | i = 0; 25 | element = list_head(queue); 26 | 27 | while (i < size) { 28 | 29 | data = list_data(element); 30 | fprintf(stdout, "--> queue[%03d]=%03d\n", i, *data); 31 | element = list_next(element); 32 | i++; 33 | 34 | } 35 | 36 | return; 37 | } 38 | 39 | int main(int argc, char **argv) 40 | { 41 | Queue queue; 42 | int *data, i; 43 | 44 | /// 初始化队列 45 | queue_init(&queue, free); 46 | 47 | /// 操作队列 48 | fprintf(stdout, "Enqueuing 10 elements\n"); 49 | 50 | for (i = 0; i < 10; i++) { 51 | 52 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 53 | 54 | *data = i + 1; 55 | 56 | if (queue_enqueue(&queue, data) != 0) return 1; 57 | 58 | } 59 | 60 | print_queue(&queue); 61 | 62 | fprintf(stdout, "Dequeuing 5 elements\n"); 63 | 64 | for (i = 0; i < 5; i++) { 65 | 66 | if (queue_dequeue(&queue, (void **)&data) == 0) { 67 | free(data); 68 | } else { 69 | return 1; 70 | } 71 | } 72 | 73 | print_queue(&queue); 74 | 75 | fprintf(stdout, "Enqueuing 100 and 200\n"); 76 | 77 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 78 | 79 | *data = 100; 80 | 81 | if (queue_enqueue(&queue, data) != 0) return 1; 82 | 83 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 84 | 85 | *data = 200; 86 | 87 | if (queue_enqueue(&queue, data) != 0) return 1; 88 | 89 | print_queue(&queue); 90 | 91 | if ((data = queue_peek(&queue)) != NULL) { 92 | fprintf(stdout, "Peeking at the head element...Value=%03d\n", *data); 93 | } else { 94 | fprintf(stdout, "Peeking at the head element...Value=NULL\n"); 95 | } 96 | 97 | print_queue(&queue); 98 | 99 | fprintf(stdout, "Dequeuing all elements\n"); 100 | 101 | while (queue_size(&queue) > 0) { 102 | 103 | if (queue_dequeue(&queue, (void **)&data) == 0) { 104 | free(data); 105 | } 106 | 107 | } 108 | 109 | if ((data = queue_peek(&queue)) != NULL) { 110 | fprintf(stdout, "Peeking at an empty queue...Value=%03d\n", *data); 111 | } else { 112 | fprintf(stdout, "Peeking at an empty queue...Value=NULL\n"); 113 | } 114 | 115 | /// 销毁队列 116 | fprintf(stdout, "Destroying the queue\n"); 117 | queue_destroy(&queue); 118 | 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /Example/stack/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using a stack (see Chapter 6). 5 | // 6 | // Created by YourtionGuo on 25/04/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "list.h" 14 | #include "stack.h" 15 | 16 | 17 | static void print_stack(const Stack *stack) 18 | { 19 | 20 | ListElmt *element; 21 | int *data, size, i; 22 | 23 | /// 打印栈 24 | fprintf(stdout, "-> Stack size is %d\n", size = stack_size(stack)); 25 | 26 | i = 0; 27 | element = list_head(stack); 28 | 29 | while (i < size) { 30 | 31 | data = list_data(element); 32 | fprintf(stdout, "--> stack[%03d]=%03d\n", i, *data); 33 | element = list_next(element); 34 | i++; 35 | 36 | } 37 | 38 | return; 39 | } 40 | 41 | int main(int argc, char **argv) 42 | { 43 | Stack stack; 44 | int *data, i; 45 | 46 | /// 初始化栈 47 | stack_init(&stack, free); 48 | 49 | /// 执行栈操作 50 | fprintf(stdout, "Pushing 10 elements\n"); 51 | 52 | for (i = 0; i < 10; i++) { 53 | 54 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 55 | 56 | *data = i + 1; 57 | 58 | if (stack_push(&stack, data) != 0) return 1; 59 | } 60 | 61 | print_stack(&stack); 62 | 63 | fprintf(stdout, "Popping 5 elements\n"); 64 | 65 | for (i = 0; i < 5; i++) { 66 | 67 | if (stack_pop(&stack, (void **)&data) == 0) { 68 | free(data); 69 | } else { 70 | return 1; 71 | } 72 | 73 | } 74 | 75 | print_stack(&stack); 76 | 77 | fprintf(stdout, "Pushing 100 and 200\n"); 78 | 79 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 80 | 81 | *data = 100; 82 | 83 | if (stack_push(&stack, data) != 0) return 1; 84 | 85 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 86 | 87 | *data = 200; 88 | 89 | if (stack_push(&stack, data) != 0) return 1; 90 | 91 | print_stack(&stack); 92 | 93 | if ((data = stack_peek(&stack)) != NULL) { 94 | fprintf(stdout, "Peeking at the top element...Value=%03d\n", *data); 95 | } else { 96 | fprintf(stdout, "Peeking at the top element...Value=NULL\n"); 97 | } 98 | 99 | print_stack(&stack); 100 | 101 | fprintf(stdout, "Popping all elements\n"); 102 | 103 | while (stack_size(&stack) > 0) { 104 | 105 | if (stack_pop(&stack, (void **)&data) == 0) { 106 | free(data); 107 | } 108 | 109 | } 110 | 111 | if ((data = stack_peek(&stack)) != NULL) { 112 | fprintf(stdout, "Peeking at an empty stack...Value=%03d\n", *data); 113 | } else { 114 | fprintf(stdout, "Peeking at an empty stack...Value=NULL\n"); 115 | } 116 | 117 | print_stack(&stack); 118 | 119 | /// 销毁栈 120 | 121 | fprintf(stdout, "Destroying the stack\n"); 122 | stack_destroy(&stack); 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /Example/pqueue/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using a priority queue (see Chapter 10). 5 | // 6 | // Created by YourtionGuo on 05/05/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "pqueue.h" 14 | 15 | 16 | static void print_pqueue(PQueue *pqueue) 17 | { 18 | int i; 19 | 20 | /// 按顺序打印队列 21 | fprintf(stdout, "Priority queue size is %d\n", pqueue_size(pqueue)); 22 | 23 | for (i = 0; i < pqueue_size(pqueue); i++) { 24 | fprintf(stdout, "Node=%03d\n", *(int *)pqueue->tree[i]); 25 | } 26 | 27 | return; 28 | } 29 | 30 | 31 | static int compare_int(const void *int1, const void *int2) 32 | { 33 | /// 比较两个整数 34 | 35 | if (*(const int *)int1 > *(const int *)int2) return 1; 36 | 37 | if (*(const int *)int1 < *(const int *)int2) return -1; 38 | 39 | return 0; 40 | } 41 | 42 | 43 | int main(int argc, char **argv) 44 | { 45 | 46 | PQueue pqueue; 47 | void *data; 48 | int intval[30], 49 | i; 50 | 51 | /// 初始化优先队列 52 | pqueue_init(&pqueue, compare_int, NULL); 53 | 54 | /// 执行优先队列操作 55 | 56 | i = 0; 57 | 58 | intval[i] = 5; 59 | fprintf(stdout, "Inserting %03d\n", intval[i]); 60 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 61 | print_pqueue(&pqueue); 62 | i++; 63 | 64 | intval[i] = 10; 65 | fprintf(stdout, "Inserting %03d\n", intval[i]); 66 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 67 | print_pqueue(&pqueue); 68 | i++; 69 | 70 | intval[i] = 20; 71 | fprintf(stdout, "Inserting %03d\n", intval[i]); 72 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 73 | print_pqueue(&pqueue); 74 | i++; 75 | 76 | intval[i] = 1; 77 | fprintf(stdout, "Inserting %03d\n", intval[i]); 78 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 79 | print_pqueue(&pqueue); 80 | i++; 81 | 82 | intval[i] = 25; 83 | fprintf(stdout, "Inserting %03d\n", intval[i]); 84 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 85 | print_pqueue(&pqueue); 86 | i++; 87 | 88 | intval[i] = 22; 89 | fprintf(stdout, "Inserting %03d\n", intval[i]); 90 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 91 | print_pqueue(&pqueue); 92 | i++; 93 | 94 | intval[i] = 12; 95 | fprintf(stdout, "Inserting %03d\n", intval[i]); 96 | if (pqueue_insert(&pqueue, &intval[i]) != 0) return 1; 97 | print_pqueue(&pqueue); 98 | i++; 99 | 100 | while (pqueue_size(&pqueue) > 0) { 101 | 102 | fprintf(stdout, "Peeking at the highest priority element..Value=%03d\n", *(int *)pqueue_peek(&pqueue)); 103 | if (pqueue_extract(&pqueue, (void **)&data) != 0) return 1; 104 | fprintf(stdout, "Extracting %03d\n", *(int *)data); 105 | print_pqueue(&pqueue); 106 | 107 | } 108 | 109 | /// 销毁优先队列 110 | fprintf(stdout, "Destroying the pqueue\n"); 111 | pqueue_destroy(&pqueue); 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /source/qksort.c: -------------------------------------------------------------------------------- 1 | // 2 | // qksort.c 3 | // Algorithms - Quicksort 4 | // 5 | // Created by YourtionGuo on 10/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "sort.h" 14 | 15 | #pragma mark - Private 16 | 17 | 18 | /** 19 | 比较两个整数(用于三位数取中值) 20 | 21 | @param int1 整数 1 22 | @param int2 整数 2 23 | @return 大于返回 1,小于返回 -1,等于返回 0 24 | */ 25 | static int compare_int(const void *int1, const void *int2) 26 | { 27 | if (*(const int *)int1 > *(const int *)int2) return 1; 28 | if (*(const int *)int1 < *(const int *)int2) return -1; 29 | return 0; 30 | } 31 | 32 | 33 | /** 34 | 分区排序函数 35 | 36 | @param data 数据数组 37 | @param esize 每个元素的大小 38 | @param i 元素分区起点 39 | @param k 元素分区终点 40 | @param compare 函数指针,用于比较两个成员大小(大于返回 1,小于返回 -1,等于返回 0) 41 | @return 成功返回 0;否则返回 -1 42 | */ 43 | static int partition(void *data, int esize, int i, int k, 44 | int (*compare)(const void *key1, const void *key2)) 45 | { 46 | char *a = data; 47 | void *pval, *temp; 48 | int r[3]; 49 | 50 | /// 初始化分区元素和临时空间 51 | 52 | if ((pval = malloc(esize)) == NULL) return -1; 53 | 54 | if ((temp = malloc(esize)) == NULL) { 55 | 56 | free(pval); 57 | return -1; 58 | } 59 | 60 | /// 使用中位数法找分区值 61 | r[0] = (rand() % (k - i + 1)) + i; 62 | r[1] = (rand() % (k - i + 1)) + i; 63 | r[2] = (rand() % (k - i + 1)) + i; 64 | issort(r, 3, sizeof(int), compare_int); 65 | memcpy(pval, &a[r[1] * esize], esize); 66 | 67 | /// 在分区元素周围创建分区空间 68 | i--; 69 | k++; 70 | 71 | while (1) { 72 | 73 | /// 将 k 往左边移动,直到找到一个小于或等于分割值的元素 74 | do { 75 | k--; 76 | } while (compare(&a[k * esize], pval) > 0); 77 | 78 | /// 将 i 往右边移动,直到找到一个大于或等于分割值的元素 79 | do { 80 | i++; 81 | } while (compare(&a[i * esize], pval) < 0); 82 | 83 | if (i >= k) { 84 | /// 当 i 跟 k 重合或者交叉时排序完成 85 | break; 86 | 87 | } else { 88 | 89 | /// 交换找到元素的位置 90 | memcpy(temp, &a[i * esize], esize); 91 | memcpy(&a[i * esize], &a[k * esize], esize); 92 | memcpy(&a[k * esize], temp, esize); 93 | 94 | } 95 | } 96 | 97 | /// 销毁排序所需空间 98 | free(pval); 99 | free(temp); 100 | 101 | /// 返回区分分区的位置 102 | return k; 103 | } 104 | 105 | #pragma mark - Public 106 | 107 | 108 | int qksort(void *data, int size, int esize, int i, int k, 109 | int (*compare)(const void *key1, const void *key2)) 110 | { 111 | int j; 112 | 113 | /// 当已经不能进行分区时排序结束 114 | 115 | if (i < k) { 116 | 117 | /// 确定分区位置 118 | if ((j = partition(data, esize, i, k, compare)) < 0) return -1; 119 | 120 | /// 递归处理右半部分 121 | if (qksort(data, size, esize, i, j, compare) < 0) return -1; 122 | 123 | /// 递归处理右半部分 124 | if (qksort(data, size, esize, j + 1, k, compare) < 0) return -1; 125 | 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | int qsrt(void *data, int size, int esize, int (*compare)(const void *key1, const void *key2)) { 132 | srand(getpid()); 133 | return qksort(data, size, esize, 0, size - 1, compare); 134 | } 135 | -------------------------------------------------------------------------------- /Algorithms.xcodeproj/xcshareddata/xcschemes/Algorithms.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /source/bfs.c: -------------------------------------------------------------------------------- 1 | // 2 | // bfs.c 3 | // Algorithms - Graph breadth-first search 4 | // 5 | // Created by YourtionGuo on 08/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #include "bfs.h" 12 | #include "graph.h" 13 | #include "list.h" 14 | #include "queue.h" 15 | 16 | #pragma mark - Public 17 | 18 | int bfs(Graph *graph, BfsVertex *start, List *hops) 19 | { 20 | Queue queue; 21 | AdjList *adjlist, *clr_adjlist; 22 | BfsVertex *clr_vertex, *adj_vertex; 23 | ListElmt *element, *member; 24 | 25 | /// 初始化图的所有顶点 26 | 27 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 28 | 29 | clr_vertex = ((AdjList *)list_data(element))->vertex; 30 | 31 | if (graph->match(clr_vertex, start)) { 32 | 33 | /// 初始化起点 34 | clr_vertex->color = gray; 35 | clr_vertex->hops = 0; 36 | 37 | } else { 38 | 39 | /// 初始化其他顶点 40 | clr_vertex->color = white; 41 | clr_vertex->hops = -1; 42 | 43 | } 44 | } 45 | 46 | /// 根据起点邻接表初始化队列 47 | 48 | queue_init(&queue, NULL); 49 | 50 | if (graph_adjlist(graph, start, &clr_adjlist) != 0) { 51 | 52 | queue_destroy(&queue); 53 | return -1; 54 | } 55 | 56 | if (queue_enqueue(&queue, clr_adjlist) != 0) { 57 | 58 | queue_destroy(&queue); 59 | return -1; 60 | } 61 | 62 | /// 执行广度优先搜索 63 | 64 | while (queue_size(&queue) > 0) { 65 | 66 | adjlist = queue_peek(&queue); 67 | 68 | /// 在当前邻接表遍历每个顶点 69 | 70 | for (member = list_head(&adjlist->adjacent); member != NULL; member = list_next(member)) { 71 | 72 | adj_vertex = list_data(member); 73 | 74 | /// 确定下个邻接顶点的颜色 75 | 76 | if (graph_adjlist(graph, adj_vertex, &clr_adjlist) != 0) { 77 | 78 | queue_destroy(&queue); 79 | return -1; 80 | } 81 | 82 | clr_vertex = clr_adjlist->vertex; 83 | 84 | /// 将白顶点着色为灰色并将邻接表入队 85 | 86 | if (clr_vertex->color == white) { 87 | 88 | clr_vertex->color = gray; 89 | clr_vertex->hops = ((BfsVertex *)adjlist->vertex)->hops + 1; 90 | 91 | if (queue_enqueue(&queue, clr_adjlist) != 0) { 92 | 93 | queue_destroy(&queue); 94 | return -1; 95 | } 96 | } 97 | } 98 | 99 | /// 将当前邻接表出队并将其着色为黑色 100 | 101 | if (queue_dequeue(&queue, (void **)&adjlist) == 0) { 102 | 103 | ((BfsVertex *)adjlist->vertex)->color = black; 104 | 105 | } else { 106 | 107 | queue_destroy(&queue); 108 | return -1; 109 | } 110 | } 111 | 112 | queue_destroy(&queue); 113 | 114 | /// 回传每个顶点的跳数到表中 115 | 116 | list_init(hops, NULL); 117 | 118 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 119 | 120 | /// 去掉跳数为 -1 的(不可达) 121 | 122 | clr_vertex = ((AdjList *)list_data(element))->vertex; 123 | 124 | if (clr_vertex->hops != -1) { 125 | 126 | if (list_ins_next(hops, list_tail(hops), clr_vertex) != 0) { 127 | 128 | list_destroy(hops); 129 | return -1; 130 | } 131 | } 132 | } 133 | 134 | return 0; 135 | } 136 | 137 | -------------------------------------------------------------------------------- /source/chtbl.c: -------------------------------------------------------------------------------- 1 | // 2 | // chtbl.c 3 | // Algorithms - chained hash table 4 | // 5 | // Created by YourtionGuo on 28/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "list.h" 13 | #include "chtbl.h" 14 | 15 | #pragma mark - Public 16 | 17 | 18 | int chtbl_init(CHTbl *htbl, int buckets, 19 | int (*h)(const void *key), 20 | int (*match)(const void *key1, const void *key2), 21 | void (*destroy)(void *data)) 22 | { 23 | 24 | int i; 25 | 26 | /// 创建 hash 表所需空间 27 | if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL) return -1; 28 | 29 | /// 初始化 buckets 30 | htbl->buckets = buckets; 31 | 32 | for (i = 0; i < htbl->buckets; i++) { 33 | list_init(&htbl->table[i], destroy); 34 | } 35 | 36 | /// 封装函数进 hash 表 37 | htbl->h = h; 38 | htbl->match = match; 39 | htbl->destroy = destroy; 40 | 41 | /// 初始化表大小为 0 42 | htbl->size = 0; 43 | 44 | return 0; 45 | } 46 | 47 | 48 | void chtbl_destroy(CHTbl *htbl) 49 | { 50 | 51 | int i; 52 | 53 | /// 删除 buckets 54 | for (i = 0; i < htbl->buckets; i++) { 55 | list_destroy(&htbl->table[i]); 56 | } 57 | 58 | /// 清理 hash 表空间 59 | free(htbl->table); 60 | /// 清理 hash 表结构体数据 61 | memset(htbl, 0, sizeof(CHTbl)); 62 | 63 | return; 64 | } 65 | 66 | 67 | int chtbl_insert(CHTbl *htbl, const void *data) 68 | { 69 | 70 | void *temp; 71 | int bucket, retval; 72 | 73 | /// 如果元素已经存在返回 1 74 | temp = (void *)data; 75 | 76 | if (chtbl_lookup(htbl, &temp) == 0) return 1; 77 | 78 | /// 计算 hash 79 | bucket = htbl->h(data) % htbl->buckets; 80 | 81 | /// 插入到相应的 bucket 82 | if ((retval = list_ins_next(&htbl->table[bucket], NULL, data)) == 0) { 83 | htbl->size++; 84 | } 85 | 86 | return retval; 87 | } 88 | 89 | 90 | int chtbl_remove(CHTbl *htbl, void **data) 91 | { 92 | 93 | ListElmt *element, *prev; 94 | int bucket; 95 | 96 | /// 计算 hash 97 | bucket = htbl->h(*data) % htbl->buckets; 98 | 99 | /// 在 bucket 中查找数据 100 | prev = NULL; 101 | 102 | for (element = list_head(&htbl->table[bucket]); element != NULL; element = list_next(element)) { 103 | 104 | if (htbl->match(*data, list_data(element))) { 105 | 106 | /// 从 bucket 中移除找到的元素 107 | if (list_rem_next(&htbl->table[bucket], prev, data) != 0) return -1; 108 | 109 | htbl->size--; 110 | return 0; 111 | 112 | } 113 | prev = element; 114 | 115 | } 116 | 117 | /// 如果没找到返回 -1 118 | return -1; 119 | } 120 | 121 | 122 | int chtbl_lookup(const CHTbl *htbl, void **data) { 123 | 124 | ListElmt *element; 125 | int bucket; 126 | 127 | /// 计算 hash 128 | bucket = htbl->h(*data) % htbl->buckets; 129 | 130 | /// 在 bucket 中查找数据 131 | for (element = list_head(&htbl->table[bucket]); element != NULL; element = list_next(element)) { 132 | 133 | if (htbl->match(*data, list_data(element))) { 134 | 135 | /// 返回找到的数据 136 | *data = list_data(element); 137 | return 0; 138 | 139 | } 140 | } 141 | 142 | /// 如果没找到返回 -1 143 | return -1; 144 | } 145 | -------------------------------------------------------------------------------- /include/dlist.h: -------------------------------------------------------------------------------- 1 | // 2 | // dlist.h 3 | // Algorithms - doubly-linked list 4 | // 5 | // Created by YourtionGuo on 24/04/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef DLIST_H 10 | #define DLIST_H 11 | 12 | #include 13 | 14 | /** 15 | 双向链表结点 16 | */ 17 | typedef struct DListElmt_ 18 | { 19 | void *data; 20 | struct DListElmt_ *prev; 21 | struct DListElmt_ *next; 22 | 23 | } DListElmt; 24 | 25 | 26 | /** 27 | 双向链表 28 | */ 29 | typedef struct DList_ 30 | { 31 | int size; 32 | int (*match)(const void *key1, const void *key2); 33 | void (*destroy)(void *data); 34 | DListElmt *head; 35 | DListElmt *tail; 36 | 37 | } DList; 38 | 39 | /** 40 | 初始化指定的双向链表 list - O(1) 41 | 42 | @param list 双向链表 43 | @param destroy 成员析构函数(free...) 44 | */ 45 | void dlist_init(DList *list, void (*destroy)(void *data)); 46 | 47 | 48 | /** 49 | 销毁指定的双向链表 list - O(n) 50 | 51 | @param list 双向链表 52 | */ 53 | void dlist_destroy(DList *list); 54 | 55 | 56 | /** 57 | 在指定双向链表 list 中 element 后面插入一个新元素 58 | 59 | @param list 指定的双向链表 - O(1) 60 | @param element 新元素,如果为 NULL 则插入空链表中 61 | @param data 元素数据 62 | @return 成功返回 0,否则返回 -1 63 | */ 64 | int dlist_ins_next(DList *list, DListElmt *element, const void *data); 65 | 66 | 67 | /** 68 | 在指定双向链表 list 中 element 前面插入一个新元素 69 | 70 | @param list 指定的双向链表 - O(1) 71 | @param element 新元素,如果为 NULL 则插入空链表中 72 | @param data 元素数据 73 | @return 成功返回 0,否则返回 -1 74 | */ 75 | int dlist_ins_prev(DList *list, DListElmt *element, const void *data); 76 | 77 | /** 78 | 在指定双向链表 list 中移除 element 元素 - O(1) 79 | 80 | @param list 指定的双向链表 81 | @param element 待移除元素 82 | @param data 已移除元素的存储数据 83 | @return 成功返回 0,否则返回 -1 84 | */ 85 | int dlist_remove(DList *list, DListElmt *element, void **data); 86 | 87 | 88 | /** 89 | 获取指定双向链表 list 的长度 - O(1) 90 | 91 | @param list 指定的双向链表 92 | @return 双向链表中元素的个数 93 | */ 94 | #define dlist_size(list) ((list)->size) 95 | 96 | 97 | /** 98 | 获取指定双向链表 list 的头元素指针 - O(1) 99 | 100 | @param list 指定的双向链表 101 | @return 双向链表的头元素指针 102 | */ 103 | #define dlist_head(list) ((list)->head) 104 | 105 | 106 | /** 107 | 获取指定双向链表 list 的尾元素指针 - O(1) 108 | 109 | @param list 指定的双向链表 110 | @return 双向链表的尾元素指针 111 | */ 112 | #define dlist_tail(list) ((list)->tail) 113 | 114 | 115 | /** 116 | 判断元素 element 是否为指定双向链表 list 的头节点 - O(1) 117 | 118 | @param element 待判断的元素 119 | @return 是返回 1,否则返回 0 120 | */ 121 | #define dlist_is_head(element) ((element)->prev == NULL ? 1 : 0) 122 | 123 | 124 | /** 125 | 判断元素 element 是否为指定双向链表 list 的尾节点 - O(1) 126 | 127 | @param element 待判断的元素 128 | @return 是返回 1,否则返回 0 129 | */ 130 | #define dlist_is_tail(element) ((element)->next == NULL ? 1 : 0) 131 | 132 | 133 | /** 134 | 获取指定元素 element 中保存的数据 - O(1) 135 | 136 | @param element 指定的元素 137 | @return 结点保存的数据 138 | */ 139 | #define dlist_data(element) ((element)->data) 140 | 141 | 142 | /** 143 | 获取指定元素 element 中保存的下一个节点 - O(1) 144 | 145 | @param element 指定的元素 146 | @return 结点的下一个节点 147 | */ 148 | #define dlist_next(element) ((element)->next) 149 | 150 | /** 151 | 获取指定元素 element 中保存的上一个节点 - O(1) 152 | 153 | @param element 指定的元素 154 | @return 结点的上一个节点 155 | */ 156 | #define dlist_prev(element) ((element)->prev) 157 | 158 | #endif /* DLIST_H */ 159 | -------------------------------------------------------------------------------- /source/mst.c: -------------------------------------------------------------------------------- 1 | // 2 | // mst.c 3 | // Algorithms - Minimum spanning tree 4 | // 5 | // Created by YourtionGuo on 23/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "graph.h" 13 | #include "graphalg.h" 14 | #include "list.h" 15 | 16 | 17 | int mst(Graph *graph, const MstVertex *start, List *span, 18 | int (*match)(const void *key1, const void *key2)) 19 | { 20 | AdjList *adjlist = NULL; 21 | MstVertex *mst_vertex, *adj_vertex; 22 | ListElmt *element, *member; 23 | double minimum; 24 | int found, i; 25 | 26 | /// 初始化图的所有顶点 27 | 28 | found = 0; 29 | 30 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 31 | 32 | mst_vertex = ((AdjList *)list_data(element))->vertex; 33 | 34 | if (match(mst_vertex, start)) { 35 | 36 | /// 初始化起点 37 | mst_vertex->color = white; 38 | mst_vertex->key = 0; 39 | mst_vertex->parent = NULL; 40 | found = 1; 41 | 42 | } else { 43 | 44 | /// 初始化起点外的其他顶点 45 | mst_vertex->color = white; 46 | mst_vertex->key = DBL_MAX; 47 | mst_vertex->parent = NULL; 48 | 49 | } 50 | } 51 | 52 | /// 如果找不到起点返回 -1 53 | if (!found) return -1; 54 | 55 | /// 使用 Prim 算法计算最小生成树 56 | 57 | i = 0; 58 | 59 | while (i < graph_vcount(graph)) { 60 | 61 | /// 选择最小权重的白色顶点 62 | minimum = DBL_MAX; 63 | 64 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 65 | 66 | mst_vertex = ((AdjList *)list_data(element))->vertex; 67 | 68 | if (mst_vertex->color == white && mst_vertex->key < minimum) { 69 | 70 | minimum = mst_vertex->key; 71 | adjlist = list_data(element); 72 | 73 | } 74 | } 75 | 76 | /// 将选中的顶点涂为黑色 77 | ((MstVertex *)adjlist->vertex)->color = black; 78 | 79 | /// 遍历选中顶点的每个邻接顶点 80 | for (member = list_head(&adjlist->adjacent); member != NULL; member = list_next(member)) { 81 | 82 | adj_vertex = list_data(member); 83 | 84 | /// 通过顶点的邻接表找到邻接顶点 85 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 86 | 87 | mst_vertex = ((AdjList *)list_data(element))->vertex; 88 | 89 | if (match(mst_vertex, adj_vertex)) { 90 | 91 | /// 决定是否改变邻接表中邻接顶点的权重和父节点 92 | if (mst_vertex->color == white && adj_vertex->weight < mst_vertex->key) { 93 | 94 | mst_vertex->key = adj_vertex->weight; 95 | mst_vertex->parent = adjlist->vertex; 96 | 97 | } 98 | 99 | break; 100 | 101 | } 102 | } 103 | } 104 | 105 | /// 准备选择下一个顶点 106 | i++; 107 | } 108 | 109 | /// 将最小生成树载入列表 110 | 111 | list_init(span, NULL); 112 | 113 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 114 | 115 | /// 从邻接表中加载每个黑色顶点 116 | mst_vertex = ((AdjList *)list_data(element))->vertex; 117 | 118 | if (mst_vertex->color == black) { 119 | 120 | if (list_ins_next(span, list_tail(span), mst_vertex) != 0) { 121 | 122 | list_destroy(span); 123 | return -1; 124 | } 125 | } 126 | } 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /include/graph.h: -------------------------------------------------------------------------------- 1 | // 2 | // graph.h 3 | // Algorithms - Graph 4 | // 5 | // Created by YourtionGuo on 08/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef GRAPH_H 10 | #define GRAPH_H 11 | 12 | #include 13 | 14 | #include "list.h" 15 | #include "set.h" 16 | 17 | 18 | /** 19 | 邻接表 20 | */ 21 | typedef struct AdjList_ 22 | { 23 | void *vertex; 24 | Set adjacent; 25 | 26 | } AdjList; 27 | 28 | 29 | /** 30 | 图 31 | */ 32 | typedef struct Graph_ 33 | { 34 | int vcount; 35 | int ecount; 36 | 37 | int (*match)(const void *key1, const void *key2); 38 | void (*destroy)(void *data); 39 | 40 | List adjlists; 41 | 42 | } Graph; 43 | 44 | /** 45 | 结点颜色 46 | */ 47 | typedef enum VertexColor_ {white, gray, black} VertexColor; 48 | 49 | 50 | /** 51 | 初始化由参数 graph 所指定的图 - O(1) 52 | 53 | @param graph 图 54 | @param match 函数指针,用于判断两个成员是否相匹配(等于返回 1,否则返回 0) 55 | @param destroy 成员析构函数(free...) 56 | */ 57 | void graph_init(Graph *graph, 58 | int (*match)(const void *key1, const void *key2), 59 | void (*destroy)(void *data)); 60 | 61 | 62 | /** 63 | 销毁由参数 graph 所指定的图 - O(V+E) V是图中顶点的个数,E是边的个数 64 | 65 | @param graph 图 66 | */ 67 | void graph_destroy(Graph *graph); 68 | 69 | 70 | /** 71 | 将顶点插入由参数 graph 所指定的图中 - O(V) 72 | 73 | @param graph 图 74 | @param data 顶点数据 75 | @return 插入成功返回0;顶点已经存在返回1;否则返回-1 76 | */ 77 | int graph_ins_vertex(Graph *graph, const void *data); 78 | 79 | 80 | /** 81 | 将由 data1 以及 data2 所指定的顶点构成的边插入图 graph 中 - O(V) 82 | 83 | @param graph 图 84 | @param data1 顶点1数据 85 | @param data2 顶点2数据 86 | @return 插入成功返回0;边已存在返回1;否则返回-1 87 | */ 88 | int graph_ins_edge(Graph *graph, const void *data1, const void *data2); 89 | 90 | 91 | /** 92 | 从 graph 指定的图中移除与 data 相匹配的顶点 - O(V+E) 93 | 94 | @param graph 图 95 | @param data 顶点 96 | @return 移除成功返回0;否则返回-1 97 | */ 98 | int graph_rem_vertex(Graph *graph, void **data); 99 | 100 | 101 | /** 102 | 从 graph 指定的图中移除从 data1 到 data2 的边 - O(V) 103 | 104 | @param graph 图 105 | @param data1 顶点1数据 106 | @param data2 顶点2数据 107 | @return 移除成功,返回0;否则返回-1 108 | */ 109 | int graph_rem_edge(Graph *graph, void *data1, void **data2); 110 | 111 | 112 | /** 113 | 取出 graph 中由 data 所指定的顶点的邻接表 - O(V) 114 | 115 | @param graph 图 116 | @param data 顶点 117 | @param adjlist 顶点的邻接表 118 | @return 取得邻接表成功返回0;否则返回-1 119 | */ 120 | int graph_adjlist(const Graph *graph, const void *data, AdjList **adjlist); 121 | 122 | 123 | /** 124 | 判断由 data2 所指定的顶点是否与 graph 中由 data1 所指定的顶点邻接 - O(V) 125 | 126 | @param graph 图 127 | @param data1 顶点1数据 128 | @param data2 顶点2数据 129 | @return 如果顶点2与顶点1邻接返回1;否则返回0 130 | */ 131 | int graph_is_adjacent(const Graph *graph, const void *data1, const void *data2); 132 | 133 | 134 | /** 135 | 返回由参数 graph 所指定的图中的邻接表结构链表 - O(1) 136 | 137 | @param graph 图 138 | @return 由邻接表结构所组成的链表 139 | */ 140 | #define graph_adjlists(graph) ((graph)->adjlists) 141 | 142 | 143 | /** 144 | 计算 graph 指定的图中顶点的个数 - O(1) 145 | 146 | @param graph 图 147 | @return 顶点个数 148 | */ 149 | #define graph_vcount(graph) ((graph)->vcount) 150 | 151 | 152 | /** 153 | 计算 graph 指定的图中边的个数 - O(1) 154 | 155 | @param graph 图 156 | @return 边的个数 157 | */ 158 | #define graph_ecount(graph) ((graph)->ecount) 159 | 160 | #endif /* GRAPH_H */ 161 | -------------------------------------------------------------------------------- /include/bitree.h: -------------------------------------------------------------------------------- 1 | // 2 | // bitree.h 3 | // Algorithms - binary tree 4 | // 5 | // Created by YourtionGuo on 03/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #ifndef BITREE_H 10 | #define BITREE_H 11 | 12 | #include 13 | 14 | 15 | /** 16 | 二叉树结点 17 | */ 18 | typedef struct BiTreeNode_ 19 | { 20 | void *data; 21 | struct BiTreeNode_ *left; 22 | struct BiTreeNode_ *right; 23 | 24 | } BiTreeNode; 25 | 26 | 27 | /** 28 | 二叉树 29 | */ 30 | typedef struct BiTree_ 31 | { 32 | int size; 33 | 34 | int (*compare)(const void *key1, const void *key2); 35 | void (*destroy)(void *data); 36 | 37 | BiTreeNode *root; 38 | 39 | } BiTree; 40 | 41 | 42 | /** 43 | 初始化由参数 tree 所指定二叉树 - O(1) 44 | 45 | @param tree 二叉树 46 | @param destroy 成员析构函数(free...) 47 | */ 48 | void bitree_init(BiTree *tree, void (*destroy)(void *data)); 49 | 50 | 51 | /** 52 | 销毁由参数 tree 所指定二叉树 - O(n) n 为结点个数 53 | 54 | @param tree 二叉树 55 | */ 56 | void bitree_destroy(BiTree *tree); 57 | 58 | 59 | /** 60 | 在 tree 所指定二叉树中插入一个 node 所指定结点的左子结点 - O(1) 61 | 62 | @param tree 二叉树 63 | @param node 指定的结点 64 | @param data 结点数据 65 | @return 插入成功返回0;否则返回-1 66 | */ 67 | int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data); 68 | 69 | 70 | /** 71 | 在 tree 所指定二叉树中插入一个 node 所指定结点的右子结点 - O(1) 72 | 73 | @param tree 二叉树 74 | @param node 指定的结点 75 | @param data 结点数据 76 | @return 插入成功返回0;否则返回-1 77 | */ 78 | int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data); 79 | 80 | 81 | /** 82 | 移除由 tree 指定二叉树中 node 的左子结点为根的子树 - O(m) m 为子树结点个数 83 | 84 | @param tree 二叉树 85 | @param node 指定结点 86 | */ 87 | void bitree_rem_left(BiTree *tree, BiTreeNode *node); 88 | 89 | 90 | /** 91 | 移除由 tree 指定二叉树中 node 的右子结点为根的子树 - O(m) m 为子树结点个数 92 | 93 | @param tree 二叉树 94 | @param node 指定结点 95 | */ 96 | void bitree_rem_right(BiTree *tree, BiTreeNode *node); 97 | 98 | 99 | /** 100 | 将 left 和 right 所指定的两棵二叉树合并为单棵二叉树 - O(1) 101 | 102 | @param merge 合并后的树 103 | @param left 合并后左子树 104 | @param right 合并后右子树 105 | @param data 新树的根节点数据 106 | @return 合并成功,返回0;否则返回-1 107 | */ 108 | int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data); 109 | 110 | 111 | /** 112 | 由参数 tree 所指定二叉树中的结点个数 - O(1) 113 | 114 | @param tree 二叉树 115 | @return 结点个数 116 | */ 117 | #define bitree_size(tree) ((tree)->size) 118 | 119 | 120 | /** 121 | 返回由参数 tree 所指定二叉树的根结点 - O(1) 122 | 123 | @param tree 二叉树 124 | @return 根结点 125 | */ 126 | #define bitree_root(tree) ((tree)->root) 127 | 128 | 129 | /** 130 | 判断由参数 node 所标识结点是否为二叉树中某个分支的结束 - O(1) 131 | 132 | @param node 待判断结点 133 | @return 分支结束则返回1;否则返回0 134 | */ 135 | #define bitree_is_eob(node) ((node) == NULL) 136 | 137 | 138 | /** 139 | 判断由参数 node 所指定结点是否为二叉树中的叶子结点 - O(1) 140 | 141 | @param node 待判断结点 142 | @return 叶子结点返回1;否则返回0 143 | */ 144 | #define bitree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL) 145 | 146 | 147 | /** 148 | 返回由参数 node 所指定结点中存储的数据 - O(1) 149 | 150 | @param node 指定结点 151 | @return 结点中存储的数据 152 | */ 153 | #define bitree_data(node) ((node)->data) 154 | 155 | 156 | /** 157 | 返回由参数 node 所指定结点的左子结点 - O(1) 158 | 159 | @param node 指定结点 160 | @return 指定结点的左子结点 161 | */ 162 | #define bitree_left(node) ((node)->left) 163 | 164 | 165 | /** 166 | 返回由参数 node 所指定结点的右子结点 - O(1) 167 | 168 | @param node 指定结点 169 | @return 指定结点的右子结点 170 | */ 171 | #define bitree_right(node) ((node)->right) 172 | 173 | #endif /* BITREE_H */ 174 | -------------------------------------------------------------------------------- /Example/list/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // MasteringAlgorithms 4 | // Illustrates using a linked list (see Chapter 5). 5 | // 6 | // Created by YourtionGuo on 18/04/2017. 7 | // Copyright © 2017 Yourtion. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | #include "list.h" 14 | 15 | static void print_list(const List *list) 16 | { 17 | ListElmt *element; 18 | 19 | int *data, i; 20 | 21 | /// 显示链表 22 | fprintf(stdout, "-> List size is %d\n", list_size(list)); 23 | 24 | i = 0; 25 | element = list_head(list); 26 | 27 | while (1) { 28 | 29 | data = list_data(element); 30 | fprintf(stdout, "--> list[%03d]=%03d\n", i, *data); 31 | 32 | i++; 33 | 34 | if (list_is_tail(element)) { 35 | break; 36 | } else { 37 | element = list_next(element); 38 | } 39 | } 40 | 41 | return; 42 | } 43 | 44 | int main(int argc, const char * argv[]) 45 | { 46 | List list; 47 | ListElmt *element; 48 | 49 | int *data, i; 50 | 51 | /// 初始化链表 52 | list_init(&list, free); 53 | 54 | /// 链表操作 55 | 56 | element = list_head(&list); 57 | 58 | for (i = 10; i > 0; i--) { 59 | 60 | if ((data = (int *)malloc(sizeof(int))) == NULL) return 1; 61 | 62 | *data = i; 63 | 64 | if (list_ins_next(&list, NULL, data) != 0) return 1; 65 | 66 | } 67 | 68 | print_list(&list); 69 | 70 | element = list_head(&list); 71 | 72 | for (i = 0; i < 7; i++) { 73 | element = list_next(element); 74 | } 75 | 76 | data = list_data(element); 77 | fprintf(stdout, "Removing an element after the one containing %03d\n", *data); 78 | 79 | if (list_rem_next(&list, element, (void **)&data) != 0) return 1; 80 | 81 | print_list(&list); 82 | 83 | fprintf(stdout, "Inserting 011 at the tail of the list\n"); 84 | 85 | *data = 11; 86 | if (list_ins_next(&list, list_tail(&list), data) != 0) return 1; 87 | 88 | print_list(&list); 89 | 90 | fprintf(stdout, "Removing an element after the first element\n"); 91 | 92 | element = list_head(&list); 93 | if (list_rem_next(&list, element, (void **)&data) != 0) return 1; 94 | 95 | print_list(&list); 96 | 97 | fprintf(stdout, "Inserting 012 at the head of the list\n"); 98 | 99 | *data = 12; 100 | if (list_ins_next(&list, NULL, data) != 0) return 1; 101 | 102 | print_list(&list); 103 | 104 | fprintf(stdout, "Iterating and removing the fourth element\n"); 105 | 106 | element = list_head(&list); 107 | element = list_next(element); 108 | element = list_next(element); 109 | 110 | if (list_rem_next(&list, element, (void **)&data) != 0) return 1; 111 | 112 | print_list(&list); 113 | 114 | fprintf(stdout, "Inserting 013 after the first element\n"); 115 | 116 | *data = 13; 117 | if (list_ins_next(&list, list_head(&list), data) != 0) return 1; 118 | 119 | print_list(&list); 120 | 121 | i = list_is_head(&list, list_head(&list)); 122 | fprintf(stdout, "Testing list_is_head...Value=%d (1=OK)\n", i); 123 | i = list_is_head(&list, list_tail(&list)); 124 | fprintf(stdout, "Testing list_is_head...Value=%d (0=OK)\n", i); 125 | i = list_is_tail(list_tail(&list)); 126 | fprintf(stdout, "Testing list_is_tail...Value=%d (1=OK)\n", i); 127 | i = list_is_tail(list_head(&list)); 128 | fprintf(stdout, "Testing list_is_tail...Value=%d (0=OK)\n", i); 129 | 130 | /// 销毁链表 131 | fprintf(stdout, "Destroying the list\n"); 132 | list_destroy(&list); 133 | 134 | return 0; 135 | } 136 | 137 | -------------------------------------------------------------------------------- /source/shortest.c: -------------------------------------------------------------------------------- 1 | // 2 | // shortest.c 3 | // Algorithms - Shortest paths (Dijkstra) 4 | // 5 | // Created by YourtionGuo on 24/05/2017. 6 | // Copyright © 2017 Yourtion. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "graph.h" 13 | #include "graphalg.h" 14 | #include "list.h" 15 | #include "set.h" 16 | 17 | #pragma mark - Private 18 | 19 | 20 | /** 21 | 释放所选顶点与相邻顶点间的边 22 | 23 | @param u 顶点 1 24 | @param v 顶点 2 25 | @param weight 权重 26 | */ 27 | static void relax(PathVertex *u, PathVertex *v, double weight) 28 | { 29 | /// 释放顶点 u 和 v 之间的边 30 | 31 | if (v->d > u->d + weight) { 32 | 33 | v->d = u->d + weight; 34 | v->parent = u; 35 | } 36 | return; 37 | } 38 | 39 | 40 | #pragma mark - Public 41 | 42 | 43 | int shortest(Graph *graph, const PathVertex *start, List *paths, 44 | int (*match)(const void *key1, const void *key2)) 45 | { 46 | AdjList *adjlist = NULL; 47 | PathVertex *pth_vertex, *adj_vertex; 48 | ListElmt *element, *member; 49 | double minimum; 50 | int found, i; 51 | 52 | /// 初始化图的所有顶点 53 | 54 | found = 0; 55 | 56 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 57 | 58 | pth_vertex = ((AdjList *)list_data(element))->vertex; 59 | 60 | if (match(pth_vertex, start)) { 61 | 62 | /// 初始化起点 63 | 64 | pth_vertex->color = white; 65 | pth_vertex->d = 0; 66 | pth_vertex->parent = NULL; 67 | found = 1; 68 | 69 | } else { 70 | 71 | /// 初始化起点外的其他顶点 72 | 73 | pth_vertex->color = white; 74 | pth_vertex->d = DBL_MAX; 75 | pth_vertex->parent = NULL; 76 | 77 | } 78 | } 79 | 80 | /// 如果找不到起点返回 -1 81 | 82 | if (!found) return -1; 83 | 84 | /// 使用 Dijkstra 算法计算最短路径 85 | 86 | i = 0; 87 | 88 | while (i < graph_vcount(graph)) { 89 | 90 | /// 选择最短路径的白色顶点 91 | 92 | minimum = DBL_MAX; 93 | 94 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 95 | 96 | pth_vertex = ((AdjList *)list_data(element))->vertex; 97 | 98 | if (pth_vertex->color == white && pth_vertex->d < minimum) { 99 | 100 | minimum = pth_vertex->d; 101 | adjlist = list_data(element); 102 | } 103 | } 104 | 105 | /// 将选中的顶点涂为黑色 106 | ((PathVertex *)adjlist->vertex)->color = black; 107 | 108 | /// 遍历选中顶点的每个邻接顶点 109 | 110 | for (member = list_head(&adjlist->adjacent); member != NULL; member = list_next(member)) { 111 | 112 | adj_vertex = list_data(member); 113 | 114 | /// 通过顶点的邻接表找到邻接顶点 115 | 116 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 117 | 118 | pth_vertex = ((AdjList *)list_data(element))->vertex; 119 | 120 | if (match(pth_vertex, adj_vertex)) { 121 | 122 | /// 释放邻接表中的邻接顶点 123 | relax(adjlist->vertex, pth_vertex, adj_vertex->weight); 124 | 125 | } 126 | } 127 | } 128 | 129 | /// 准备选择下一个顶点 130 | i++; 131 | } 132 | 133 | /// 将最短路径载入列表 134 | list_init(paths, NULL); 135 | 136 | for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) { 137 | 138 | /// 从邻接表中加载每个黑色顶点 139 | pth_vertex = ((AdjList *)list_data(element))->vertex; 140 | 141 | if (pth_vertex->color == black) { 142 | 143 | if (list_ins_next(paths, list_tail(paths), pth_vertex) != 0) { 144 | 145 | list_destroy(paths); 146 | return -1; 147 | } 148 | } 149 | } 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C07-Set.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C14-Bit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C05-List.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C05-Page.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C10-Heap.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C12-Sort.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C05-CList.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C05-DList.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C06-Queue.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C06-Stack.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C07-Cover.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C11-Graph.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C12-Spell.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C09-BiTree.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MasteringAlgorithms.xcodeproj/xcshareddata/xcschemes/C10-PQueue.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | --------------------------------------------------------------------------------