├── 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 | 
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 |
--------------------------------------------------------------------------------