diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..8226360b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: cpp +compiler: + - clang +script: + - make diff --git a/Makefile b/Makefile index 04870219..82f536a5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all clean -CC=gcc -CPP=g++ +CC=clang +CPP=clang++ AR=ar RANLIB=ranlib CFLAGS= -g -Wall -Wno-unused-function @@ -13,6 +13,7 @@ LIBS = -lm PROGRAMS = m_based_demo \ integer_demo \ insertion_sort_demo \ + shell_sort_demo \ radix_sort_demo \ shuffle_demo \ quick_sort_demo \ @@ -53,8 +54,6 @@ PROGRAMS = m_based_demo \ random_demo \ k-means_demo \ kmp_demo \ - heap_sort_demo \ - kruskal_mst_demo \ LRU_cache_demo \ base64_demo \ max_subarray_demo \ @@ -83,6 +82,9 @@ integer_demo: $(SRCDIR)/integer_demo.cpp insertion_sort_demo: $(SRCDIR)/insertion_sort_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) +shell_sort_demo: $(SRCDIR)/shell_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + radix_sort_demo: $(SRCDIR)/radix_sort_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) @@ -209,9 +211,6 @@ k-means_demo: $(SRCDIR)/k-means_demo.cpp kmp_demo : $(SRCDIR)/kmp_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) -heap_sort_demo: $(SRCDIR)/heap_sort_demo.cpp - $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) - kruskal_mst_demo: $(SRCDIR)/kruskal_mst_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) @@ -264,5 +263,5 @@ suffix_array_demo: $(SRCDIR)/suffix_array_demo.cpp $(CPP) $(C11FLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) clean: - rm -rf $(PROGRAMS) *.dSYM + rm -rf $(PROGRAMS) *.dSYM *.o diff --git a/README.md b/README.md index 9f2ddb6f..91d25f57 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ -###Algorithms & Data Structures in C++ +### Algorithms & Data Structures in C++ -####目标 ( goal ) : +[![Build Status][1]][2] + +[1]: https://img.shields.io/github/created-at/xtaci/algorithms +[2]: https://img.shields.io/github/created-at/xtaci/algorithms + +#### 目标 ( goal ) : 1. 经典的算法实现 (classical algorithms implementations) @@ -9,7 +14,7 @@ 3. 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. (correct! and ease of use, one .header file per algorithm) -####约定 ( Convention ): +#### 约定 ( Convention ): 1. 一个算法用一个.h文件表示放到include下. ( one .header file per algorithm. ) 2. 算法演示的demo程序放到src下. ( one demo per algorithm. ) @@ -21,79 +26,73 @@ eg: ![demograph](demo_graph.png) -####已实现 ( Implemented ): - - Array shuffle - Prime test(trial division) - Prime test(Miller-Rabin's method) - 2D Array - Arbitary Integer - Linear congruential generator - Maximum subarray problem - - Bit-Set - Queue - Stack - Binary Heap - Fibonacci Heap - Priority Queue (list based) - - Bubble sort - Selection sort - Insertion sort - Radix sort - Quick sort - Merge sort - Heap sort - Double linked list - Skip list - Self-organized linked-list ops (move-to-front, move-ahead-one) - Largest common sequence - - Binary search tree - AVL tree - Dynamic order statistics - Red-black tree - Interval tree - Prefix Tree(Trie) - Suffix Tree - B-Tree - Suffix Array - - Hash by multiplication - Hash table - Universal hash function - Perfect hash - Java's string hash - FNV-1a string hash - SimHash - Bloom Filter - SHA-1 Message Digest Algorithm - MD5 - Base64 - - Graph data structure - Strongly Connected Components(SCC) - Prim's minimum spanning tree - Kruskal MST - Directed/Undirected graph ops - Breadth First Search - Depth First Search - Dijkstra's algorithm - Bellman-Ford algorithm - Edmonds-Karp Maximal Flow - Push–Relabel algorithm +#### 已实现 ( Implemented ): - Huffman Coding - Word segementation(CHN/GB18030) using HMM and viterbi algorithm. - A* algorithm - K-Means - Knuth–Morris–Pratt algorithm - Disjoint-Set - 8-Queue Problem - Palindrome +| Name | File | +|------|------| +|Array shuffle|https://github.com/xtaci/algorithms/blob/master/include/shuffle.h | +|Prime test(trial division)|https://github.com/xtaci/algorithms/blob/master/include/prime.h| +|Prime test(Miller-Rabin's method)|https://github.com/xtaci/algorithms/blob/master/include/prime.h| +|2D Array|https://github.com/xtaci/algorithms/blob/master/include/2darray.h| +|Arbitrary Integer|https://github.com/xtaci/algorithms/blob/master/include/integer.h| +|Linear congruential generator|https://github.com/xtaci/algorithms/blob/master/include/random.h| +|Maximum subarray problem|https://github.com/xtaci/algorithms/blob/master/include/max_subarray.h| +|Bit-Set|https://github.com/xtaci/algorithms/blob/master/include/bitset.h| +|Queue|https://github.com/xtaci/algorithms/blob/master/include/queue.h| +|Stack|https://github.com/xtaci/algorithms/blob/master/include/stack.h| +|Binary Heap|https://github.com/xtaci/algorithms/blob/master/include/heap.h| +|Fibonacci Heap|https://github.com/xtaci/algorithms/blob/master/include/fib-heap.h| +|Priority Queue (list based)|https://github.com/xtaci/algorithms/blob/master/include/priority_queue.h| +|Bubble sort|https://github.com/xtaci/algorithms/blob/master/include/bubble_sort.h| +|Selection sort|https://github.com/xtaci/algorithms/blob/master/include/selection_sort.h| +|Insertion sort|https://github.com/xtaci/algorithms/blob/master/include/insertion_sort.h| +|Shell sort|https://github.com/xtaci/algorithms/blob/master/include/shell_sort.h| +|Radix sort|https://github.com/xtaci/algorithms/blob/master/include/radix_sort.h| +|Quicksort|https://github.com/xtaci/algorithms/blob/master/include/quick_sort.h| +|Merge sort|https://github.com/xtaci/algorithms/blob/master/include/merge_sort.h| +|Double linked list|https://github.com/xtaci/algorithms/blob/master/include/double_linked_list.h| +|Skip list|https://github.com/xtaci/algorithms/blob/master/include/skiplist.h| +|Largest common sequence|https://github.com/xtaci/algorithms/blob/master/include/lcs.h| +|Binary search tree|https://github.com/xtaci/algorithms/blob/master/include/binary_search_tree.h| +|AVL tree|https://github.com/xtaci/algorithms/blob/master/include/avl.h| +|Dynamic order statistics|https://github.com/xtaci/algorithms/blob/master/include/dos_tree.h| +|Red-black tree|https://github.com/xtaci/algorithms/blob/master/include/rbtree.h| +|Interval tree|https://github.com/xtaci/algorithms/blob/master/include/interval_tree.h| +|Prefix Tree(Trie)|https://github.com/xtaci/algorithms/blob/master/include/trie.h| +|Suffix Tree|https://github.com/xtaci/algorithms/blob/master/include/suffix_tree.h| +|B-Tree|https://github.com/xtaci/algorithms/blob/master/include/btree.h| +|Suffix Array|https://github.com/xtaci/algorithms/blob/master/include/suffix_array.h| +|Hash by multiplication|https://github.com/xtaci/algorithms/blob/master/include/hash_multi.h| +|Hash table|https://github.com/xtaci/algorithms/blob/master/include/hash_table.h| +|Universal hash function|https://github.com/xtaci/algorithms/blob/master/include/universal_hash.h| +|Perfect hash|https://github.com/xtaci/algorithms/blob/master/include/perfect_hash.h| +|Java's string hash|https://github.com/xtaci/algorithms/blob/master/include/hash_string.h| +|FNV-1a string hash|https://github.com/xtaci/algorithms/blob/master/include/hash_string.h| +|SimHash|https://github.com/xtaci/algorithms/blob/master/include/simhash.h| +|Bloom Filter|https://github.com/xtaci/algorithms/blob/master/include/bloom_filter.h| +|SHA-1 Message Digest Algorithm|https://github.com/xtaci/algorithms/blob/master/include/sha1.h| +|MD5|https://github.com/xtaci/algorithms/blob/master/include/md5.h| +|Base64|https://github.com/xtaci/algorithms/blob/master/include/base64.h| +|Strongly Connected Components(SCC)|https://github.com/xtaci/algorithms/blob/master/include/scc.h| +|Prim's minimum spanning tree|https://github.com/xtaci/algorithms/blob/master/include/prim_mst.h| +|Kruskal MST|https://github.com/xtaci/algorithms/blob/master/include/kruskal_mst.h| +|Breadth First Search|https://github.com/xtaci/algorithms/blob/master/include/graph_search.h| +|Depth First Search|https://github.com/xtaci/algorithms/blob/master/include/graph_search.h| +|Dijkstra's algorithm|https://github.com/xtaci/algorithms/blob/master/include/dijkstra.h| +|Bellman-Ford algorithm|https://github.com/xtaci/algorithms/blob/master/include/bellman_ford.h| +|Edmonds-Karp Maximal Flow|https://github.com/xtaci/algorithms/blob/master/include/edmonds_karp.h| +|Push–Relabel algorithm|https://github.com/xtaci/algorithms/blob/master/include/relabel_to_front.h| +|Huffman Coding|https://github.com/xtaci/algorithms/blob/master/include/huffman.h| +|Word segementation|https://github.com/xtaci/algorithms/blob/master/include/word_seg.h| +|A\* algorithm|https://github.com/xtaci/algorithms/blob/master/include/astar.h| +|K-Means|https://github.com/xtaci/algorithms/blob/master/include/k-means.h| +|Knuth–Morris–Pratt algorithm|https://github.com/xtaci/algorithms/blob/master/include/kmp.h| +|Disjoint-Set|https://github.com/xtaci/algorithms/blob/master/include/disjoint-set.h| +|8-Queen Problem|https://github.com/xtaci/algorithms/blob/master/include/8queen.h| +|Palindrome|https://github.com/xtaci/algorithms/blob/master/include/palindrome.h| +|LCA using Binary Lifting|https://github.com/xtaci/algorithms/blob/master/include/LCA.h| -####贡献者 ( Contributors ) : +#### 贡献者 ( Contributors ) : Samana: for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST diff --git a/donate_alg.png b/donate_alg.png new file mode 100644 index 00000000..04e73bb0 Binary files /dev/null and b/donate_alg.png differ diff --git a/include/2darray.h b/include/2darray.h index 1383e242..2a565810 100644 --- a/include/2darray.h +++ b/include/2darray.h @@ -10,8 +10,8 @@ * Simulated by 1-dimension array. ******************************************************************************/ -#ifndef __2D_ARRAY_H__ -#define __2D_ARRAY_H__ +#ifndef ALGO_2D_ARRAY_H__ +#define ALGO_2D_ARRAY_H__ #include #include diff --git a/include/8queen.h b/include/8queen.h index 27062e3a..511ebe21 100644 --- a/include/8queen.h +++ b/include/8queen.h @@ -9,8 +9,8 @@ * http://en.wikipedia.org/wiki/Eight_queens_puzzle ******************************************************************************/ -#ifndef __8QUEEN_H__ -#define __8QUEEN_H__ +#ifndef ALGO_8QUEEN_H__ +#define ALGO_8QUEEN_H__ #include #include @@ -84,4 +84,4 @@ namespace alg { }; } -#endif //__8QUEEN_H__ +#endif //ALGO_8QUEEN_H__ diff --git a/include/LCA.h b/include/LCA.h new file mode 100644 index 00000000..ef0eb098 --- /dev/null +++ b/include/LCA.h @@ -0,0 +1,38 @@ +/******************************************************************************* + * + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * LCA Finding using Binary Lifting and Dynamic Programming + * + * Features: + * 1. Answers Query about LCA of two nodes in O(log N) + * where N is the total number of nodes in a tree. + * + * https://en.wikipedia.org/wiki/Lowest_common_ancestor + * http://www.csegeek.com/csegeek/view/tutorials/algorithms/trees/tree_part12.php + ******************************************************************************/ + +#ifndef LCA_H +#define LCA_H +#include + +class LCA +{ + public: + LCA(std::vector< std::pair > edges); + int lcaQuery(int a, int b); + + private: + int getMaxLog(); + void initDP(); + void dfs(int currentNode, int currentParent); + std::vector< std::vector > adjList, binaryLiftDp; + std::vector parent, nodeHeight; + std::vector visited; + int _numberOfNodes, _maxLog; +}; + +#endif // LCA_H diff --git a/include/astar.h b/include/astar.h index 78fa276f..a821488d 100644 --- a/include/astar.h +++ b/include/astar.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef __ASTAR_H__ -#define __ASTAR_H__ +#ifndef ALGO_ASTAR_H__ +#define ALGO_ASTAR_H__ #include #include @@ -93,7 +93,7 @@ namespace alg { // initialy containing the start node // encoding [x,y] to [x*ncol + y] // using binary heap ... - m_openset.insert(0, x1*ncol+y1); + m_openset.push(0, x1*ncol+y1); // record the starting point in openset_grid m_openset_grid(x1,y1) = true; @@ -109,7 +109,8 @@ namespace alg { // the main A*algorithm while(!m_openset.is_empty()) { - uint32_t value = m_openset.min_value(); + Heap::elem e = m_openset.pop(); + uint32_t value = e.data; int cx = value/ncol; int cy = value%ncol; @@ -136,8 +137,7 @@ namespace alg { return as; } - // delete current positon from openset and move it into closed set. - m_openset.delete_min(); + // move it into closed set. m_closedset(cx, cy) = true; m_openset_grid(cx, cy) = false; @@ -168,7 +168,7 @@ namespace alg { g_score(nx,ny) = tentative; // update path cost for current position f_score(nx,ny) = tentative + estimate(nx,ny,x2,y2); // record path cost to this neighbour if (!m_openset_grid(nx,ny)) { // only insert the neighbour if it hasn't been add to the openset. - m_openset.insert(f_score(nx,ny), nx*ncol+ny); + m_openset.push(f_score(nx,ny), nx*ncol+ny); m_openset_grid(nx,ny) = true; } } diff --git a/include/avl.h b/include/avl.h index 4b8f00cd..697317ab 100644 --- a/include/avl.h +++ b/include/avl.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef __AVL_H__ -#define __AVL_H__ +#ifndef ALGO_AVL_H__ +#define ALGO_AVL_H__ #include #include diff --git a/include/bellman_ford.h b/include/bellman_ford.h index 2d6df417..40771ae4 100644 --- a/include/bellman_ford.h +++ b/include/bellman_ford.h @@ -44,8 +44,8 @@ * ******************************************************************************/ -#ifndef __BELLMAN_FORD_H__ -#define __BELLMAN_FORD_H__ +#ifndef ALGO_BELLMAN_FORD_H__ +#define ALGO_BELLMAN_FORD_H__ #include #include diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 5066c771..574914af 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -18,8 +18,8 @@ * ******************************************************************************/ -#ifndef __BINARY_SEARCH_TREE_H__ -#define __BINARY_SEARCH_TREE_H__ +#ifndef ALGO_BINARY_SEARCH_TREE_H__ +#define ALGO_BINARY_SEARCH_TREE_H__ #include #include @@ -31,7 +31,7 @@ namespace alg { class BST { private: /** - * binary search tree definiton. + * binary search tree definition. */ struct treeNode { KeyT key; // key @@ -57,7 +57,7 @@ namespace alg { BST():m_root(NULL){}; ~BST() { - __destruct(m_root); + destruct_(m_root); } /** @@ -159,10 +159,10 @@ namespace alg { } private: - void __destruct(treeNode *n) { + void destruct_(treeNode *n) { if (n==NULL) return; - __destruct(n->left); - __destruct(n->right); + destruct_(n->left); + destruct_(n->right); delete n; } diff --git a/include/bitset.h b/include/bitset.h index 83171c12..9e7b9bbc 100644 --- a/include/bitset.h +++ b/include/bitset.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __BIT_SET_H__ -#define __BIT_SET_H__ +#ifndef ALGO_BIT_SET_H__ +#define ALGO_BIT_SET_H__ #include #include diff --git a/include/bloom_filter.h b/include/bloom_filter.h index 810badd5..08253593 100644 --- a/include/bloom_filter.h +++ b/include/bloom_filter.h @@ -18,8 +18,8 @@ * ******************************************************************************/ -#ifndef __BLOOM_FILTER_H__ -#define __BLOOM_FILTER_H__ +#ifndef ALGO_BLOOM_FILTER_H__ +#define ALGO_BLOOM_FILTER_H__ #include #include diff --git a/include/btree.h b/include/btree.h index bec96048..6e17050f 100644 --- a/include/btree.h +++ b/include/btree.h @@ -24,8 +24,8 @@ * http://en.wikipedia.org/wiki/B-tree ******************************************************************************/ -#ifndef __BTREE_H__ -#define __BTREE_H__ +#ifndef ALGO_BTREE_H__ +#define ALGO_BTREE_H__ #include #include diff --git a/include/dijkstra.h b/include/dijkstra.h index c7b9c9c3..853376cc 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef __DIJKSTRA_H__ -#define __DIJKSTRA_H__ +#ifndef ALGO_DIJKSTRA_H__ +#define ALGO_DIJKSTRA_H__ #include #include @@ -37,6 +37,7 @@ namespace alg { class Dijkstra { public: static const int UNDEFINED = -1; + static const int LARGE_NUMBER = 999999; // run dijkstra algorithm, and return the previous table static HashTable * run(const Graph & g, uint32_t src_id) { // a binary heap @@ -51,43 +52,35 @@ namespace alg { // all vertices Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node){ - dist[a->v.id] = INT_MAX; // set inital distance to each vertex as INT_MAX + dist[a->v.id] = LARGE_NUMBER; // set initial distance to each vertex to a large number (*previous)[a->v.id] = UNDEFINED; // clear path to UNDEFINED visited[a->v.id] = false; // all vertices are not visited + Q.push(LARGE_NUMBER, a->v.id); // push all vertices to heap } // source vertex, the first vertex in Heap-Q - Q.insert(0, src_id); dist[src_id] = 0; + // decrease-key the source vertex to 0 + Q.decrease_key(src_id,0); while(!Q.is_empty()) { // for every un-visited vertex, try relaxing the path - int32_t id = Q.min_value(); - Q.delete_min(); // remove u from Q - if (visited[id]) { // jump visited vertex, it means a closer vertex has found - // printf("visted:%d %d\n", id, dist[id]); + Heap::elem e = Q.pop(); + uint32_t id = e.data; + if (visited[id]) { // ignore visited vertex continue; } Graph::Adjacent * u = g[id]; // the vertex to process int dist_u = dist[id]; // current known shortest distance to u - visited[id] = true; // mark the vertex as visited. + visited[id] = true; // mark the vertex as visited. Graph::Vertex * v; list_for_each_entry(v, &u->v_head, v_node){ uint32_t alt = dist_u + v->weight; - uint32_t dist_v = dist[v->id]; - if (alt < dist_v && !visited[v->id]) { - /* - uint32_t tmp = dist[v->id]; - if (tmp != INT_MAX) { - printf("old %d %d\n", v->id, tmp); - printf("new %d %d\n", v->id, dist[v->id]); - } - */ - + if (alt < dist[v->id]) { dist[v->id] = alt; - (*previous)[v->id] = u->v.id; - Q.insert(alt, v->id); + (*previous)[v->id] = id; + Q.decrease_key(v->id, alt); // decrease-key } } } diff --git a/include/directed_graph.h b/include/directed_graph.h index 0eb8e56e..9e46cfe0 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __DIRECTED_GRAPH_H__ -#define __DIRECTED_GRAPH_H__ +#ifndef ALGO_DIRECTED_GRAPH_H__ +#define ALGO_DIRECTED_GRAPH_H__ #include #include diff --git a/include/disjoint-set.h b/include/disjoint-set.h index c13a002e..be6bff7d 100644 --- a/include/disjoint-set.h +++ b/include/disjoint-set.h @@ -18,8 +18,8 @@ * http://en.wikipedia.org/wiki/Disjoint-set_data_structure ******************************************************************************/ -#ifndef __DISJOINTSET_H__ -#define __DISJOINTSET_H__ +#ifndef ALGO_DISJOINTSET_H__ +#define ALGO_DISJOINTSET_H__ namespace alg { template diff --git a/include/dos_tree.h b/include/dos_tree.h index 7440990f..42689457 100644 --- a/include/dos_tree.h +++ b/include/dos_tree.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef __DOS_TREE_H__ -#define __DOS_TREE_H__ +#ifndef ALGO_DOS_TREE_H__ +#define ALGO_DOS_TREE_H__ #include #include diff --git a/include/double_linked_list.h b/include/double_linked_list.h index 7b8a8637..678c66b8 100644 --- a/include/double_linked_list.h +++ b/include/double_linked_list.h @@ -16,8 +16,8 @@ * http://en.wikipedia.org/wiki/Double_linked_list ******************************************************************************/ -#ifndef __DOUBLE_LINKED_LIST_H__ -#define __DOUBLE_LINKED_LIST_H__ +#ifndef ALGO_DOUBLE_LINKED_LIST_H__ +#define ALGO_DOUBLE_LINKED_LIST_H__ struct list_head { struct list_head *next, *prev; @@ -39,7 +39,7 @@ struct list_head { * the prev/next entries already! */ static inline void -__list_add(struct list_head *n, +list_add_(struct list_head *n, struct list_head *prev, struct list_head *next) { @@ -57,14 +57,14 @@ __list_add(struct list_head *n, * the prev/next entries already! */ static inline void -__list_del(struct list_head *prev, struct list_head *next) +list_del_(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } static inline void -__list_splice(struct list_head *list, struct list_head *head) +list_splice_(struct list_head *list, struct list_head *head) { struct list_head *first = list->next; struct list_head *last = list->prev; @@ -88,7 +88,7 @@ __list_splice(struct list_head *list, struct list_head *head) static inline void list_add(struct list_head *n, struct list_head *head) { - __list_add(n, head, head->next); + list_add_(n, head, head->next); } /** @@ -102,7 +102,7 @@ list_add(struct list_head *n, struct list_head *head) static inline void list_add_tail(struct list_head *n, struct list_head *head) { - __list_add(n, head->prev, head); + list_add_(n, head->prev, head); } /** @@ -113,7 +113,7 @@ list_add_tail(struct list_head *n, struct list_head *head) static inline void list_del(struct list_head *entry) { - __list_del(entry->prev, entry->next); + list_del_(entry->prev, entry->next); entry->next = NULL; entry->prev = NULL; } @@ -125,7 +125,7 @@ list_del(struct list_head *entry) static inline void list_del_init(struct list_head *entry) { - __list_del(entry->prev, entry->next); + list_del_(entry->prev, entry->next); INIT_LIST_HEAD(entry); } @@ -137,7 +137,7 @@ list_del_init(struct list_head *entry) static inline void list_move(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); + list_del_(list->prev, list->next); list_add(list, head); } @@ -149,7 +149,7 @@ list_move(struct list_head *list, struct list_head *head) static inline void list_move_tail(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); + list_del_(list->prev, list->next); list_add_tail(list, head); } @@ -172,7 +172,7 @@ static inline void list_splice(struct list_head *list, struct list_head *head) { if (!list_empty(list)) - __list_splice(list, head); + list_splice_(list, head); } /** @@ -186,7 +186,7 @@ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { - __list_splice(list, head); + list_splice_(list, head); INIT_LIST_HEAD(list); } } diff --git a/include/edmonds_karp.h b/include/edmonds_karp.h index 396c9fbc..295de725 100644 --- a/include/edmonds_karp.h +++ b/include/edmonds_karp.h @@ -21,8 +21,8 @@ * ******************************************************************************/ -#ifndef __EDMONDS_KARP_H__ -#define __EDMONDS_KARP_H__ +#ifndef ALGO_EDMONDS_KARP_H__ +#define ALGO_EDMONDS_KARP_H__ #include #include diff --git a/include/fenwick_tree.h b/include/fenwick_tree.h new file mode 100644 index 00000000..4806536e --- /dev/null +++ b/include/fenwick_tree.h @@ -0,0 +1,61 @@ +/******************************************************************************* + * Fenwick Tree + * + * Data structure providing prefix sums and modify the table in O(log n) - n is the size o the table. + * + * In this algorithm we use two functions: + * - RSQ - This function calculates the range sum query in O(log n) + * - Update - This function adjusts the values in the given range in O(log n) + * + * https://en.wikipedia.org/wiki/Fenwick_tree + * + * @author Gabriel Duarte (gabriellagoa10@yahoo.com.br) + * @github Gabriel123Duarte + * + ******************************************************************************/ + +#ifndef ALGO_FENWICK_H__ +#define ALGO_FENWICK_H__ + +#include + +#define LSONE(x) (x & (-x)) + +class Fenwick +{ + private: + // Vector representing the table + std::vector fen; + public: + Fenwick() {} + + // We don't use the index 0, because it is the base case + Fenwick(int n) + { + fen.assign(n + 1, 0); + } + + // Calculate the + int rsq(int a) + { + int ans = 0; + for(; a; a -= LSONE(a)) + ans += fen[a]; + return ans; + } + + // RSQ a..b + inline int rsq(int a, int b) + { + return rsq(b) - (a == 1 ? 0 : rsq(a - 1)); + } + + // Update the value of the k-th element by x + void update(int k, int x) + { + for(; k < (int)fen.size(); k += LSONE(k)) + fen[k] += x; + } +}; + +#endif diff --git a/include/fib-heap.h b/include/fib-heap.h index 68100b8b..44af130a 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Fibonacci_heap ******************************************************************************/ -#ifndef __FIB_HEAP_H__ -#define __FIB_HEAP_H__ +#ifndef ALGO_FIB_HEAP_H__ +#define ALGO_FIB_HEAP_H__ #include #include #include diff --git a/include/generic.h b/include/generic.h index 8671f740..785e5078 100644 --- a/include/generic.h +++ b/include/generic.h @@ -9,8 +9,8 @@ * ******************************************************************************/ -#ifndef __ALG_INC_H__ -#define __ALG_INC_H__ +#ifndef ALGO_ALG_INC_H__ +#define ALGO_ALG_INC_H__ #include #include #include diff --git a/include/graph_defs.h b/include/graph_defs.h index 8860c9b1..06e77be2 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -1,5 +1,5 @@ -#ifndef __GRAPH_DEFS_H__ -#define __GRAPH_DEFS_H__ +#ifndef ALGO_GRAPH_DEFS_H__ +#define ALGO_GRAPH_DEFS_H__ #include "double_linked_list.h" diff --git a/include/graph_search.h b/include/graph_search.h index 438ea660..e0d18f4d 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -20,8 +20,8 @@ * ******************************************************************************/ -#ifndef __BREADTH_FIRST_SEARCH_H__ -#define __BREADTH_FIRST_SEARCH_H__ +#ifndef ALGO_BREADTH_FIRST_SEARCH_H__ +#define ALGO_BREADTH_FIRST_SEARCH_H__ #include #include diff --git a/include/hash_code.h b/include/hash_code.h index 89f22b2b..a310580c 100644 --- a/include/hash_code.h +++ b/include/hash_code.h @@ -1,5 +1,5 @@ -#ifndef __HASH_CODE_H__ -#define __HASH_CODE_H__ +#ifndef ALGO_HASH_CODE_H__ +#define ALGO_HASH_CODE_H__ #include #include "hash_string.h" namespace alg { diff --git a/include/hash_multi.h b/include/hash_multi.h index 4639e229..ec22f65f 100644 --- a/include/hash_multi.h +++ b/include/hash_multi.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __HASH_MULTIPLICATION_H__ -#define __HASH_MULTIPLICATION_H__ +#ifndef ALGO_HASH_MULTIPLICATION_H__ +#define ALGO_HASH_MULTIPLICATION_H__ #include #include diff --git a/include/hash_string.h b/include/hash_string.h index 52d1b7cf..6eee926c 100644 --- a/include/hash_string.h +++ b/include/hash_string.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef __STRING_HASH_H__ -#define __STRING_HASH_H__ +#ifndef ALGO_STRING_HASH_H__ +#define ALGO_STRING_HASH_H__ #include diff --git a/include/hash_table.h b/include/hash_table.h index 0fcdb713..72018610 100644 --- a/include/hash_table.h +++ b/include/hash_table.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __HASH_TABLE_H__ -#define __HASH_TABLE_H__ +#ifndef ALGO_HASH_TABLE_H__ +#define ALGO_HASH_TABLE_H__ #include #include @@ -36,7 +36,7 @@ namespace alg { typedef _HashCode hash_code_fn; private: /** - * definiton of Key-Value pair. + * definition of Key-Value pair. */ struct HashKV { key_type key; // 32-bit key diff --git a/include/heap.h b/include/heap.h index 3462660a..d793cdab 100644 --- a/include/heap.h +++ b/include/heap.h @@ -7,28 +7,36 @@ * * Heap Data structure * - * Heaps can be used as an array. For any key at array position I, - I left child is at ( 2i ), right child is at ( 2i+1 ) and parent is - I at (int) (i / 2). Heap size is stored at index 0. + * In computer science, a heap is a specialized tree-based data structure that + * satisfies the heap property: If A is a parent node of B then the key of node + * A is ordered with respect to the key of node B with the same ordering applying + * across the heap. Heaps can be classified further as either a "max heap" or + * a "min heap". In a max heap, the keys of parent nodes are always greater + * than or equal to those of the children and the highest key is in the root node. + * In a min heap, the keys of parent nodes are less than or equal to those of + * the children and the lowest key is in the root node. Heaps are crucial in + * several efficient graph algorithms such as Dijkstra's algorithm, and in + * the sorting algorithm heapsort. A common implementation of a heap is the + * binary heap, in which the tree is a complete binary tree (see figure). * * Basic operations of a heap are: * - * 1. Insert – Insert an key. - * 2. Delete minimum – Delete and return the smallest item in the heap. + * 1. Push – Insert an key. + * 2. Pop – Delete and return the smallest item in the heap. + * 3. Remove - Remove an element * * http://en.wikipedia.org/wiki/Binary_heap ******************************************************************************/ -#ifndef __HEAP_H__ -#define __HEAP_H__ +#ifndef ALGO_HEAP_H__ +#define ALGO_HEAP_H__ #include #include #include #include #include -#include "hash_code.h" -#include "hash_table.h" +#include "generic.h" namespace alg { /** @@ -36,33 +44,29 @@ namespace alg { */ template class Heap { - private: + public: /** * define key-value pair of heap struct. */ - struct KV { + struct elem { public: - int32_t key; - T value; + int key; + T data; }; - int32_t m_size; // current heap size. - int32_t m_max; // max heap size. - KV * m_kvs; // key value pairs. - - HashTable * m_idx; // key -> idx + private: + int m_size; // current heap size. + int m_max; // max heap size. + elem * m_heap; // key value pairs. public: Heap(int max) { m_size = 0; - m_max = max+1; - m_kvs = new KV[m_max]; - m_kvs[0].key = INT_MIN; - m_idx = new HashTable(m_max); + m_max = max; + m_heap = new elem[m_max]; }; ~Heap() { - delete [] m_kvs; - delete m_idx; + delete [] m_heap; }; private: @@ -70,37 +74,20 @@ namespace alg { Heap& operator=(const Heap&); public: - - inline int min_key() const { return m_kvs[1].key; }; - inline const T & min_value() const { return m_kvs[1].value; }; - // for loop through the kvs - inline uint32_t count() const { return m_size; }; - inline const T & operator[] (uint32_t idx) const { return m_kvs[idx+1].value; }; + inline int count() const { return m_size; }; /** * insert a 'key'->'value' pair into the heap. */ - void insert(int key, const T & value) { + void push(int key, const T & data) { // heap full, just return; if(m_size == m_max) return; - + // put in the back, and try move upward the heap + m_heap[m_size].key = key; + m_heap[m_size].data= data; + up(m_size); m_size++; - m_kvs[m_size].key = key; - m_kvs[m_size].value = value; - (*m_idx)[value] = m_size; - - // Adjust its position - int now = m_size; - while(m_kvs[now/2].key > key) { - m_kvs[now] = m_kvs[now/2]; - (*m_idx)[m_kvs[now/2].value] = now; - now /= 2; - } - - m_kvs[now].key = key; - m_kvs[now].value = value; - (*m_idx)[value] = now; } /** @@ -113,84 +100,94 @@ namespace alg { */ inline void clear() { m_size = 0; } + bool contains(const T & data) { + for(int i=0;i heap top. + * decrease key + * simpliy implemented as remove then push */ - void delete_min() { - // heap[1] is the minimum key. So we remove heap[1]. - // Size of the heap is decreased. Now heap[1] has to be filled. - // We put the last key in its place and see if it fits. If it - // does not fit, take minimum key among both its children and - // replaces parent with it. Again See if the last key fits - //in that place. - int32_t lastKey; - T lastValue; - int32_t child,now; - - // empty heap, just return - if (m_size == 0) return; - - lastKey = m_kvs[m_size].key; - lastValue = m_kvs[m_size].value; - m_size--; + void decrease_key(const T &data, int newkey) { + if (remove(data)) { + push(newkey, data); + } + } - // now refers to the index at which we are now - for(now = 1; now*2 <= m_size ;now = child) { - // child is the index of the key which is minimum among - // both the children, Indexes of children are i*2 and i*2 + 1 - child = now*2; - // child!=heapSize beacuse heap[heapSize+1] does not exist, - // which means it has only one child - if(child != m_size && m_kvs[child+1].key < m_kvs[child].key) { - child++; // choose the minium one. + void up(int j) { + for (;;) { + int i = (j-1)/2; // parent + if (i==j || !less(j,i)) { // j not smaller than i + break; } - // To check if the last key fits or not it suffices to check - // if the last key is less than the minimum key among both the children - if(lastKey > m_kvs[child].key) { - m_kvs[now] = m_kvs[child]; - (*m_idx)[m_kvs[now].value] = now; // record index + swap(m_heap[i], m_heap[j]); + j=i; + } + } + + void down(int i, int n) { + for(;;) { + int j1 = 2*i+1; // left child + if (j1 >=n || j1 < 0) { // j1 < 0 after int overflow + break; + } + + int j = j1; + int j2 = j1+1; // right child + if (j2 < n && !less(j1,j2)) { + j = j2; // choose the minium one. } - else { // It fits there + + if (!less(j,i)) { break; } + swap(m_heap[i], m_heap[j]); + i=j; } - - m_kvs[now].key = lastKey; - m_kvs[now].value= lastValue; - (*m_idx)[lastValue] = now; // record index } - /** - * so called DECREASE KEY operation. - * step 1. find the value - * step 2. decrease the key to the newkey - */ - void decrease_key(T value, int32_t newkey) { - int32_t index = (*m_idx)[value]; - if (index > m_size || index == 0) return; // value not found - if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning. - T oldvalue = m_kvs[index].value; - - int now = index; - while(m_kvs[now/2].key > newkey) { - m_kvs[now] = m_kvs[now/2]; - (*m_idx)[m_kvs[now].value] = now; // record index - now /= 2; + void print_heap() { + for (int i=0;i - * _| - * - * HEAPSORT - * - * Features: - * 1. Although somewhat slower in practice on most machines than a well-implemented quicksort, - it has the advantage of a more favorable worst-case O(n log n) runtime - * - * http://en.wikipedia.org/wiki/Heapsort - * - ******************************************************************************/ - -#ifndef __HEAPSORT_H__ -#define __HEAPSORT_H__ - -#include - -namespace alg { - /** - * heap sort an array - */ - template - static void heapsort(T *array,int number_of_elements) { - Heap heap(number_of_elements); - int i; - - // In order to build a heap structure from input array - for(i=0;i #include diff --git a/include/imath.h b/include/imath.h index 6a23ab52..b3fa2430 100644 --- a/include/imath.h +++ b/include/imath.h @@ -9,8 +9,8 @@ * ******************************************************************************/ -#ifndef __IMATH_H__ -#define __IMATH_H__ +#ifndef ALGO_IMATH_H__ +#define ALGO_IMATH_H__ #include #include diff --git a/include/insertion_sort.h b/include/insertion_sort.h index 42427e4b..eb9f58ef 100644 --- a/include/insertion_sort.h +++ b/include/insertion_sort.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef __INSERTION_SORT_H__ -#define __INSERTION_SORT_H__ +#ifndef ALGO_INSERTION_SORT_H__ +#define ALGO_INSERTION_SORT_H__ namespace alg { /** diff --git a/include/integer.h b/include/integer.h index f177d5ad..1d5ff609 100644 --- a/include/integer.h +++ b/include/integer.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef __INTEGER_H__ -#define __INTEGER_H__ +#ifndef ALGO_INTEGER_H__ +#define ALGO_INTEGER_H__ #include #include diff --git a/include/interval_tree.h b/include/interval_tree.h index c4edca19..ec107364 100644 --- a/include/interval_tree.h +++ b/include/interval_tree.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef __INTERVAL_TREE_H__ -#define __INTERVAL_TREE_H__ +#ifndef ALGO_INTERVAL_TREE_H__ +#define ALGO_INTERVAL_TREE_H__ #include #include diff --git a/include/k-means.h b/include/k-means.h index 953430de..86fdef3c 100644 --- a/include/k-means.h +++ b/include/k-means.h @@ -12,8 +12,8 @@ * https://github.com/wycg1984 ******************************************************************************/ -#ifndef __KMEANS_H__ -#define __KMEANS_H__ +#ifndef ALGO_KMEANS_H__ +#define ALGO_KMEANS_H__ #include #include #include diff --git a/include/kmp.h b/include/kmp.h index ada982a1..d75d207b 100644 --- a/include/kmp.h +++ b/include/kmp.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __KMP_H__ -#define __KMP_H__ +#ifndef ALGO_KMP_H__ +#define ALGO_KMP_H__ #include namespace alg { diff --git a/include/kruskal_mst.h b/include/kruskal_mst.h index e5305868..6db3458f 100644 --- a/include/kruskal_mst.h +++ b/include/kruskal_mst.h @@ -25,8 +25,8 @@ * By Contibutor:xmuliang ******************************************************************************/ -#ifndef __KRUSKAL_MST_H__ -#define __KRUSKAL_MST_H__ +#ifndef ALGO_KRUSKAL_MST_H__ +#define ALGO_KRUSKAL_MST_H__ #include #include @@ -91,7 +91,7 @@ namespace alg { Graph::Vertex * v; list_for_each_entry(v, &a.v_head, v_node){ - pa->heap.insert(v->weight, v); // weight->vertex + pa->heap.push(v->weight, v); // weight->vertex } } diff --git a/include/lcs.h b/include/lcs.h index a3c3e9d9..ce218022 100644 --- a/include/lcs.h +++ b/include/lcs.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __LCS_H__ -#define __LCS_H__ +#ifndef ALGO_LCS_H__ +#define ALGO_LCS_H__ #include "generic.h" #include "2darray.h" diff --git a/include/max_subarray.h b/include/max_subarray.h index c791df3b..96b0d943 100644 --- a/include/max_subarray.h +++ b/include/max_subarray.h @@ -21,8 +21,8 @@ * http://en.wikipedia.org/wiki/Maximum_subarray_problem ******************************************************************************/ -#ifndef __MAX_SUBARRAY__ -#define __MAX_SUBARRAY__ +#ifndef MAX_SUBARRAY__ +#define MAX_SUBARRAY__ namespace alg { /** diff --git a/include/md5.h b/include/md5.h index 5ff52525..284d8c70 100644 --- a/include/md5.h +++ b/include/md5.h @@ -23,8 +23,8 @@ */ -#ifndef __MD5_H__ -#define __MD5_H__ +#ifndef ALGO_MD5_H__ +#define ALGO_MD5_H__ #include /* Data structure for MD5 (Message Digest) computation */ diff --git a/include/merge_sort.h b/include/merge_sort.h index 8a45aece..b50d1976 100644 --- a/include/merge_sort.h +++ b/include/merge_sort.h @@ -13,8 +13,8 @@ * and right part. * Example: Say the input is -10 32 45 -78 91 1 0 -16 then the left part will be * -10 32 45 -78 and the right part will be 91 1 0 6. - * (2) Sort Each of them seperately. Note that here sort does not mean to sort it using some other - * method. We already wrote fucntion to sort it. Use the same. + * (2) Sort Each of them separately. Note that here sort does not mean to sort it using some other + * method. We already wrote function to sort it. Use the same. * (3) Then merge the two sorted parts. * * ------------ @@ -32,15 +32,15 @@ * ******************************************************************************/ -#ifndef __MERGE_SORT_H__ -#define __MERGE_SORT_H__ +#ifndef ALGO_MERGE_SORT_H__ +#define ALGO_MERGE_SORT_H__ namespace alg { /** * Merge functions merges the two sorted parts. Sorted parts will be from [left, mid] and [mid+1, right]. */ template - static void __merge(T *array, int left, int mid, int right) { + static void merge_(T *array, int left, int mid, int right) { /*We need a Temporary array to store the new sorted part*/ T tempArray[right-left+1]; int pos=0,lpos = left,rpos = mid + 1; @@ -75,7 +75,7 @@ namespace alg { /* Sort the right part */ merge_sort(array,mid+1,right); /* Merge the two sorted parts */ - __merge(array,left,mid,right); + merge_(array,left,mid,right); } } diff --git a/include/perfect_hash.h b/include/perfect_hash.h index 52dd9801..55af66c1 100644 --- a/include/perfect_hash.h +++ b/include/perfect_hash.h @@ -10,8 +10,8 @@ * http://en.wikipedia.org/wiki/Perfect_hash * ******************************************************************************/ -#ifndef __PERFECT_HASH_H__ -#define __PERFECT_HASH_H__ +#ifndef ALGO_PERFECT_HASH_H__ +#define ALGO_PERFECT_HASH_H__ #include #include #include diff --git a/include/prim_mst.h b/include/prim_mst.h index b3bf5069..be48ab58 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -22,18 +22,20 @@ * ******************************************************************************/ -#ifndef __PRIM_MST_H__ -#define __PRIM_MST_H__ +#ifndef ALGO_PRIM_MST_H__ +#define ALGO_PRIM_MST_H__ #include #include #include "undirected_graph.h" #include "double_linked_list.h" #include "heap.h" +#include "hash_table.h" namespace alg { class Prim { public: + static const int LARGE_NUMBER = 999999; /** * Prim's Algorithm. * @@ -62,19 +64,16 @@ namespace alg { // all vertices Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node){ - if (a->v.id != src_id) { - Q.insert(INT_MAX, a->v.id); - keys[a->v.id] = INT_MAX; - } + Q.push(LARGE_NUMBER, a->v.id); + keys[a->v.id] = LARGE_NUMBER; } - - Q.insert(0, src_id); + + Q.decrease_key(src_id, 0); keys[src_id] = 0; while (!Q.is_empty()) { - int32_t id = Q.min_value(); - Q.delete_min(); // remove u from Q - + Heap::elem e = Q.pop(); + uint32_t id = e.data; Graph::Adjacent * u = g[id]; // the vertex to process Graph::Vertex * v; list_for_each_entry(v, &u->v_head, v_node) { diff --git a/include/prime.h b/include/prime.h index 81f772e4..357f8b96 100644 --- a/include/prime.h +++ b/include/prime.h @@ -11,8 +11,8 @@ * http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test * ******************************************************************************/ -#ifndef __PRIME_H__ -#define __PRIME_H__ +#ifndef ALGO_PRIME_H__ +#define ALGO_PRIME_H__ #include #include diff --git a/include/priority_queue.h b/include/priority_queue.h index 4a8dbe28..8795bc08 100644 --- a/include/priority_queue.h +++ b/include/priority_queue.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __PRIORITY_QUEUE_H__ -#define __PRIORITY_QUEUE_H__ +#ifndef ALGO_PRIORITY_QUEUE_H__ +#define ALGO_PRIORITY_QUEUE_H__ #include #include @@ -75,12 +75,12 @@ namespace alg { list_add(&n->node, &m_head); m_count++; } else { - // sequentially find the apropriate position + // sequentially find the appropriate position PQNode * pos; bool found = false; list_for_each_entry(pos, &m_head, node) { if (n->priority <= pos->priority) { - __list_add(&n->node, pos->node.prev, &pos->node); + list_add_(&n->node, pos->node.prev, &pos->node); m_count++; found = true; break; diff --git a/include/queue.h b/include/queue.h index 1de7b292..55051228 100644 --- a/include/queue.h +++ b/include/queue.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef __QUEUE_H__ -#define __QUEUE_H__ +#ifndef ALGO_QUEUE_H__ +#define ALGO_QUEUE_H__ #include #include diff --git a/include/quick_sort.h b/include/quick_sort.h index b8962216..b3a74489 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __QUICKSORT_H__ -#define __QUICKSORT_H__ +#ifndef ALGO_QUICKSORT_H__ +#define ALGO_QUICKSORT_H__ #include @@ -25,7 +25,7 @@ namespace alg { * the quick-sort partition routine */ template - static int __partition(T list[],int begin, int end) { + static int partition_(T list[],int begin, int end) { int pivot_idx = RANDOM(begin,end); T pivot = list[pivot_idx]; swap(list[begin], list[pivot_idx]); @@ -52,7 +52,7 @@ namespace alg { template static void quicksort(T list[],int begin,int end) { if( begin < end) { - int pivot_idx = __partition(list, begin, end); + int pivot_idx = partition_(list, begin, end); quicksort(list, begin, pivot_idx-1); quicksort(list, pivot_idx+1, end); } diff --git a/include/radix_sort.h b/include/radix_sort.h index 4272ce48..ec5e0733 100644 --- a/include/radix_sort.h +++ b/include/radix_sort.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __RADIX_SORT_H__ -#define __RADIX_SORT_H__ +#ifndef ALGO_RADIX_SORT_H__ +#define ALGO_RADIX_SORT_H__ #include #include @@ -29,7 +29,7 @@ namespace alg { /** * couting sort */ - static void __radix(int byte, const unsigned N, const uint32_t *source, uint32_t *dest) { + static void radix_(int byte, const unsigned N, const uint32_t *source, uint32_t *dest) { unsigned count[256]; unsigned index[256]; memset(count, 0, sizeof (count)); @@ -51,10 +51,10 @@ namespace alg { */ static void radix_sort(uint32_t *source, const unsigned N) { uint32_t * temp = new uint32_t[N]; - __radix(0, N, source, temp); - __radix(1, N, temp, source); - __radix(2, N, source, temp); - __radix(3, N, temp, source); + radix_(0, N, source, temp); + radix_(1, N, temp, source); + radix_(2, N, source, temp); + radix_(3, N, temp, source); delete [] temp; } diff --git a/include/random.h b/include/random.h index 456ab698..1b2fd82e 100644 --- a/include/random.h +++ b/include/random.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __RANDOM_H__ -#define __RANDOM_H__ +#ifndef ALGO_RANDOM_H__ +#define ALGO_RANDOM_H__ #include #include diff --git a/include/random_select.h b/include/random_select.h index 3577bdd9..8893008d 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -17,8 +17,8 @@ * ******************************************************************************/ -#ifndef __RANDOM_SELECT_H__ -#define __RANDOM_SELECT_H__ +#ifndef ALGO_RANDOM_SELECT_H__ +#define ALGO_RANDOM_SELECT_H__ #include @@ -27,7 +27,7 @@ namespace alg { * the random_select partition routine */ template - static int __partition(T list[],int begin, int end) { + static int partition_(T list[],int begin, int end) { int pivot_idx = RANDOM(begin,end); T pivot = list[pivot_idx]; swap(list[begin],list[pivot_idx]); @@ -56,7 +56,7 @@ namespace alg { if(begin == end) return begin; - int pivot_idx = __partition(list, begin, end); + int pivot_idx = partition_(list, begin, end); int human_idx = pivot_idx - begin + 1; if(k < human_idx) diff --git a/include/rbtree.h b/include/rbtree.h index c9b8a318..61c129bd 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -15,8 +15,8 @@ * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ -#ifndef __RBTREE_H__ -#define __RBTREE_H__ +#ifndef ALGO_RBTREE_H__ +#define ALGO_RBTREE_H__ #include #include #include diff --git a/include/rbtree_defs.h b/include/rbtree_defs.h index ab5ef4ea..a99a26b0 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -15,8 +15,8 @@ * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ -#ifndef __RBTREE_DEFS_H__ -#define __RBTREE_DEFS_H__ +#ifndef ALGO_RBTREE_DEFS_H__ +#define ALGO_RBTREE_DEFS_H__ #include #include diff --git a/include/relabel_to_front.h b/include/relabel_to_front.h index c8a4d950..ef933e02 100644 --- a/include/relabel_to_front.h +++ b/include/relabel_to_front.h @@ -9,8 +9,8 @@ * * */ -#ifndef __RELABEL_TO_FRONT_H__ -#define __RELABEL_TO_FRONT_H__ +#ifndef ALGO_RELABEL_TO_FRONT_H__ +#define ALGO_RELABEL_TO_FRONT_H__ #include #include diff --git a/include/scc.h b/include/scc.h index 23e34e0e..ef41af12 100644 --- a/include/scc.h +++ b/include/scc.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Strongly_connected_component ******************************************************************************/ -#ifndef __SCC_H__ -#define __SCC_H__ +#ifndef ALGO_SCC_H__ +#define ALGO_SCC_H__ #include #include #include @@ -39,7 +39,7 @@ namespace alg { Heap Q(g.vertex_count()) ; Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node) { - Q.insert(INT_MAX - a->f, a->v.id); // descending order of a->f + Q.push(INT_MAX - a->f, a->v.id); // descending order of a->f } // step 2. discover @@ -51,9 +51,9 @@ namespace alg { // step 3. call DFS(GT), but in the main loop of DFS, consider the vertices // in order of decreasing u.f (as computed in line 1) while(!Q.is_empty()) { - int32_t key = Q.min_key(); - int32_t id = Q.min_value(); - Q.delete_min(); + Heap::elem e = Q.pop(); + int32_t key = e.key; + int32_t id = e.data; if ((*GT)[id]->color == Graph::WHITE) { printf("component:%d %d\n",id, INT_MAX - key); _DFS_VISIT(*GT, (*GT)[id]); diff --git a/include/selection_sort.h b/include/selection_sort.h index a956ad9a..7b0f53e3 100644 --- a/include/selection_sort.h +++ b/include/selection_sort.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Selection_sort ******************************************************************************/ -#ifndef __SELECTION_SORT_H__ -#define __SELECTION_SORT_H__ +#ifndef ALGO_SELECTION_SORT_H__ +#define ALGO_SELECTION_SORT_H__ #include #include @@ -49,4 +49,4 @@ namespace alg { } } -#endif //__SELECTION_SORT_H__ +#endif //ALGO_SELECTION_SORT_H__ diff --git a/include/sha1.h b/include/sha1.h index 3079e20c..da529b94 100644 --- a/include/sha1.h +++ b/include/sha1.h @@ -37,8 +37,8 @@ * http://en.wikipedia.org/wiki/SHA-1 */ -#ifndef __SHA1_H__ -#define __SHA1_H__ +#ifndef ALGO_SHA1_H__ +#define ALGO_SHA1_H__ #include diff --git a/include/shell_sort.h b/include/shell_sort.h new file mode 100644 index 00000000..7d9285c2 --- /dev/null +++ b/include/shell_sort.h @@ -0,0 +1,44 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * SHELL SORT + * + * 1. sort array in O(n^(3/2)) time. + * + * https://en.wikipedia.org/wiki/Shellsort + * + ******************************************************************************/ + +#ifndef ALGO_SHELL_SORT_H__ +#define ALGO_SHELL_SORT_H__ + +namespace alg { + /** + * shell sort an array + */ + template + static void shell_sort(T *array, int len) { + int h = 1; + while (h < len / 3) { + h = 3 * h + 1; // 1, 4, 13, 40, 121, ... + } + while (h >= 1) { + for (int i = h; i < len; i++) { + int cur = array[i]; + int j = i - h; + while (j >= 0 && array[j] > cur) { + array[j + h] = array[j]; + j = j - h; + } + array[j + h] = cur; + } + h = h / 3; + } + } +} + +#endif // diff --git a/include/shuffle.h b/include/shuffle.h index fe8b97ab..0bdd69cd 100644 --- a/include/shuffle.h +++ b/include/shuffle.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __SHUFFLE_H__ -#define __SHUFFLE_H__ +#ifndef ALGO_SHUFFLE_H__ +#define ALGO_SHUFFLE_H__ #include #include diff --git a/include/simhash.h b/include/simhash.h index f68e9e58..650af6c2 100644 --- a/include/simhash.h +++ b/include/simhash.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef __SIMHASH_H__ -#define __SIMHASH_H__ +#ifndef ALGO_SIMHASH_H__ +#define ALGO_SIMHASH_H__ #include #include diff --git a/include/skiplist.h b/include/skiplist.h index 1c330ba7..7469511d 100644 --- a/include/skiplist.h +++ b/include/skiplist.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __SKIP_LIST_H__ -#define __SKIP_LIST_H__ +#ifndef ALGO_SKIP_LIST_H__ +#define ALGO_SKIP_LIST_H__ #include #include #include @@ -97,7 +97,7 @@ namespace alg { if(x == NULL || x->key != key) { int lvl = random_level(); // random promotion - // for nodes higer than current max level + // for nodes higher than current max level // make 'header node' as it's prev if(lvl > m_level) { for(int i = m_level + 1; i <= lvl; i++) { diff --git a/include/sol.h b/include/sol.h index 070ee4c5..c8064fc8 100644 --- a/include/sol.h +++ b/include/sol.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef __SOL_H__ -#define __SOL_H__ +#ifndef ALGO_SOL_H__ +#define ALGO_SOL_H__ #include "double_linked_list.h" namespace alg { @@ -26,8 +26,8 @@ namespace alg { */ static inline void list_mtf(struct list_head *entry, struct list_head *head) { if (entry->prev == head) return; - __list_del(entry->prev, entry->next); - __list_add(entry, head, head->next); + list_del_(entry->prev, entry->next); + list_add_(entry, head, head->next); } @@ -38,8 +38,8 @@ namespace alg { // if the entry in the 1st position if (entry->prev == head) return; struct list_head * prev = entry->prev; - __list_del(entry->prev, entry->next); - __list_add(entry, prev->prev, prev); + list_del_(entry->prev, entry->next); + list_add_(entry, prev->prev, prev); } } #endif // diff --git a/include/stack.h b/include/stack.h index acc75414..21ab1159 100644 --- a/include/stack.h +++ b/include/stack.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __STACK_H__ -#define __STACK_H__ +#ifndef ALGO_STACK_H__ +#define ALGO_STACK_H__ #include #include diff --git a/include/suffix_array.h b/include/suffix_array.h index c078bd0a..8c7e11fb 100644 --- a/include/suffix_array.h +++ b/include/suffix_array.h @@ -20,8 +20,8 @@ * AUTHOR: nowerzt@gmail.com ******************************************************************************/ -#ifndef __SUFFIX_ARRAY_H__ -#define __SUFFIX_ARRAY_H__ +#ifndef ALGO_SUFFIX_ARRAY_H__ +#define ALGO_SUFFIX_ARRAY_H__ #include #include @@ -100,4 +100,4 @@ namespace alg { } } -#endif // __SUFFIX_ARRAY_H__ +#endif // ALGO_SUFFIX_ARRAY_H__ diff --git a/include/suffix_tree.h b/include/suffix_tree.h index 23bd04d6..7fd684e6 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -24,15 +24,13 @@ class SuffixTree SuffixTree(string str):test_str(str), root(test_str), active_point(&root, 0, 0), remainder(0), pos(0), active_e(0), ls() {} int construct(void); - // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist + // return -1 if no such sub exist, return the beginning position of this substring in thr original string if it exist int search(string sub); // return the length of the longest prefix of sub which can be matched in suffix tree template Iterator inc_search(Iterator sub) { - typedef typename Iterator::value_type T; // extract real type - Iterator result = sub; Node* node = &root; Edge* edge = NULL; @@ -73,13 +71,7 @@ class SuffixTree return result; } - int print_tree(void); -private: - string test_str; - struct Node; - typedef struct Node Node; - struct Edge{ // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) unsigned int begin, end; @@ -146,7 +138,6 @@ class SuffixTree bool is_none(void) { return begin == 0 && end == 0; } }; - typedef struct Edge Edge; struct Node{ string& test_node_str; @@ -224,10 +215,9 @@ class SuffixTree return os; } }; - //typedef struct Node Node; - - friend struct Node; - + int print_tree(void); +private: + string test_str; class ActivePoint{ public: Node* active_node; @@ -257,7 +247,7 @@ class SuffixTree int remainder; // how many characters inserted? unsigned int pos; - unsigned int active_e; // the beginnig position of suffixes need to be inserted + unsigned int active_e; // the beginning position of suffixes need to be inserted char get_ele(int i) { return test_str[i]; } // insert a char from pos to suffix tree int insert(); @@ -266,7 +256,7 @@ class SuffixTree int print_node(Node* node, int level); - Node* seperate_edge(Node * node, Edge* edge); + Node* separate_edge(Node * node, Edge* edge); // check if we can change active node bool check_active_node(void) diff --git a/include/trie.h b/include/trie.h index c9990f28..0cdba5ef 100644 --- a/include/trie.h +++ b/include/trie.h @@ -10,8 +10,8 @@ * http://en.wikipedia.org/wiki/Trie ******************************************************************************/ -#ifndef __TRIE_H__ -#define __TRIE_H__ +#ifndef ALGO_TRIE_H__ +#define ALGO_TRIE_H__ #include #include #include diff --git a/include/undirected_graph.h b/include/undirected_graph.h index 5570267c..51804de4 100644 --- a/include/undirected_graph.h +++ b/include/undirected_graph.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __UNDIRECTED_GRAPH_H__ -#define __UNDIRECTED_GRAPH_H__ +#ifndef ALGO_UNDIRECTED_GRAPH_H__ +#define ALGO_UNDIRECTED_GRAPH_H__ #include #include diff --git a/include/universal_hash.h b/include/universal_hash.h index 29afcf7d..40c454ce 100644 --- a/include/universal_hash.h +++ b/include/universal_hash.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __UNIVERSAL_HASH_H__ -#define __UNIVERSAL_HASH_H__ +#ifndef ALGO_UNIVERSAL_HASH_H__ +#define ALGO_UNIVERSAL_HASH_H__ #include #include @@ -63,7 +63,7 @@ namespace alg { } /** - * hash an arbitary length integer. + * hash an arbitrary length integer. * len, number of 32-bit integer, max len is 32 */ static uint32_t uhash_bigint(const struct UHash * params, uint32_t * key, uint32_t len) { diff --git a/include/word_seg.h b/include/word_seg.h index eb0f65c7..ed99b763 100644 --- a/include/word_seg.h +++ b/include/word_seg.h @@ -17,8 +17,8 @@ * ******************************************************************************/ -#ifndef __WORD_SEG_H__ -#define __WORD_SEG_H__ +#ifndef ALGO_WORD_SEG_H__ +#define ALGO_WORD_SEG_H__ #include #include diff --git a/msvc/alg_vs.h b/msvc/alg_vs.h index 13b5aa67..ca1d0163 100644 --- a/msvc/alg_vs.h +++ b/msvc/alg_vs.h @@ -1,5 +1,5 @@ -#ifndef __ALGVS_H__ -#define __ALGVS_H__ +#ifndef ALGO_ALGVS_H__ +#define ALGO_ALGVS_H__ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS @@ -15,4 +15,4 @@ #define typeof decltype #endif//_MSC_VER -#endif//__ALGVS_H__ \ No newline at end of file +#endif//ALGO_ALGVS_H__ \ No newline at end of file diff --git a/src/fenwick_tree_demo.cpp b/src/fenwick_tree_demo.cpp new file mode 100644 index 00000000..d5e294de --- /dev/null +++ b/src/fenwick_tree_demo.cpp @@ -0,0 +1,16 @@ +#include +#include "fenwick_tree.h" + +int main() +{ + Fenwick ft(5); + + ft.update(2, 1); + ft.update(4, 10); + + printf("%d\n", ft.rsq(1)); + + ft.update(1, 5); + printf("%d\n", ft.rsq(1)); + return 0; +} \ No newline at end of file diff --git a/src/heap_demo.cpp b/src/heap_demo.cpp index bf761a66..ccae4aea 100644 --- a/src/heap_demo.cpp +++ b/src/heap_demo.cpp @@ -9,20 +9,25 @@ int main() int MAXELEMENTS=10; Heap heap(MAXELEMENTS); - int32_t i; + int i; srand(time(NULL)); for (i=0;i < MAXELEMENTS; i++) { - int32_t value = i; - heap.insert(i, value); - printf("inserting: %d->%d\n", i, value); + heap.push(100-i, i); + printf("push: key:%d->value:%d\n", 100-i, i); } + heap.print_heap(); + + for (i=0;i%d\n", heap.min_key(), heap.min_value()); - heap.delete_min(); + Heap::elem e = heap.pop(); + printf("pop: key:%d->value:%d\n", e.key, e.data); } + heap.print_heap(); return 0; } diff --git a/src/lca_demo.cpp b/src/lca_demo.cpp new file mode 100644 index 00000000..899cc1ba --- /dev/null +++ b/src/lca_demo.cpp @@ -0,0 +1,117 @@ +#include "LCA.h" +#include +#include +#include +/** +*Constructor is initialized with a Adjacency List that +*describe a tree and If It doesn't describe a tree it asserts failure. +*/ + +LCA::LCA(std::vector< std::pair > edges): _numberOfNodes(edges.size() + 1), _maxLog(getMaxLog()) +{ + //First we initialize the needed vectors + parent.resize(_numberOfNodes); + nodeHeight.resize(_numberOfNodes); + visited.resize(_numberOfNodes); + adjList.resize(_numberOfNodes); + binaryLiftDp = std::vector< std::vector >(_numberOfNodes, std::vector(_maxLog)); + /**Construction of the Adjacency List to increase + *The efficiency of the tree traversal to O(V + E). + */ + for(auto edge : edges){ + adjList[edge.first].push_back(edge.second); + adjList[edge.second].push_back(edge.first); + } + //Initialize the Dynamic programming Vector. + initDP(); +} + +/** +*DFS is used to find the parent and the height of each node +*allowing the use of Binary Lifting. +*/ +void LCA::dfs(int currentNode, int currentParent) +{ + visited[currentNode] = true; + parent[currentNode] = currentParent; + nodeHeight[currentNode] = nodeHeight[currentParent] + 1; + int adjacencySize = adjList[currentNode].size(); + for(int idx = 0; idx < adjacencySize; idx++){ + int nextNode = adjList[currentNode][idx]; + if(!visited[nextNode]) + { + dfs(nextNode, currentNode); + } + } +} + +/** +*Used to Calculate the Log to the base of two +*for the number of the nodes to create the sparse table +*used in binary Lifting. +*/ +int LCA::getMaxLog(){ + int curValue = 1; + int curLog = 1; + while(curValue < _numberOfNodes) curValue *= 2, curLog++; + return curLog; +} + +void LCA::initDP() +{ + dfs(0, -1); + for(int i = 0; i < _numberOfNodes; i++) binaryLiftDp[i][0] = parent[i]; + for(int i = 1; i <= _maxLog; i++) + { + for(int j = 0; j < _numberOfNodes; j++) + { + /** + * Since the ith parent of the current node is equal to + * the ith / 2 parent to the ith /2 parent of the current node + * That's why the Recurrence relation is described as follow + */ + if(binaryLiftDp[j][i - 1] != -1) + binaryLiftDp[j][i] = binaryLiftDp[binaryLiftDp[j][i - 1]][i - 1]; + else binaryLiftDp[j][i] = -1; + } + } +} + +int LCA::lcaQuery(int a, int b) +{ + /** + * First Both nodes must have same height + * So we will rise the node with the deeper height up in + * the tree to where they're equal. + */ + if(nodeHeight[a] < nodeHeight[b]) std::swap(a,b); + for(int i = _maxLog; i >= 0; i--) + { + if(binaryLiftDp[a][i] + 1 && nodeHeight[binaryLiftDp[a][i]] >= nodeHeight[b]) + a = binaryLiftDp[a][i]; + } + /** + * If the node Lower is the LCA then return it. + * Else keep moving both nodes up as much as they aren't the same + * until it's only 1 node left which is the direct parent of both of them + */ + if(a == b) return a; + for(int i = _maxLog; i >= 0; i--) + { + if(binaryLiftDp[a][i] + 1 && binaryLiftDp[a][i] - binaryLiftDp[b][i]) + a = binaryLiftDp[a][i], b = binaryLiftDp[b][i]; + } + return parent[a]; +} + +int main(){ + std::vector< std::pair > edges; + edges.push_back({0,1}); + edges.push_back({1,2}); + edges.push_back({2,3}); + edges.push_back({1,4}); + LCA* l = new LCA(v); + std::cout << l->lcaQuery(0,1) << endl; + std::cout << l->lcaQuery(3,4) << endl; + std::cout << l->lcaQuery(3,2) << endl; +} diff --git a/src/lcs_demo.cpp b/src/lcs_demo.cpp index 838c5d4b..71c2db20 100644 --- a/src/lcs_demo.cpp +++ b/src/lcs_demo.cpp @@ -6,9 +6,9 @@ #define printlistC(list,n) \ do { \ - int __list_counter; \ - for(__list_counter=0;__list_counter +#include #include "random.h" int main(void) { - printf("generate random numbers\n"); + std::cout <<"generate random numbers\n"; for (int i=0;i<100;i++) { - printf("%u\n",alg::LCG()); + std::cout< -#include +#include +#include #include #include "generic.h" -#include "heap_sort.h" +#include "shell_sort.h" using namespace alg; @@ -22,13 +22,11 @@ int main() printf("The list before sorting is:\n"); printlist(list,MAX_ELEMENTS); - // sort the list using heap sort - heapsort(&list[0],MAX_ELEMENTS); + // sort the list using shell sort + shell_sort(&list[0],MAX_ELEMENTS); // print the result - printf("The list after sorting using heapsort algorithm:\n"); + printf("The list after sorting using shell sort algorithm:\n"); printlist(list,MAX_ELEMENTS); return 0; } - - diff --git a/src/suffix_tree_demo.cpp b/src/suffix_tree_demo.cpp index 8862e9b2..4a5170b5 100644 --- a/src/suffix_tree_demo.cpp +++ b/src/suffix_tree_demo.cpp @@ -82,7 +82,7 @@ int SuffixTree::construct(void) ls.ins_link(node); break; } - Node *newnode = seperate_edge(node, a_edge); + Node *newnode = separate_edge(node, a_edge); Edge* newedge = new Edge(pos, numeric_limits::max(), test_str); newnode->add_edge(newedge); ls.ins_link(newnode); @@ -104,9 +104,9 @@ int SuffixTree::construct(void) return 0; } -SuffixTree::Node* SuffixTree::seperate_edge(Node * node, Edge* a_edge) +SuffixTree::Node* SuffixTree::separate_edge(Node * node, Edge* a_edge) { - cout << "seperate the old edge here: " << (*a_edge) << endl; + cout << "separate the old edge here: " << (*a_edge) << endl; int new_begin = a_edge->begin + get_active_length(); int new_end = a_edge->end; @@ -175,7 +175,7 @@ using namespace std; int main() { - cout << "Begining" << endl; + cout << "Beginning" << endl; SuffixTree st("mississippi"); cout << "Constructing..." << endl; diff --git a/utils/byteorder.h b/utils/byteorder.h index ca2fada9..b54222df 100644 --- a/utils/byteorder.h +++ b/utils/byteorder.h @@ -1,5 +1,5 @@ -#ifndef __BYTEORDER_H__ -#define __BYTEORDER_H__ +#ifndef ALGO_BYTEORDER_H__ +#define ALGO_BYTEORDER_H__ #include #include diff --git a/utils/gb18030.h b/utils/gb18030.h index 88d28e85..5da8c9f3 100644 --- a/utils/gb18030.h +++ b/utils/gb18030.h @@ -1,5 +1,5 @@ -#ifndef __GB18030_H__ -#define __GB18030_H__ +#ifndef ALGO_GB18030_H__ +#define ALGO_GB18030_H__ /** * Read from the string encoded in GB18030 into WORD