diff --git a/.travis.yml b/.travis.yml index e4d9ce7f..8226360b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,5 @@ language: cpp - compiler: - - gcc - clang - script: - make diff --git a/Makefile b/Makefile index c0c50190..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 @@ -263,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 d9b7eb9f..91d25f57 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ -###Algorithms & Data Structures in C++ +### Algorithms & Data Structures in C++ + [![Build Status][1]][2] -[1]: https://travis-ci.org/xtaci/algorithms.svg?branch=master -[2]: https://travis-ci.org/xtaci/algorithms -####目标 ( goal ) : +[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) @@ -12,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. ) @@ -24,79 +26,73 @@ eg: ![demograph](demo_graph.png) -####已实现 ( Implemented ): - - Array shuffle - Prime test(trial division) - Prime test(Miller-Rabin's method) - 2D Array - Arbitrary 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 - Shell sort - Radix sort - Quick sort - Merge sort - Double linked list - Skip list - Self-organized linked-list ops (move-to-front, move-ahead-one) - Largest common sequence +#### 已实现 ( Implemented ): - Binary search tree - AVL tree - Dynamic order statistics - Red-black tree - Interval tree - Prefix Tree(Trie) - Suffix Tree - B-Tree - Suffix Array +| 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| - 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 - - 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 - -####贡献者 ( Contributors ) : +#### 贡献者 ( Contributors ) : Samana: for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST @@ -104,7 +100,3 @@ ZhangYou0122: Push-Relabel algorithm, Suffix Tree UsingtcNower: Suffix Array afernandez90: AVL trees - -####支持此项目 ( Donations ) : -![donate](donate_alg.png) -欢迎使用支付宝扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化补全及完善。 diff --git a/include/.goutputstream-UUQE8X b/include/.goutputstream-UUQE8X deleted file mode 100644 index e92d1ab5..00000000 --- a/include/.goutputstream-UUQE8X +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * 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 __FENWICK_H__ -#define __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/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/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; +}