diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0a1b001d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.dSYM +*_demo 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 beaa08cd..82f536a5 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,29 @@ .PHONY: all clean -CC=gcc -CPP=g++ +CC=clang +CPP=clang++ AR=ar RANLIB=ranlib -CFLAGS= -O2 -Wall -Wno-unused-function +CFLAGS= -g -Wall -Wno-unused-function +C11FLAGS= -g -Wall -Wno-unused-function -std=c++11 SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = LIBS = -lm -PROGRAMS = m_based \ + +PROGRAMS = m_based_demo \ integer_demo \ - insertion_sort_demo \ - radix_sort_demo \ - shuffle_demo \ - quick_sort_demo \ - merge_sort_demo \ - random_select_demo \ - hash_multi_demo \ - hash_table_demo \ - double_linked_list_demo \ - stack_demo \ - queue_demo \ - priority_queue_demo \ - prime_test \ + insertion_sort_demo \ + shell_sort_demo \ + radix_sort_demo \ + shuffle_demo \ + quick_sort_demo \ + merge_sort_demo \ + random_select_demo \ + hash_multi_demo \ + hash_table_demo \ + double_linked_list_demo \ + stack_demo \ + queue_demo \ universal_hash_demo \ perfect_hash_demo \ binary_search_tree_demo \ @@ -30,7 +31,7 @@ PROGRAMS = m_based \ heap_demo \ interval_tree_demo \ dos_tree_demo \ - skip_list_demo \ + skiplist_demo \ lcs_demo \ prim_mst_demo \ directed_graph_demo \ @@ -53,13 +54,214 @@ PROGRAMS = m_based \ random_demo \ k-means_demo \ kmp_demo \ - heap_sort_demo \ - kruskal_mst_demo + LRU_cache_demo \ + base64_demo \ + max_subarray_demo \ + disjoint-set_demo \ + relabel_to_front_demo \ + btree_demo \ + sort_demo \ + fib-heap_demo \ + scc_demo \ + sort_demo \ + bubble_sort_demo \ + selection_sort_demo \ + 8queue_demo \ + palindrome_demo \ + suffix_tree_demo \ + avl_demo all: $(PROGRAMS) -%: $(SRCDIR)/%.cpp $(DEPS) - $(CPP) $(CFLAGS) -o $@ $< $(INCLUDEDIR) $(LIBS) +m_based_demo: $(SRCDIR)/m_based_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +integer_demo: $(SRCDIR)/integer_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +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) + +shuffle_demo: $(SRCDIR)/shuffle_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +quick_sort_demo: $(SRCDIR)/quick_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +merge_sort_demo: $(SRCDIR)/merge_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +random_select_demo: $(SRCDIR)/random_select_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +hash_multi_demo: $(SRCDIR)/hash_multi_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +hash_table_demo: $(SRCDIR)/hash_table_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +double_linked_list_demo: $(SRCDIR)/double_linked_list_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +stack_demo: $(SRCDIR)/stack_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +queue_demo: $(SRCDIR)/queue_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +priority_queue_demo: $(SRCDIR)/priority_queue_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +prime_demo: $(SRCDIR)/prime_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +universal_hash_demo: $(SRCDIR)/universal_hash_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +perfect_hash_demo: $(SRCDIR)/perfect_hash_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +binary_search_tree_demo: $(SRCDIR)/binary_search_tree_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +rbtree_demo: $(SRCDIR)/rbtree_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +heap_demo: $(SRCDIR)/heap_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +interval_tree_demo: $(SRCDIR)/interval_tree_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +dos_tree_demo: $(SRCDIR)/dos_tree_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +skiplist_demo: $(SRCDIR)/skiplist_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +lcs_demo: $(SRCDIR)/lcs_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +prim_mst_demo: $(SRCDIR)/prim_mst_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +directed_graph_demo: $(SRCDIR)/directed_graph_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +undirected_graph_demo: $(SRCDIR)/undirected_graph_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +dijkstra_demo: $(SRCDIR)/dijkstra_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +bellman_ford_demo: $(SRCDIR)/bellman_ford_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +graph_search_demo: $(SRCDIR)/graph_search_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +edmonds_karp_demo: $(SRCDIR)/edmonds_karp_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +astar_demo: $(SRCDIR)/astar_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +hash_string_demo: $(SRCDIR)/hash_string_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +bitset_demo: $(SRCDIR)/bitset_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +bloom_filter_demo: $(SRCDIR)/bloom_filter_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +sha1_demo: $(SRCDIR)/sha1_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +huffman_demo: $(SRCDIR)/huffman_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +word_seg_demo: $(SRCDIR)/word_seg_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +md5_demo: $(SRCDIR)/md5_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +trie_demo: $(SRCDIR)/trie_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +simhash_demo: $(SRCDIR)/simhash_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +imath_demo: $(SRCDIR)/imath_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +random_demo: $(SRCDIR)/random_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +k-means_demo: $(SRCDIR)/k-means_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +kmp_demo : $(SRCDIR)/kmp_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +kruskal_mst_demo: $(SRCDIR)/kruskal_mst_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +LRU_cache_demo: $(SRCDIR)/LRU_cache_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +base64_demo: $(SRCDIR)/base64_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +max_subarray_demo: $(SRCDIR)/max_subarray_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +disjoint-set_demo: $(SRCDIR)/disjoint-set_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +relabel_to_front_demo: $(SRCDIR)/relabel_to_front_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +btree_demo: $(SRCDIR)/btree_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +sort_demo: $(SRCDIR)/sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +fib-heap_demo: $(SRCDIR)/fib-heap_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +scc_demo: $(SRCDIR)/scc_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +bubble_sort_demo: $(SRCDIR)/bubble_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +selection_sort_demo: $(SRCDIR)/selection_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +8queue_demo: $(SRCDIR)/8queue_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +palindrome_demo: $(SRCDIR)/palindrome_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +suffix_tree_demo: $(SRCDIR)/suffix_tree_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +avl_demo: $(SRCDIR)/avl_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +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 5c137574..91d25f57 100644 --- a/README.md +++ b/README.md @@ -1,81 +1,102 @@ -###Algorithms & Data Structures in C++ +### Algorithms & Data Structures in C++ -####目标 ( goal ) : +[![Build Status][1]][2] - 经典的算法实现 - (classical algorithms implementations) - 服务器端 - (based on linux/gcc) - 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. - (corret! and ease of use, one .header file per algorithm) +[1]: https://img.shields.io/github/created-at/xtaci/algorithms +[2]: https://img.shields.io/github/created-at/xtaci/algorithms -####约定 ( Convention ): +#### 目标 ( goal ) : - 1. 一个算法用一个.h文件表示放到include下. ( one .header file per algorithm. ) - 2. 算法演示的demo程序放到src下. ( one demo per algorithm. ) - 3. 程序正确通过后,请发起Pull Requests,代码被验证后入库,并在README中发布新算法实现。 - (Please Use Fork+Pull Requests !!! Correctness is the most important!) + 1. 经典的算法实现 + (classical algorithms implementations) + 2. 服务器端 + (based on linux/gcc) + 3. 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. + (correct! and ease of use, one .header file per algorithm) -####已实现 ( Implemented ): +#### 约定 ( Convention ): - Array shuffle - Prime test(trial division) - Prime test(Miller-Rabin's method) - 2D Array - Arbitary Integer - Linear congruential generator + 1. 一个算法用一个.h文件表示放到include下. ( one .header file per algorithm. ) + 2. 算法演示的demo程序放到src下. ( one demo per algorithm. ) + 3. 程序正确通过后,请发起Pull Requests,代码被验证后入库,并在README中发布新算法实现。 + (Please Use Fork+Pull Requests !!! Correctness is the most important!) + 4. TAB = 4 space. set ts=4 in vim + 5. Graph的输出格式为 [Graphviz](http://www.graphviz.org/) Dot格式. + (the output format of the graph is in dot of graphviz.) + eg: + ![demograph](demo_graph.png) - Bit-Set data structure - Queue data structure - Stack data structure - Binary heap data structure - Priority queue +#### 已实现 ( Implemented ): - 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 +| 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| - Binary search tree - Dynamic order statistics - Red-black tree - Interval tree - Prefix Tree(Trie) - *Suffix Tree(未实现)* - - 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 - - Graph data structure - 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 - - Huffman Coding - Word segementation(CHN/GB18030) using HMM and viterbi algorithm. - A* algorithm - K-Means - Knuth–Morris–Pratt algorithm - -####贡献者 ( Contributors ) : - Samana : for heavy work of MSVC compatability +#### 贡献者 ( Contributors ) : + Samana: for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST + wyh267: for base64, LRU, bubble sort, selection sort + ZhangYou0122: Push-Relabel algorithm, Suffix Tree + UsingtcNower: Suffix Array + afernandez90: AVL trees diff --git a/demo_graph.png b/demo_graph.png new file mode 100644 index 00000000..86c8ac97 Binary files /dev/null and b/demo_graph.png differ 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 2fb0b999..2a565810 100644 --- a/include/2darray.h +++ b/include/2darray.h @@ -10,76 +10,72 @@ * 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 -namespace alg -{ +namespace alg { /** * 2D Array definition */ template - class Array2D - { - private: - uint32_t NR; // num of rows - uint32_t NC; // num of columns - T * m_data; // the place where the array resides. + class Array2D { + private: + uint32_t NR; // num of rows + uint32_t NC; // num of columns + T * m_data; // the place where the array resides. - public: - /** - * construct an array of size [nrow,col] - */ - Array2D(uint32_t nrow, uint32_t ncol) { - NR = nrow; - NC = ncol; - m_data = new T[nrow*ncol]; - } - - /** - * destructor - */ - ~Array2D() { - delete [] m_data; - } + public: + /** + * construct an array of size [nrow,col] + */ + Array2D(uint32_t nrow, uint32_t ncol) { + NR = nrow; + NC = ncol; + m_data = new T[nrow*ncol]; + } - private: - Array2D(const Array2D&); - Array2D& operator=(const Array2D&); + /** + * destructor + */ + ~Array2D() { + delete [] m_data; + } - public: + private: + Array2D(const Array2D&); + Array2D& operator=(const Array2D&); - /** - * return number of rows of this array - */ - inline const uint32_t row() const { return NR; } - /** - * return number of columns of this array - */ - inline const uint32_t col() const { return NC; } + public: - /** - * return the value by the given (row, col); - */ - inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; } - const inline T& operator() (int row, int col) const { return this->m_data[row*NC + col]; } + /** + * return number of rows of this array + */ + inline const uint32_t row() const { return NR; } + /** + * return number of columns of this array + */ + inline const uint32_t col() const { return NC; } - inline T* operator[] (int row) { return &(m_data[row * NC]); } - inline const T* operator[] (int row) const { return &(m_data[row * NC]); } + /** + * return the value by the given (row, col); + */ + inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; } + const inline T& operator() (int row, int col) const { return this->m_data[row*NC + col]; } - /** - * clear the array by a given value - */ - void clear(const T & value) - { - for(uint32_t i=0; i + * _| + * 8-Queue + * + * http://en.wikipedia.org/wiki/Eight_queens_puzzle + ******************************************************************************/ + +#ifndef ALGO_8QUEEN_H__ +#define ALGO_8QUEEN_H__ + +#include +#include + +namespace alg { + class Queen8 { + private: + char board[8][8]; + int cnt; + public: + void solve() { + memset(board, '0', sizeof(board)); + cnt = 0; + _solve(0); + } + private: + void _solve(int row) { // start from 0 + int i; + for (i=0;i<8;i++) { + board[row][i] = '1'; + if (check(row, i)) { + if (row == 7) print(); + else _solve(row+1); + } + board[row][i] = '0'; // rollback + } + } + + void print() { + printf("chessboard: %d\n",++cnt); + int i,j; + for (i=0;i<8;i++) { + for (j=0;j<8;j++) { + printf("%c ", board[i][j]); + } + printf("\n"); + } + } + + bool check(int row, int col) { + int i,j; + + // cannot be same column + for (i=0;i=0 && j >=0) { + if (board[i][j] == '1') { + return false; + } + i--; + j--; + } + + i = row-1, j = col+1; + while (i>=0 && j <8) { + if (board[i][j] == '1') { + return false; + } + i--; + j++; + } + + return true; + } + }; +} + +#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/LRU_cache.h b/include/LRU_cache.h new file mode 100644 index 00000000..c5cc43ce --- /dev/null +++ b/include/LRU_cache.h @@ -0,0 +1,159 @@ +/******************************************************************************* + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * Least Recently Used (LRU): + * discards the least recently used items first. This algorithm requires + * keeping track of what was used when, which is expensive if one wants to make + * sure the algorithm always discards the least recently used item. General + * implementations of this technique require keeping "age bits" for cache-lines + * and track the "Least Recently Used" cache-line based on age-bits. In such an + * implementation, every time a cache-line is used, + * the age of all other cache-lines changes + * + * We use this double list to store the cache like this: + * + * NodeHead <==> Node1 <==> Node2 <==> ... ... <==> NodeN <==>NodeNear + * + * the "NodeHead" and "NodeNear" have no data , them just for head and near. + * + * Two Interface: + * getValue : get the value by key ,and put the Node to first + * putValue : add or update the Node's Key and Value, and then, + * put the Node to first + * + * http://en.wikipedia.org/wiki/LRU_cache#Least_Recently_Used + * + ******************************************************************************/ + +#ifndef _LRUCACHE_ +#define _LRUCACHE_ + +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace alg { + template + class LRUCache { + typedef struct _Node_{ + K key; + V value; + + struct _Node_ *next; + struct _Node_ *pre; + } CacheNode; + + public: + LRUCache(int cache_size=10) { + cache_size_ = cache_size; + p_cache_list_head = new CacheNode(); + p_cache_list_near = new CacheNode(); + p_cache_list_head->next = p_cache_list_near; + p_cache_list_head->pre = NULL; + p_cache_list_near->pre = p_cache_list_head; + p_cache_list_near->next = NULL; + } + + ~LRUCache() { + CacheNode *p; + p = p_cache_list_head->next; + while(p!=NULL) { + delete p->pre; + p=p->next; + } + + delete p_cache_list_near; + cache_hash.clear(); + } + + V getValue(K key) { + //put the value in front of the list if find the key + if(cache_hash.find(key) != cache_hash.end()){ + CacheNode *p=cache_hash[key]; + detachNode(p); + addFristNode(p); + return (cache_hash[key]->value); + }else{ + + cout << "[ERROR]No key with name ::" << key << endl; + return V(); + } + + } + + bool putValue(K key,V value) { + if (cache_hash.find(key) != cache_hash.end()) { + cache_hash[key]->value=value; + detachNode((CacheNode *)cache_hash[key]); + addFristNode((CacheNode *)cache_hash[key]); + if (cache_hash.size()>cache_size_) { + delEndNode(); + } + } else { + CacheNode *p=new CacheNode(); + p->key=key; + p->value=value; + addFristNode(p); + cache_hash[key]=p; + if(cache_hash.size()>cache_size_){ + cout << "[INFO]LRU Cache is full ... Delete Last One..." << endl; + delEndNode(); + } + } + + return true; + } + + void display(){ + CacheNode *p=p_cache_list_head->next; + while(p->next!=NULL) { + std::cout << " KEY[" << p->key << "]<==>VALUE[" << p->value <<"]" << std::endl; + p=p->next; + } + std::cout << std::endl; + } + + private: + int cache_size_; + CacheNode *p_cache_list_head; + CacheNode *p_cache_list_near; + mapcache_hash; + + + void detachNode(CacheNode *node){ + node->pre->next=node->next; + node->next->pre=node->pre; + } + + void addFristNode(CacheNode *node){ + node->pre=p_cache_list_head; + if(cache_hash.empty()) { + node->next=p_cache_list_near; + p_cache_list_near->pre=node; + p_cache_list_head->next=node; + } else { + node->next=p_cache_list_head->next; + p_cache_list_head->next->pre=node; + p_cache_list_head->next=node; + } + } + + void delEndNode(){ + CacheNode *p=p_cache_list_near->pre; + detachNode(p); + cout << "[INFO]Delete key ::: " << p->key <key); + free(p); + } + }; +} + +#endif diff --git a/include/astar.h b/include/astar.h index d376546e..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 @@ -30,138 +30,164 @@ #include "hash_table.h" #include "2darray.h" -namespace alg -{ - class AStar - { - public: - /** - * A-Star algorithm result; - */ - struct AStarResult { - int * path; // the path format: - // [X1Y1X2Y2X3Y3.....XnYnX1Y1] - // interleaving X,Y coordinate - int num_nodes; - ~AStarResult() - { - delete [] path; - path = NULL; - } - }; - - static const unsigned char WALL = 0xFF; - static const float SQRT2 = 1.414213562373095; - - private: - const Array2D & m_grid; - // The set of nodes already evaluated. - Array2D m_closedset; - // Cost from start along best known path. - Array2D g_score; - // Estimated total cost from start to goal through y. - Array2D f_score; - public: - AStar(const Array2D & grid) : +namespace alg { + class AStar { + public: + /** + * A-Star algorithm result; + */ + struct AStarResult { + int * path; // the path format: + // [X1Y1X2Y2X3Y3.....XnYnX1Y1] + // interleaving X,Y coordinate + int num_nodes; + ~AStarResult() + { + delete [] path; + path = NULL; + } + }; + + static const unsigned char WALL = 0xFF; + + private: + const Array2D & m_grid; + // the openset + Heap m_openset; + // The set of nodes open -- for fast testing of a point in openset. heap contains test is quite slow -- O(n) + Array2D m_openset_grid; + // The set of nodes already evaluated. + Array2D m_closedset; + // Cost from start along best known path. + Array2D g_score; + // Estimated total cost from start to goal through y. + Array2D f_score; + public: + AStar(const Array2D & grid) : m_grid(grid), + m_openset(grid.row()*grid.col()), + m_openset_grid(grid.row(),grid.col()), m_closedset(grid.row(),grid.col()), g_score(grid.row(),grid.col()), - f_score(grid.row(),grid.col()) { } - - /** - * the A* algorithm - * search a path from (x1,y1) to (x2,y2) - * a integer representing path is returned, you should delete it after. - */ - AStarResult * run(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2) - { - uint32_t nrow = m_grid.row(); - uint32_t ncol = m_grid.col(); - m_closedset.clear(false); - - // the set of tentavie nodes to be evaluated, - // initialy containing the start node - // encoding [x,y] to [x*ncol + y] - // using binary heap ... - Heap openset(nrow*ncol); - openset.insert(0, x1*ncol+y1); - - // The map of navigated nodes. - HashTable came_from(nrow*ncol); - - g_score(x1,y1) = 0.0f; - f_score(x1,y1) = g_score(x1,y1) + estimate(x1,y1,x2,y2); - - AStarResult * as = new AStarResult; - as->path = NULL; - as->num_nodes = 0; - - while(!openset.is_empty()) { - uint32_t value = openset.min_value(); - int cx = value/ncol; - int cy = value%ncol; - - if(cx == (int)x2 && cy==(int)y2) { // we reached (x2,y2) - // reconstruct path & return - uint32_t tmp = x2*ncol+y2; - while((tmp=came_from[tmp]) != x1*ncol+y1) { - as->num_nodes++; - } - - as->path = new int[2*as->num_nodes]; + f_score(grid.row(),grid.col()) { + m_openset_grid.clear(false); + m_closedset.clear(false); + } - tmp = x2*ncol+y2; - int idx=0; - while((tmp=came_from[tmp]) != x1*ncol+y1) { - as->path[idx++] = tmp/ncol; - as->path[idx++] = tmp%ncol; - } - return as; + /** + * the A* algorithm + * search a path from (x1,y1) to (x2,y2) + * a integer representing path is returned, you should delete it after. + */ + AStarResult * run(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2) { + static float SQRT2 = 1.414213562373095; + uint32_t nrow = m_grid.row(); + uint32_t ncol = m_grid.col(); + + // test wheather the (x1, y1) is the wall, we don't do stupid searching. + if (m_grid(x1, y1) == WALL) { + return NULL; } - openset.delete_min(); - m_closedset(cx, cy) = true; - - // for each neighbor - int nx, ny; - for(nx=cx-1;nx<=cx+1;nx++) { - if (nx<0 || nx>=(int)ncol) continue; - for(ny=cy-1;ny<=cy+1;ny++) { - if (ny<0 || ny>=(int)nrow) continue; - - // except the wall; - if(m_grid(nx,ny) == WALL) continue; - // except the cur itself - if(nx == cx && ny==cy) continue; - // if neighbour in the closed set - if(m_closedset(nx,ny)) continue; - - float tentative = g_score(cx,cy); - if (nx == cx || ny == cy) { - tentative += 1; - } else { - tentative += SQRT2; + // the set of tentavie nodes to be evaluated, + // initialy containing the start node + // encoding [x,y] to [x*ncol + y] + // using binary heap ... + m_openset.push(0, x1*ncol+y1); + // record the starting point in openset_grid + m_openset_grid(x1,y1) = true; + + // The map of navigated nodes. + HashTable came_from(nrow*ncol); + + g_score(x1,y1) = 0.0f; + f_score(x1,y1) = g_score(x1,y1) + estimate(x1,y1,x2,y2); + + AStarResult * as = new AStarResult; + as->path = NULL; + as->num_nodes = 0; + + // the main A*algorithm + while(!m_openset.is_empty()) { + Heap::elem e = m_openset.pop(); + uint32_t value = e.data; + int cx = value/ncol; + int cy = value%ncol; + + if(cx == (int)x2 && cy==(int)y2) { // great! we've reached the target position (x2,y2) + // reconstruct path + as->num_nodes = 2; + uint32_t tmp = x2*ncol+y2; + while((tmp=came_from[tmp]) != x1*ncol+y1) { + as->num_nodes++; } - - // if neighbour not in the openset or dist < g_score[neighbour] - if (!openset.contains(nx*ncol+ny) || tentative < g_score(nx,ny)) { - came_from[nx*ncol+ny] = cx*ncol+cy; // record path - g_score(nx,ny) = tentative; - f_score(nx,ny) = tentative + estimate(nx,ny,x2,y2); - if (!openset.contains(nx*ncol+ny)) { - openset.insert(f_score(nx,ny), nx*ncol+ny); + + as->path = new int[2*as->num_nodes]; + + tmp = x2*ncol+y2; + int idx=0; + as->path[idx++] = x2; + as->path[idx++] = y2; + while((tmp=came_from[tmp]) != x1*ncol+y1) { + as->path[idx++] = tmp/ncol; + as->path[idx++] = tmp%ncol; + } + as->path[idx++] = x1; + as->path[idx++] = y1; + return as; + } + + // move it into closed set. + m_closedset(cx, cy) = true; + m_openset_grid(cx, cy) = false; + + // for each valid neighbor of current position + int nx, ny; + for(nx=cx-1;nx<=cx+1;nx++) { + for(ny=cy-1;ny<=cy+1;ny++) { + // exclude invalid position + if (nx<0 || nx>=(int)ncol || ny<0 || ny>=(int)nrow) continue; + // except the cur itself + if(nx == cx && ny==cy) continue; + // except the wall; + if(m_grid(nx,ny) == WALL) continue; + // exclude the neighbour in the closed set + if(m_closedset(nx,ny)) continue; + + // ok, we got a valid neighbour + float tentative = g_score(cx,cy); + if (nx == cx || ny == cy) { // horizontal/vertical neighbour is near + tentative += 1; + } else { // diagonal neighbour is farther. + tentative += SQRT2; + } + + // if neighbour not in the openset or dist < g_score[neighbour] + if (!m_openset_grid(nx,ny) || tentative < g_score(nx,ny)) { + came_from[nx*ncol+ny] = cx*ncol+cy; // record the path + 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.push(f_score(nx,ny), nx*ncol+ny); + m_openset_grid(nx,ny) = true; + } } } } } + + // haven't reached target + return as; + } + private: + /** + * Estimate the cost for going this way, such as: + * acrossing the swamp will be much slower than walking on the road. + * design for you game. + */ + inline float estimate(int x1, int y1, int x2, int y2) const { + return sqrtf((x2-x1) * (x2-x1) + (y2-y1)*(y2-y1)); } - return as; - } - private: - inline float estimate(int x1, int y1, int x2, int y2) const - { - return sqrtf((x2-x1) * (x2-x1) + (y2-y1)*(y2-y1)); - } }; } diff --git a/include/avl.h b/include/avl.h new file mode 100644 index 00000000..697317ab --- /dev/null +++ b/include/avl.h @@ -0,0 +1,243 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * Adelson-Velskii and Landis' (AVL) tree + * + * Features, being N the number of elements in the tree: + * 1. Guaranteed search time is O(log(N)). + * 2. Dynamically updated/balanced tree structure O(N) storage. + * 3. Exportable to GraphViz format for easy visualization and verification + * + * http://en.wikipedia.org/wiki/AVL_tree + * + * @author Alejandro Fernandez (alejandro.fernandez.suarez@gmail.com) + * @github afernandez90 + * + ******************************************************************************/ + +#ifndef ALGO_AVL_H__ +#define ALGO_AVL_H__ + +#include +#include +#include +#include +#include + +namespace alg { + +template +class AVL { + + public: + + AVL() : tree(0), numNodes(0) {} + + T root () const { return tree->value; } + unsigned height() const { return Node::getHeight(tree); } + unsigned size() const { return numNodes; } + bool isEmpty() const { return numNodes == 0; } + + bool contains(const T &x) const { + if (!isEmpty()) { + return tree->contains(x); + } else return false; + } + + void insert(const T &x) { + if (isEmpty()) tree = new Node(x); + else tree = tree->insert(x); + numNodes++; + } + + void erase(const T &x) { + if (!isEmpty()) { + bool found = false; + tree = tree->erase(x, found); + if (found) numNodes--; + } + } + + void toGraphViz(std::ostream &stream, std::string name) const { + if (!isEmpty()) { + stream << "digraph " << name << " {" << std::endl; + tree->toGraphViz(stream); + stream << "}" << std::endl; + } + } + + public: + + struct Node { + Node *left, *right; + T value; + unsigned height; + + Node(const T &x) : left(0), right(0), value(x), height(1) {} + + bool contains(const T &x) const { + if (value == x) return true; + else if (x < value && left != 0) return left->contains(x); + else if (right != 0) return right->contains(x); + else return false; + } + + Node *insert(const T &x) { + if (x <= value) { + if (left == 0) left = new Node(x); + else left = left->insert(x); + } + else { + if (right == 0) right = new Node(x); + else right = right->insert(x); + } + + return update(); + } + + Node *erase(const T &x, bool &found) { + if (value == x) { + found = true; + if (left == 0 && right == 0) { + delete this; + return 0; + } else if (left == 0) { + Node *aux = right; + *this = *right; + delete aux; + } else if (right == 0) { + Node *aux = left; + *this = *left; + delete aux; + } else { + // Tracing path to rightmost leaf of the left subtree + std::stack trace; + + Node *current = left; + while (current != 0) { + trace.push(current); + current = current->right; + } + + current = trace.top(); + value = current->value; + Node *lsubtree = current->left; + delete current; + trace.pop(); + + if (trace.empty()) { left = lsubtree; } + else { + trace.top()->right = lsubtree; + trace.pop(); + while (!trace.empty()) { + current = trace.top(); + current->right = current->right->update(); + trace.pop(); + } + } + } + return update(); + } + else if (x < value) { + if (left != 0) { + left = left->erase(x, found); + return update(); + } else return this; + } + else { + if (right != 0) { + right = right->erase(x, found); + return update(); + } else return this; + } + } + + Node *update() { + updateHeight(); + + if (getBF(this) >= 2) { + if (getBF(left) <= -1) LR(); + return LL(); + } else if (getBF(this) <= -2) { + if (getBF(right) >= 1) RL(); + return RR(); + } else return this; + } + + void updateHeight() { height = std::max(getHeight(left), getHeight(right)) + 1; } + + void LR() { + Node *lrcopy = left->right; + left->right = lrcopy->left; + lrcopy->left = left; + left = lrcopy; + left->left->updateHeight(); + left->updateHeight(); + updateHeight(); + } + + void RL() { + Node *rlcopy = right->left; + right->left = rlcopy->right; + rlcopy->right = right; + right = rlcopy; + right->right->updateHeight(); + right->updateHeight(); + updateHeight(); + } + + Node *LL() { + Node *lcopy = left; + left = left->right; + lcopy->right = this; + lcopy->left->updateHeight(); + lcopy->right->updateHeight(); + lcopy->updateHeight(); + return lcopy; + } + + Node *RR() { + Node *rcopy = right; + right = right->left; + rcopy->left = this; + rcopy->left->updateHeight(); + rcopy->right->updateHeight(); + rcopy->updateHeight(); + return rcopy; + } + + static int getBF(const Node *t) { + return getHeight(t->left) - getHeight(t->right); + } + + static int getHeight(const Node *t) { + return t == 0 ? 0 : t->height; + } + + void toGraphViz(std::ostream &stream) const { + stream << value << ";" << std::endl; + if (left != 0) { + stream << left->value << ";" << std::endl; + stream << value << "->" << left->value << ";" << std::endl; + left->toGraphViz(stream); + } + if (right != 0) { + stream << right->value << ";" << std::endl; + stream << value << "->" << right->value << ";" << std::endl; + right->toGraphViz(stream); + } + } + }; + + Node *tree; + unsigned numNodes; +}; + +} // namespace alg + +#endif // _ALG_AVL_HPP + diff --git a/include/base64.h b/include/base64.h new file mode 100644 index 00000000..c3e89e1d --- /dev/null +++ b/include/base64.h @@ -0,0 +1,111 @@ +/******************************************************************************* + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * Base64 + * Base64 is a group of similar binary-to-text encoding schemes that represent + * binary data in an ASCII string format by translating it into a radix-64 + * representation. The term Base64 originates from a specific MIME content + * transfer encoding. + * + * http://en.wikipedia.org/wiki/Base64 + ******************************************************************************/ + +#ifndef _CBASE64_H_ +#define _CBASE64_H_ + + +#include +#include +#include + +namespace alg { + class CBase64 { + public: + static std::string encodeBase64(unsigned char *input , int input_len) { + const char * code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned char input_char[3]; + char output_char[5]; + int output_num; + std::string output_str=""; + int near=input_len%3; + + for (int i=0;i>18) & 0xff)]; + output_char[1]=code[((output_num>>12) & 0x3f)]; + output_char[2]='='; + output_char[3]='='; + output_char[4]='\0'; + } + + if (near==2) { + output_char[0]=code[((output_num>>18) & 0xff)]; + output_char[1]=code[((output_num>>12) & 0x3f)]; + output_char[2]=code[((output_num>>6) & 0x3f)];; + output_char[3]='='; + output_char[4]='\0'; + } + + output_str.append(output_char); + break; + } + + output_num=((int)input_char[0]<<16)+((int)input_char[1]<<8)+(int)input_char[2]; + output_char[0]=code[((output_num>>18) & 0xff)]; + output_char[1]=code[((output_num>>12) & 0x3f)]; + output_char[2]=code[((output_num>>6) & 0x3f)]; + output_char[3]=code[((output_num) & 0x3f)]; + output_char[4]='\0'; + output_str.append(output_char); + } + + return output_str; + } + + static std::string decodeBase64(std::string input) { + unsigned char input_char[4]; + unsigned char output_char[4]; + int output_num=0; + int k=0; + std::string output_str=""; + + for (unsigned int i=0;i> 16) ; + output_char[1]=(unsigned char)((output_num & 0x0000FF00 ) >> 8) ; + output_char[2]=(unsigned char)(output_num & 0x000000FF) ; + output_char[3]='\0'; + output_str.append((char *)output_char); + k=0; + } + } + + return output_str; + } + + static int indexOfCode(const char c) { + const char * code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (unsigned int i=0;i<64;i++) { + if (code[i]==c) + return i; + } + return 0; + } + }; +} + +#endif diff --git a/include/bellman_ford.h b/include/bellman_ford.h index 13d42a30..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 @@ -59,78 +59,73 @@ // define UNDEFINED previous vertex. #define UNDEFINED -1 -namespace alg -{ - - class BellmanFord - { - private: - HashTable dist; // hash table for distance. - bool has_neg_cycle; // negative weighted cycle mark. - const Graph & g; - public: - BellmanFord(const Graph & graph): - dist(graph.vertex_count()),g(graph) - { } - - /** - * Bellman-Ford algorithm - */ - HashTable * run(uint32_t source) - { - // hash table for previous vertex - HashTable * previous = new HashTable(g.vertex_count()); - // source vertex - dist[source] = 0; - - // other vertices - Graph::Adjacent * a; - list_for_each_entry(a, &g.list(), a_node){ - if (source != a->v.id) { - dist[a->v.id] = INT_MAX; +namespace alg { + class BellmanFord { + private: + HashTable dist; // hash table for distance. + bool has_neg_cycle; // negative weighted cycle mark. + const Graph & g; + public: + BellmanFord(const Graph & graph): + dist(graph.vertex_count()),g(graph) { } + + /** + * Bellman-Ford algorithm + */ + HashTable * run(uint32_t source) { + // hash table for previous vertex + HashTable * previous = new HashTable(g.vertex_count()); + // source vertex + dist[source] = 0; + + // other vertices + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node){ + if (source != a->v.id) { + dist[a->v.id] = INT_MAX; + } + (*previous)[a->v.id] = UNDEFINED; } - (*previous)[a->v.id] = UNDEFINED; - } - has_neg_cycle = false; // negative cycle mark set to 'false'. + has_neg_cycle = false; // negative cycle mark set to 'false'. + + // relax edges repeatedly + Graph::Adjacent * u; + for (uint32_t i=0;iv.id]; + + Graph::Vertex * v; + list_for_each_entry(v, &u->v_head, v_node){ + int32_t dist_v = dist[v->id]; + + if (dist_u + v->weight < dist_v) { + dist[v->id] = dist_u + v->weight; + (*previous)[v->id] = u->v.id; + } + } + } + } - // relax edges repeatedly - Graph::Adjacent * u; - for (uint32_t i=0;iv.id]; Graph::Vertex * v; - list_for_each_entry(v, &u->v_head, v_node){ + list_for_each_entry(v, &u->v_head, v_node){ int32_t dist_v = dist[v->id]; if (dist_u + v->weight < dist_v) { - dist[v->id] = dist_u + v->weight; - (*previous)[v->id] = u->v.id; + has_neg_cycle = true; // graph contains a negative-weight cycle + return previous; } - } + } } - } - - // check for negative-weight cycles - list_for_each_entry(u, &g.list(), a_node) { - int32_t dist_u = dist[u->v.id]; - Graph::Vertex * v; - list_for_each_entry(v, &u->v_head, v_node){ - int32_t dist_v = dist[v->id]; - - if (dist_u + v->weight < dist_v) { - has_neg_cycle = true; // graph contains a negative-weight cycle - return previous; - } - } + return previous; } - - return previous; - } - - inline bool has_negative_cycle() { return has_neg_cycle; } + + inline bool has_negative_cycle() { return has_neg_cycle; } }; } diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 72a47678..574914af 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -1,5 +1,5 @@ /******************************************************************************* - * DANIEL'S ALGORITHM IMPLEMENTAIONS + * ALGORITHM IMPLEMENTAIONS * * /\ | _ _ ._ o _|_ |_ ._ _ _ * /--\ | (_| (_) | | |_ | | | | | _> @@ -8,7 +8,7 @@ * BINARY SEARCH TREE * * Features: - * 1. Expected search time is O(nlogn). + * 1. Expected search time is O(log(n)), with worst case O(n). * 2. Data should be !!!SHUFFLED!!! first before tree creation. * 3. First initialize the value of the root (pointer to the * structure treeNode) with NULL. eg: @@ -18,135 +18,182 @@ * ******************************************************************************/ -#ifndef __BINARY_SEARCH_TREE_H__ -#define __BINARY_SEARCH_TREE_H__ +#ifndef ALGO_BINARY_SEARCH_TREE_H__ +#define ALGO_BINARY_SEARCH_TREE_H__ #include #include #include +#include -namespace alg -{ +namespace alg { template - class BST - { - private: - /** - * binary search tree definiton. - */ - struct treeNode - { - KeyT key; // key - ValueT value; // data - treeNode *left; // left child - treeNode *right; // right child - }; + class BST { + private: + /** + * binary search tree definition. + */ + struct treeNode { + KeyT key; // key + ValueT value; // data + treeNode *parent; // parent + treeNode *left; // left child + treeNode *right; // right child + }; + + class BSTException: public std::exception { + public: + virtual const char * what() const throw() { + return "key does not exist"; + } + } excp_key; - class BSTException: public std::exception - { + private: + treeNode * m_root; // the root + private: + BST(const BST&); + BST& operator=(const BST&); public: - virtual const char * what() const throw() - { - return "key does not exist"; - } - }; - - private: - treeNode * m_root; - const BSTException error; - - public: - BST():m_root(NULL){}; - - ~BST() - { - destruct(m_root); - } - - ValueT operator[] (const KeyT & key) - { - if (m_root == NULL) throw error; - treeNode * tmp = m_root; - - while(true) { - if (key == tmp->key) return tmp->value; - else if(key < tmp->key) { - if (tmp->left == NULL) throw error; - tmp = tmp->left; - } else { - if (tmp->right == NULL) throw error; - tmp = tmp->right; + BST():m_root(NULL){}; + + ~BST() { + destruct_(m_root); + } + + /** + * find key + */ + treeNode * find(const KeyT & key) { + treeNode * n= m_root; + while (n!=NULL && key != n->key) { + if (key < n->key) { + n = n->left; + } else { + n = n->right; + } + } + + return n; + } + + /** + * insert a new data into the binary search tree. + */ + void insert(const KeyT & key, const ValueT & value) { + treeNode *z= new treeNode; + z->key = key; + z->value = value; + z->left = z->right = z->parent = NULL; + + treeNode * n = m_root; + treeNode * y = NULL; + while(n!=NULL) { + y = n; + if(key < n->key) { + n = n->left; + } else { + n = n->right; + } + } + + z->parent = y; + if (y==NULL) { + m_root = z; + } else if (key < y->key) { + y->left = z; + } else { + y->right = z; + } + } + + /** + * delete a key from the binary search tree. + */ + bool deleteKey(const KeyT & key) { + treeNode *z = find(key); + if (z == NULL) { + return false; + } + + if (z->left == NULL) { + transplant(z, z->right); + } else if (z->right == NULL) { + transplant(z, z->left); + } else { + // find the minimum element of the right subtree + treeNode *y = minimum(z->right); + if (y->parent != z) { + // replace y with right-child + transplant(y, y->right); + // replace right-child of y with the right-child of z + y->right = z->right; + // make y the parent of the right-child + y->right->parent = y; + } + + // replace z with y + transplant(z,y); + y->left = z->left; + y->left->parent = y; + } + + delete z; + return true; } - } - } - - /** - * test whether the key is in the tree - */ - bool contains(const KeyT & key) - { - if (m_root == NULL) return false; - treeNode * tmp = m_root; - - while(true) { - if (key == tmp->key) return true; - else if(key < tmp->key) { - if (tmp->left == NULL) return false; - tmp = tmp->left; - } else { - if (tmp->right == NULL) return false; - tmp = tmp->right; + + void print_tree(treeNode * n, int indent) { + if (n == NULL) { + return; + } + print_tree(n->right, indent+1); + int i; + for (i=0;ikey << "," << n->value << "]" << std::endl; + print_tree(n->left, indent+1); } - } - } - - /** - * insert a new data into the binary search tree. - */ - bool insert(const KeyT & key, const ValueT & value) - { - treeNode *n = new treeNode; - n->key = key; - n->value = value; - n->left = n->right = NULL; - - if (m_root == NULL){ - m_root = n; - return true; - } - treeNode * tmp = m_root; - - while(true) { - if (key == tmp->key) { // already inserted + + void print_helper() { + print_tree(m_root, 0); + } + + private: + void destruct_(treeNode *n) { + if (n==NULL) return; + destruct_(n->left); + destruct_(n->right); delete n; - return false; } - else if(key < tmp->key) { - if (tmp->left == NULL) { - tmp->left = n; - return true; - } else tmp = tmp->left; - } else { - if (tmp->right == NULL) { - tmp->right = n; - return true; - } else tmp = tmp->right; + + /** + * replace node u with v. + */ + void transplant(treeNode *u, treeNode *v) { + if (u->parent == NULL) { + m_root = v; + } else if (u == u->parent->left) { + u->parent->left = v; + } else { + u->parent->right = v; + } + + if (v!=NULL) { + v->parent = u->parent; + } + } + + /** + * find the minimum element of the subtree + */ + treeNode * minimum(treeNode *x) { + while (x->left != NULL) { + x = x->left; + } + + return x; } - } - } - private: - void destruct(treeNode *n) - { - if (n==NULL) return; - destruct(n->left); - destruct(n->right); - delete n; - } - - private: - BST(const BST&); - BST& operator=(const BST&); - }; + }; } #endif // diff --git a/include/bitset.h b/include/bitset.h index 0e66ad1c..9e7b9bbc 100644 --- a/include/bitset.h +++ b/include/bitset.h @@ -11,93 +11,85 @@ * ******************************************************************************/ -#ifndef __BIT_SET_H__ -#define __BIT_SET_H__ +#ifndef ALGO_BIT_SET_H__ +#define ALGO_BIT_SET_H__ #include #include #include #include -namespace alg -{ +namespace alg { /** * definition of bitset class */ - class BitSet - { - private: - uint32_t m_size; //size in bits - uint32_t m_bytes; // size in bytes - unsigned char * m_bits; // the bits - - public: - /** - * construct BitSet by a give number of bits - */ - BitSet(uint32_t num_bits) - { - // round up - m_bytes = num_bits/8+1; - m_size = m_bytes * 8; - m_bits = new unsigned char[m_bytes]; - memset(m_bits, 0, m_bytes); - } - - /** - * safely free - */ - ~BitSet() - { - delete [] m_bits; - } - - private: - BitSet(const BitSet&); - BitSet& operator=(const BitSet&); - - public: - - /** - * set 1 to position [bit] - */ - inline void set(uint32_t bit) - { - if (bit>=m_size) return; - - uint32_t n = bit/8; - uint32_t off = bit%8; - - m_bits[n] |= 128U>>off; - } - - /** - * set 0 to position [bit] - */ - inline void unset(uint32_t bit) - { - if (bit>=m_size) return; - - uint32_t n = bit/8; - uint32_t off = bit%8; - - m_bits[n] &= ~(128U>>off); - } - - /** - * test a bit , true if set, false if not. - */ - inline bool test(uint32_t bit) - { - if (bit>=m_size) return false; - - uint32_t n = bit/8; - uint32_t off = bit%8; - - if (m_bits[n] & (128U>>off))return true; - return false; - } - + class BitSet { + private: + uint32_t m_size; //size in bits + uint32_t m_bytes; // size in bytes + unsigned char * m_bits; // the bits + + public: + /** + * construct BitSet by a give number of bits + */ + BitSet(uint32_t num_bits) { + // round up + m_bytes = num_bits/8+1; + m_size = m_bytes * 8; + m_bits = new unsigned char[m_bytes]; + memset(m_bits, 0, m_bytes); + } + + /** + * safely free + */ + ~BitSet() { + delete [] m_bits; + } + + private: + BitSet(const BitSet&); + BitSet& operator=(const BitSet&); + + public: + + /** + * set 1 to position [bit] + */ + inline void set(uint32_t bit) { + if (bit>=m_size) return; + + uint32_t n = bit/8; + uint32_t off = bit%8; + + m_bits[n] |= 128U>>off; + } + + /** + * set 0 to position [bit] + */ + inline void unset(uint32_t bit) { + if (bit>=m_size) return; + + uint32_t n = bit/8; + uint32_t off = bit%8; + + m_bits[n] &= ~(128U>>off); + } + + /** + * test a bit , true if set, false if not. + */ + inline bool test(uint32_t bit) { + if (bit>=m_size) return false; + + uint32_t n = bit/8; + uint32_t off = bit%8; + + if (m_bits[n] & (128U>>off))return true; + return false; + } }; } 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 new file mode 100644 index 00000000..6e17050f --- /dev/null +++ b/include/btree.h @@ -0,0 +1,543 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * B-TREE + * + * In computer science, a B-tree is a tree data structure that keeps data sorted + * and allows searches, sequential access, insertions, and deletions in + * logarithmic time. The B-tree is a generalization of a binary search tree in + * that a node can have more than two children. (Comer 1979, p. 123) Unlike + * self-balancing binary search trees, the B-tree is optimized for systems that + * read and write large blocks of data. It is commonly used in databases and + * filesystems. + * + * NOTES ON PRACTICAL USAGE: + * 1. Implement a buffer manager for B-Tree, such as using Hash and + * LRU, to control which node is in memory, and of course O_DIRECT flag. + * 2. Extend the node struct with satellite data pointer(offset), enlarge the + * node size to 2*PAGE or even more. + * + * http://en.wikipedia.org/wiki/B-tree + ******************************************************************************/ + +#ifndef ALGO_BTREE_H__ +#define ALGO_BTREE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BLOCKSIZE 4096 +#define T 255 +#define LEAF 0x0001 +#define ONDISK 0x0002 +#define MARKFREE 0x0004 + +namespace alg { + class BTree { + private: + // 4K node, 4096 bytes to write + // t = 255 + struct node_t { + uint16_t n; // num key + uint16_t flag; // flags + uint32_t offset; // lseek offset related to file beginning + char padding[12]; // padding to 4096 + int32_t key[509]; // key + int32_t c[510]; // childs pointers (represented as file offsets) + } __attribute__ ((packed)); + typedef struct node_t *node; + + public: + // node and index + struct Res { + uint32_t offset; + int32_t idx; + }; + private: + int fd; + private: + BTree(const BTree &); + BTree& operator=(const BTree&); + public: + BTree(const char * path) { + fd = open(path, O_RDWR|O_CREAT, 0640); + if (fd == -1) + return; + node x = (node)ALLOCBLK(); + int n = read(fd,x,BLOCKSIZE); + if (n != BLOCKSIZE) { // init new btree + x->flag |= LEAF; + WRITE(x); + } + } + + ~BTree() { + close(fd); + } + + Res Search(int32_t x) { + node root = ROOT(); + return search(root, x); + } + + void Insert(int32_t k) { + node r = ROOT(); + if (r->n == 2*T - 1) { + // place the old root node to the end of the file + r->flag &= ~ONDISK; + WRITE(r); + // new root + node s = (node)ALLOCBLK(); + s->flag &= ~LEAF; + s->flag |= ONDISK; // write to offset 0 + s->offset = 0; + s->n = 0; + s->c[0] = r->offset; + split_child(s, 0); // split_child with write s + insert_nonfull(s, k); + } else { + insert_nonfull(r, k); + } + } + + void DeleteKey(int32_t k) { + node root = ROOT(); + delete_op(root, k); + } + + private: + /** + * search a key, returns node and index + */ + Res search(node x, int32_t k) { + int32_t i = 0; + Res ret; + while (in && k > x->key[i]) i++; + + if (in && k == x->key[i]) { // search in [0,n-1] + ret.offset = x->offset; + ret.idx = i; + return ret; + } else if (x->flag & LEAF) { // leaf, no more childs + ret.offset = 0; + ret.idx = -1; + return ret; + } else { + std::auto_ptr xi(READ(x, i)); // search in a child + return search(xi.get(), k); + } + } + + /** + * insert into non-full node + */ + void insert_nonfull(node x, int32_t k) { + int32_t i = x->n-1; + if (x->flag & LEAF) { // insert into this leaf + while (i>=0 && k < x->key[i]) { // right shift to + x->key[i+1] = x->key[i]; // make place for k + i = i - 1; + } + x->key[i+1] = k; + x->n = x->n + 1; + WRITE(x); + } else { + while(i>=0 && k < x->key[i]) { + i = i-1; + } + i=i+1; + node xi = READ(x, i); // insert the key into one child. + if (xi->n == 2*T-1) { + split_child(x, i); + if (k > x->key[i]) { + i = i+1; + } + // NOTICE! + // reload x[i] after split_child. + xi = READ(x, i); + } + insert_nonfull(xi, k); + delete xi; + } + } + + /** + * split a node into 2. + */ + void split_child(node x, int32_t i) { + std::auto_ptr z((node)ALLOCBLK()); + std::auto_ptr y(READ(x, i)); + z->flag &= ~LEAF; + z->flag |= (y->flag & LEAF); + z->n = T - 1; + + int32_t j; + for (j=0;jkey[j] = y->key[j+T]; + } + + if (!(y->flag & LEAF)) { // if not leaf, copy childs too. + for (j=0;jc[j] = y->c[j+T]; + } + } + + y->n = T-1; // shrink y to t-1 elements + WRITE(y.get()); + WRITE(z.get()); + + for (j=x->n;j>=i+1;j--) { // make place for the new child in x + x->c[j+1] = x->c[j]; + } + + x->c[i+1] = z->offset; // make z the child of x + for (j=x->n-1;j>=i;j--) { // move keys in x + x->key[j+1] = x->key[j]; + } + x->key[i] = y->key[T-1]; // copy the middle element of y into x + x->n = x->n+1; + WRITE(x); + } + + /** + * recursive deletion. + */ + void delete_op(node x, int32_t k) { + int32_t i; + /* + int t; + printf("key:%d n:%d\n",k, x->n); + for (t=0;tn;t++) { + printf("=%d=", x->key[t]); + } + printf("\n"); + */ + + if (x->n == 0) { // emtpy node + return; + } + + i = x->n - 1; + while (i>=0 && k < x->key[i]) { // search the key. + i = i - 1; + } + + if (i >= 0 && x->key[i] == k) { // key exists in this node. + if (x->flag & LEAF) { + //printf("in case 1 [%d] [%d]\n", i,x->n); + case1(x, i, k); + } else { + //printf("in case 2 [%d] [%d]\n", i,x->n); + case2(x, i, k); + } + } else { + // case 3. on x.c[i+1] + case3(x, i+1, k); + } + } + + /** + * case 1. + * If the key k is in node x and x is a leaf, delete the key k from x. + */ + void case1(node x, int32_t i, int32_t k) { + int j; + for (j = i;jn-1;j++) { // shifting the keys only, no childs available. + x->key[j] = x->key[j+1]; + } + x->n = x->n - 1; + WRITE(x); + } + + void case2(node x, int32_t i, int32_t k) { + // case 2a: + // If the child y that precedes k in node x has at least t + // keys, then find the predecessor k0 of k in the subtree + // rooted at y. Recursively delete k0, and replace k by k0 in x. + // (We can find k0 and delete it in a single downward pass.) + std::auto_ptr y(READ(x, i)); + if (y->n >= T) { + int32_t k0 = y->key[y->n-1]; + //printf("case2a %d %d\n", k0, x->key[i]); + x->key[i] = k0; + WRITE(x); + delete_op(y.get(), k0); + return; + } + + // case 2b. + // If y has fewer than t keys, then, symmetrically, examine + // the child z that follows k in node x. If z has at least t keys, + // then find the successor k0 of k in the subtree rooted at z. + // Recursively delete k0, and replace k by k0 in x. (We can find k0 + // and delete it in a single downward pass.) + std::auto_ptr z(READ(x, i+1)); + if (z->n >= T) { + int32_t k0 = z->key[0]; + //printf("case2b %d %d\n", k0, x->key[i]); + x->key[i] = k0; + WRITE(x); + delete_op(z.get(), k0); + return; + } + + // case 2c: + // Otherwise, if both y and z have only t-1 keys, + // merge k and all of z into y, so that x loses both k and the + // pointer to z, and y now contains 2t - 1 keys. + // Then free z and recursively delete k from y. + if (y->n == T-1 && z->n == T-1) { + //printf("case2c"); + // merge k & z into y + y->key[y->n] = k; + + int j; + for (j=0;jn;j++) { // merge keys of z + y->key[y->n+1+j] = z->key[j]; + } + for (j=0;jn+1;j++) { // merge childs of z + y->c[y->n+1+j] = z->c[j]; + } + + // mark free z + z->flag |= MARKFREE; + y->n = y->n + z->n + 1; // size after merge + WRITE(z.get()); + WRITE(y.get()); + + for (j=i;jn-1;j++) { // delete k from node x + x->key[j] = x->key[j+1]; + } + + for (j=i+1;jn;j++){ // delete pointer to z --> (i+1)th + x->c[j] = x->c[j+1]; + } + x->n = x->n - 1; + WRITE(x); + + // recursive delete k + delete_op(y.get(), k); + return; + } + + // cannot reach here + assert(false); + } + + void case3(node x, int32_t i, int32_t k) { + std::auto_ptr ci(READ(x, i)); + if (ci->n > T-1) { // ready to delete in child. + delete_op(ci.get(), k); + return; + } + + // case 3a. + // If x.c[i] has only t - 1 keys but has an immediate sibling with at least t keys, + // give x.c[i] an extra key by moving a key from x down into x.c[i], moving a + // key from x.c[i]’s immediate left or right sibling up into x, and moving the + // appropriate child pointer from the sibling into x.c[i]. + std::auto_ptr left(READ(x, i-1)); + if (i-1>=0 && left->n >= T) { + // printf("case3a, left"); + // right shift keys and childs of x.c[i] to make place for a key + // right shift ci childs + int j; + for (j=ci->n-1;j>0;j--) { + ci->key[j] = ci->key[j-1]; + } + + for (j=ci->n;j>0;j--) { + ci->c[j] = ci->c[j-1]; + } + ci->n = ci->n+1; + ci->key[0] = x->key[i-1]; // copy key from x[i-1] to ci[0] + ci->c[0] = left->c[left->n]; // copy child from left last child. + x->key[i] = left->key[left->n-1]; // copy left last key into x[i] + left->n = left->n-1; // decrease left size + + WRITE(ci.get()); + WRITE(x); + WRITE(left.get()); + delete_op(ci.get(), k); + return; + } + + // case 3a. right sibling + std::auto_ptr right(READ(x, i+1)); + if (i+1<=x->n && right->n >= T) { + // printf("case3a, right"); + ci->key[ci->n] = x->key[i]; // append key from x + ci->c[ci->n+1] = right->c[0]; // append child from right + ci->n = ci->n+1; + x->key[i] = right->key[0]; // subsitute key in x + + int j; + for (j=0;jn-1;j++) { // remove key[0] from right sibling + right->key[j] = right->key[j+1]; + } + + for (j=0;jn;j++) { // and also the child c[0] of the right sibling. + right->c[j] = right->c[j+1]; + } + right->n = right->n - 1; // reduce the size of the right sibling. + + WRITE(ci.get()); + WRITE(x); + WRITE(right.get()); + delete_op(ci.get(), k); // recursive delete key in x.c[i] + return; + } + + // case 3b. + // If x.c[i] and both of x.c[i]’s immediate siblings have t-1 keys, merge x.c[i] + // with one sibling, which involves moving a key from x down into the new + // merged node to become the median key for that node. + if ((i-1<0 ||left->n == T-1) && (i+1 <=x->n || right->n == T-1)) { + if (left->n == T-1) { + // copy x[i] to left + left->key[left->n] = x->key[i]; + left->n = left->n + 1; + + // remove key[i] from x and also the child + // shrink the size & set the child-0 to left + delete_i(x, i); + + int j; + // append x.c[i] into left sibling + for (j=0;jn;j++) { + left->key[left->n + j] = ci->key[j]; + } + + for (j=0;jn+1;j++) { + left->c[left->n + j] = ci->c[j]; + } + left->n += ci->n; // left became 2T-1 + ci->flag |= MARKFREE; // free ci + ci->n = 0; + WRITE(ci.get()); + WRITE(x); + // root check + if (x->n == 0 && x->offset ==0) { + left->flag |= MARKFREE; + WRITE(left.get()); + left->flag &= ~MARKFREE; + left->offset = 0; + } + WRITE(left.get()); + delete_op(left.get(), k); + return; + } else if (right->n == T-1) { + // copy x[i] to x.c[i] + ci->key[ci->n] = x->key[i]; + ci->n = ci->n + 1; + // remove key[i] from x and also the child + // shrink the size & set the child-0 to ci + delete_i(x, i); + + int j; + // append right sibling into x.c[i] + for (j=0;jn;j++) { + ci->key[ci->n + j] = right->key[j]; + } + + for (j=0;jn+1;j++) { + ci->c[ci->n + j] = right->c[j]; + } + ci->n += right->n; // ci became 2T-1 + right->flag |= MARKFREE; // free right + right->n = 0; + WRITE(right.get()); + WRITE(x); + // root check + if (x->n == 0 && x->offset ==0) { + ci->flag |= MARKFREE; + WRITE(ci.get()); + ci->flag &= ~MARKFREE; + ci->offset = 0; + } + WRITE(ci.get()); + delete_op(ci.get(), k); + return; + } + } + } + + /** + * delete ith key & child. + */ + void delete_i(node x, int32_t i) { + int j; + for (j=i;jn-1;j++) { + x->key[j] = x->key[j+1]; + } + + for (j=i+1;jn;j++) { + x->c[j] = x->c[j+1]; + } + x->n = x->n - 1; + } + + /** + * Allocate empty node struct. + * A better allocator should be consider in practice, such as + * re-cycling the freed up blocks on disk, so used blocks + * should be traced in some data strucuture, file header maybe. + */ + void * ALLOCBLK() { + node x = new node_t; + x->n = 0; + x->offset = 0; + x->flag = 0; + memset(x->key, 0, sizeof(x->key)); + memset(x->c, 0, sizeof(x->c)); + memset(x->padding, 0xcc, sizeof(x->padding)); + return x; + } + + /** + * Load the root block + */ + node ROOT() { + void *root = ALLOCBLK(); + lseek(fd, 0, SEEK_SET); + read(fd, root, BLOCKSIZE); + return (node)root; + } + + /** + * Read a 4K-block from disk, and returns the node struct. + */ + node READ(node x, int32_t i) { + void *xi = ALLOCBLK(); + if (i >=0 && i <= x->n) { + lseek(fd, x->c[i], SEEK_SET); + read(fd, xi, BLOCKSIZE); + } + return (node)xi; + } + + /** + * update a node struct to file, create if offset is -1. + */ + void WRITE(node x) { + if (x->flag & ONDISK) { + lseek(fd, x->offset, SEEK_SET); + } else { + x->offset = lseek(fd,0, SEEK_END); + } + x->flag |= ONDISK; + write(fd, x, BLOCKSIZE); + } + }; +} +#endif // diff --git a/include/bubble_sort.h b/include/bubble_sort.h new file mode 100644 index 00000000..ca194ced --- /dev/null +++ b/include/bubble_sort.h @@ -0,0 +1,51 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * BUBBLE SORT + * + * Bubble sort, sometimes incorrectly referred to as sinking sort, is a simple + * sorting algorithm that works by repeatedly stepping through the list to be + * sorted, comparing each pair of adjacent items and swapping them if they are + * in the wrong order. The pass through the list is repeated until no swaps are + * needed, which indicates that the list is sorted. The algorithm gets its name + * from the way smaller elements "bubble" to the top of the list. Because it + * only uses comparisons to operate on elements, it is a comparison sort. + * Although the algorithm is simple, most of the other sorting algorithms are + * more efficient for large lists. + * + * http://en.wikipedia.org/wiki/Bubble_sort + ******************************************************************************/ + +#ifndef _BUBBLE_SORT_H_ +#define _BUBBLE_SORT_H_ + +#include +#include + +namespace alg { + template + static void BubbleSort(T list[], int start, int end){ + int i; + bool swapped; + + assert(start < end); + + do { + swapped = false; + for(i = start+1; i <= end; i++) { + if(list[i-1] > list[i]) { + // swap them and remember something changed + swap(list[i-1], list[i]); + swapped = true; + } + } + } while(swapped); + } +} + + +#endif // _BUBBLE_SORT_H_ diff --git a/include/dictionary.h b/include/dictionary.h new file mode 100644 index 00000000..4c38a9cf --- /dev/null +++ b/include/dictionary.h @@ -0,0 +1,562 @@ +/******************************************************************************* +* DANIEL'S ALGORITHM IMPLEMENTAIONS +* +* /\ | _ _ ._ o _|_ |_ ._ _ _ +* /--\ | (_| (_) | | |_ | | | | | _> +* _| +* +* .Net Dictionary Implementation (Cache friendly hash table) +* +******************************************************************************/ + +#pragma once + +#include +#include +#include +#include "hash_code.h" +#include "prime.h" + +namespace alg +{ + +template< typename TKey, typename TValue, typename THash = hash_code > +class Dictionary +{ +public: + struct KeyValuePair + { + TKey Key; + TValue Value; + }; + +private: + struct Entry : public KeyValuePair + { + int32_t HashCode; + int32_t Next; + + Entry() + : HashCode(-1) + , Next(-1) + { + } + + void Reset() + { + HashCode = -1; + Next = -1; + Key = TKey(); + Value = TValue(); + } + }; + +private: + std::vector m_Buckets; + std::vector m_Entries; + int32_t m_Count; + int32_t m_FreeList; + int32_t m_FreeCount; + + friend class Iterator; +public: + + template + class IteratorBase + { + protected: + DictType* Dict; + int32_t Index; + EntryType* Current; + + friend class Dictionary; + + IteratorBase(DictType* dict) + : Dict(dict) + , Index(0) + , Current(nullptr) + { + } + + public: + TIter& operator++() + { + while ((uint32_t) Index < (uint32_t) Dict->m_Count) + { + if (Dict->m_Entries[Index].HashCode >= 0) + { + Current = &Dict->m_Entries[Index]; + Index++; + return *static_cast(this); + } + Index++; + } + + Index = Dict->m_Count + 1; + Current = nullptr; + return *static_cast(this); + } + + TIter operator++(int32_t) + { + TIter tmp = *static_cast(this); + ++(*this); + return tmp; + } + + bool operator == (const TIter& other) const + { + return Dict == other.Dict + && Index == other.Index + && Current == other.Current; + } + + bool operator != (const TIter& other) const + { + return !(*this == other); + } + }; + + class Iterator : public IteratorBase + { + friend class Dictionary; + private: + Iterator(Dictionary* dict) + : IteratorBase(dict) + { + } + public: + KeyValuePair& operator*() const + { + return *Current; + } + }; + + class ConstIterator : public IteratorBase + { + friend class Dictionary; + private: + ConstIterator(const Dictionary* dict) + : IteratorBase(dict) + { + } + public: + const KeyValuePair& operator*() const + { + return *Current; + } + }; + +public: + typedef Iterator iterator; + typedef ConstIterator const_iterator; + +public: + Dictionary(int32_t capacity = 0) + : m_Count(0) + , m_FreeList(-1) + , m_FreeCount(0) + { + _Init(capacity); + } + + ~Dictionary() + { + Clear(); + } + + int32_t Size() const + { + return m_Count - m_FreeCount; + } + + TValue& operator[](const TKey& key) + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return m_Entries[i].Value; + } + throw MxKeyNotFoundException(); + } + const TValue& operator[](const TKey& key) const + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return m_Entries[i].Value; + } + throw MxKeyNotFoundException(); + } + + bool TryGetValue(const TKey& key, TValue& outValue) const + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + outValue = m_Entries[i].Value; + return true; + } + else + { + return false; + } + } + + TValue TryGetValueOrDefault(const TKey& key, const TValue& defaultValue) const + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return m_Entries[i].Value; + } + else + { + return defaultValue; + } + } + + const TValue& TryGetValueRefOrDefault(const TKey& key, const TValue& defaultValue) const + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return m_Entries[i].Value; + } + else + { + return defaultValue; + } + } + + TValue* TryGetValuePtr(const TKey& key) + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return &m_Entries[i].Value; + } + else + { + return nullptr; + } + } + + const TValue* TryGetValuePtr(const TKey& key) const + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return &m_Entries[i].Value; + } + else + { + return nullptr; + } + } + + void AddOrUpdate(const TKey& key, const TValue& value) + { + _Insert(key, value, false); + } + + bool ContainsKey(const TKey& key) const + { + int32_t i = _FindEntry(key); + return i >= 0; + } + + bool Contains(const std::pair& pair) const + { + int32_t i = _FindEntry(pair.first); + return i >= 0 && pair.second == m_Entries[i].Value; + } + + bool Add(const TKey& key, const TValue& value) + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return false; + } + + return _Insert(key, value, true); + } + + bool Add(const TKey& key, TValue&& value) + { + int32_t i = _FindEntry(key); + if (i >= 0) + { + return false; + } + + return _Insert(key, value, true); + } + + bool Remove(const TKey& key) + { + int32_t hashCode = THash()(key) & 0x7FFFFFFF; + int32_t bucket = hashCode % m_Buckets.size(); + int32_t last = -1; + for (int i = m_Buckets[bucket]; i >= 0; last = i, i = m_Entries[i].Next) + { + if (m_Entries[i].HashCode == hashCode && m_Entries[i].Key == key) + { + if (last < 0) + { + m_Buckets[bucket] = m_Entries[i].Next; + } + else + { + m_Entries[last].Next = m_Entries[i].Next; + } + m_Entries[i].HashCode = -1; + m_Entries[i].Next = m_FreeList; + m_Entries[i].Key = TKey(); + m_Entries[i].Value = TValue(); + m_FreeList = i; + m_FreeCount++; + + return true; + } + } + return false; + } + + void Clear() + { + if (m_Count > 0) + { + memset(m_Buckets.data(), -1, m_Buckets.size() * sizeof(m_Buckets[0])); + for (auto& entry : m_Entries) + { + entry.Reset(); + } + m_FreeList = -1; + m_FreeCount = 0; + m_Count = 0; + } + } + + Iterator Begin() + { + return ++Iterator(this); + } + + ConstIterator Begin() const + { + return CBegin(); + } + + ConstIterator CBegin() const + { + return ++ConstIterator(this); + } + + Iterator End() + { + Iterator ret(this); + ret.Index = m_Count + 1; + ret.Current = nullptr; + return ret; + } + + ConstIterator End() const + { + return CEnd(); + } + + ConstIterator CEnd() const + { + ConstIterator ret(this); + ret.Index = m_Count + 1; + ret.Current = nullptr; + return ret; + } + + //STL style + iterator begin() + { + return Begin(); + } + + const_iterator begin() const + { + return CBegin(); + } + + const_iterator cbegin() const + { + return CBegin(); + } + + iterator end() + { + return End(); + } + + const_iterator end() const + { + return CEnd(); + } + + const_iterator cend() const + { + return CEnd(); + } +private: + int32_t _FindEntry(const TKey& key) const + { + if (m_Buckets.size() > 0) + { + int32_t hashCode = THash()(key) & 0x7FFFFFFF; + for (int32_t i = m_Buckets[hashCode % m_Buckets.size()]; i >= 0; i = m_Entries[i].Next) + { + if (m_Entries[i].HashCode == hashCode && m_Entries[i].Key == key) + { + return i; + } + } + } + return -1; + } + + void _Init(int32_t capacity) + { + int32_t size = GetNextPrime(capacity); + m_Buckets.clear(); + m_Buckets.resize(size, -1); + m_Entries.clear(); + m_Entries.resize(size); + m_FreeList = -1; + } + + template + bool _Insert(const TKey& key, TValueRef value, bool add) + { + if (m_Buckets.size() == 0) + { + _Init(3); + } + + int32_t hashCode = THash()(key) & 0x7FFFFFFF; + int32_t targetBucket = hashCode % m_Buckets.size(); + + for (int32_t i = m_Buckets[targetBucket]; i >= 0; i = m_Entries[i].Next) + { + if (m_Entries[i].HashCode == hashCode && m_Entries[i].Key == key) + { + if (add) + { + return false; + } + m_Entries[i].Value = value; + return true; + } + } + + int32_t index; + if (m_FreeCount > 0) + { + index = m_FreeList; + m_FreeList = m_Entries[index].Next; + m_FreeCount--; + } + else + { + if (m_Count == m_Entries.size()) + { + _Resize(); + targetBucket = hashCode % m_Buckets.size(); + } + index = m_Count; + m_Count++; + } + + m_Entries[index].HashCode = hashCode; + m_Entries[index].Next = m_Buckets[targetBucket]; + m_Entries[index].Key = key; + m_Entries[index].Value = value; + + m_Buckets[targetBucket] = index; + + return true; + } + + void _Resize() + { + _Resize(GetNextPrime(m_Count * 2), false); + } + + void _Resize(int32_t newSize, bool forceNewHashCodes) + { + assert(newSize >= m_Entries.size()); + + m_Buckets.resize(0); + m_Buckets.resize(newSize, -1); + m_Entries.resize(newSize); + + if (forceNewHashCodes) + { + for (int32_t i = 0; i < m_Count; i++) + { + if (m_Entries[i].HashCode != -1) + { + m_Entries[i].HashCode = (THash()(m_Entries[i].Key) & 0x7FFFFFFF); + } + } + } + for (int32_t i = 0; i < m_Count; i++) + { + if (m_Entries[i].HashCode >= 0) + { + int32_t bucket = m_Entries[i].HashCode % newSize; + m_Entries[i].Next = m_Buckets[bucket]; + m_Buckets[bucket] = i; + } + } + } + + + static int GetNextPrime(int n) + { + static const int c_PrimeArraySize = 72; + static const int c_Primes[c_PrimeArraySize] = + { + 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, + 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, + 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, + 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, + 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 + }; + static const int c_HashPrime = 101; + + if (n < 0) + { + return -1; + } + + for (int i = 0; i < c_PrimeArraySize; i++) + { + int prime = c_Primes[i]; + if (prime >= n) + { + return prime; + } + } + + //outside of our predefined table. + //compute the hard way. + for (int i = (n | 1); i < INT32_MAX; i += 2) + { + if (is_prime(i) && ((i - 1) % c_HashPrime != 0)) + { + return i; + } + } + return n; + } +}; + +} \ No newline at end of file diff --git a/include/dijkstra.h b/include/dijkstra.h index 3dbeec33..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 @@ -33,74 +33,60 @@ #include "stack.h" #include "hash_table.h" -namespace alg -{ - /** - * the dijkstra algorithm workspace - */ +namespace alg { class Dijkstra { - private: - const Graph & g; - Heap Q; // a binary heap - HashTable dist; // distance hash table - public: - static const int UNDEFINED = -1; - /** - * init dijkstra workspace - */ - Dijkstra(const struct Graph & graph):g(graph), - Q(g.vertex_count()), - dist(g.vertex_count()) {} - - // run dijkstra algorithm, and return the previous table - HashTable * run(uint32_t src_id) - { - // previous vertex hash table - HashTable * previous = new HashTable(g.vertex_count()); + 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 + Heap Q(g.vertex_count() + g.edge_count()); + // distance hash table + HashTable dist(g.vertex_count()); + // previous vertex hash table + HashTable * previous = new HashTable(g.vertex_count()); + // record whether the vertex is visited + HashTable visited(g.vertex_count()); - Q.clear(); - dist.clear(); + // all vertices + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node){ + 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 - Graph::Adjacent * source = g[src_id]; - Q.insert(0, source->v.id); // weight->id binary heap - dist[source->v.id] = 0; + // source vertex, the first vertex in Heap-Q + dist[src_id] = 0; + // decrease-key the source vertex to 0 + Q.decrease_key(src_id,0); - // other vertices - Graph::Adjacent * a; - list_for_each_entry(a, &g.list(), a_node){ - if (a->v.id != source->v.id) { - Q.insert(INT_MAX, a->v.id); - // set inital distance to INT_MAX - dist[a->v.id] = INT_MAX; - // set initial value to UNDEFINED - } - (*previous)[a->v.id] = UNDEFINED; - } + while(!Q.is_empty()) { // for every un-visited vertex, try relaxing the path + Heap::elem e = Q.pop(); + uint32_t id = e.data; + if (visited[id]) { // ignore visited vertex + continue; + } - while(!Q.is_empty()) { // The main loop - Graph::Adjacent * u = g[Q.min_value()]; - int dist_u = Q.min_key(); - Q.delete_min(); + 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. - if (dist_u == INT_MAX) { - break; - } - - 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) { - dist[v->id] = alt; - Q.decrease_key(v->id, alt); - (*previous)[v->id] = u->v.id; + Graph::Vertex * v; + list_for_each_entry(v, &u->v_head, v_node){ + uint32_t alt = dist_u + v->weight; + if (alt < dist[v->id]) { + dist[v->id] = alt; + (*previous)[v->id] = id; + Q.decrease_key(v->id, alt); // decrease-key + } } } - } - - return previous; - }; + + return previous; + }; }; } diff --git a/include/directed_graph.h b/include/directed_graph.h index 9f41e874..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 @@ -26,103 +26,140 @@ #include "graph_defs.h" #include "double_linked_list.h" -namespace alg -{ - class DirectedGraph:public Graph - { - private: - /** - * delete a vertex from adjacent lists - */ - void delete_me(uint32_t id) - { - // delete every connection, iterator through every adjacent list - Adjacent * adj; - list_for_each_entry(adj, &a_head, a_node){ - if (adj->v.id != id) { - if((*adj)[id]!=NULL) { // if connected to id - adj->delete_vertex(id); - num_edges--; +namespace alg { + class DirectedGraph:public Graph { + private: + /** + * delete a vertex from adjacent lists + */ + void delete_me(uint32_t id) { + // delete every connection, iterator through every adjacent list + Adjacent * adj; + list_for_each_entry(adj, &a_head, a_node){ + if (adj->v.id != id) { + if((*adj)[id]!=NULL) { // if connected to id + adj->delete_vertex(id); + num_edges--; + } + } + } + } + public: + /** + * randomly generate a graph, for test purpose + */ + static DirectedGraph * randgraph(int nvertex) { + DirectedGraph * g = new DirectedGraph; + int i; + + for(i=0;iadd_vertex(i); + } + + // random connect + for(i=0;iadd_edge(i, j, w); + } } } + return g; + } + + public: + /** + * delete a vertex with specified id + */ + void delete_vertex(uint32_t id) { + Adjacent * a = (*this)[id]; + if (a==NULL) return; + delete_me(id); + // delete adjacent list itself. + num_vertex--; + num_edges -= a->num_neigh; + list_del(&a->a_node); + delete a; + } + + /** + * create a new vertex and add to the graph, with specified id. + */ + bool add_vertex(uint32_t id) { + if ((*this)[id]!=NULL) return false; + + // new empty adjacent list + Adjacent * a = new Adjacent(id); + list_add_tail(&a->a_node, &a_head); + num_vertex++; + + return true; } - } - public: - /** - * delete a vertex with specified id - */ - void delete_vertex(uint32_t id) - { - Adjacent * a = (*this)[id]; - if (a==NULL) return; - delete_me(id); - // delete adjacent list itself. - num_vertex--; - num_edges -= a->num_neigh; - list_del(&a->a_node); - delete a; - } - - /** - * create a new vertex and add to the graph, with specified id. - */ - bool add_vertex(uint32_t id) - { - if ((*this)[id]!=NULL) return false; - - // new empty adjacent list - Adjacent * a = new Adjacent(id); - list_add_tail(&a->a_node, &a_head); - num_vertex++; - - return true; - } - - /** - * add an edge for x -> y - */ - bool add_edge(uint32_t x, uint32_t y, int32_t weight) - { - struct Adjacent * a1 = (*this)[x]; - struct Adjacent * a2 = (*this)[y]; - - // make sure both vertex exists & not connected from x->y - if (a1==NULL || a2==NULL) return false; - if (is_adjacent(a1, a2)) return false; - - // create new vertex & add to adjacent list - Vertex * n = new Vertex(y); - n->weight = weight; - list_add_tail(&n->v_node, &a1->v_head); - - num_edges++; - a1->num_neigh++; - - return true; - } - - /** - * delete an edge for x -> y - */ - void delete_edge(uint32_t x, uint32_t y) - { - struct Adjacent * a1 = (*this)[x]; - struct Adjacent * a2 = (*this)[y]; - if (a1==NULL || a2==NULL) return ; - if (!is_adjacent(a1, a2)) return ; - - Vertex * v, *n; - // find y in adjacent list of x - list_for_each_entry_safe(v, n, &a1->v_head, v_node){ - if (v->id == y) { - list_del(&v->v_node); - delete v; - num_edges--; - a1->num_neigh--; + + /** + * add an edge for x -> y + */ + bool add_edge(uint32_t x, uint32_t y, int32_t weight) { + struct Adjacent * a1 = (*this)[x]; + struct Adjacent * a2 = (*this)[y]; + + // make sure both vertex exists & not connected from x->y + if (a1==NULL || a2==NULL) return false; + if (is_adjacent(a1, a2)) return false; + + // create new vertex & add to adjacent list + Vertex * n = new Vertex(y); + n->weight = weight; + list_add_tail(&n->v_node, &a1->v_head); + + num_edges++; + a1->num_neigh++; + + return true; + } + + /** + * delete an edge for x -> y + */ + void delete_edge(uint32_t x, uint32_t y) { + struct Adjacent * a1 = (*this)[x]; + struct Adjacent * a2 = (*this)[y]; + if (a1==NULL || a2==NULL) return ; + if (!is_adjacent(a1, a2)) return ; + + Vertex * v, *n; + // find y in adjacent list of x + list_for_each_entry_safe(v, n, &a1->v_head, v_node){ + if (v->id == y) { + list_del(&v->v_node); + delete v; + num_edges--; + a1->num_neigh--; + } } } - } + /** + * create the transpose of a directed-graph + */ + DirectedGraph * transpose() { + DirectedGraph * trans = new DirectedGraph; + Adjacent * a; + list_for_each_entry(a, &a_head, a_node){ + trans->add_vertex(a->v.id); + Vertex * v; + list_for_each_entry(v, &a->v_head, v_node){ + trans->add_vertex(v->id); + trans->add_edge(v->id, a->v.id, v->weight); + } + } + + return trans; + } }; } diff --git a/include/disjoint-set.h b/include/disjoint-set.h new file mode 100644 index 00000000..be6bff7d --- /dev/null +++ b/include/disjoint-set.h @@ -0,0 +1,64 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * Disjoint-set data structure + * + * In computing, a disjoint-set data structure is a data structure that keeps + * track of a set of elements partitioned into a number of disjoint (nonoverlapping) + * subsets. A union-find algorithm is an algorithm that performs two useful + * operations on such a data structure: + * Find: Determine which subset a particular element is in. This can be used + * for determining if two elements are in the same subset. + * Union: Join two subsets into a single subset. + * + * http://en.wikipedia.org/wiki/Disjoint-set_data_structure + ******************************************************************************/ + +#ifndef ALGO_DISJOINTSET_H__ +#define ALGO_DISJOINTSET_H__ + +namespace alg { + template + struct Set{ + Set* parent; + int rank; + }; + + template + void MakeSet(T *s){ + s->parent = s; + s->rank = 0; + } + + template + void Union(T *x, T *y) { + Link(FindSet(x), FindSet(y)); + } + + template + void Link(T *x, T *y) { + if (x->rank > y->rank) { + y->parent = x; + } else { + x->parent = y; + if (x->rank == y->rank) { + y->rank +=1; + } + } + } + + template + T* FindSet(T *x) { + if (x != x->parent) { + x->parent = FindSet(x->parent); + } + + return x->parent; + } +} + +#endif // diff --git a/include/dos_tree.h b/include/dos_tree.h index f0838411..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 @@ -27,200 +27,182 @@ #include "double_linked_list.h" #include "rbtree.h" -namespace alg -{ - class DosTree:public RBTreeAbstract - { - public: - /** - * dynamic order stat node structure definition - */ - typedef struct dostree_node_t : public rbtree_node_t { - int key; // the key - int size; // the size of this subtree - } *dostree_node; +namespace alg { + class DosTree:public RBTreeAbstract { + public: + /** + * dynamic order stat node structure definition + */ + typedef struct dostree_node_t : public rbtree_node_t { + int key; // the key + int size; // the size of this subtree + } *dostree_node; #define DOSNODE(rbnode) static_cast(rbnode) #define DOSNODE_SIZE(rbnode) (rbnode?DOSNODE(rbnode)->size:0) - public: - DosTree() { } - ~DosTree() { - destruct(DOSNODE(get_root())); - } - private: - DosTree(const DosTree&); - DosTree& operator=(const DosTree&); - - void destruct(dostree_node n) - { - if (n==NULL) return; - destruct(DOSNODE(n->left)); - destruct(DOSNODE(n->right)); - delete n; - } - - public: - - dostree_node index(int index) - { - return lookup_node(get_root(),index); - } - - /** - * dostree_insert - * insert a new key into the dos tree - */ - void insert(int key) - { - dostree_node inserted_node = new_node(key, RED, NULL, NULL); - - if (get_root() == NULL) { - set_root(inserted_node); + public: + DosTree() { } + ~DosTree() { + destruct(DOSNODE(get_root())); } - else { - rbtree_node n = DOSNODE(get_root()); - while (1) { - // incr 1 for each node on the path traversed from the root - DOSNODE(n)->size+=1; - if (key < DOSNODE(n)->key) { - if (n->left == NULL) { - n->left = inserted_node; - break; - } else { - n = n->left; - } - } else { - if (n->right == NULL) { - n->right = inserted_node; - break; + private: + DosTree(const DosTree&); + DosTree& operator=(const DosTree&); + + void destruct(dostree_node n) { + if (n==NULL) return; + destruct(DOSNODE(n->left)); + destruct(DOSNODE(n->right)); + delete n; + } + + public: + dostree_node index(int index) { + return lookup_node(get_root(),index); + } + + /** + * dostree_insert + * insert a new key into the dos tree + */ + void insert(int key) { + dostree_node inserted_node = new_node(key, RED, NULL, NULL); + + if (get_root() == NULL) { + set_root(inserted_node); + } + else { + rbtree_node n = DOSNODE(get_root()); + while (1) { + // incr 1 for each node on the path traversed from the root + DOSNODE(n)->size+=1; + if (key < DOSNODE(n)->key) { + if (n->left == NULL) { + n->left = inserted_node; + break; + } else { + n = n->left; + } } else { - n = n->right; + if (n->right == NULL) { + n->right = inserted_node; + break; + } else { + n = n->right; + } } } + inserted_node->parent = n; } - inserted_node->parent = n; + + // fix red-black properties + insert_case1(inserted_node); } - // fix red-black properties - insert_case1(inserted_node); - } - - /** - * delete the key in the red-black tree - */ - void delete_key(dostree_node n) - { - rbtree_node child; - - /* Copy key/value from predecessor and then delete it instead */ - if (n->left != NULL && n->right != NULL) { - dostree_node pred = DOSNODE(maximum_node(n->left)); - DOSNODE(n)->key = DOSNODE(pred)->key; - DOSNODE(n)->size = DOSNODE(pred)->size; - n = pred; + /** + * delete the key in the red-black tree + */ + void delete_key(dostree_node n) { + rbtree_node child; + + /* Copy key/value from predecessor and then delete it instead */ + if (n->left != NULL && n->right != NULL) { + dostree_node pred = DOSNODE(maximum_node(n->left)); + DOSNODE(n)->key = DOSNODE(pred)->key; + DOSNODE(n)->size = DOSNODE(pred)->size; + n = pred; + } + + // fix up size from pred + fixup_size(n); + + assert(n->left == NULL || n->right == NULL); + child = n->right == NULL ? n->left : n->right; + if (node_color(n) == BLACK) { + n->color = node_color(child); + delete_case1(n); + } + replace_node(n, child); + if (n->parent == NULL && child != NULL) // root + child->color = BLACK; + delete (DOSNODE(n)); } - // fix up size from pred - fixup_size(n); + void print() { + print_helper(get_root(), 0); + puts(""); + } - assert(n->left == NULL || n->right == NULL); - child = n->right == NULL ? n->left : n->right; - if (node_color(n) == BLACK) { - n->color = node_color(child); - delete_case1(n); + void print_helper(rbtree_node n, int indent) { + int i; + if (n == NULL) { + fputs("", stdout); + return; + } + if (n->right != NULL) { + print_helper(n->right, indent + INDENT_STEP); + } + for(i=0; icolor == BLACK) + printf("[key:%d size:%d]\n", DOSNODE(n)->key,DOSNODE(n)->size); + else + printf("*[key:%d size:%d]\n", DOSNODE(n)->key, DOSNODE(n)->size); + if (n->left != NULL) { + print_helper(n->left, indent + INDENT_STEP); + } } - replace_node(n, child); - // copy child value if exists - if (child != NULL) { - DOSNODE(n)->key = DOSNODE(child)->key; - DOSNODE(n)->size = DOSNODE(child)->size; + private: + /** + * dostree_lookup + * + * select the i-th largest element + */ + dostree_node lookup_node(rbtree_node n, int i) { + if (n == NULL) return NULL; // beware of NULL pointer + int size = DOSNODE_SIZE(n->left) + 1; + + if(i == size) return DOSNODE(n); + if(i < size ) return lookup_node(n->left, i); + else return lookup_node(n->right, i-size); } - if (n->parent == NULL && child != NULL) - child->color = BLACK; - - delete (DOSNODE(n)); - } - - void print() { - print_helper(get_root(), 0); - puts(""); - } - - void print_helper(rbtree_node n, int indent) { - int i; - if (n == NULL) { - fputs("", stdout); - return; + + /** + * left/right rotation call back function + */ + void rotate_left_callback(rbtree_node n, rbtree_node parent) { + DOSNODE(parent)->size = DOSNODE_SIZE(n); + DOSNODE(n)->size = DOSNODE_SIZE(n->left) + DOSNODE_SIZE(n->right) + 1; } - if (n->right != NULL) { - print_helper(n->right, indent + INDENT_STEP); + + void rotate_right_callback(rbtree_node n, rbtree_node parent) { + rotate_left_callback(n,parent); } - for(i=0; icolor == BLACK) - printf("[key:%d size:%d]\n", DOSNODE(n)->key,DOSNODE(n)->size); - else - printf("*[key:%d size:%d]\n", DOSNODE(n)->key, DOSNODE(n)->size); - if (n->left != NULL) { - print_helper(n->left, indent + INDENT_STEP); + + /** + * fix procedure caused by deletion + */ + void fixup_size(rbtree_node n) { + // fix up to the root + do { + DOSNODE(n)->size -= 1; + n = n->parent; + } while(n != NULL); + } + + static inline dostree_node new_node(int key, color rbtree_node_color, rbtree_node left, rbtree_node right) { + dostree_node result =new dostree_node_t; + result->key = key; + result->size = 1; + result->color = rbtree_node_color; + result->left = NULL; + result->right = NULL; + if(left !=NULL) left->parent = result; + if(right!=NULL) right->parent = result; + result->parent = NULL; + return result; } - } - private: - /** - * dostree_lookup - * - * select the i-th largest element - */ - dostree_node lookup_node(rbtree_node n, int i) - { - if (n == NULL) return NULL; // beware of NULL pointer - int size = DOSNODE_SIZE(n->left) + 1; - - if(i == size) return DOSNODE(n); - if(i < size ) return lookup_node(n->left, i); - else return lookup_node(n->right, i-size); - } - /** - * left/right rotation call back function - */ - void rotate_left_callback(rbtree_node n, rbtree_node parent) - { - DOSNODE(parent)->size = DOSNODE_SIZE(n); - DOSNODE(n)->size = DOSNODE_SIZE(n->left) + DOSNODE_SIZE(n->right) + 1; - } - - void rotate_right_callback(rbtree_node n, rbtree_node parent) - { - rotate_left_callback(n,parent); - } - - /** - * fix procedure caused by deletion - */ - void fixup_size(rbtree_node n) - { - // fix up to the root - do { - DOSNODE(n)->size -= 1; - n = n->parent; - } while(n != NULL); - } - - static inline dostree_node - new_node(int key, color rbtree_node_color, rbtree_node left, rbtree_node right) - { - dostree_node result =new dostree_node_t; - result->key = key; - result->size = 1; - result->color = rbtree_node_color; - result->left = NULL; - result->right = NULL; - if(left !=NULL) left->parent = result; - if(right!=NULL) right->parent = result; - result->parent = NULL; - return result; - } }; } 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 bdbeb044..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 @@ -33,130 +33,123 @@ #include "queue.h" #include "2darray.h" -namespace alg -{ +namespace alg { /** * Edmonds Karp maximal flow class */ - class EdmondsKarp - { - private: - const Graph & g; - Array2D m_residual; // residual network , 2d array - HashTable m_pre; // pre node of current node - bool * m_visits; // mark whether current node is visited - - HashTable m_map; // vertex id to ordinary row/col number mapping - HashTable m_rmap; // reverse mapping of map. - - public: - EdmondsKarp(const Graph & graph): - g(graph), + class EdmondsKarp { + private: + const Graph & g; + Array2D m_residual; // residual network , 2d array + HashTable m_pre; // pre node of current node + bool * m_visits; // mark whether current node is visited + + HashTable m_map; // vertex id to ordinary row/col number mapping + HashTable m_rmap; // reverse mapping of map. + + public: + EdmondsKarp(const Graph & graph): g(graph), m_residual(g.vertex_count(), g.vertex_count()), m_pre(g.vertex_count()), - m_map(g.vertex_count()), m_rmap(g.vertex_count()) - { - m_visits = new bool[g.vertex_count()]; - // map vertex ids to ordinal row/col number, and reverse mapping. - // for residual network, using sequential order - Graph::Adjacent * a; - int id=0; - list_for_each_entry(a, &g.list(), a_node){ - m_map[a->v.id] = id; - m_rmap[id] = a->v.id; - id++; - } - - // init residual network - m_residual.clear(0); - - list_for_each_entry(a, &g.list(), a_node){ - Graph::Vertex * v; - list_for_each_entry(v, &a->v_head, v_node){ - int from = m_map[a->v.id]; - int to = m_map[v->id]; - m_residual(from, to) = v->weight; - } - } - } - - ~EdmondsKarp() - { - delete [] m_visits; - } - - /** - * edmonds karp algorithm for maximal flow - * returns the maxflow from src to sink - */ - uint32_t run(uint32_t src, uint32_t sink) - { - // find augument path repeatedly. - int _src = m_map[src]; - int _sink = m_map[sink]; - - uint32_t maxflow = 0; - - while(find_path(_src, _sink)) { - int delta = INT_MAX; - - // find minimal delta - int i; - for (i=_sink;i!=_src;i= m_pre[i]) { - delta = Min(delta, m_residual(m_pre[i],i)); + m_map(g.vertex_count()), m_rmap(g.vertex_count()) { + m_visits = new bool[g.vertex_count()]; + // map vertex ids to ordinal row/col number, and reverse mapping. + // for residual network, using sequential order + Graph::Adjacent * a; + int id=0; + list_for_each_entry(a, &g.list(), a_node){ + m_map[a->v.id] = id; + m_rmap[id] = a->v.id; + id++; } - // for each edge, change residual network - for (i=_sink; i!=_src;i= m_pre[i]) { - m_residual(m_pre[i],i) -= delta; - m_residual(i,m_pre[i]) += delta; + // init residual network + m_residual.clear(0); + + list_for_each_entry(a, &g.list(), a_node){ + Graph::Vertex * v; + list_for_each_entry(v, &a->v_head, v_node){ + int from = m_map[a->v.id]; + int to = m_map[v->id]; + m_residual(from, to) = v->weight; + } } + } - maxflow += delta; + ~EdmondsKarp() { + delete [] m_visits; } - return maxflow; - } + /** + * edmonds karp algorithm for maximal flow + * returns the maxflow from src to sink + */ + uint32_t run(int32_t src, int32_t sink) { + // find augument path repeatedly. + int32_t _src = m_map[src]; + int32_t _sink = m_map[sink]; - inline const Array2D & residual() const { return m_residual;} - inline const HashTable & map() const { return m_map;} - inline const HashTable & rmap() const { return m_rmap;} + uint32_t maxflow = 0; - private: - /** - * find a augument path. using breadth first search - */ - bool find_path(uint32_t _src, uint32_t _sink) - { - Queue Q(g.vertex_count()); + while(find_path(_src, _sink)) { + int delta = INT_MAX; - // clear visit flag & path - memset(m_visits, false, sizeof(bool) * g.vertex_count()); + // find minimal delta + int i; + for (i=_sink;i!=_src;i= m_pre[i]) { + delta = Min(delta, m_residual(m_pre[i],i)); + } - // src setting - m_pre[_src] = _src; - m_visits[_src] = true; - Q.enqueue(_src); + // for each edge, change residual network + for (i=_sink; i!=_src;i= m_pre[i]) { + m_residual(m_pre[i],i) -= delta; + m_residual(i,m_pre[i]) += delta; + } - while(!Q.is_empty()) { - int p = Q.front(); - Q.dequeue(); + maxflow += delta; + } - for (uint32_t i=0;i< g.vertex_count();i++) { - if (m_residual(p,i) >0 && !m_visits[i]) { - m_pre[i] = p; - m_visits[i] = true; + return maxflow; + } - if (i==_sink) { // nice, we've got to sink point. - return true; + inline const Array2D & residual() const { return m_residual;} + inline const HashTable & map() const { return m_map;} + inline const HashTable & rmap() const { return m_rmap;} + + private: + /** + * find a augument path. using breadth first search + */ + bool find_path(int32_t _src, int32_t _sink) { + Queue Q(g.vertex_count()); + + // clear visit flag & path + memset(m_visits, false, sizeof(bool) * g.vertex_count()); + + // src setting + m_pre[_src] = _src; + m_visits[_src] = true; + Q.enqueue(_src); + + while(!Q.is_empty()) { + int p = Q.front(); + Q.dequeue(); + + for (uint32_t i=0;i< g.vertex_count();i++) { + if (m_residual(p,i) >0 && !m_visits[i]) { + m_pre[i] = p; + m_visits[i] = true; + + if (i==uint32_t(_sink)) { // nice, we've got to sink point. + return true; + } + Q.enqueue(i); } - Q.enqueue(i); } } - } - return false; - } + return false; + } }; } 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 new file mode 100644 index 00000000..44af130a --- /dev/null +++ b/include/fib-heap.h @@ -0,0 +1,228 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * FIBONACCI HEAP + * + * In computer science, a Fibonacci heap is a heap data structure consisting of + * a collection of trees. It has a better amortized running time than a binomial + * heap. Fibonacci heaps were developed by Michael L. Fredman and Robert E. Tarjan + * in 1984 and first published in a scientific journal in 1987. The name of + * Fibonacci heap comes from Fibonacci numbers which are used in the + * running time analysis. + * + * http://en.wikipedia.org/wiki/Fibonacci_heap + ******************************************************************************/ + +#ifndef ALGO_FIB_HEAP_H__ +#define ALGO_FIB_HEAP_H__ +#include +#include +#include +#include "double_linked_list.h" +namespace alg { + template + class FibHeap { + public: + typedef _Key key_type; + typedef _Val value_type; + struct node_t { + int32_t degree; + node_t * parent; + bool mark; + key_type key; + value_type value; + struct list_head child_head; // child list head + struct list_head node; // sibling list + }; + typedef struct node_t *Node; + private: + FibHeap(const FibHeap &); + FibHeap& operator=(const FibHeap&); + private: + int32_t n; + Node min; + struct list_head m_root; // root list + public: + FibHeap():n(0),min(NULL){ + INIT_LIST_HEAD(&m_root); + } + + /** + * insert a value into the Fibonacci Heap + */ + void Insert(key_type key, value_type value) { + Node x = new node_t; + x->degree = 0; + x->parent = NULL; + x->mark = false; + x->key = key; + x->value = value; + INIT_LIST_HEAD(&x->child_head); + if (min == NULL) { + min = x; + list_add(&x->node, &m_root); + } else { + list_add(&x->node, &m_root); + if (x->key < min->key) { + min = x; + } + } + n = n+1; + } + + /** + * Union 2 Fibonacci-Heap + */ + static FibHeap* Union(FibHeap *H1, FibHeap *H2) { + FibHeap * H = new FibHeap(); + H->min = H1->min; + H->m_root = H1->m_root; + list_splice(&H->m_root, &H1->m_root); // concat 2 root-list + list_splice(&H->m_root, &H2->m_root); + if (H1->min == NULL || (H2->min != NULL && H2->min.key < H1->min.key)) { + H->min = H2->min; + } + H->n = H1->n + H2->n; + return H; + } + + /** + * Extract Min Element + */ + Node ExtractMin() { + Node z = min; + if (z != NULL) { + Node x, xs; + // for each child x of z, add x to the root list of H + list_for_each_entry_safe(x, xs, &z->child_head, node) { + list_del(&x->node); + list_add(&x->node, &m_root); + x->parent = NULL; + } + + list_del(&z->node); + if (!list_empty(&m_root)) { + min = list_entry(m_root.next, node_t, node); // is this necessary? + CONSOLIDATE(); + } else { // the only node on the root list + min = NULL; + } + // remove z from the root list of H + n = n + 1; + } + return z; + } + + /** + * FIB-HEAP-DECREASE-KEY(H,x, k) / + */ + void DecreaseKey(Node x, key_type k) { + if (k > x->key) { + return; + } + x->key = k; + Node y = x->parent; + if (y != NULL && x->key < y->key) { + CUT(x,y); + CASCADING_CUT(y); + } + } + + private: + /** + * CUT(H,x,y) + * 1 remove x from the child list of y, decrementing y.degree + * 2 add x to the root list of H + * 3 x.p = NIL + * 4 x.mark = FALSE + */ + void CUT(Node x, Node y) { + list_del(&x->node); + list_add(&x->node, &m_root); + x->parent = NULL; + x->mark = false; + } + + void CASCADING_CUT(Node y) { + Node z = y->parent; + if (z!=NULL) { + if (y->mark == false) { + y->mark = true; + } else { + CUT(y,z); + CASCADING_CUT(z); + } + } + } + + void CONSOLIDATE() { + int32_t dn = D(n); + Node A[dn+1]; // let A[0..D(H.n)] to be a new array + int32_t i; + for (i=0;i<=dn;i++) { + A[i] = NULL; + } + + Node w, ws; + // for each node w in the root list of H + list_for_each_entry_safe(w, ws, &m_root, node) { + Node x = w; + int32_t d = x->degree; + while (A[d] != NULL) { + Node y = A[d]; // another node with the same degree as x + if (x->key > y->key) { // exchange x with y + Node tmp = x; + x = y; + y = tmp; + } + LINK(y,x); + A[d] = NULL; + d = d + 1; + } + A[d] = x; + } + min = NULL; + for (i=0;i<=dn;i++) { + if (A[i]!=NULL) { + if (min == NULL) { + // create a root list for H containing just A[i] + INIT_LIST_HEAD(&m_root); + list_add(&A[i]->node, &m_root); + min = A[i]; + } else { + list_add(&A[i]->node, &m_root); + if (A[i]->key < min->key) { + min = A[i]; + } + } + } + } + } + + int32_t D(int32_t n) { + float p1 = logf(n); + float p2 = logf(1.61803); // golden ratio + //printf("D(n) = %f\n", floor(p1/p2)); + return int32_t(floor(p1/p2)); + } + + /** + * FIB-HEAP-LINK(H, y, x) + * 1 remove y from the root list of H + * 2 makey a child of x, incrementing x.degree + * 3 y.mark = FALSE + */ + void LINK(Node y, Node x) { + y->parent = x; + list_add(&y->node, &x->child_head); + x->degree = x->degree + 1; + y->mark = false; + } + }; +} + +#endif // diff --git a/include/generic.h b/include/generic.h index b936c76a..785e5078 100644 --- a/include/generic.h +++ b/include/generic.h @@ -8,9 +8,9 @@ * GENERIC METHODS FOR ALGORITHMS * ******************************************************************************/ - -#ifndef __ALG_INC_H__ -#define __ALG_INC_H__ + +#ifndef ALGO_ALG_INC_H__ +#define ALGO_ALG_INC_H__ #include #include #include @@ -24,59 +24,56 @@ #define Min(a, b) ( (a < b) ? a : b ) #define RANDOM_INIT() srand(time(NULL)) -#define RANDOM(L, R) (L + rand() % ((R) - (L))) // gen a random integer in [L, R] +#define RANDOM(L, R) (L + rand() % ((R) - (L) + 1)) // gen a random integer in [L, R] -namespace alg -{ +namespace alg { /** * swap 2-element, orignal value */ template - static inline void swap(T &x, T &y) - { - T _t(x); - x = y; - y = _t; - } + static inline void swap(T &x, T &y) + { + T _t(x); + x = y; + y = _t; + } /** * print all of the elements in `list` with size `n` */ template - static void printlist(T & list,int count) - { - int i; - for(i=0;i - static uint32_t remove_dup(T a[], uint32_t len) - { - uint32_t i; - uint32_t newlen = len; - for (i=0; iv_node); - delete v; + Vertex(uint32_t vid) { + id = vid; + weight = -INT_MAX; } - } + }; - const Vertex & vertex() const { return v;} + enum VertexColor { GRAY, WHITE, BLACK }; - void delete_vertex(uint32_t id) - { - Vertex * v, *vn; - list_for_each_entry_safe(v, vn, &v_head, v_node){ - if (v->id == id ) { + /** + * Adjacent Lists. + */ + struct Adjacent { + struct Vertex v; + int32_t color; // color for searching + int32_t d; // discover time + int32_t f; // finish time + struct list_head v_head; // vertex list header + struct list_head a_node; + uint32_t num_neigh; // num of neighbours + + Adjacent(uint32_t id):v(id) { + INIT_LIST_HEAD(&v_head); + num_neigh = 0; + } + + ~Adjacent() { + Vertex * v, *vn; + list_for_each_entry_safe(v, vn, &v_head, v_node){ list_del(&v->v_node); - num_neigh--; delete v; - break; } } + + const Vertex & vertex() const { return v;} + + void delete_vertex(uint32_t id) { + Vertex * v, *vn; + list_for_each_entry_safe(v, vn, &v_head, v_node){ + if (v->id == id ) { + list_del(&v->v_node); + num_neigh--; + delete v; + break; + } + } + } + + /** + * get the Vertex from an adjacent list, according to vertex id + */ + Vertex * operator[] (uint32_t id) const { + Vertex * v; + list_for_each_entry(v, &v_head, v_node){ + if (v->id == id) { + return v; + } + } + return NULL; + } + }; + + protected: + uint32_t num_vertex; + uint32_t num_edges; + struct list_head a_head; // list header + public: + int32_t graph_tick; // for counting discover & finish time + + Graph() { + num_vertex = 0; + num_edges = 0; + INIT_LIST_HEAD(&a_head); + } + + virtual ~Graph() { + Adjacent * a, *an; + list_for_each_entry_safe(a, an, &a_head, a_node){ + list_del(&a->a_node); + delete a; + } } - + private: + Graph(const Graph &); + Graph& operator=(const Graph &); + public: + uint32_t vertex_count() const { return num_vertex; } + uint32_t edge_count() const { return num_edges; } /** - * get the Vertex from an adjacent list, according to vertex id + * find an adjacent list with vertex id == id */ - Vertex * operator[] (uint32_t id) const - { - Vertex * v; - list_for_each_entry(v, &v_head, v_node){ - if (v->id == id) { - return v; - } + Adjacent * operator[] (uint32_t id) const { + Adjacent * a; + list_for_each_entry(a, &a_head, a_node){ + if (a->v.id == id) { return a;} } + return NULL; } - }; - - protected: - uint32_t num_vertex; - uint32_t num_edges; - struct list_head a_head; // list header - public: - Graph() - { - num_vertex = 0; - num_edges = 0; - INIT_LIST_HEAD(&a_head); - } - - virtual ~Graph() - { - Adjacent * a, *an; - list_for_each_entry_safe(a, an, &a_head, a_node){ - list_del(&a->a_node); - delete a; - } - } - private: - Graph(const Graph &); - Graph& operator=(const Graph &); - public: - uint32_t vertex_count() const { return num_vertex; } - uint32_t edge_count() const { return num_edges; } - /** - * find an adjacent list with vertex id == id - */ - Adjacent * operator[] (uint32_t id) const - { - Adjacent * a; - list_for_each_entry(a, &a_head, a_node){ - if (a->v.id == id) { return a;} + + /** + * print a graph + */ + void print() const { + Adjacent * a; + printf("Graph : %d vertex, %d edges\n", num_vertex,num_edges); + list_for_each_entry(a, &a_head, a_node){ + printf("%d(neigh:%d)->{", a->v.id, a->num_neigh); + Vertex * v; + list_for_each_entry(v, &a->v_head, v_node){ + printf("%d(w:%d)\t", v->id, v->weight); + } + printf("}\n"); + } } - - return NULL; - } - - /** - * print a graph - */ - void print() const - { - Adjacent * a; - printf("Graph : %d vertex, %d edges\n", num_vertex,num_edges); - list_for_each_entry(a, &a_head, a_node){ - printf("%d(neigh:%d)->{", a->v.id, a->num_neigh); - Vertex * v; - list_for_each_entry(v, &a->v_head, v_node){ - printf("%d(w:%d)\t", v->id, v->weight); + + /** + * print a graph as graphviz '.dot' format + */ + void printdot() const { + Adjacent * a; + printf("==== BEGIN OF DOT ====\n"); + printf("digraph G {\n"); + printf("\tnode [shape = circle];\n"); + list_for_each_entry(a, &a_head, a_node){ + Vertex * v; + switch (a->color) { + case GRAY: + printf("\t%d [style=filled fillcolor=gray];\n", a->v.id); + break; + case BLACK: + printf("\t%d [style=filled fillcolor=black fontcolor=white];\n", a->v.id); + break; + default: + printf("\t%d;\n", a->v.id); + } + + list_for_each_entry(v, &a->v_head, v_node){ + printf("\t%d -> %d [label = \"%d\"];\n", a->v.id, v->id, v->weight); + } } printf("}\n"); - } - } - - const list_head & list() const {return a_head; } - - // Interface - virtual bool add_vertex(uint32_t id) = 0; - virtual void delete_vertex(uint32_t id) = 0; - virtual bool add_edge(uint32_t x, uint32_t y, int32_t weight) = 0; - virtual void delete_edge(uint32_t x, uint32_t y) = 0; - - protected: - /** - * test if an edge exists - */ - bool is_adjacent(const struct Adjacent * from, const struct Adjacent * to) - { - struct Vertex * v; - list_for_each_entry(v, &from->v_head, v_node){ - if (v->id == to->v.id ) { return true; } + printf("==== END OF DOT ====\n"); + } + + const list_head & list() const {return a_head; } + + // Interface + virtual bool add_vertex(uint32_t id) = 0; + virtual void delete_vertex(uint32_t id) = 0; + virtual bool add_edge(uint32_t x, uint32_t y, int32_t weight) = 0; + virtual void delete_edge(uint32_t x, uint32_t y) = 0; + + protected: + /** + * test if an edge exists + */ + bool is_adjacent(const struct Adjacent * from, const struct Adjacent * to) { + struct Vertex * v; + list_for_each_entry(v, &from->v_head, v_node){ + if (v->id == to->v.id ) { return true; } + } + return false; } - return false; - } }; } diff --git a/include/graph_search.h b/include/graph_search.h index dd51db13..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 @@ -32,68 +32,83 @@ #include "directed_graph.h" #include "hash_table.h" -namespace alg -{ - static void breadth_first_search(const Graph & g, uint32_t source) - { - static const uint32_t MARK = 0xDEAD; - - Graph::Adjacent * root = g[source]; - HashTable ht(g.vertex_count()); - - if (root==NULL) return; +namespace alg { + /** + * BREADTH FIRST SEARCH + */ + static void BFS(const Graph & g, int32_t src_id) { + // mark all vertex color to WHITE + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node) { + a->color = Graph::WHITE; + a->d = INT_MAX; + } - // init + Graph::Adjacent * s = g[src_id]; + s->d = 0; Queue Q(g.vertex_count()); - Q.enqueue(root->v.id); - ht[root->v.id] = MARK; - + Q.enqueue(s->v.id); + while(!Q.is_empty()) { - uint32_t t = Q.front(); - printf("%d->", t); + uint32_t id = Q.front(); + printf("%d->", id); // output discovered id Q.dequeue(); - Graph::Vertex * v; - Graph::Adjacent * a = g[t]; - list_for_each_entry(v, &a->v_head, v_node) { - if (!ht.contains(v->id) || ht[v->id]!=MARK) { - ht[v->id] = MARK; - Q.enqueue(v->id); + Graph::Vertex * _v; + Graph::Adjacent * u = g[id]; + list_for_each_entry(_v, &u->v_head, v_node) { + Graph::Adjacent * v = g[_v->id]; // retrive the original adjacent list + if (v->color == Graph::WHITE) { // to change node color + v->color = Graph::GRAY; + v->d = u->d + 1; + Q.enqueue(v->v.id); } } + u->color = Graph::BLACK; } - printf("\n"); } - static void depth_first_search(const Graph & g, uint32_t source) - { - static const uint32_t MARK = 0xDEAD; + static void _DFS_VISIT(Graph &g, Graph::Adjacent * u); + /** + * DEPTH FIRST SEARCH + */ + static void DFS(Graph & g) { + // mark all vertex color to WHITE + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node) { + a->color = Graph::WHITE; + } - Graph::Adjacent * root = g[source]; - HashTable ht(g.vertex_count()); + // for each vertex + g.graph_tick = 0; + list_for_each_entry(a, &g.list(), a_node) { + if (a->color == Graph::WHITE) { + printf("DFS from : %d\t",a->v.id); + _DFS_VISIT(g, a); + printf("\n"); + } + } + printf("\n"); + } - if (root==NULL) return; + /** + * recursivly visit (Call Stack) + */ + static void _DFS_VISIT(Graph &g, Graph::Adjacent * u) { + // white vertex u has just benn discovered + u->d = ++g.graph_tick; + u->color = Graph::GRAY; - // init - Stack S(g.vertex_count()); - S.push(root->v.id); - ht[root->v.id] = MARK; - - while(!S.is_empty()) { - uint32_t t = S.top(); - printf("%d->", t); - S.pop(); - Graph::Vertex * v; - Graph::Adjacent * a = g[t]; - list_for_each_entry(v, &a->v_head, v_node) { - if (!ht.contains(v->id) || ht[v->id] !=MARK) { - ht[v->id] = MARK; - S.push(v->id); - } + Graph::Vertex * _v; + list_for_each_entry(_v, &u->v_head, v_node) { // explore edge (u, v) + Graph::Adjacent * v = g[_v->id]; // retrive the original adjacent list + if (v->color == Graph::WHITE) { + _DFS_VISIT(g, v); } } - - printf("\n"); + u->color = Graph::BLACK; + u->f = ++g.graph_tick; + printf("%d(d:%d, f:%d) -> ", u->v.id, u->d, u->f); } } diff --git a/include/hash_code.h b/include/hash_code.h new file mode 100644 index 00000000..a310580c --- /dev/null +++ b/include/hash_code.h @@ -0,0 +1,38 @@ +#ifndef ALGO_HASH_CODE_H__ +#define ALGO_HASH_CODE_H__ +#include +#include "hash_string.h" +namespace alg { + /** + * default compare funcs + */ + template + struct hash_code { + uint32_t operator()(T) { + printf("must provide a hash function for _Key\n"); + return 0; + } + }; + + template<> + struct hash_code { + uint32_t operator()(const char* value) { + return hash_fnv1a(value, strlen(value)); + } + }; + + template<> + struct hash_code { + uint32_t operator()(uint32_t value) { + return value; + } + }; + + template<> + struct hash_code { + uint32_t operator()(int32_t value) { + return (uint32_t)value; + } + }; +} +#endif // diff --git a/include/hash_multi.h b/include/hash_multi.h index d8a98f57..ec22f65f 100644 --- a/include/hash_multi.h +++ b/include/hash_multi.h @@ -15,45 +15,42 @@ * ******************************************************************************/ -#ifndef __HASH_MULTIPLICATION_H__ -#define __HASH_MULTIPLICATION_H__ +#ifndef ALGO_HASH_MULTIPLICATION_H__ +#define ALGO_HASH_MULTIPLICATION_H__ #include #include #include "generic.h" #include "prime.h" -namespace alg -{ +namespace alg { struct MultiHash { uint64_t A; uint32_t r; // prime, init your hash table with size -> r }; - static const short BITWIDTH=32; + static const short BITWIDTH = 32; static inline uint32_t multi_hash_table_size(const struct MultiHash * ht) { return 1<<(ht->r); } /** * multi_hash. */ - static inline uint32_t multi_hash(const struct MultiHash * ht, uint32_t key) - { + static inline uint32_t multi_hash(const struct MultiHash * ht, uint32_t key) { uint32_t hash; hash = ((ht->A * key)&0xFFFFFFFF)>>(BITWIDTH-ht->r); //mod 2^w equals logic bitmask ops return hash; } #ifdef _MSC_VER -#define log2(x) (log(x) / log(2)) +#define log2(x) (log(x) / log(2.0)) #endif /** * init a hash table with size specified. */ - static MultiHash * multi_hash_init(uint32_t size) - { + static MultiHash * multi_hash_init(uint32_t size) { // find prime larger than log2(size) - uint32_t r = ceil(log2(size)); + uint32_t r = ceil(log2((double)size)); int i; for (i = r; ;i++) { if (is_prime(i)) { diff --git a/include/hash_string.h b/include/hash_string.h index 75f60857..6eee926c 100644 --- a/include/hash_string.h +++ b/include/hash_string.h @@ -12,19 +12,17 @@ * ******************************************************************************/ -#ifndef __STRING_HASH_H__ -#define __STRING_HASH_H__ +#ifndef ALGO_STRING_HASH_H__ +#define ALGO_STRING_HASH_H__ #include -namespace alg -{ +namespace alg { /** * hash a string into integer * using java's hashCode() implementation */ - static uint32_t hash_string(const char * str, uint32_t len) - { + static uint32_t hash_string(const char * str, uint32_t len) { uint32_t hash=0; uint32_t i; for (i=0;i +#include #include #include #include "double_linked_list.h" +#include "hash_code.h" #include "hash_multi.h" -namespace alg -{ +namespace alg { /** * definition of a hash table. */ - template - class HashTable { - private: - /** - * definiton of Key-Value pair. - */ - struct HashKV { - uint32_t key; // 32-bit key - T value; // value - struct list_head node; // KV is a list element. - }; - - private: - uint32_t m_size; // the size of the hash table. - struct list_head * m_slots; // all of the slots, each slot is an linked-list - struct MultiHash * m_multi; // the hash function parameter. - - public: - /** - * create a hash table with max size . - */ - HashTable(uint32_t max) { - // init multiplication hash function - m_multi = multi_hash_init(max); - m_size = multi_hash_table_size(m_multi); - m_slots = new list_head[m_size]; - - for (uint32_t i=0; inode); - delete kv; + template > + class HashTable { + typedef _Key key_type; + typedef _Value value_type; + typedef _HashCode hash_code_fn; + private: + /** + * definition of Key-Value pair. + */ + struct HashKV { + key_type key; // 32-bit key + value_type value; // value + struct list_head node; // KV is a list element. + }; + + private: + uint32_t m_size; // the size of the hash table. + struct list_head * m_slots; // all of the slots, each slot is an linked-list + struct MultiHash * m_multi; // the hash function parameter. + + public: + /** + * create a hash table with max size . + */ + HashTable(uint32_t max) { + // init multiplication hash function + m_multi = multi_hash_init(max); + m_size = multi_hash_table_size(m_multi); + m_slots = new list_head[m_size]; + + for (uint32_t i=0; ikey == key) { // ok, found in the list. - return true; + + ~HashTable() { + for (uint32_t i=0;inode); + delete kv; + } + } + + delete m_multi; + delete [] m_slots; } - } - return false; - } - - /** - * delete by key - */ - bool delete_key(uint32_t key) - { - // hash the key using a hash function. - uint32_t hash = multi_hash(m_multi, key); - - HashKV * kv, *nkv; - list_for_each_entry_safe(kv,nkv,&m_slots[hash], node) { - if (kv->key == key) { - list_del(&kv->node); - delete kv; - return true; + private: + HashTable(const HashTable &); + HashTable& operator=(const HashTable &); + public: + + /** + * test if the hash table has the key + */ + bool contains(key_type key) const { + // hash the key using a hash function. + uint32_t hash = multi_hash(m_multi, hash_code_fn()(key)); + + // we iterate through the list. + HashKV * kv; + list_for_each_entry(kv, &m_slots[hash], node){ + if (kv->key == key) { // ok, found in the list. + return true; + } + } + return false; } - } - return false; - } - - // const version of operator [] - const T& operator[] (uint32_t key) const - { - // hash the key using a hash function. - uint32_t hash = multi_hash(m_multi, key); + /** + * delete by key + */ + bool delete_key(key_type key) { + // hash the key using a hash function. + uint32_t hash = multi_hash(m_multi, hash_code_fn()(key)); + + HashKV * kv, *nkv; + list_for_each_entry_safe(kv,nkv,&m_slots[hash], node) { + if (kv->key == key) { + list_del(&kv->node); + delete kv; + return true; + } + } + + return false; + } - // we iterate through the list. - HashKV * kv; - list_for_each_entry(kv, &m_slots[hash], node){ - if (kv->key == key) { // ok, found in the list. + // const version of operator [] + const value_type& operator[] (key_type key) const { + // hash the key using a hash function. + uint32_t hash = multi_hash(m_multi, hash_code_fn()(key)); + + // we iterate through the list. + HashKV * kv; + list_for_each_entry(kv, &m_slots[hash], node){ + if (kv->key == key) { // ok, found in the list. + return kv->value; + } + } + + // reaching here means a new key is given, + // create a new HashKV struct for it. + kv = new HashKV; + kv->key = key; + list_add(&kv->node, &m_slots[hash]); return kv->value; } - } - - // reaching here means a new key is given, - // create a new HashKV struct for it. - kv = new HashKV; - kv->key = key; - list_add(&kv->node, &m_slots[hash]); - return kv->value; - } - - /** - * operator [] - */ - T& operator[] (uint32_t key) - { - return const_cast(static_cast(*this)[key]); - } - - void clear() - { - HashKV * kv, *nkv; - for (uint32_t i=0;inode); - delete kv; + + /** + * operator [] + */ + value_type& operator[] (key_type key) { + return const_cast(static_cast(*this)[key]); + } + + void clear() { + HashKV * kv, *nkv; + for (uint32_t i=0;inode); + delete kv; + } + } } - } - } - }; + }; } #endif // diff --git a/include/heap.h b/include/heap.h index b5734910..d793cdab 100644 --- a/include/heap.h +++ b/include/heap.h @@ -7,198 +7,189 @@ * * 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 "generic.h" -namespace alg -{ +namespace alg { /** * define binary heap structure. */ template - class Heap { - private: - /** - * define key-value pair of heap struct. - */ - struct KV { - public: - int key; - T value; - }; - uint32_t m_size; // current heap size. - uint32_t m_max; // max heap size. - KV * m_kvs; // 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; - }; + class Heap { + public: + /** + * define key-value pair of heap struct. + */ + struct elem { + public: + int key; + T data; + }; + + 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; + m_heap = new elem[m_max]; + }; + + ~Heap() { + delete [] m_heap; + }; + + private: + Heap(const Heap &); + Heap& operator=(const Heap&); + + public: + // for loop through the kvs + inline int count() const { return m_size; }; + + /** + * insert a 'key'->'value' pair into the heap. + */ + 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++; + } - ~Heap() - { - delete [] m_kvs; - }; + /** + * emptiness test + */ + inline bool is_empty() const { return (m_size==0)?true:false; } + + /** + * clear the heap + */ + inline void clear() { m_size = 0; } + + bool contains(const T & data) { + for(int i=0;i'value' pair into the heap. - */ - void insert(int key, const T & value) - { - // heap full, just return; - if(m_size == m_max) return; - - m_size++; - m_kvs[m_size].key = key; - m_kvs[m_size].value = value; - - /*Adjust its position*/ - int now = m_size; - while(m_kvs[now/2].key > key) - { - m_kvs[now] = m_kvs[now/2]; - now /= 2; - } - - m_kvs[now].key = key; - m_kvs[now].value = value; - } - - /** - * emptiness test - */ - inline bool is_empty() const { return (m_size==0)?true:false; } - - /** - * clear the heap - */ - inline void clear() { m_size = 0; } - - /** - * contains test - */ - bool contains(const T & value) - { - for(uint32_t i=1;i<=m_size;i++) { - if(m_kvs[i].value == value) return true; - } - - return false; - } - - /** - * delete the min element --> heap top. - */ - 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. - int lastKey; - T lastValue; - uint32_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--; - - // 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. + /** + * pop the min element + */ + elem pop() { + int n = m_size-1; + swap(m_heap[0],m_heap[n]); + down(0, n); + m_size--; + return m_heap[m_size]; } - // 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]; + + /** + * remove the given data + */ + bool remove(const T &data) { + for (int i=0;i m_size) return; // value not found - - if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning. - - int now = index; - while(m_kvs[now/2].key > newkey) - { - m_kvs[now] = m_kvs[now/2]; - now /= 2; - } - - m_kvs[now].key = newkey; - m_kvs[now].value= value; - } - }; + + 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. + } + + if (!less(j,i)) { + break; + } + swap(m_heap[i], m_heap[j]); + i=j; + } + } + + 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 @@ -31,208 +31,198 @@ #include "hash_table.h" #include "stack.h" -namespace alg -{ - +namespace alg { /** * The Huffman tree definition */ class HuffTree { - private: - /** - * The Huffman tree node definition - */ - struct HuffNode{ - unsigned char symbol; - struct HuffNode *left, *right; - }; - - /** - * The code for a symbol of huffman - */ - struct HuffCode { - char code[256]; // max length is 256 - uint32_t length; // the length of the code; - }; - - private: - HashTable m_symbol; // hash table for encoding - HuffNode * m_root; // the root node for decoding - uint32_t m_freqs[256]; // frequency array, you can pass this array - // to the peer for constructing huffman - // tree. - public: - /** - * Construct a Huffman Tree with a sample string. - * the string is either the characteristic of the text - * or simply the original text to compress. - */ - HuffTree(const char * sample) : m_symbol(256) { - // count frequency for each char(8-bit). - memset(m_freqs, 0, sizeof(m_freqs)); - - int i; - for(i=0; sample[i]!='\0'; i++) - m_freqs[(unsigned char) sample[i]]++; - - recreate_from_freqs(); - }; - - ~HuffTree() { - // TODO: free HuffNodes - }; - - private: - HuffTree(const HuffTree&); - HuffTree& operator=(const HuffTree&); - public: - - /** - * Encoding - * encode a message into codes, codes should be large enough to hold the output - * eg:. the length of string - * the length in BITS will be returned. - */ - uint32_t encode(const char * msg, char * codes) - { - uint32_t cursor = 0; - for(uint32_t i=0; msg[i]!='\0'; i++) - { - HuffCode & hcode = m_symbol[(uint32_t)msg[i]]; - - for (uint32_t j=0;j m_symbol; // hash table for encoding + HuffNode * m_root; // the root node for decoding + uint32_t m_freqs[256]; // frequency array, you can pass this array + // to the peer for constructing huffman + // tree. + public: + /** + * Construct a Huffman Tree with a sample string. + * the string is either the characteristic of the text + * or simply the original text to compress. + */ + HuffTree(const char * sample) : m_symbol(256) { + // count frequency for each char(8-bit). + memset(m_freqs, 0, sizeof(m_freqs)); + + int i; + for(i=0; sample[i]!='\0'; i++) + m_freqs[(unsigned char) sample[i]]++; + + recreate_from_freqs(); + }; + + ~HuffTree() { + // TODO: free HuffNodes + }; + + private: + HuffTree(const HuffTree&); + HuffTree& operator=(const HuffTree&); + public: + + /** + * Encoding + * encode a message into codes, codes should be large enough to hold the output + * eg:. the length of string + * the length in BITS will be returned. + */ + uint32_t encode(const char * msg, char * codes) { + uint32_t cursor = 0; + for (uint32_t i=0; msg[i]!='\0'; i++) { + HuffCode & hcode = m_symbol[(uint32_t)msg[i]]; + + for (uint32_t j=0;jleft == NULL && node->right == NULL) { + printf("%c",node->symbol); + node = m_root; //reset tree + } + uint32_t off = cursor%8; uint32_t base= cursor/8; - - if (hcode.code[j] =='0') { - codes[base] &= ~(1<<(7-off)); + + char bit = codes[base] & (1<<(7-off)); + + if (bit == 0) { + node = node->left; } else { - codes[base] |= 1<<(7-off); + node = node->right; } - cursor++; } - } - - return cursor; - }; - - /** - * Decoding - * decoding is based on tree traversal - * pass length of Bits - */ - void decode(const char * codes, uint32_t length) - { - HuffNode * node = m_root; - - //For each "bit" of the string to decode - //we take a step to the left for 0 - //or ont to the right for 1 - uint32_t cursor; - - for(cursor=0;cursorleft == NULL && node->right == NULL) { printf("%c",node->symbol); - node = m_root; //reset tree } - - uint32_t off = cursor%8; - uint32_t base= cursor/8; - char bit = codes[base] & (1<<(7-off)); + printf("\n"); + }; + + private: + /** + * recreate the huff tree from an array[256] i.e. 8bit + * useful for peer reconstructing decoding tree. + */ + void recreate_from_freqs() { + // construct a priority queue for huffman tree building + PQ pq; + + int i; + for(i=0; i<256; i++) + if(m_freqs[i] !=0) { + HuffNode * n = new HuffNode(); + n->left = NULL; + n->right = NULL; + n->symbol = (unsigned char) i; + + pq.queue(n, m_freqs[i]); // freq. as priority + } - if (bit == 0) { - node = node->left; - } else { - node = node->right; + // tree building subroutine + while(pq.count()>1) { + int prio1, prio2, newprio; + HuffNode * node1, *node2, *new_node; + + node1 = pq.top(&prio1); pq.dequeue(); + node2 = pq.top(&prio2); pq.dequeue(); + + newprio = prio1+prio2; + + new_node = new HuffNode; + new_node->left = node1; + new_node->right = node2; + + pq.queue(new_node, newprio); } - } - - if(node->left == NULL && node->right == NULL) { - printf("%c",node->symbol); - } - - printf("\n"); - }; - - private: - /** - * recreate the huff tree from an array[256] i.e. 8bit - * useful for peer reconstructing decoding tree. - */ - void recreate_from_freqs() { - // construct a priority queue for huffman tree building - PQ pq; - - int i; - for(i=0; i<256; i++) - if(m_freqs[i] !=0) - { - HuffNode * n = new HuffNode(); - n->left = NULL; - n->right = NULL; - n->symbol = (unsigned char) i; - - pq.queue(n, m_freqs[i]); // freq. as priority + + // set root + int prio; + m_root = pq.top(&prio); + pq.dequeue(); + + // construct symbol lookup table + char code[256]; + build_symbol(m_root, 0, code); + }; + + /** + * building symbol lookup table + */ + void build_symbol(struct HuffNode * node, int k, char code[256]) { + //If we reach the leaf node we introduce the code in the table + if(node->left == NULL && node->right == NULL) { + code[k] = '\0'; + HuffCode hcode; + strncpy(hcode.code, code, k); + hcode.length = k; + m_symbol[(uint32_t)node->symbol] = hcode; + // printf("k %d, code :%s symbol %d-> %c\n",k, hcode->code, node->symbol, node->symbol); + } + + //We concatenate a 0 for each step to the left + if(node->left!=NULL) { + code[k] = '0'; + build_symbol(node->left, k+1,code); } - // tree building subroutine - while(pq.count()>1) - { - int prio1, prio2, newprio; - HuffNode * node1, *node2, *new_node; - - node1 = pq.top(&prio1); pq.dequeue(); - node2 = pq.top(&prio2); pq.dequeue(); - - newprio = prio1+prio2; - - new_node = new HuffNode; - new_node->left = node1; - new_node->right = node2; - - pq.queue(new_node, newprio); - } - - // set root - int prio; - m_root = pq.top(&prio); - pq.dequeue(); - - // construct symbol lookup table - char code[256]; - build_symbol(m_root, 0, code); - }; - - /** - * building symbol lookup table - */ - void build_symbol(struct HuffNode * node, int k, char code[256]) { - //If we reach the leaf node we introduce the code in the table - if(node->left == NULL && node->right == NULL) - { - code[k] = '\0'; - HuffCode hcode; - strncpy(hcode.code, code, k); - hcode.length = k; - m_symbol[(uint32_t)node->symbol] = hcode; - // printf("k %d, code :%s symbol %d-> %c\n",k, hcode->code, node->symbol, node->symbol); - } - - //We concatenate a 0 for each step to the left - if(node->left!=NULL) - { - code[k] = '0'; - build_symbol(node->left, k+1,code); - } - - //We concatenate a 1 for each step to the right - if(node->right!=NULL) - { - code[k] = '1'; - build_symbol(node->right, k+1,code); - } - }; + //We concatenate a 1 for each step to the right + if(node->right!=NULL) { + code[k] = '1'; + build_symbol(node->right, k+1,code); + } + }; }; } diff --git a/include/imath.h b/include/imath.h index 252c70c9..b3fa2430 100644 --- a/include/imath.h +++ b/include/imath.h @@ -8,21 +8,19 @@ * COMMON MATH OPS * ******************************************************************************/ - -#ifndef __IMATH_H__ -#define __IMATH_H__ + +#ifndef ALGO_IMATH_H__ +#define ALGO_IMATH_H__ #include #include #include -namespace alg -{ +namespace alg { /** * dot product of given arrays K and A of len, saved in SUM */ - static uint32_t dot_product(const uint32_t * K, const uint32_t * A, uint32_t len) - { + static uint32_t dot_product(const uint32_t * K, const uint32_t * A, uint32_t len) { uint32_t i; uint32_t sum = 0; for (i=0; i> 1; // Set v's trailing 0s to 1s and zero rest - for (c = 0; v; c++) { - v >>= 1; - } + v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest + for (c = 0; v; c++) { + v >>= 1; + } } else { - c = CHAR_BIT * sizeof(v); + c = CHAR_BIT * sizeof(v); } return c; diff --git a/include/insertion_sort.h b/include/insertion_sort.h index 9a72a9e4..eb9f58ef 100644 --- a/include/insertion_sort.h +++ b/include/insertion_sort.h @@ -13,30 +13,26 @@ * ******************************************************************************/ -#ifndef __INSERTION_SORT_H__ -#define __INSERTION_SORT_H__ +#ifndef ALGO_INSERTION_SORT_H__ +#define ALGO_INSERTION_SORT_H__ -namespace alg -{ +namespace alg { /** * insertion sort an array */ template - static void insertion_sort(T *array , int number_of_elements) - { - int iter,jter; - for(iter=1;iter=0 && array[jter] > current_element) - { - array[jter+1] = array[jter]; - jter--; + static void insertion_sort(T *array , int number_of_elements) { + int iter,jter; + for(iter=1;iter=0 && array[jter] > current_element) { + array[jter+1] = array[jter]; + jter--; + } + array[jter+1] = current_element; } - array[jter+1] = current_element; } - } } #endif // diff --git a/include/integer.h b/include/integer.h index dc1887d3..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 @@ -23,306 +23,288 @@ #include #include "generic.h" -namespace alg -{ - class Integer - { - private: - typedef unsigned short component_t; - typedef unsigned long double_component_t; - - #define Max_COMPONENT ((component_t)(-1)) - #define COMPONENT_BITS (sizeof(component_t)*CHAR_BIT) - - #define LOG_2_10 3.3219280948873623478703194294894 - - component_t* c; /* least-significant word first */ - int num_components; - - public: - Integer(int components) - { - num_components = components; - c = new component_t[components]; - memset(c, 0, sizeof(component_t)*num_components); - } - - Integer(const Integer & rhs) - { - num_components = rhs.size(); - c = new component_t[num_components]; - memcpy(c, rhs.components(), num_components*sizeof(component_t)); - } - - ~Integer() - { - delete [] c; - } - - inline const component_t & operator[] (int i) const { return c[i]; } - inline component_t & operator[] (int i) { return c[i]; } - - inline const component_t * components() const { return c; } - inline uint32_t size() const { return num_components; } - - static const Integer from_string(const char* s) - { - Integer result((int)ceil(LOG_2_10*strlen(s)/COMPONENT_BITS)); - Integer digit(1); - - int i; - for (i = 0; s[i] != '\0'; i++) { - result = result*10; - digit[0] = s[i] - '0'; - result = result + digit; - } +namespace alg { + class Integer { + private: + typedef unsigned short component_t; + typedef unsigned long double_component_t; - return result; - } +#define Max_COMPONENT ((component_t)(-1)) +#define COMPONENT_BITS (sizeof(component_t)*CHAR_BIT) - char * to_string() const - { - Integer x = (*this); - int i, result_len; - char* result = new char[(int)ceil(COMPONENT_BITS*size()/LOG_2_10) + 2]; +#define LOG_2_10 3.3219280948873623478703194294894 - Integer ten(1); - ten[0] = 10; + component_t* c; /* least-significant word first */ + int num_components; - if (x.is_zero()) { - strcpy(result, "0"); - } else { - for (i = 0; !x.is_zero(); i++) { - result[i] = (char)(x%10) + '0'; - x=x/10; - } - result[i] = '\0'; + public: + Integer(int components) { + num_components = components; + c = new component_t[components]; + memset(c, 0, sizeof(component_t)*num_components); } - result_len = strlen(result); - for(i=0; i < result_len/2; i++) { - char temp = result[i]; - result[i] = result[result_len - i - 1]; - result[result_len - i - 1] = temp; + Integer(const Integer & rhs) { + num_components = rhs.size(); + c = new component_t[num_components]; + memcpy(c, rhs.components(), num_components*sizeof(component_t)); } - return result; - } - - bool is_zero() - { - uint32_t i; - for(i=0; i < size(); i++) { - if ((*this)[i] != 0) return false; + ~Integer() { + delete [] c; } - return true; - } - // Integer Assignment - Integer & operator= (const Integer & source) - { - memmove(c, source.components(), sizeof(component_t)*Min(source.size(), size())); + inline const component_t & operator[] (int i) const { return c[i]; } + inline component_t & operator[] (int i) { return c[i]; } - if (size() > source.size()) { - memset(c + source.size(), 0, sizeof(component_t)*(size() - source.size())); - } + inline const component_t * components() const { return c; } + inline uint32_t size() const { return num_components; } + + static const Integer from_string(const char* s) { + Integer result((int)ceil(LOG_2_10*strlen(s)/COMPONENT_BITS)); + Integer digit(1); - return (*this); - } - - const Integer operator+ (const Integer & rhs) - { - Integer result(Max(size(), rhs.size())+1); - - double_component_t carry = 0; - uint32_t i; - for(i=0; i Max_COMPONENT) { - partial_sum &= Max_COMPONENT; - carry = 1; + int i; + for (i = 0; s[i] != '\0'; i++) { + result = result*10; + digit[0] = s[i] - '0'; + result = result + digit; } - result[i] = (component_t)partial_sum; + + return result; } - for ( ; i < result.size(); i++) { result[i] = 0; } - - return result; - } - - const Integer operator- (const Integer & right) - { - Integer result(Max(size(), right.size())); - - int borrow = 0; - uint32_t i; - for(i=0; i> COMPONENT_BITS; - result[i] = (component_t)(partial_sum & Max_COMPONENT); + + bool is_zero() { + uint32_t i; + for(i=0; i < size(); i++) { + if ((*this)[i] != 0) return false; + } + return true; } - return result; - } - - const Integer operator* (const Integer & rhs) - { - Integer result(Max(size(), rhs.size())*2); - - uint32_t i, lidx, ridx; - double_component_t carry = 0; - uint32_t max_size_no_carry; - uint32_t left_max_component = size() - 1; - uint32_t right_max_component = rhs.size() - 1; - while((*this)[left_max_component] == 0) left_max_component--; - while(rhs[right_max_component] == 0) right_max_component--; - max_size_no_carry = left_max_component + right_max_component; - for(i=0; i <= max_size_no_carry || carry != 0; i++) { - double_component_t partial_sum = carry; - carry = 0; - lidx = Min(i, left_max_component); - ridx = i - lidx; - while(lidx >= 0 && ridx <= right_max_component) { - partial_sum += ((double_component_t)(*this)[lidx])*rhs[ridx]; - carry += partial_sum >> COMPONENT_BITS; - partial_sum &= Max_COMPONENT; - lidx--; ridx++; + + // Integer Assignment + Integer & operator= (const Integer & source) + { + memmove(c, source.components(), sizeof(component_t)*Min(source.size(), size())); + + if (size() > source.size()) { + memset(c + source.size(), 0, sizeof(component_t)*(size() - source.size())); } - result[i] = partial_sum; + + return (*this); } - for ( ; i < result.size(); i++) { result[i] = 0; } - return result; - } - - const Integer operator/ (component_t rhs) - { - Integer result(size()); - double_component_t dividend = 0; - int i; - for (i = size() - 1; i >= 0; i--) { - dividend |= (*this)[i]; - result[i] = dividend/rhs; - dividend = (dividend % rhs) << COMPONENT_BITS; + + const Integer operator+ (const Integer & rhs) { + Integer result(Max(size(), rhs.size())+1); + + double_component_t carry = 0; + uint32_t i; + for(i=0; i Max_COMPONENT) { + partial_sum &= Max_COMPONENT; + carry = 1; + } + result[i] = (component_t)partial_sum; + } + for ( ; i < result.size(); i++) { result[i] = 0; } + + return result; } - return result; - } - - component_t operator% (component_t right) - { - double_component_t mod_two_power = 1; - double_component_t result = 0; - uint32_t i, bit; - for(i=0; i= right) { - result -= right; + const Integer operator- (const Integer & right) { + Integer result(Max(size(), right.size())); + + int borrow = 0; + uint32_t i; + for(i=0; i= right) { - mod_two_power -= right; + if (lhs < rhs) { + borrow = 1; + lhs += Max_COMPONENT + 1; } + result[i] = lhs - rhs; } + for ( ; i < result.size(); i++) { result[i] = 0; } + + return result; } - return (component_t)result; - } - - const Integer operator% (const Integer & rhs) - { - Integer result = rhs; - Integer mod_two_power(rhs.size() + 1); - - uint32_t i, bit; - mod_two_power[0] = 1; - for(i=0; i= 0) { - result = result - rhs; + + const Integer operator* (const component_t & rhs) { + Integer result(size()+1); + + double_component_t carry = 0; + uint32_t i; + for(i=0; i> COMPONENT_BITS; + result[i] = (component_t)(partial_sum & Max_COMPONENT); + } + return result; + } + + const Integer operator* (const Integer & rhs) { + Integer result(Max(size(), rhs.size())*2); + + uint32_t i, lidx, ridx; + double_component_t carry = 0; + uint32_t max_size_no_carry; + uint32_t left_max_component = size() - 1; + uint32_t right_max_component = rhs.size() - 1; + while((*this)[left_max_component] == 0) left_max_component--; + while(rhs[right_max_component] == 0) right_max_component--; + max_size_no_carry = left_max_component + right_max_component; + for(i=0; i <= max_size_no_carry || carry != 0; i++) { + double_component_t partial_sum = carry; + carry = 0; + lidx = Min(i, left_max_component); + ridx = i - lidx; + while(lidx >= 0 && ridx <= right_max_component) { + partial_sum += ((double_component_t)(*this)[lidx])*rhs[ridx]; + carry += partial_sum >> COMPONENT_BITS; + partial_sum &= Max_COMPONENT; + lidx--; ridx++; + } + result[i] = partial_sum; + } + for ( ; i < result.size(); i++) { result[i] = 0; } + return result; + } + + const Integer operator/ (component_t rhs) { + Integer result(size()); + double_component_t dividend = 0; + int i; + for (i = size() - 1; i >= 0; i--) { + dividend |= (*this)[i]; + result[i] = dividend/rhs; + dividend = (dividend % rhs) << COMPONENT_BITS; + } + + return result; + } + + component_t operator% (component_t right) { + double_component_t mod_two_power = 1; + double_component_t result = 0; + uint32_t i, bit; + for(i=0; i= right) { + result -= right; + } + } + mod_two_power <<= 1; + if (mod_two_power >= right) { + mod_two_power -= right; } } - mod_two_power.shift_left_one_integer(); - if (mod_two_power.compare(rhs) >= 0) { - mod_two_power = mod_two_power - rhs; + } + return (component_t)result; + } + + const Integer operator% (const Integer & rhs) { + Integer result = rhs; + Integer mod_two_power(rhs.size() + 1); + + uint32_t i, bit; + mod_two_power[0] = 1; + for(i=0; i= 0) { + result = result - rhs; + } + } + mod_two_power.shift_left_one_integer(); + if (mod_two_power.compare(rhs) >= 0) { + mod_two_power = mod_two_power - rhs; + } } } + + return result; } - return result; - } - - int compare(const Integer & rhs) - { - uint32_t i = Max(size() - 1, rhs.size() - 1); - for ( ; i >= 0; i--) { - component_t left_comp = - (i < size()) ? (*this)[i] : 0; - component_t right_comp = - (i < rhs.size()) ? rhs[i] : 0; - if (left_comp < right_comp) - return -1; - else if (left_comp > right_comp) - return 1; + int compare(const Integer & rhs) { + uint32_t i = Max(size() - 1, rhs.size() - 1); + for ( ; i >= 0; i--) { + component_t left_comp = + (i < size()) ? (*this)[i] : 0; + component_t right_comp = + (i < rhs.size()) ? rhs[i] : 0; + if (left_comp < right_comp) + return -1; + else if (left_comp > right_comp) + return 1; + } + return 0; } - return 0; - } - -private: - void shift_left_one_integer() - { - uint32_t i; - (*this)[size() - 1] <<= 1; - for (i = size() - 2; i >= 0; i--) { - (*this)[i + 1] |= (*this)[i] >> (COMPONENT_BITS - 1); - (*this)[i] <<= 1; + + private: + void shift_left_one_integer() { + uint32_t i; + (*this)[size() - 1] <<= 1; + for (i = size() - 2; i >= 0; i--) { + (*this)[i + 1] |= (*this)[i] >> (COMPONENT_BITS - 1); + (*this)[i] <<= 1; + } } - } - - void shift_right_one_integer() - { - uint32_t i; - (*this)[0] >>= 1; - for (i = 1; i < size(); i++) { - (*this)[i - 1] |= ((*this)[i] & 1) << (COMPONENT_BITS - 1); - (*this)[i] >>= 1; + + void shift_right_one_integer() { + uint32_t i; + (*this)[0] >>= 1; + for (i = 1; i < size(); i++) { + (*this)[i - 1] |= ((*this)[i] & 1) << (COMPONENT_BITS - 1); + (*this)[i] >>= 1; + } } - } }; } diff --git a/include/interval_tree.h b/include/interval_tree.h index d87b913d..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 @@ -27,230 +27,211 @@ #include "double_linked_list.h" #include "rbtree.h" -namespace alg -{ - class IntervalTree:public RBTreeAbstract - { - public: - /** - * Interval-Tree node definition - */ - typedef struct ivltree_node_t : public rbtree_node_t { - int low; // lower-bound - int high; // higher-bound - int m; // max subtree upper bound value - } * ivltree_node; +namespace alg { + class IntervalTree:public RBTreeAbstract { + public: + /** + * Interval-Tree node definition + */ + typedef struct ivltree_node_t : public rbtree_node_t { + int low; // lower-bound + int high; // higher-bound + int m; // max subtree upper bound value + } * ivltree_node; #define IVLNODE(rbnode) static_cast(rbnode) #define IVLNODE_M(rbnode) (rbnode?IVLNODE(rbnode)->m:INT_MIN) - public: - /** - * ivltree_create - * initialized an interval tree - * same as init an red-black tree - */ - IntervalTree() { } + public: + /** + * ivltree_create + * initialized an interval tree + * same as init an red-black tree + */ + IntervalTree() { } + + /** + * ivltree_lookup + * + * search range [low, high] for overlap, return only one element + * use lookup & delete & insert schema to get multiple elements + * + * NULL is returned if not found. + */ + ivltree_node lookup(int low, int high) { + ivltree_node n = IVLNODE(get_root()); + while (n != NULL && (low > n->high || n->low > high)) { // should search in childs + if (n->left !=NULL && low <=IVLNODE(n->left)->m) n = IVLNODE(n->left); // path choice on m. + else n = IVLNODE(n->right); + } - /** - * ivltree_lookup - * - * search range [low, high] for overlap, return only one element - * use lookup & delete & insert schema to get multiple elements - * - * NULL is returned if not found. - */ - ivltree_node lookup(int low, int high) - { - ivltree_node n = IVLNODE(get_root()); - while (n != NULL && (low > n->high || n->low > high)) { // should search in childs - if (n->left !=NULL && low <=IVLNODE(n->left)->m) n = IVLNODE(n->left); // path choice on m. - else n = IVLNODE(n->right); + return n; } - return n; - } - - /** - * ivltree_insert - * insert range [low, high] into red-black tree - */ - void insert(int low, int high) - { - ivltree_node inserted_node = new_node(low, high, RED, NULL, NULL); - if (get_root() == NULL) { - set_root(inserted_node); - } else { - ivltree_node n = IVLNODE(get_root()); - while (1) { - // update 'm' for each node traversed from root - if (inserted_node->m > n->m) { - n->m = inserted_node->m; - } - - // find a proper position - if (low < n->low) { - if (n->left == NULL) { - n->left = inserted_node; - break; - } else { - n = IVLNODE(n->left); + /** + * ivltree_insert + * insert range [low, high] into red-black tree + */ + void insert(int low, int high) { + ivltree_node inserted_node = new_node(low, high, RED, NULL, NULL); + if (get_root() == NULL) { + set_root(inserted_node); + } else { + ivltree_node n = IVLNODE(get_root()); + while (1) { + // update 'm' for each node traversed from root + if (inserted_node->m > n->m) { + n->m = inserted_node->m; } - } else { - if (n->right == NULL) { - n->right = inserted_node; - break; + + // find a proper position + if (low < n->low) { + if (n->left == NULL) { + n->left = inserted_node; + break; + } else { + n = IVLNODE(n->left); + } } else { - n = IVLNODE(n->right); + if (n->right == NULL) { + n->right = inserted_node; + break; + } else { + n = IVLNODE(n->right); + } } } + inserted_node->parent = n; } - inserted_node->parent = n; + insert_case1(inserted_node); } - insert_case1(inserted_node); - } - /** - * delete the key in the red-black tree - */ - void delete_key(ivltree_node n) - { - rbtree_node child; - if (n == NULL) return; + /** + * delete the key in the red-black tree + */ + void delete_key(ivltree_node n) { + rbtree_node child; + if (n == NULL) return; + + /* Copy fields from predecessor and then delete it instead */ + if (n->left != NULL && n->right != NULL) { + ivltree_node pred = IVLNODE(maximum_node(n->left)); + n->low = pred->low; + n->high= pred->high; + n = pred; + } - /* Copy fields from predecessor and then delete it instead */ - if (n->left != NULL && n->right != NULL) { - ivltree_node pred = IVLNODE(maximum_node(n->left)); - n->low = pred->low; - n->high= pred->high; - n = pred; - } - - // fixup the 'm' value until m is not the max value of the path. - fixup_m(n); + // fixup the 'm' value until m is not the max value of the path. + fixup_m(n); - assert(n->left == NULL || n->right == NULL); - child = n->right == NULL ? n->left : n->right; - if (node_color(n) == BLACK) { - n->color = node_color(child); - delete_case1(n); - } + assert(n->left == NULL || n->right == NULL); + child = n->right == NULL ? n->left : n->right; + if (node_color(n) == BLACK) { + n->color = node_color(child); + delete_case1(n); + } - replace_node(n, child); - // copy child value if exists, add your fields if you got one - if (child != NULL) { - IVLNODE(n)->low = IVLNODE(child)->low; - IVLNODE(n)->high = IVLNODE(child)->high; + replace_node(n, child); + if (n->parent == NULL && child != NULL) // root + child->color = BLACK; + delete(n); } - if (n->parent == NULL && child != NULL) - child->color = BLACK; - - delete(n); - } + void print() { + print_helper(IVLNODE(get_root()), 0); + puts(""); + } - void print() { - print_helper(IVLNODE(get_root()), 0); - puts(""); - } + void print_helper(ivltree_node n, int indent) { + int i; - void print_helper(ivltree_node n, int indent) { - int i; + if (n == NULL) { + fputs("", stdout); + return; + } - if (n == NULL) { - fputs("", stdout); - return; + if (n->right != NULL) { + print_helper(IVLNODE(n->right), indent + INDENT_STEP); + } + for(i=0; icolor == BLACK) + printf("[%d %d, m->%d]\n", n->low,n->high,n->m); + else + printf("*[%d %d, m->%d]\n", n->low, n->high,n->m); + if (n->left != NULL) { + print_helper(IVLNODE(n->left), indent + INDENT_STEP); + } } - if (n->right != NULL) { - print_helper(IVLNODE(n->right), indent + INDENT_STEP); - } - for(i=0; icolor == BLACK) - printf("[%d %d, m->%d]\n", n->low,n->high,n->m); - else - printf("*[%d %d, m->%d]\n", n->low, n->high,n->m); - if (n->left != NULL) { - print_helper(IVLNODE(n->left), indent + INDENT_STEP); + ~IntervalTree() { + destruct(IVLNODE(get_root())); } - } - - ~IntervalTree() - { - destruct(IVLNODE(get_root())); - } - - private: - - void destruct(ivltree_node n) - { - if (n==NULL) return; - destruct(IVLNODE(n->left)); - destruct(IVLNODE(n->right)); - delete n; - } - /** - * fix 'm' value caused by rotation - */ - void rotate_left_callback(rbtree_node n, rbtree_node parent) - { - // parent inherit max m value - IVLNODE(parent)->m = IVLNODE(n)->m; - // update node 'm' value by it's children. - IVLNODE(n)->m = Max(IVLNODE(n)->high, Max(IVLNODE_M(n->left), IVLNODE_M(n->right))); - } - - void rotate_right_callback(rbtree_node n, rbtree_node parent) - { - rotate_left_callback(n, parent); - } - - /** - * fix up 'm' value caued by deletion - */ - void fixup_m(rbtree_node n) - { - int m = IVLNODE(n)->m; - int m_new = Max(IVLNODE_M(n->left), IVLNODE_M(n->right)); + private: + void destruct(ivltree_node n) { + if (n==NULL) return; + destruct(IVLNODE(n->left)); + destruct(IVLNODE(n->right)); + delete n; + } - // if current 'm' is not decided by n->high, just return. - if (m==m_new) return; + /** + * fix 'm' value caused by rotation + */ + void rotate_left_callback(rbtree_node n, rbtree_node parent) { + // parent inherit max m value + IVLNODE(parent)->m = IVLNODE(n)->m; + // update node 'm' value by it's children. + IVLNODE(n)->m = Max(IVLNODE(n)->high, Max(IVLNODE_M(n->left), IVLNODE_M(n->right))); + } - while(n->parent !=NULL) { - /* - parent(high) - / \ - n(m_new) sibling(m) - - */ - IVLNODE(n->parent)->m = - Max(IVLNODE(n->parent)->high, Max(m_new, IVLNODE_M(sibling(n)))); + void rotate_right_callback(rbtree_node n, rbtree_node parent) { + rotate_left_callback(n, parent); + } - if(IVLNODE_M(n->parent) > m) break; // since node n does not affect - // the result anymore, we break. - n = n->parent; + /** + * fix up 'm' value caued by deletion + */ + void fixup_m(rbtree_node n) { + int m = IVLNODE(n)->m; + int m_new = Max(IVLNODE_M(n->left), IVLNODE_M(n->right)); + + // if current 'm' is not decided by n->high, just return. + if (m==m_new) return; + + while(n->parent !=NULL) { + /* + parent(high) + / \ + n(m_new) sibling(m) + + */ + IVLNODE(n->parent)->m = + Max(IVLNODE(n->parent)->high, Max(m_new, IVLNODE_M(sibling(n)))); + + if(IVLNODE_M(n->parent) > m) break; // since node n does not affect + // the result anymore, we break. + n = n->parent; + } } - } - /** - * create a new node, and set default vales. - */ - ivltree_node new_node(int low, int high, color rbtree_node_color, rbtree_node left, rbtree_node right) - { - ivltree_node result = new ivltree_node_t; - result->low = low; - result->high = high; - result->m = high; - result->color = rbtree_node_color; - result->left = left; - result->right = right; - if(left !=NULL) left->parent = result; - if(right!=NULL) right->parent = result; - result->parent = NULL; - return result; - } + /** + * create a new node, and set default vales. + */ + ivltree_node new_node(int low, int high, color rbtree_node_color, rbtree_node left, rbtree_node right) { + ivltree_node result = new ivltree_node_t; + result->low = low; + result->high = high; + result->m = high; + result->color = rbtree_node_color; + result->left = left; + result->right = right; + if(left !=NULL) left->parent = result; + if(right!=NULL) right->parent = result; + result->parent = NULL; + return result; + } }; } diff --git a/include/k-means.h b/include/k-means.h index 3ad60138..86fdef3c 100644 --- a/include/k-means.h +++ b/include/k-means.h @@ -11,9 +11,9 @@ * First Contributor: * https://github.com/wycg1984 ******************************************************************************/ - -#ifndef __KMEANS_H__ -#define __KMEANS_H__ + +#ifndef ALGO_KMEANS_H__ +#define ALGO_KMEANS_H__ #include #include #include @@ -23,26 +23,21 @@ #include using namespace std; -namespace alg -{ - class KMeans - { +namespace alg { + class KMeans { public: - enum InitMode - { + enum InitMode { InitRandom, InitManual, InitUniform, }; - - KMeans(int dimNum = 1, int clusterNum = 1) - { + + KMeans(int dimNum = 1, int clusterNum = 1) { m_dimNum = dimNum; m_clusterNum = clusterNum; m_means = new double*[m_clusterNum]; - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { m_means[i] = new double[m_dimNum]; memset(m_means[i], 0, sizeof(double) * m_dimNum); } @@ -51,50 +46,48 @@ namespace alg m_maxIterNum = 100; m_endError = 0.001; } - - ~KMeans() - { + + ~KMeans() { for(int i = 0; i < m_clusterNum; i++) { delete[] m_means[i]; } delete[] m_means; } - void SetMean(int i, const double* u) - { + + void SetMean(int i, const double* u) { memcpy(m_means[i], u, sizeof(double) * m_dimNum); } - void SetInitMode(int i) - { + + void SetInitMode(int i) { m_initMode = i; } - void SetMaxIterNum(int i) - { + + void SetMaxIterNum(int i) { m_maxIterNum = i; } - void SetEndError(double f) - { + + void SetEndError(double f) { m_endError = f; } - double* GetMean(int i) - { + double* GetMean(int i) { return m_means[i]; } - int GetInitMode() - { + + int GetInitMode() { return m_initMode; } - int GetMaxIterNum() - { + + int GetMaxIterNum() { return m_maxIterNum; } - double GetEndError() - { + + double GetEndError() { return m_endError; } - void Cluster(const char* sampleFileName, const char* labelFileName) - { + + void Cluster(const char* sampleFileName, const char* labelFileName) { // Check the sample file ifstream sampleFile(sampleFileName, ios_base::binary); assert(sampleFile); @@ -120,13 +113,11 @@ namespace alg int* counts = new int[m_clusterNum]; double** next_means = new double*[m_clusterNum]; // New model for reestimation - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { next_means[i] = new double[m_dimNum]; } - while(loop) - { + while(loop) { //clean buffer for classification memset(counts, 0, sizeof(int) * m_clusterNum); for(int i = 0; i < m_clusterNum; i++) @@ -141,24 +132,20 @@ namespace alg sampleFile.seekg(sizeof(int) * 2, ios_base::beg); // Classification - for(int i = 0; i < size; i++) - { + for(int i = 0; i < size; i++) { sampleFile.read((char*)x, sizeof(double) * m_dimNum); currCost += GetLabel(x, &label); counts[label]++; - for(int d = 0; d < m_dimNum; d++) - { + for(int d = 0; d < m_dimNum; d++) { next_means[label][d] += x[d]; } } currCost /= size; // Reestimation - for(int i = 0; i < m_clusterNum; i++) - { - if(counts[i] > 0) - { + for(int i = 0; i < m_clusterNum; i++) { + if(counts[i] > 0) { for(int d = 0; d < m_dimNum; d++) { next_means[i][d] /= counts[i]; @@ -169,12 +156,11 @@ namespace alg // Terminal conditions iterNum++; - if(fabs(lastCost - currCost) < m_endError * lastCost) - { + if(fabs(lastCost - currCost) < m_endError * lastCost) { unchanged++; } - if(iterNum >= m_maxIterNum || unchanged >= 3) - { + + if(iterNum >= m_maxIterNum || unchanged >= 3) { loop = false; } } @@ -187,8 +173,7 @@ namespace alg sampleFile.clear(); sampleFile.seekg(sizeof(int) * 2, ios_base::beg); - for(int i = 0; i < size; i++) - { + for(int i = 0; i < size; i++) { sampleFile.read((char*)x, sizeof(double) * m_dimNum); GetLabel(x, &label); labelFile.write((char*)&label, sizeof(int)); @@ -199,28 +184,25 @@ namespace alg delete[] counts; delete[] x; - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { delete[] next_means[i]; } delete[] next_means; } - void Init(std::ifstream& sampleFile) - { + + void Init(std::ifstream& sampleFile) { int size = 0; sampleFile.seekg(0, ios_base::beg); sampleFile.read((char*)&size, sizeof(int)); - if(m_initMode == InitRandom) - { + if (m_initMode == InitRandom) { int inteval = size / m_clusterNum; double* sample = new double[m_dimNum]; // Seed the random-number generator with current time srand((unsigned)time(NULL)); - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { int select = inteval * i + (inteval - 1) * rand() / RAND_MAX; int offset = sizeof(int) * 2 + select * sizeof(double) * m_dimNum; @@ -230,13 +212,10 @@ namespace alg } delete[] sample; - } - else if(m_initMode == InitUniform) - { + } else if(m_initMode == InitUniform) { double* sample = new double[m_dimNum]; - for (int i = 0; i < m_clusterNum; i++) - { + for (int i = 0; i < m_clusterNum; i++) { int select = i * size / m_clusterNum; int offset = sizeof(int) * 2 + select * sizeof(double) * m_dimNum; @@ -246,26 +225,22 @@ namespace alg } delete[] sample; - } - else if(m_initMode == InitManual) - { + } else if(m_initMode == InitManual) { // Do nothing } } - void Init(double *data, int N) - { + + void Init(double *data, int N) { int size = N; - if(m_initMode == InitRandom) - { + if(m_initMode == InitRandom) { int inteval = size / m_clusterNum; double* sample = new double[m_dimNum]; // Seed the random-number generator with current time srand((unsigned)time(NULL)); - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { int select = inteval * i + (inteval - 1) * rand() / RAND_MAX; for(int j = 0; j < m_dimNum; j++) sample[j] = data[select*m_dimNum+j]; @@ -273,13 +248,10 @@ namespace alg } delete[] sample; - } - else if(m_initMode == InitUniform) - { + } else if(m_initMode == InitUniform) { double* sample = new double[m_dimNum]; - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { int select = i * size / m_clusterNum; for(int j = 0; j < m_dimNum; j++) sample[j] = data[select*m_dimNum+j]; @@ -287,14 +259,12 @@ namespace alg } delete[] sample; - } - else if(m_initMode == InitManual) - { + } else if(m_initMode == InitManual) { // Do nothing } } - void Cluster(double *data, int N, int *Label) - { + + void Cluster(double *data, int N, int *Label) { int size = 0; size = N; @@ -314,13 +284,11 @@ namespace alg int* counts = new int[m_clusterNum]; double** next_means = new double*[m_clusterNum]; // New model for reestimation - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { next_means[i] = new double[m_dimNum]; } - while(loop) - { + while(loop) { //clean buffer for classification memset(counts, 0, sizeof(int) * m_clusterNum); for(int i = 0; i < m_clusterNum; i++) @@ -332,8 +300,7 @@ namespace alg currCost = 0; // Classification - for(int i = 0; i < size; i++) - { + for(int i = 0; i < size; i++) { for(int j = 0; j < m_dimNum; j++) x[j] = data[i*m_dimNum+j]; @@ -348,12 +315,9 @@ namespace alg currCost /= size; // Reestimation - for(int i = 0; i < m_clusterNum; i++) - { - if(counts[i] > 0) - { - for(int d = 0; d < m_dimNum; d++) - { + for(int i = 0; i < m_clusterNum; i++) { + if(counts[i] > 0) { + for(int d = 0; d < m_dimNum; d++) { next_means[i][d] /= counts[i]; } memcpy(m_means[i], next_means[i], sizeof(double) * m_dimNum); @@ -362,10 +326,10 @@ namespace alg // Terminal conditions iterNum++; - if(fabs(lastCost - currCost) < m_endError * lastCost) - { + if(fabs(lastCost - currCost) < m_endError * lastCost) { unchanged++; } + if(iterNum >= m_maxIterNum || unchanged >= 3) { loop = false; @@ -373,8 +337,7 @@ namespace alg } // Output the label file - for(int i = 0; i < size; i++) - { + for(int i = 0; i < size; i++) { for(int j = 0; j < m_dimNum; j++) x[j] = data[i*m_dimNum+j]; GetLabel(x,&label); @@ -382,23 +345,20 @@ namespace alg } delete[] counts; delete[] x; - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { delete[] next_means[i]; } delete[] next_means; } - friend std::ostream& operator<<(std::ostream& out, KMeans& kmeans) - { + + friend std::ostream& operator<<(std::ostream& out, KMeans& kmeans) { out << "" << endl; out << " " << kmeans.m_dimNum << " " << endl; out << " " << kmeans.m_clusterNum << " " << endl; out << "" << endl; - for(int i = 0; i < kmeans.m_clusterNum; i++) - { - for(int d = 0; d < kmeans.m_dimNum; d++) - { + for(int i = 0; i < kmeans.m_clusterNum; i++) { + for(int d = 0; d < kmeans.m_dimNum; d++) { out << kmeans.m_means[i][d] << " "; } out << endl; @@ -412,34 +372,29 @@ namespace alg int m_dimNum; int m_clusterNum; double** m_means; - + int m_initMode; int m_maxIterNum; double m_endError; - double GetLabel(const double* sample, int* label) - { + double GetLabel(const double* sample, int* label) { double dist = -1; - for(int i = 0; i < m_clusterNum; i++) - { + for(int i = 0; i < m_clusterNum; i++) { double temp = CalcDistance(sample, m_means[i], m_dimNum); - if(temp < dist || dist == -1) - { + if(temp < dist || dist == -1) { dist = temp; *label = i; } } return dist; } - - double CalcDistance(const double* x,const double* u,int dimNum) - { + + double CalcDistance(const double* x,const double* u,int dimNum) { double temp = 0; - for(int d = 0; d < dimNum; d++) - { + for(int d = 0; d < dimNum; d++) { temp += (x[d] - u[d]) * (x[d] - u[d]); } return sqrt(temp); } - }; - } + }; +} #endif diff --git a/include/kmp.h b/include/kmp.h index 12df81b5..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 { @@ -33,7 +33,7 @@ namespace alg { int m = 0; int i = 0; int T[LEN_W]; - + kmp_table(W,T, LEN_W); while (m+i < LEN_S) { diff --git a/include/kruskal_mst.h b/include/kruskal_mst.h index 0a5f00dc..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 @@ -34,125 +34,122 @@ #include "double_linked_list.h" #include "heap.h" -namespace alg -{ - class Kruskal - { - private: - /** - * Kruskal's Adjacent Lists, for Kruskal's Algorithm caculation - */ - struct KruskalAdjacent { - Heap heap; // binary heap representation of weight->node - // the top of the heap is always the minimal element - const Graph::Vertex & v; - - KruskalAdjacent(const Graph::Vertex & vertex, uint32_t num_neigh):heap(num_neigh),v(vertex) { } - - struct list_head pa_node; - }; - - /** - * Kruskal's Graph, simplified to list. - */ - typedef struct list_head KruskalGraph; - private: - KruskalGraph m_pg; - uint32_t num_vertex; - public: - /** - * construct Kruskal's DataStrcuture by a given graph - */ - Kruskal(const Graph & g) { - INIT_LIST_HEAD(&m_pg); - - Graph::Adjacent * a; - list_for_each_entry(a, &g.list(), a_node){ - add_adjacent(*a); - } - this->num_vertex=g.vertex_count(); - } - - ~Kruskal() { - KruskalAdjacent * pa, *pan; - list_for_each_entry_safe(pa, pan, &m_pg, pa_node){ - list_del(&pa->pa_node); - delete pa; +namespace alg { + class Kruskal { + private: + /** + * Kruskal's Adjacent Lists, for Kruskal's Algorithm caculation + */ + struct KruskalAdjacent { + Heap heap; // binary heap representation of weight->node + // the top of the heap is always the minimal element + const Graph::Vertex & v; + + KruskalAdjacent(const Graph::Vertex & vertex, uint32_t num_neigh):heap(num_neigh),v(vertex) { } + + struct list_head pa_node; + }; + + /** + * Kruskal's Graph, simplified to list. + */ + typedef struct list_head KruskalGraph; + private: + KruskalGraph m_pg; + uint32_t num_vertex; + public: + /** + * construct Kruskal's DataStrcuture by a given graph + */ + Kruskal(const Graph & g) { + INIT_LIST_HEAD(&m_pg); + + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node){ + add_adjacent(*a); + } + this->num_vertex=g.vertex_count(); } - } - private: - Kruskal(const Kruskal&); - Kruskal& operator= (const Kruskal&); - private: - /** - * add an adjacent list to Kruskal's graph - */ - void add_adjacent(const Graph::Adjacent & a) { - KruskalAdjacent * pa = new KruskalAdjacent(a.vertex(), a.num_neigh); - list_add_tail(&pa->pa_node, &m_pg); - - Graph::Vertex * v; - list_for_each_entry(v, &a.v_head, v_node){ - pa->heap.insert(v->weight, v); // weight->vertex + + ~Kruskal() { + KruskalAdjacent * pa, *pan; + list_for_each_entry_safe(pa, pan, &m_pg, pa_node){ + list_del(&pa->pa_node); + delete pa; + } } - } - - /** - * lookup up a given id - * the related adjacent list is returned. - */ - KruskalAdjacent * lookup(uint32_t id) const { - KruskalAdjacent * pa; - list_for_each_entry(pa, &m_pg, pa_node){ - if (pa->v.id == id) { return pa;} + private: + Kruskal(const Kruskal&); + Kruskal& operator= (const Kruskal&); + private: + /** + * add an adjacent list to Kruskal's graph + */ + void add_adjacent(const Graph::Adjacent & a) { + KruskalAdjacent * pa = new KruskalAdjacent(a.vertex(), a.num_neigh); + list_add_tail(&pa->pa_node, &m_pg); + + Graph::Vertex * v; + list_for_each_entry(v, &a.v_head, v_node){ + pa->heap.push(v->weight, v); // weight->vertex + } } - return NULL; - } - public: - /** - * Kruskal's Algorithm. - * - * Input: A non-empty connected weighted graph with vertices V and edges E - * (the weights can be negative). - * - * Initialize: Enew = {} - * - * Repeat until edges = V-1: - * Choose an edge {u, v} with minimal weight and promise that two nodes come from different set - * - * Output: Vnew and Enew describe a minimal spanning tree - */ - Graph * run() { - UndirectedGraph * mst = new UndirectedGraph(); // empty Grapph - - uint32_t mark[num_vertex];// mark the different set - for(uint32_t i=0;iheap.is_empty()&&pa->heap.min_key()heap.min_key(); - v = pa->heap.min_value(); - best_to = v->id; - best_from = pa; - } + if (pa->v.id == id) { return pa;} } - // loop until the chosen edges to total_nodes-1 - if (flag<(total_nodes-1)&&(weight != INT_MAX)) { + return NULL; + } + public: + /** + * Kruskal's Algorithm. + * + * Input: A non-empty connected weighted graph with vertices V and edges E + * (the weights can be negative). + * + * Initialize: Enew = {} + * + * Repeat until edges = V-1: + * Choose an edge {u, v} with minimal weight and promise that two nodes come from different set + * + * Output: Vnew and Enew describe a minimal spanning tree + */ + Graph * run() { + UndirectedGraph * mst = new UndirectedGraph(); // empty Grapph + + uint32_t mark[num_vertex];// mark the different set + for(uint32_t i=0;iheap.is_empty()&&pa->heap.min_key()heap.min_key(); + v = pa->heap.min_value(); + best_to = v->id; + best_from = pa; + } + } + + // loop until the chosen edges to total_nodes-1 + if (flag<(total_nodes-1)&&(weight != INT_MAX)) { // if the node not been added,construct it if((*mst)[best_from->v.id]==NULL) { mst->add_vertex(best_from->v.id); @@ -162,7 +159,7 @@ namespace alg mst->add_vertex(best_to); } - // two nodes must belongs to set,to keep uncircle + // two nodes must belongs to set,to keep uncircle if(mark[best_from->v.id]!=mark[best_to]) { mst->add_edge(best_from->v.id, best_to, weight); @@ -176,27 +173,27 @@ namespace alg best_from->heap.delete_min(); lookup(best_to)->heap.delete_min(); - } else break; + } else break; + } + + return mst; } - return mst; - } - - /** - * print the KruskalGraph - */ - void print() { - struct KruskalAdjacent * pa; - printf("Kruskal Graph: \n"); - list_for_each_entry(pa, &m_pg, pa_node){ - printf("%d->{", pa->v.id); - for(uint32_t i=0;iheap.count();i++) { - Graph::Vertex * v = pa->heap[i]; - printf("id:%d->w:%d \t", v->id, v->weight); + /** + * print the KruskalGraph + */ + void print() { + struct KruskalAdjacent * pa; + printf("Kruskal Graph: \n"); + list_for_each_entry(pa, &m_pg, pa_node){ + printf("%d->{", pa->v.id); + for(uint32_t i=0;iheap.count();i++) { + Graph::Vertex * v = pa->heap[i]; + printf("id:%d->w:%d \t", v->id, v->weight); + } + printf("}\n"); } - printf("}\n"); } - } }; } diff --git a/include/lcs.h b/include/lcs.h index ba9ae484..ce218022 100644 --- a/include/lcs.h +++ b/include/lcs.h @@ -11,77 +11,74 @@ * ******************************************************************************/ -#ifndef __LCS_H__ -#define __LCS_H__ +#ifndef ALGO_LCS_H__ +#define ALGO_LCS_H__ #include "generic.h" #include "2darray.h" #include "stack.h" -namespace alg -{ +namespace alg { /** * calculate Length matrix * X -- array of size m * Y -- array of size n * eg: - 0 1 2 3 4 5 6 7 - Ø M Z J A W X U - 0 Ø 0 0 0 0 0 0 0 0 - 1 X 0 0 0 0 0 0 1 1 - 2 M 0 1 1 1 1 1 1 1 - 3 J 0 1 1 2 2 2 2 2 - 4 Y 0 1 1 2 2 2 2 2 - 5 A 0 1 1 2 3 3 3 3 - 6 U 0 1 1 2 3 3 3 4 - 7 Z 0 1 2 2 3 3 3 4 + 0 1 2 3 4 5 6 7 + Ø M Z J A W X U + 0 Ø 0 0 0 0 0 0 0 0 + 1 X 0 0 0 0 0 0 1 1 + 2 M 0 1 1 1 1 1 1 1 + 3 J 0 1 1 2 2 2 2 2 + 4 Y 0 1 1 2 2 2 2 2 + 5 A 0 1 1 2 3 3 3 3 + 6 U 0 1 1 2 3 3 3 4 + 7 Z 0 1 2 2 3 3 3 4 */ template - static Array2D * lcs_length(const T X[], uint32_t m, const T Y[], uint32_t n) - { - Array2D & A = *new Array2D(m+1,n+1); + static Array2D * lcs_length(const T X[], uint32_t m, const T Y[], uint32_t n) { + Array2D & A = *new Array2D(m+1,n+1); - uint32_t i,j; + uint32_t i,j; - // set initial state - for(i=0; i<=m; i++) { - A(i,0) = 0; - } - - for(j=0; j<=n; j++) { - A(0,j) = 0; - } + // set initial state + for(i=0; i<=m; i++) { + A(i,0) = 0; + } - for(i=1;i<=m;i++) { - for(j=1;j<=n;j++) { - if(X[i-1]==Y[j-1]) A(i,j) = A(i-1,j-1) + 1; - else A(i,j) = Max(A(i,j-1), A(i-1,j)); + for(j=0; j<=n; j++) { + A(0,j) = 0; } - } - return &A; - }; + for(i=1;i<=m;i++) { + for(j=1;j<=n;j++) { + if(X[i-1]==Y[j-1]) A(i,j) = A(i-1,j-1) + 1; + else A(i,j) = Max(A(i,j-1), A(i-1,j)); + } + } + + return &A; + }; /** * pass an empty stack, pop out the result in sequential order. */ template - static void lcs_backtrack(Stack & S, struct Array2D & A, - const T X[], const T Y[], - const uint32_t i, uint32_t j) - { - if (i==0 || j==0) return; - else if (X[i-1] == Y[j-1]) { - S.push(X[i-1]); - lcs_backtrack(S, A, X, Y, i-1, j-1); - } - else { - if (A(i, j-1) > A(i-1, j)) - lcs_backtrack(S, A, X, Y, i, j-1); - else - lcs_backtrack(S, A, X, Y, i-1, j); + static void lcs_backtrack(Stack & S, Array2D & A, + const T X[], const T Y[], + const uint32_t i, uint32_t j) { + if (i==0 || j==0) return; + else if (X[i-1] == Y[j-1]) { + S.push(X[i-1]); + lcs_backtrack(S, A, X, Y, i-1, j-1); + } + else { + if (A(i, j-1) > A(i-1, j)) + lcs_backtrack(S, A, X, Y, i, j-1); + else + lcs_backtrack(S, A, X, Y, i-1, j); + } } - } } #endif // diff --git a/include/max_subarray.h b/include/max_subarray.h new file mode 100644 index 00000000..96b0d943 --- /dev/null +++ b/include/max_subarray.h @@ -0,0 +1,56 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * MAXIMUM SUBARRAY + * + * In computer science, the maximum subarray problem is the task of finding the + * contiguous subarray within a one-dimensional array of numbers (containing at + * least one positive number) which has the largest sum. For example, for the + * sequence of values −2, 1, −3, 4, −1, 2, 1, −5, 4; the contiguous subarray + * with the largest sum is 4, −1, 2, 1, with sum 6. + * + * The problem was first posed by Ulf Grenander of Brown University in 1977, as + * a simplified model for maximum likelihood estimation of patterns in digitized + * images. A linear time algorithm was found soon afterwards by Jay Kadane of + * Carnegie-Mellon University (Bentley 1984). + * + * http://en.wikipedia.org/wiki/Maximum_subarray_problem + ******************************************************************************/ + +#ifndef MAX_SUBARRAY__ +#define MAX_SUBARRAY__ + +namespace alg { + /** + * To calc the maximum subarray, and return the range. + */ + static void max_subarray(int arr[], int len, int *begin, int *end) { + int i; + int subvalue = arr[0]; + int maxvalue = arr[0]; + *begin = 0; + *end = 0; + int new_begin; + + for (i = 1;i < len;i++) { + if (subvalue > 0) { // positive contribute to the following element + subvalue += arr[i]; + } else { + subvalue = arr[i]; // negative contribute, drop it! + new_begin = i; // then set the new beginning. + } + + if (maxvalue < subvalue) { // if a larger subarray appears, record the range + maxvalue = subvalue; + *begin = new_begin; + *end = i; + } + } + } +} + +#endif // 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 f0effe15..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,60 +32,52 @@ * ******************************************************************************/ -#ifndef __MERGE_SORT_H__ -#define __MERGE_SORT_H__ +#ifndef ALGO_MERGE_SORT_H__ +#define ALGO_MERGE_SORT_H__ -namespace alg -{ +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; - while(lpos <= mid && rpos <= right) - { - if(array[lpos] < array[rpos]) - { - tempArray[pos++] = array[lpos++]; - } - else - { - tempArray[pos++] = array[rpos++]; - } + while(lpos <= mid && rpos <= right) { + if(array[lpos] < array[rpos]) { + tempArray[pos++] = array[lpos++]; + } + else { + tempArray[pos++] = array[rpos++]; + } } while(lpos <= mid) tempArray[pos++] = array[lpos++]; while(rpos <= right)tempArray[pos++] = array[rpos++]; int iter; /* Copy back the sorted array to the original array */ - for(iter = 0;iter < pos; iter++) - { - array[iter+left] = tempArray[iter]; + for(iter = 0;iter < pos; iter++) { + array[iter+left] = tempArray[iter]; } return; - } + } /** * sort an array from left->right */ template - static void merge_sort(T *array, int left, int right) - { + static void merge_sort(T *array, int left, int right) { int mid = (left+right)/2; /* We have to sort only when left + * _| + * + * PALINDROMES + * + * WORDS LIKE: + * RACECAR DEED LEVEL PIP + * ROTOR CIVIC POP MADAM + * EYE NUN RADAR TOOT + * + * This program will find the longest part of mirror. + * + * http://en.wikipedia.org/wiki/Palindrome + ******************************************************************************/ + +#ifndef _PALINDROME_H_ +#define _PALINDROME_H_ + +#include +#include +#include + +namespace alg { + static void palindrome(const char * S) { + char *R= strdup(S); + int len = strlen(S); + // reverse + for(int i=0;i= 0 && len-i-1-offset >= 0) { + if (S[i-offset] == R[len-i-1-offset]) { + curlen++; + } else { + break; + } + offset++; + } + + if (curlen > maxlen) { + maxlen = curlen; + middle = i; + } + + // try even + while (i-offset>= 0 && len-i-2-offset >= 0) { + if (S[i-offset] == R[len-i-2-offset]) { + curlen++; + } else { + break; + } + offset++; + } + + if (curlen > maxlen) { + maxlen = curlen; + middle = i; + } + } + + printf("str:%s len:%d middle:%d\n",S, maxlen, middle); + free(R); + } +} + +#endif // diff --git a/include/perfect_hash.h b/include/perfect_hash.h index 4a4fb5d4..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 @@ -20,160 +20,149 @@ #include "universal_hash.h" #include "stack.h" -namespace alg -{ +namespace alg { template - class PerfHT - { - private: - class PerfHTException: public std::exception - { - public: - virtual const char * what() const throw() - { - return "key does not exist"; - } - }; + class PerfHT { + private: + class PerfHTException: public std::exception { + public: + virtual const char * what() const throw() { + return "key does not exist"; + } + } excp_key; + + // Level-2 Slot definition + struct SlotL2 { + public: + uint32_t cnt; // collison count + uint32_t key; //key + T value; // value + }; + + // Level-1 Slot definition + struct SlotL1 { + public: + uint32_t cnt; // collison count + struct UHash params; // 2nd level + struct SlotL2 * lv2_slots; // level 2 slots + + uint32_t key; // key + T value; // value + + ~SlotL1() { + if (cnt>1) delete [] lv2_slots; + } + }; + + struct SlotL1 * slots; // level 1 slots + struct UHash params; // 1st level + uint32_t num_slots; + public: + PerfHT(uint32_t keys[], uint32_t len) { + // remove duplicate keys + uint32_t newlen = remove_dup(keys, len); + + // 1-level hashing + uhash_init(&this->params, newlen); + + this->slots = new SlotL1[this->params.prime]; + for(uint32_t i=0;iparams.prime;i++) { + this->slots[i].cnt = 0; + } - // Level-2 Slot definition - class SlotL2 { - public: - uint32_t cnt; // collison count - uint32_t key; //key - T value; // value - }; + for (uint32_t i = 0; i < newlen; i++) { + uint32_t hash = uhash_integer(&this->params, keys[i]); + slots[hash].cnt++; + slots[hash].key = keys[i]; + } - // Level-1 Slot definition - struct SlotL1 { - public: - uint32_t cnt; // collison count - struct UHash params; // 2nd level - struct SlotL2 * lv2_slots; // level 2 slots + // 2-level processing + lv2_init(keys, newlen); + }; - uint32_t key; // key - T value; // value + ~PerfHT() { + delete [] slots; + } + private: + PerfHT(const PerfHT&); + PerfHT& operator=(const PerfHT&); + + public: + const T& operator[] (uint32_t key) const throw (PerfHTException) { + uint32_t hash; + hash = uhash_integer(¶ms, key); + if (slots[hash].key == key) { + return slots[hash].value; + } else if (slots[hash].cnt > 1) { // maybe in the 2nd level slot + SlotL1 & slot = slots[hash]; + uint32_t hash2 = uhash_integer(&slot.params, key); + + // 2nd-level available + if (slot.lv2_slots[hash2].key == key) { + return slot.lv2_slots[hash2].value; + } + } - ~SlotL1() { - if (cnt>1) delete [] lv2_slots; - } - }; - - struct SlotL1 * slots; // level 1 slots - struct UHash params; // 1st level - uint32_t num_slots; - const PerfHTException error; - - public: - PerfHT(uint32_t keys[], uint32_t len) - { - // remove duplicate keys - uint32_t newlen = remove_dup(keys, len); - - // 1-level hashing - uhash_init(&this->params, newlen); - - this->slots = new SlotL1[this->params.prime]; - for(uint32_t i=0;iparams.prime;i++) { - this->slots[i].cnt = 0; - } - - for (uint32_t i = 0; i < newlen; i++) { - uint32_t hash = uhash_integer(&this->params, keys[i]); - slots[hash].cnt++; - slots[hash].key = keys[i]; - } - - // 2-level processing - lv2_init(keys, newlen); - }; + throw excp_key; + } - ~PerfHT() { - delete [] slots; - } - private: - PerfHT(const PerfHT&); - PerfHT& operator=(const PerfHT&); - - public: - const T& operator[] (uint32_t key) const throw (PerfHTException) - { - uint32_t hash; - hash = uhash_integer(¶ms, key); - if (slots[hash].key == key) { - return slots[hash].value; - } else if (slots[hash].cnt > 1) { // maybe in the 2nd level slot - SlotL1 & slot = slots[hash]; - uint32_t hash2 = uhash_integer(&slot.params, key); - - // 2nd-level available - if (slot.lv2_slots[hash2].key == key) { - return slot.lv2_slots[hash2].value; + /** + * operator [] + */ + T& operator[] (uint32_t key) throw (PerfHTException) { + return const_cast(static_cast(*this)[key]); } - } - - throw error; - } - - /** - * operator [] - */ - T& operator[] (uint32_t key) throw (PerfHTException) - { - return const_cast(static_cast(*this)[key]); - } - - private: - /** - * level-2 hash pre-work - * collect collides for each level-1 slots - */ - void lv2_init(uint32_t keys[], uint32_t len) - { - for (uint32_t i = 0; i < params.prime; i++) { - if (slots[i].cnt > 1) { - // stacks for temporary storing keys - Stack collides(len); - - // find collide keys - for(uint32_t j=0;j 1) { + // stacks for temporary storing keys + Stack collides(len); + + // find collide keys + for(uint32_t j=0;j & collides) - { - // init another hash function & 2nd level - uhash_init(&lv1_slot->params, lv1_slot->cnt * lv1_slot->cnt); - SlotL2 * lv2_slots = new SlotL2[lv1_slot->params.prime]; - lv1_slot->lv2_slots = lv2_slots; - - retry: - for(uint32_t i=0;iparams.prime;i++) { - lv2_slots[i].cnt = 0; - } - - // try another hash function - uhash_init(&lv1_slot->params, lv1_slot->cnt * lv1_slot->cnt); - - // check collide - for(uint32_t i=0; iparams, key); - lv2_slots[hash].key = key; - if (++lv2_slots[hash].cnt > 1) { goto retry; } - } - } - }; + + /** + * init level-2 slots with known collides + * the routine will find another hash function never collides again!! + */ + void lv2_slot_init(struct SlotL1 * lv1_slot, Stack & collides) { + // init another hash function & 2nd level + uhash_init(&lv1_slot->params, lv1_slot->cnt * lv1_slot->cnt); + SlotL2 * lv2_slots = new SlotL2[lv1_slot->params.prime]; + lv1_slot->lv2_slots = lv2_slots; + +retry: + for(uint32_t i=0;iparams.prime;i++) { + lv2_slots[i].cnt = 0; + } + + // try another hash function + uhash_init(&lv1_slot->params, lv1_slot->cnt * lv1_slot->cnt); + + // check collide + for(uint32_t i=0; iparams, key); + lv2_slots[hash].key = key; + if (++lv2_slots[hash].cnt > 1) { goto retry; } + } + } + }; } #endif // diff --git a/include/prim_mst.h b/include/prim_mst.h index dead9516..be48ab58 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -22,170 +22,80 @@ * ******************************************************************************/ -#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" - -namespace alg -{ - class Prim - { - private: - /** - * Prim's Adjacent Lists, for Prim's Algorithm caculation - */ - struct PrimAdjacent { - Heap heap; // binary heap representation of weight->node - // the top of the heap is always the minimal element - const Graph::Vertex & v; - - PrimAdjacent(const Graph::Vertex & vertex, uint32_t num_neigh):heap(num_neigh),v(vertex) { } - - struct list_head pa_node; - }; - - /** - * Prim's Graph, simplified to list. - */ - typedef struct list_head PrimGraph; - private: - PrimGraph m_pg; - public: - /** - * construct Prim's DataStrcuture by a given graph - */ - Prim(const Graph & g) - { - INIT_LIST_HEAD(&m_pg); - - Graph::Adjacent * a; - list_for_each_entry(a, &g.list(), a_node){ - add_adjacent(*a); - } - } - - ~Prim() - { - PrimAdjacent * pa, *pan; - list_for_each_entry_safe(pa, pan, &m_pg, pa_node){ - list_del(&pa->pa_node); - delete pa; - } - } - private: - Prim(const Prim&); - Prim& operator= (const Prim&); - private: - /** - * add an adjacent list to prim's graph - */ - void add_adjacent(const Graph::Adjacent & a) - { - PrimAdjacent * pa = new PrimAdjacent(a.vertex(), a.num_neigh); - list_add_tail(&pa->pa_node, &m_pg); - - Graph::Vertex * v; - list_for_each_entry(v, &a.v_head, v_node){ - pa->heap.insert(v->weight, v); // weight->vertex - } - } - - /** - * lookup up a given id - * the related adjacent list is returned. - */ - PrimAdjacent * lookup(uint32_t id) const - { - PrimAdjacent * pa; - list_for_each_entry(pa, &m_pg, pa_node){ - if (pa->v.id == id) { return pa;} - } - - return NULL; - } - public: - /** - * Prim's Algorithm. - * - * Input: A non-empty connected weighted graph with vertices V and edges E - * (the weights can be negative). - * - * Initialize: Vnew = {x}, where x is an arbitrary node (starting point) from V, Enew = {} - * - * Repeat until Vnew = V: - * 1. Choose an edge {u, v} with minimal weight such that u is in Vnew and v - * is not (if there are multiple edges with the same weight, any of them may be picked) - * 2. Add v to Vnew, and {u, v} to Enew - * - * Output: Vnew and Enew describe a minimal spanning tree - */ - Graph * run() - { - UndirectedGraph * mst = new UndirectedGraph(); // empty set == Vnew +#include "hash_table.h" + +namespace alg { + class Prim { + public: + static const int LARGE_NUMBER = 999999; + /** + * Prim's Algorithm. + * + * Input: A non-empty connected weighted graph with vertices V and edges E + * (the weights can be negative). + * + * Initialize: Vnew = {x}, where x is an arbitrary node (starting point) from V, Enew = {} + * + * Repeat until Vnew = V: + * 1. Choose an edge {u, v} with minimal weight such that u is in Vnew and v + * is not (if there are multiple edges with the same weight, any of them may be picked) + * 2. Add v to Vnew, and {u, v} to Enew + * + * Output: Vnew and Enew describe a minimal spanning tree + */ + static Graph * run(const Graph & g, int32_t src_id) { + UndirectedGraph * mst = new UndirectedGraph(); // empty set == Vnew + // weight hash table + HashTable keys(g.vertex_count()); + // previous vertex hash table + HashTable pi(g.vertex_count()); + + // a binary heap + Heap Q(g.vertex_count()); + + // all vertices + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node){ + Q.push(LARGE_NUMBER, a->v.id); + keys[a->v.id] = LARGE_NUMBER; + } - // choose the first vertex as the starting point - PrimAdjacent * pa; - list_for_each_entry(pa, &m_pg, pa_node){ break; } - const Graph::Vertex * v = &pa->v; - mst->add_vertex(v->id); - - // Prim's Algorithm - while(true) { - int weight = INT_MAX; // loop tmp variables - uint32_t best_to; - struct PrimAdjacent * best_from; - - // for each Vnew, find a new vertex in V that has minimal weight. - Graph::Adjacent * a; - list_for_each_entry(a, &mst->list(), a_node){ - pa = lookup(a->v.id); - while (!pa->heap.is_empty()) { // find one neighbour - v = pa->heap.min_value(); - if ((*mst)[v->id]==NULL) { // if new V appears - if (pa->heap.min_key() < weight) { - weight = pa->heap.min_key(); - best_to = v->id; - best_from = pa; - } - break; - } else { - pa->heap.delete_min(); + Q.decrease_key(src_id, 0); + keys[src_id] = 0; + + while (!Q.is_empty()) { + 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) { + if (Q.contains(v->id) && v->weight < keys[v->id]) { + pi[v->id] = id; + Q.decrease_key(v->id, v->weight); + keys[v->id] = v->weight; } } } - if (weight != INT_MAX) { - // congrats , new V & E - mst->add_vertex(best_to); - mst->add_edge(best_from->v.id, best_to, weight); - best_from->heap.delete_min(); - } else break; - }; - - return mst; - } - - /** - * print the PrimGraph - */ - void print() - { - struct PrimAdjacent * pa; - printf("Prim Graph: \n"); - list_for_each_entry(pa, &m_pg, pa_node){ - printf("%d->{", pa->v.id); - for(uint32_t i=0;iheap.count();i++) { - Graph::Vertex * v = pa->heap[i]; - printf("id:%d->w:%d \t", v->id, v->weight); + // create graph + list_for_each_entry(a, &g.list(), a_node){ + mst->add_vertex(a->v.id); + if (pi[a->v.id] != 0) { + mst->add_vertex(pi[a->v.id]); + mst->add_edge(pi[a->v.id], a->v.id, (*a)[pi[a->v.id]]->weight); + } } - printf("}\n"); - } - } + + return mst; + }; }; } diff --git a/include/prime.h b/include/prime.h index 64bf1538..357f8b96 100644 --- a/include/prime.h +++ b/include/prime.h @@ -11,35 +11,33 @@ * 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 #include "imath.h" -namespace alg -{ +namespace alg { /** * check whether a given number is a prime number. * using naive method. */ - static bool test_prime(unsigned int n) - { + static bool test_prime(unsigned int n) { switch (n) { - case 0: - case 1: - return false; - case 2: - return true; + case 0: + case 1: + return false; + case 2: + return true; } if (n%2 == 0) return false; - unsigned sqrtn = sqrt(n); - for (unsigned int i = 2; i <= sqrtn; ++i) { - if (n % i == 0) { - return false; + unsigned sqrtn = sqrt((double)n); + for (unsigned int i = 3; i <= sqrtn; i+=2) { + if (n % i == 0) { + return false; } } return true; @@ -50,12 +48,12 @@ namespace alg */ static inline bool miller_rabin_test(unsigned int n) { switch (n) { - case 0: - case 1: - return false; - case 2: - case 3: - return true; + case 0: + case 1: + return false; + case 2: + case 3: + return true; } if (n%2 == 0) return false; @@ -66,7 +64,7 @@ namespace alg // test 3-times for (int k=0;k<3;k++){ unsigned a = rand()%(n-4) + 2; - + unsigned x = Exp(a, d, n); //printf("%u %u %u %u\n", a,d, n,x); if (x == 1 || x == n - 1) { @@ -78,13 +76,13 @@ namespace alg if (x == 1) return false; if (x == n-1) continue; } - + return false; } return true; } - + /** * mixed implementation */ diff --git a/include/priority_queue.h b/include/priority_queue.h index 80bfda70..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 @@ -24,123 +24,113 @@ #include "double_linked_list.h" -namespace alg -{ +namespace alg { /** * definition of a Priority Queue. */ template - class PQ { - /** - * definition of a node of priority queue. - */ - struct PQNode { - int priority; - T value; - struct list_head node; - }; + class PQ { + /** + * definition of a node of priority queue. + */ + struct PQNode { + int priority; + T value; + struct list_head node; + }; - private: - uint32_t m_count; - struct list_head m_head; - public: - /** - * create an empty priority queue. - */ - PQ() - { - m_count = 0; - INIT_LIST_HEAD(&m_head); - } - - ~PQ() - { - PQNode * pos, * n; - list_for_each_entry_safe(pos,n, &m_head, node) { - list_del(&pos->node); - delete pos; + private: + uint32_t m_count; + struct list_head m_head; + public: + /** + * create an empty priority queue. + */ + PQ() { + m_count = 0; + INIT_LIST_HEAD(&m_head); } - } - private: - PQ(const PQ&); - PQ& operator=(const PQ&); - public: - - /** - * queue a value with priority into the priority queue. - */ - void queue(const T &value, uint32_t priority) - { - PQNode * n = new PQNode; - n->priority = priority; - n->value = value; - if (list_empty(&m_head)) // empty list, just add in. - { - list_add(&n->node, &m_head); - m_count++; + ~PQ() { + PQNode * pos, * n; + list_for_each_entry_safe(pos,n, &m_head, node) { + list_del(&pos->node); + delete pos; + } } - else - { - // sequentially find the apropriate 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); + private: + PQ(const PQ&); + PQ& operator=(const PQ&); + public: + + /** + * queue a value with priority into the priority queue. + */ + void queue(const T &value, uint32_t priority) { + PQNode * n = new PQNode; + n->priority = priority; + n->value = value; + + if (list_empty(&m_head)) { // empty list, just add in. + list_add(&n->node, &m_head); + m_count++; + } else { + // 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); + m_count++; + found = true; + break; + } + } + + if (!found) { // we reach the end of the list. + list_add_tail(&n->node, &m_head); m_count++; - found = true; - break; } } + } - if (!found) { // we reach the end of the list. - list_add_tail(&n->node, &m_head); - m_count++; - } + /** + * return top element + * check is_empty() before top(). + */ + inline const T & top(int * prio) const { + PQNode * n; + n = list_entry(m_head.next, PQNode, node); + *prio = n->priority; + return n->value; + } + + /** + * dequeue the most priority element, i.e. the first element. + */ + inline void dequeue() { + if (list_empty(&m_head)) return; + + PQNode * n; + n = list_entry(m_head.next, PQNode, node); + list_del(&n->node); + m_count--; + delete n; } - } - - /** - * return top element - * check is_empty() before top(). - */ - inline const T & top(int * prio) const - { - PQNode * n; - n = list_entry(m_head.next, PQNode, node); - *prio = n->priority; - return n->value; - } - - /** - * dequeue the most priority element, i.e. the first element. - */ - inline void dequeue() - { - if (list_empty(&m_head)) return; - - PQNode * n; - n = list_entry(m_head.next, PQNode, node); - list_del(&n->node); - m_count--; - delete n; - } - /** - * test whether the priority queue is empty - */ - inline bool is_empty() const - { - if (list_empty(&m_head)) return true; - return false; - } + /** + * test whether the priority queue is empty + */ + inline bool is_empty() const { + if (list_empty(&m_head)) return true; + return false; + } - /** - * get the exact number of data - */ - inline uint32_t count() const { return m_count; } - }; + /** + * get the exact number of data + */ + inline uint32_t count() const { return m_count; } + }; } #endif // diff --git a/include/queue.h b/include/queue.h index 7eace7ff..55051228 100644 --- a/include/queue.h +++ b/include/queue.h @@ -13,131 +13,124 @@ * ******************************************************************************/ -#ifndef __QUEUE_H__ -#define __QUEUE_H__ +#ifndef ALGO_QUEUE_H__ +#define ALGO_QUEUE_H__ #include #include #include -namespace alg -{ +namespace alg { /** * Queue Definition */ template - class Queue - { - private: - class QueueEmptyException: public std::exception - { + class Queue { + private: + class QueueEmptyException: public std::exception { + public: + virtual const char * what() const throw() { + return "Queue is empty."; + } + } excp_empty; + + private: + uint32_t m_capacity; // queue capacity + uint32_t m_size; // current queue size + uint32_t m_front; // index of the first element + uint32_t m_rear; // index of the last element + T * m_elements; // the elements + public: - virtual const char * what() const throw() - { - return "Queue is empty."; - } - }; + /** + * constructor takes argument the maximum number of elements the Queue + * can hold, creates a Queue according to it and returns a pointer to the + * Queue. + */ + Queue(uint32_t max) { + this->m_elements = new T[max]; + this->m_size = 0; + this->m_capacity = max; + this->m_front =0; + this->m_rear = -1; + }; - private: - uint32_t m_capacity; // queue capacity - uint32_t m_size; // current queue size - uint32_t m_front; // index of the first element - uint32_t m_rear; // index of the last element - T * m_elements; // the elements + ~Queue() { + delete [] m_elements; + }; + private: + Queue(const Queue &); + Queue& operator=(const Queue &); + public: + /** + * Dequeue + */ + inline void dequeue() { + /* If Queue size is zero then it is empty. So we cannot pop */ + if(m_size==0) { + return; + } + /* Removing an element is equivalent to incrementing index of front by one */ + else { + m_size--; + m_front++; + /* As we fill elements in circular fashion */ + if(m_front==m_capacity) { + m_front=0; + } + } + return; + }; - const QueueEmptyException exp_empty; + /** + * return the front element. + */ + inline const T& front() const { + if (m_size==0) throw excp_empty; + return m_elements[m_front]; + }; - public: - /** - * constructor takes argument the maximum number of elements the Queue - * can hold, creates a Queue according to it and returns a pointer to the - * Queue. - */ - Queue(uint32_t max) - { - this->m_elements = new T[max]; - this->m_size = 0; - this->m_capacity = max; - this->m_front =0; - this->m_rear = -1; - }; + /** + * test weather the queue is empty + */ + inline bool is_empty() const { + if (m_size ==0) return true; + return false; + }; - ~Queue() - { - delete [] m_elements; - }; - private: - Queue(const Queue &); - Queue& operator=(const Queue &); - public: - /** - * Dequeue - */ - inline void dequeue() - { - /* If Queue size is zero then it is empty. So we cannot pop */ - if(m_size==0) { - return; - } - /* Removing an element is equivalent to incrementing index of front by one */ - else { - m_size--; - m_front++; - /* As we fill elements in circular fashion */ - if(m_front==m_capacity) { - m_front=0; - } - } - return; - }; + /** + * enqueue an element + * returns false when queue is full + */ + bool enqueue(const T & element) { + // If the Queue is full, we cannot push an element into it + // as there is no space for it.*/ + if(m_size == m_capacity) { + return false; + } + else { + m_size++; + m_rear++; + /* As we fill the queue in circular fashion */ + if(m_rear == m_capacity) { + m_rear = 0; + } + /* Insert the element in its rear side */ + m_elements[m_rear] = element; - /** - * return the front element. - */ - inline const T& front() const - { - if (m_size==0) throw exp_empty; - return m_elements[m_front]; - }; + return true; + } + }; - /** - * test weather the queue is empty - */ - inline bool is_empty() const - { - if (m_size ==0) return true; - return false; - }; + /** + * return the queue count. + */ + inline uint32_t count() const { return m_size; }; - /** - * enqueue an element - * returns false when queue is full - */ - bool enqueue(const T & element) - { - // If the Queue is full, we cannot push an element into it - // as there is no space for it.*/ - if(m_size == m_capacity) { - return false; - } - else { - m_size++; - m_rear++; - /* As we fill the queue in circular fashion */ - if(m_rear == m_capacity) { - m_rear = 0; - } - /* Insert the element in its rear side */ - m_elements[m_rear] = element; - - return true; - } + /** + * return the queue capacity. + */ + inline uint32_t capcity() const { return m_capacity; }; }; - - /** - * return the queue count. - */ - inline int count() const { return m_size; }; - }; } #endif // diff --git a/include/quick_sort.h b/include/quick_sort.h index 633e63d2..b3a74489 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -15,53 +15,48 @@ * ******************************************************************************/ -#ifndef __QUICKSORT_H__ -#define __QUICKSORT_H__ +#ifndef ALGO_QUICKSORT_H__ +#define ALGO_QUICKSORT_H__ #include -namespace alg -{ +namespace alg { /** * the quick-sort partition routine */ template - 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]); + 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]); - int i = begin + 1; - int j = end; - - while(i <= j) - { - while((i <= end) && (list[i] <= pivot)) - i++; - while((j >= begin) && (list[j] > pivot)) - j--; - if(i < j) - swap(list[i],list[j]); + int i = begin + 1; + int j = end; + + while(i <= j) { + while((i <= end) && (list[i] <= pivot)) + i++; + while((j >= begin) && (list[j] > pivot)) + j--; + if(i < j) + swap(list[i],list[j]); + } + + swap(list[begin],list[j]); + return j; // final pivot position } - - swap(list[begin],list[j]); - return j; // final pivot position - } /** * quick sort an array of range [begin, end] */ template - static void quicksort(T list[],int begin,int end) - { - if( begin < end) - { - int pivot_idx = __partition(list, begin, end); - quicksort(list, begin, pivot_idx-1); - quicksort(list, pivot_idx+1, end); + static void quicksort(T list[],int begin,int end) { + if( begin < end) { + int pivot_idx = partition_(list, begin, end); + quicksort(list, begin, pivot_idx-1); + quicksort(list, pivot_idx+1, end); + } } - } } #endif // diff --git a/include/radix_sort.h b/include/radix_sort.h index 010609a4..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 @@ -25,13 +25,11 @@ #include #include -namespace alg -{ +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,13 +49,12 @@ namespace alg /** * radix sort a given unsigned 32-bit integer array of size N */ - static void radix_sort(uint32_t *source, const unsigned N) - { + 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; } @@ -65,8 +62,7 @@ namespace alg /** * check whether the array is in order */ - static void check_order(const uint32_t *data, unsigned N) - { + static void check_order(const uint32_t *data, unsigned N) { for(--N ; N > 0; --N, ++data) assert(data[0] <= data[1]); } diff --git a/include/random.h b/include/random.h index 74cf2726..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 @@ -26,7 +26,7 @@ namespace alg { static uint32_t a = 1664525U; static uint32_t c = 1013904223U; static uint32_t X0 = 0; - + X0 = a*X0+c; return X0; } diff --git a/include/random_select.h b/include/random_select.h index 45dd608d..8893008d 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -5,69 +5,67 @@ * /--\ | (_| (_) | | |_ | | | | | _> * _| * - * RANDOM-SELECT + * Quickselect + * In computer science, a quickselect is a selection algorithm related to the + * quicksort sorting algorithm. Like quicksort, it was developed by Tony Hoare, + * and thus is also known as Hoare's selection algorithm. Like quicksort, it is + * efficient in practice and has good average-case performance, but has poor + * worst-case performance. Quickselect and variants is the selection algorithm + * most often used in efficient real-world implementations. * - * Features: - * 1. select the smallest k-th element - * 2. will modify orignal list - * - * http://en.wikipedia.org/wiki/Order_statistic + * http://en.wikipedia.org/wiki/Quickselect * ******************************************************************************/ -#ifndef __RANDOM_SELECT_H__ -#define __RANDOM_SELECT_H__ +#ifndef ALGO_RANDOM_SELECT_H__ +#define ALGO_RANDOM_SELECT_H__ #include -namespace alg -{ +namespace alg { /** * the random_select partition routine */ template - 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]); + 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]); + + int i = begin + 1; + int j = end; + + while(i <= j) { + while((i <= end) && (list[i] <= pivot)) + i++; + while((j >= begin) && (list[j] > pivot)) + j--; + if(i < j) + swap(list[i],list[j]); + } - int i = begin + 1; - int j = end; - - while(i <= j) - { - while((i <= end) && (list[i] <= pivot)) - i++; - while((j >= begin) && (list[j] > pivot)) - j--; - if(i < j) - swap(list[i],list[j]); + swap(list[begin],list[j]); + return j; // final pivot position } - - swap(list[begin],list[j]); - return j; // final pivot position - } /** * select the k-th smallest number in 'list' of range [begin, end] */ template - static int random_select(T list[], int begin, int end, int k) - { - if(begin == end) - return begin; - - int pivot_idx = __partition(list, begin, end); - int human_idx = pivot_idx - begin + 1; + static int random_select(T list[], int begin, int end, int k) { + if(begin == end) + return begin; + + int pivot_idx = partition_(list, begin, end); + int human_idx = pivot_idx - begin + 1; + + if(k < human_idx) + return random_select(list, begin, pivot_idx - 1, k); + else if(k > human_idx) + return random_select(list, pivot_idx+1, end, k - human_idx); - if(k == human_idx) return pivot_idx; - if(k < human_idx) - return random_select(list, begin, pivot_idx - 1, k); - if(k > human_idx) - return random_select(list, pivot_idx+1, end, k - human_idx); - } + } } #endif // diff --git a/include/rbtree.h b/include/rbtree.h index ae558ec8..61c129bd 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -12,183 +12,176 @@ * 2. O(logn) lookup performance * * http://en.wikipedia.org/wiki/Red_black_tree - * + * 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 #include "rbtree_defs.h" -namespace alg -{ +namespace alg { template - class RBTree:public RBTreeAbstract - { - private: - // a default Key-Value node. - struct KVNode: public rbtree_node_t { - KeyT key; - ValueT value; - }; - + class RBTree:public RBTreeAbstract { + private: + // a default Key-Value node. + struct KVNode: public rbtree_node_t { + KeyT key; + ValueT value; + }; + #define KVNODE(node) static_cast(node) - void destruct(KVNode * n) - { - if (n==NULL) return; - destruct(KVNODE(n->left)); - destruct(KVNODE(n->right)); - delete n; - } + void destruct(KVNode * n) { + if (n==NULL) return; + destruct(KVNODE(n->left)); + destruct(KVNODE(n->right)); + delete n; + } - public: - ~RBTree() - { - destruct(KVNODE(get_root())); - } - - /** - * rbtree_insert - * insert a key-value pair into red-black tree - */ - void insert(const KeyT & key, const ValueT & value) - { - KVNode * inserted_node = new_node(key, value, RED, NULL, NULL); - if (get_root() == NULL) { - set_root(inserted_node); - } else { - KVNode * n = KVNODE(get_root()); - while (1) { - if (key == n->key) { - n->value = value; - /* inserted_node isn't going to be used, don't leak it */ - delete (inserted_node); - return; - } else if (key < n->key) { - if (n->left == NULL) { - n->left = inserted_node; - break; - } else { - n = static_cast(n->left); - } + public: + ~RBTree() { + destruct(KVNODE(get_root())); + } + + /** + * rbtree_insert + * insert a key-value pair into red-black tree + */ + void insert(const KeyT & key, const ValueT & value) { + KVNode * inserted_node = new_node(key, value, RED, NULL, NULL); + if (get_root() == NULL) { + set_root(inserted_node); } else { - assert (key > n->key); - if (n->right == NULL) { - n->right = inserted_node; - break; - } else { - n = static_cast(n->right); + KVNode * n = KVNODE(get_root()); + while (1) { + if (key == n->key) { + n->value = value; + /* inserted_node isn't going to be used, don't leak it */ + delete (inserted_node); + return; + } else if (key < n->key) { + if (n->left == NULL) { + n->left = inserted_node; + break; + } else { + n = static_cast(n->left); + } + } else { + assert (key > n->key); + if (n->right == NULL) { + n->right = inserted_node; + break; + } else { + n = static_cast(n->right); + } + } } + inserted_node->parent = n; } + insert_case1(inserted_node); } - inserted_node->parent = n; - } - insert_case1(inserted_node); - } - /** - * contain test - */ - bool contains(KeyT key) - { - if (lookup_node(key)) - return true; - return false; - } - - /** - * rbtree_lookup - * search in red-black tree - */ - ValueT operator [] (KeyT key) - { - KVNode * n = lookup_node(key); - if (n==NULL) throw std::out_of_range ("no such key"); - return n->value; - } + /** + * contain test + */ + bool contains(KeyT key) { + if (lookup_node(key)) + return true; + return false; + } - /** - * delete the key in the red-black tree - */ - void delete_key(KeyT key) - { - rbtree_node child; - KVNode * n = lookup_node(key); - if (n == NULL) return; /* Key not found, do nothing */ - if (n->left != NULL && n->right != NULL) { - /* Copy key/value from predecessor and then delete it instead */ - KVNode * pred = static_cast(maximum_node(n->left)); - n->key = pred->key; - n->value = pred->value; - n = pred; - } + /** + * rbtree_lookup + * search in red-black tree + */ + ValueT operator [] (KeyT key) { + KVNode * n = lookup_node(key); + if (n==NULL) throw std::out_of_range ("no such key"); + return n->value; + } - assert(n->left == NULL || n->right == NULL); - child = n->right == NULL ? n->left : n->right; - if (node_color(n) == BLACK) { - n->color = node_color(child); - delete_case1(n); - } - replace_node(n, child); - if (n->parent == NULL && child != NULL) - child->color = BLACK; - delete(n); - } + /** + * delete the key in the red-black tree + */ + void delete_key(KeyT key) { + rbtree_node child; + KVNode * n = lookup_node(key); + if (n == NULL) return; /* Key not found, do nothing */ + if (n->left != NULL && n->right != NULL) { + /* Copy key/value from predecessor and then delete it instead */ + KVNode * pred = static_cast(maximum_node(n->left)); + n->key = pred->key; + n->value = pred->value; + n = pred; + } - void print() { - print_helper(KVNODE(get_root()), 0); - puts(""); - } - protected: - void print_helper(KVNode * n, int indent) { - int i; - if (n == NULL) { - fputs("", stdout); - return; - } - if (n->right != NULL) { - print_helper(KVNODE(n->right), indent + INDENT_STEP); - } - for(i=0; icolor == BLACK) - printf("%d\n", (int)n->key); - else - printf("<%d>\n", (int)n->key); - if (n->left != NULL) { - print_helper(KVNODE(n->left), indent + INDENT_STEP); - } - } + assert(n->left == NULL || n->right == NULL); + child = n->right == NULL ? n->left : n->right; + if (node_color(n) == BLACK) { + n->color = node_color(child); + delete_case1(n); + } + replace_node(n, child); - KVNode * new_node(KeyT key, ValueT value, color rbtree_node_color, rbtree_node left, rbtree_node right) { - KVNode * result =new KVNode; - result->key = key; - result->value = value; - result->color = rbtree_node_color; - result->left = left; - result->right = right; - if (left != NULL) left->parent = result; - if (right != NULL) right->parent = result; - result->parent = NULL; - return result; - } + if (n->parent == NULL && child != NULL) // root + child->color = BLACK; + delete(n); + } - KVNode * lookup_node(KeyT key) { - KVNode * n = KVNODE(get_root()); - while (n != NULL) { - if (key == n->key) { + void print() { + print_helper(KVNODE(get_root()), 0); + puts(""); + } + protected: + void print_helper(KVNode * n, int indent) { + int i; + if (n == NULL) { + fputs("", stdout); + return; + } + if (n->right != NULL) { + print_helper(KVNODE(n->right), indent + INDENT_STEP); + } + for(i=0; icolor == BLACK) + printf("%d\n", (int)n->key); + else + printf("<%d>\n", (int)n->key); + if (n->left != NULL) { + print_helper(KVNODE(n->left), indent + INDENT_STEP); + } + } + + KVNode * new_node(KeyT key, ValueT value, color rbtree_node_color, rbtree_node left, rbtree_node right) { + KVNode * result =new KVNode; + result->key = key; + result->value = value; + result->color = rbtree_node_color; + result->left = left; + result->right = right; + if (left != NULL) left->parent = result; + if (right != NULL) right->parent = result; + result->parent = NULL; + return result; + } + + KVNode * lookup_node(KeyT key) { + KVNode * n = KVNODE(get_root()); + while (n != NULL) { + if (key == n->key) { + return n; + } else if (key < n->key) { + n = KVNODE(n->left); + } else { + n = KVNODE(n->right); + } + } return n; - } else if (key < n->key) { - n = KVNODE(n->left); - } else { - n = KVNODE(n->right); } - } - return n; - } - }; + }; } #endif diff --git a/include/rbtree_defs.h b/include/rbtree_defs.h index aab419ba..a99a26b0 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -12,284 +12,252 @@ * 2. O(logn) lookup performance * * http://en.wikipedia.org/wiki/Red_black_tree - * + * 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 -namespace alg -{ - class RBTreeAbstract - { - protected: - static const int INDENT_STEP=4; - - enum rbtree_node_color { RED, BLACK }; - typedef enum rbtree_node_color color; - - typedef struct rbtree_node_t { - rbtree_node_t* left; - rbtree_node_t* right; - rbtree_node_t* parent; - enum rbtree_node_color color; - } *rbtree_node; - - private: - rbtree_node m_root; - - public: - /** - * init a red-black tree - */ - RBTreeAbstract() : m_root(NULL) {} - virtual ~RBTreeAbstract() {} - - private: - RBTreeAbstract(const RBTreeAbstract &); - RBTreeAbstract& operator=(const RBTreeAbstract &); - protected: - // - inline rbtree_node get_root( ) { return m_root; } - inline void set_root(rbtree_node new_root) { m_root = new_root; } - - protected: - /// - /// THE RED-BLACK TREE CORE - /// - rbtree_node grandparent(rbtree_node n) - { - assert (n != NULL); - assert (n->parent != NULL); /* Not the root rbtree_node */ - assert (n->parent->parent != NULL); /* Not child of root */ - return n->parent->parent; - } - - rbtree_node sibling(rbtree_node n) - { - assert (n != NULL); - assert (n->parent != NULL); /* Root rbtree_node has no sibling */ - if (n == n->parent->left) - return n->parent->right; - else - return n->parent->left; - } - - rbtree_node uncle(rbtree_node n) - { - assert (n != NULL); - assert (n->parent != NULL); /* Root rbtree_node has no uncle */ - assert (n->parent->parent != NULL); /* Children of root have no uncle */ - return sibling(n->parent); - } - - color node_color(rbtree_node n) - { - return n == NULL ? BLACK : n->color; - } - - /** - * According to rotation operation, n1 is the node, n2 is parent node affected by rotation - */ - virtual void rotate_left_callback(rbtree_node n1, rbtree_node n2) { } - - virtual void rotate_right_callback(rbtree_node n1, rbtree_node n2) { } - - - void rotate_left(rbtree_node n) - { - rbtree_node r = n->right; - replace_node(n, r); - n->right = r->left; - if (r->left != NULL) { - r->left->parent = n; +namespace alg { + class RBTreeAbstract { + protected: + static const int INDENT_STEP=4; + + enum rbtree_node_color { RED, BLACK }; + typedef enum rbtree_node_color color; + + typedef struct rbtree_node_t { + rbtree_node_t* left; + rbtree_node_t* right; + rbtree_node_t* parent; + enum rbtree_node_color color; + } *rbtree_node; + + private: + rbtree_node m_root; + + public: + /** + * init a red-black tree + */ + RBTreeAbstract() : m_root(NULL) {} + virtual ~RBTreeAbstract() {} + + private: + RBTreeAbstract(const RBTreeAbstract &); + RBTreeAbstract& operator=(const RBTreeAbstract &); + protected: + // + inline rbtree_node get_root( ) { return m_root; } + inline void set_root(rbtree_node new_root) { m_root = new_root; } + + protected: + /// + /// THE RED-BLACK TREE CORE + /// + rbtree_node grandparent(rbtree_node n) { + assert (n != NULL); + assert (n->parent != NULL); /* Not the root rbtree_node */ + assert (n->parent->parent != NULL); /* Not child of root */ + return n->parent->parent; } - r->left = n; - n->parent = r; - - rotate_left_callback(n, r); - } - - void rotate_right(rbtree_node n) - { - rbtree_node L = n->left; - replace_node(n, L); - n->left = L->right; - if (L->right != NULL) { - L->right->parent = n; - } - L->right = n; - n->parent = L; - - rotate_right_callback(n, L); - } - - void replace_node(rbtree_node oldn, rbtree_node newn) - { - if (oldn->parent == NULL) { - m_root = newn; - } else { - if (oldn == oldn->parent->left) - oldn->parent->left = newn; + + rbtree_node sibling(rbtree_node n) { + assert (n != NULL); + assert (n->parent != NULL); /* Root rbtree_node has no sibling */ + if (n == n->parent->left) + return n->parent->right; else - oldn->parent->right = newn; + return n->parent->left; } - if (newn != NULL) { - newn->parent = oldn->parent; + + rbtree_node uncle(rbtree_node n) { + assert (n != NULL); + assert (n->parent != NULL); /* Root rbtree_node has no uncle */ + assert (n->parent->parent != NULL); /* Children of root have no uncle */ + return sibling(n->parent); } - } - - void insert_case1(rbtree_node n) - { - if (n->parent == NULL) - n->color = BLACK; - else - insert_case2(n); - } - - void insert_case2(rbtree_node n) - { - if (node_color(n->parent) == BLACK) - return; /* Tree is still valid */ - else - insert_case3(n); - } - - void insert_case3(rbtree_node n) - { - if (node_color(uncle(n)) == RED) { - n->parent->color = BLACK; - uncle(n)->color = BLACK; - grandparent(n)->color = RED; - insert_case1(grandparent(n)); - } else { - insert_case4(n); + + color node_color(rbtree_node n) { + return n == NULL ? BLACK : n->color; } - } - - void insert_case4(rbtree_node n) - { - if (n == n->parent->right && n->parent == grandparent(n)->left) { - rotate_left(n->parent); - n = n->left; - } else if (n == n->parent->left && n->parent == grandparent(n)->right) { - rotate_right(n->parent); - n = n->right; + + /** + * According to rotation operation, n1 is the node, n2 is parent node affected by rotation + */ + virtual void rotate_left_callback(rbtree_node n1, rbtree_node n2) { } + + virtual void rotate_right_callback(rbtree_node n1, rbtree_node n2) { } + + + void rotate_left(rbtree_node n) { + rbtree_node r = n->right; + replace_node(n, r); + n->right = r->left; + if (r->left != NULL) { + r->left->parent = n; + } + r->left = n; + n->parent = r; + + rotate_left_callback(n, r); } - insert_case5(n); - } - - void insert_case5(rbtree_node n) - { - n->parent->color = BLACK; - grandparent(n)->color = RED; - if (n == n->parent->left && n->parent == grandparent(n)->left) { - rotate_right(grandparent(n)); - } else { - assert (n == n->parent->right && n->parent == grandparent(n)->right); - rotate_left(grandparent(n)); + + void rotate_right(rbtree_node n) { + rbtree_node L = n->left; + replace_node(n, L); + n->left = L->right; + if (L->right != NULL) { + L->right->parent = n; + } + L->right = n; + n->parent = L; + + rotate_right_callback(n, L); } - } - rbtree_node maximum_node(rbtree_node n) - { - assert (n != NULL); - while (n->right != NULL) { - n = n->right; + void replace_node(rbtree_node oldn, rbtree_node newn) { + if (oldn->parent == NULL) { + m_root = newn; + } else { + if (oldn == oldn->parent->left) + oldn->parent->left = newn; + else + oldn->parent->right = newn; + } + if (newn != NULL) { + newn->parent = oldn->parent; + } } - return n; - } - - void delete_case1(rbtree_node n) - { - if (n->parent == NULL) - return; - else - delete_case2(n); - } - - void delete_case2(rbtree_node n) - { - if (node_color(sibling(n)) == RED) { - n->parent->color = RED; - sibling(n)->color = BLACK; - if (n == n->parent->left) - rotate_left(n->parent); + + void insert_case1(rbtree_node n) { + if (n->parent == NULL) + n->color = BLACK; else - rotate_right(n->parent); + insert_case2(n); } - delete_case3(n); - } - - void delete_case3(rbtree_node n) - { - if (node_color(n->parent) == BLACK && - node_color(sibling(n)) == BLACK && - node_color(sibling(n)->left) == BLACK && - node_color(sibling(n)->right) == BLACK) - { - sibling(n)->color = RED; - delete_case1(n->parent); + + void insert_case2(rbtree_node n) { + if (node_color(n->parent) == BLACK) + return; /* Tree is still valid */ + else + insert_case3(n); + } + + void insert_case3(rbtree_node n) { + if (node_color(uncle(n)) == RED) { + n->parent->color = BLACK; + uncle(n)->color = BLACK; + grandparent(n)->color = RED; + insert_case1(grandparent(n)); + } else { + insert_case4(n); + } } - else - delete_case4(n); - } - - void delete_case4(rbtree_node n) - { - if (node_color(n->parent) == RED && - node_color(sibling(n)) == BLACK && - node_color(sibling(n)->left) == BLACK && - node_color(sibling(n)->right) == BLACK) - { - sibling(n)->color = RED; + + void insert_case4(rbtree_node n) { + if (n == n->parent->right && n->parent == grandparent(n)->left) { + rotate_left(n->parent); + n = n->left; + } else if (n == n->parent->left && n->parent == grandparent(n)->right) { + rotate_right(n->parent); + n = n->right; + } + insert_case5(n); + } + + void insert_case5(rbtree_node n) { n->parent->color = BLACK; + grandparent(n)->color = RED; + if (n == n->parent->left && n->parent == grandparent(n)->left) { + rotate_right(grandparent(n)); + } else { + assert (n == n->parent->right && n->parent == grandparent(n)->right); + rotate_left(grandparent(n)); + } + } + + rbtree_node maximum_node(rbtree_node n) { + assert (n != NULL); + while (n->right != NULL) { + n = n->right; + } + return n; + } + + void delete_case1(rbtree_node n) { + if (n->parent == NULL) + return; + else + delete_case2(n); } - else - delete_case5(n); - } - - void delete_case5(rbtree_node n) - { - if (n == n->parent->left && - node_color(sibling(n)) == BLACK && - node_color(sibling(n)->left) == RED && - node_color(sibling(n)->right) == BLACK) - { - sibling(n)->color = RED; - sibling(n)->left->color = BLACK; - rotate_right(sibling(n)); + + void delete_case2(rbtree_node n) { + if (node_color(sibling(n)) == RED) { + n->parent->color = RED; + sibling(n)->color = BLACK; + if (n == n->parent->left) + rotate_left(n->parent); + else + rotate_right(n->parent); + } + delete_case3(n); } - else if (n == n->parent->right && - node_color(sibling(n)) == BLACK && - node_color(sibling(n)->right) == RED && - node_color(sibling(n)->left) == BLACK) - { - sibling(n)->color = RED; - sibling(n)->right->color = BLACK; - rotate_left(sibling(n)); + + void delete_case3(rbtree_node n) { + if (node_color(n->parent) == BLACK && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->left) == BLACK && + node_color(sibling(n)->right) == BLACK) { + sibling(n)->color = RED; + delete_case1(n->parent); + } else delete_case4(n); + } + + void delete_case4(rbtree_node n) { + if (node_color(n->parent) == RED && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->left) == BLACK && + node_color(sibling(n)->right) == BLACK) { + sibling(n)->color = RED; + n->parent->color = BLACK; + } else delete_case5(n); } - delete_case6(n); - } - - void delete_case6(rbtree_node n) - { - sibling(n)->color = node_color(n->parent); - n->parent->color = BLACK; - if (n == n->parent->left) { - assert (node_color(sibling(n)->right) == RED); - sibling(n)->right->color = BLACK; - rotate_left(n->parent); + + void delete_case5(rbtree_node n) { + if (n == n->parent->left && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->left) == RED && + node_color(sibling(n)->right) == BLACK) { + sibling(n)->color = RED; + sibling(n)->left->color = BLACK; + rotate_right(sibling(n)); + } else if (n == n->parent->right && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->right) == RED && + node_color(sibling(n)->left) == BLACK) { + sibling(n)->color = RED; + sibling(n)->right->color = BLACK; + rotate_left(sibling(n)); + } + delete_case6(n); } - else - { - assert (node_color(sibling(n)->left) == RED); - sibling(n)->left->color = BLACK; - rotate_right(n->parent); + + void delete_case6(rbtree_node n) { + sibling(n)->color = node_color(n->parent); + n->parent->color = BLACK; + if (n == n->parent->left) { + assert (node_color(sibling(n)->right) == RED); + sibling(n)->right->color = BLACK; + rotate_left(n->parent); + } else { + assert (node_color(sibling(n)->left) == RED); + sibling(n)->left->color = BLACK; + rotate_right(n->parent); + } } - } }; } diff --git a/include/relabel_to_front.h b/include/relabel_to_front.h new file mode 100644 index 00000000..ef933e02 --- /dev/null +++ b/include/relabel_to_front.h @@ -0,0 +1,241 @@ +/* + * Relabel-To-Front algorithm + * + * Features: Relabel-to-front maxflow algorithm's upper bound is O(V3), faster than Edmonds-Karp in theory. Relabel-to-front algorithm is a kind of push-relabel algorithm using FIFO heuristic. + * But the funny thing is, in practice, this method is much slower than Edmonds-Karp. + * You can test it by running relabel_to_front.cpp. + * + * http://en.wikipedia.org/wiki/Push%E2%80%93relabel_maximum_flow_algorithm + * + * */ + +#ifndef ALGO_RELABEL_TO_FRONT_H__ +#define ALGO_RELABEL_TO_FRONT_H__ + +#include +#include +#include + +#include "directed_graph.h" +#include "hash_table.h" +#include "2darray.h" + +namespace alg { + class RelabelToFront { + private: + const Graph & g; + DirectedGraph * possible_residual_edge; // record possible residual edges + + Array2D m_residual; + + HashTable m_map; + HashTable m_rmap; + + HashTable e; //excess flow + HashTable h; //value of height function + + public: + RelabelToFront(const Graph & graph): + g(graph), + m_residual(g.vertex_count(), g.vertex_count()), + m_map(g.vertex_count()), m_rmap(g.vertex_count()), + e(g.vertex_count()), h(g.vertex_count()) { + Graph::Adjacent * a; + int id=0; + list_for_each_entry(a, &g.list(), a_node){ + m_map[a->v.id] = id; + m_rmap[id] = a->v.id; + id++; + } + + m_residual.clear(0); + + possible_residual_edge = new DirectedGraph; + for (uint32_t i=0; iadd_vertex(i); + } + + list_for_each_entry(a, &g.list(), a_node){ + Graph::Vertex *v; + list_for_each_entry(v, &a->v_head, v_node){ + int from = m_map[a->v.id]; + int to = m_map[v->id]; + m_residual(from, to) = v->weight; + + possible_residual_edge->add_edge(from, to, 0); + possible_residual_edge->add_edge(to, from, 0); + } + } + } + + ~RelabelToFront() { + delete possible_residual_edge; + } + + void initialize_preflow(uint32_t src) { + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node){ + h[m_map[a->v.id]] = 0; + e[m_map[a->v.id]] = 0; + } + + int _src = m_map[src]; + h[_src] = g.vertex_count(); + + Graph::Vertex * v; + a = g[src]; + list_for_each_entry(v, &a->v_head, v_node){ + int from = m_map[src]; + int to = m_map[v->id]; + m_residual(from, to) = 0; + m_residual(to, from) += v->weight; + e[from] -= v->weight; + e[to] = v->weight; + } + } + + void push(int from, int to) { + int delta = Min(e[from], m_residual(from, to)); + m_residual(from, to) -= delta; + m_residual(to, from) += delta; + e[from] -= delta; + e[to] += delta; + } + + void relabel(int from, int height) { + h[from] = height + 1; + } + + void relabel(int from) { + int min_height = INT_MAX; + Graph::Adjacent * a = (* possible_residual_edge)[from]; + Graph::Vertex * v; + + list_for_each_entry(v, &a->v_head, v_node){ + int id_to = v->id; + int to = m_map[id_to]; + if (m_residual(from, to) > 0) + { + min_height = Min(min_height, h[to]); + } + else if (m_residual(from, to) == 0) + ; + else + printf("Negtive edge in residual network. Error!\n"); + } + h[from] = min_height + 1; + } + + void discharge(int from) { + if (e[from] <= 0){ + return; + } + + Graph::Adjacent * a = (* possible_residual_edge)[from]; + Graph::Vertex * current; + bool overflow = true; + + while(overflow) + { + int to; + + list_for_each_entry(current, &a->v_head, v_node){ + to = m_map[current->id]; + if (m_residual(from, to) > 0 && h[from] == h[to] + 1){ + push(from, to); + if (e[from] <= 0){ + overflow = false; + break; + } + } + } + if (overflow == true){ + relabel(from); + } + } + } + + int run(uint32_t src, uint32_t sink) { + initialize_preflow(src); + + DirectedGraph * VertexList = new DirectedGraph; + Graph::Adjacent * a; + + list_for_each_entry(a, &g.list(), a_node){ + if (a->v.id != src && a->v.id != sink){ + VertexList->add_vertex(a->v.id); + } + } + + list_for_each_entry(a, &(*VertexList).list(), a_node){ + int from = m_map[a->v.id]; + int old_height = h[from]; + + discharge(from); + if (h[from] > old_height){ + list_move(&a->a_node, const_cast(&(*VertexList).list())); + } + } + + delete VertexList; + + int maxflow = e[g.vertex_count()-1]; + + return maxflow; + } + + /* + * This function implemented push-relabel algorithm in a naive way. But it's not push-to-front. + */ + int run_push_relabel(uint32_t src, uint32_t sink) { + initialize_preflow(src); + + bool overflow = true; + while (overflow){ + overflow = false; + // source point and sink point are not overflow-point by definition. + for (uint32_t i=1; i 0) { + overflow = true; + bool need_relabel = true, residual_edge = false; + int min_height = INT_MAX; + + Graph::Adjacent * cur = (* possible_residual_edge)[from]; + Graph::Vertex * v; + list_for_each_entry(v, &cur->v_head, v_node){ + int id_to = v->id; + int to = m_map[id_to]; + if (m_residual(from, to) > 0){ + residual_edge = true; + min_height = Min(min_height, h[to]); + if (h[from] > h[to]) + { + need_relabel = false; + if (h[from] == h[to] + 1){ + push(from, to); + } + } + } + } + if (need_relabel && residual_edge){ + relabel(from, min_height); + } + } + } + } + + int maxflow = e[g.vertex_count()-1]; // The value of maxflow is equal to e[sink]. + + return maxflow; + } + + inline const Array2D & residual() const { return m_residual; } + inline const HashTable & map() const {return m_map; } + inline const HashTable & rmap() const { return m_rmap; } + inline const HashTable & excess() const { return e; } + inline const HashTable & height() const { return h; } + }; +} + +#endif diff --git a/include/scc.h b/include/scc.h new file mode 100644 index 00000000..ef41af12 --- /dev/null +++ b/include/scc.h @@ -0,0 +1,67 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * STRONGLY CONNECTED COMPONENT + * + * In the mathematical theory of directed graphs, a graph is said to be strongly + * connected if every vertex is reachable from every other vertex. The strongly + * connected components of an arbitrary directed graph form a partition into + * subgraphs that are themselves strongly connected. It is possible to test the + * strong connectivity of a graph, or to find its strongly connected components, + * in linear time. + * + * http://en.wikipedia.org/wiki/Strongly_connected_component + ******************************************************************************/ + +#ifndef ALGO_SCC_H__ +#define ALGO_SCC_H__ +#include +#include +#include +#include "graph_defs.h" +#include "graph_search.h" +#include "heap.h" + +namespace alg { + /** + * Output Strongly Connected Component of a Graph + */ + static void SCC(DirectedGraph &g) { + // call DFS(G) to compute finishing times u.f for each vertex u + DFS(g); + // the transpose of the graph + DirectedGraph * GT = g.transpose(); + // step 1. discover vertices of G in decreasing of u.f + Heap Q(g.vertex_count()) ; + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node) { + Q.push(INT_MAX - a->f, a->v.id); // descending order of a->f + } + + // step 2. discover + // mark all vertex color to WHITE + list_for_each_entry(a, >->list(), a_node) { + a->color = Graph::WHITE; + } + + // 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()) { + 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]); + printf("\n"); + } + } + delete GT; + } +} + +#endif // diff --git a/include/selection_sort.h b/include/selection_sort.h new file mode 100644 index 00000000..7b0f53e3 --- /dev/null +++ b/include/selection_sort.h @@ -0,0 +1,52 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * SELECTION SORT + * + * In computer science, selection sort is a sorting algorithm, specifically an + * in-place comparison sort. It has O(n2) time complexity, making it inefficient + * on large lists, and generally performs worse than the similar insertion sort. + * Selection sort is noted for its simplicity, and it has performance advantages + * over more complicated algorithms in certain situations, particularly where + * auxiliary memory is limited. + * + * http://en.wikipedia.org/wiki/Selection_sort + ******************************************************************************/ + +#ifndef ALGO_SELECTION_SORT_H__ +#define ALGO_SELECTION_SORT_H__ + +#include +#include + +namespace alg { + template + static void SelectionSort(T list[], int start, int end) { + int i,j; + int iMin; + + assert(start <= end); + + for(j = start; j <= end-1; j++) { + // assume the min is the first element */ + iMin = j; + // test against elements after i to find the smallest + for(i = j+1; i <= end; i++) { + if (list[i] < list[iMin]) { + iMin = i; + } + } + + // iMin is the index of the minimum element. Swap it with the current position + if (iMin != j) { + swap(list[j], list[iMin]); + } + } + } +} + +#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 49d2ae3e..0bdd69cd 100644 --- a/include/shuffle.h +++ b/include/shuffle.h @@ -14,33 +14,31 @@ * ******************************************************************************/ -#ifndef __SHUFFLE_H__ -#define __SHUFFLE_H__ +#ifndef ALGO_SHUFFLE_H__ +#define ALGO_SHUFFLE_H__ #include #include #include -namespace alg -{ +namespace alg { /** * shuffle the 'list' of length 'len' */ template - static void shuffle(T * list, int len) - { - srand(time(NULL)); - int i = len, j; - T temp; + static void shuffle(T * list, int len) { + srand(time(NULL)); + int i = len, j; + T temp; - if ( i == 0 ) return; - while ( --i ) { - j = rand() % (i+1); - temp = list[i]; - list[i] = list[j]; - list[j] = temp; + if ( i == 0 ) return; + while ( --i ) { + j = rand() % (i+1); + temp = list[i]; + list[i] = list[j]; + list[j] = temp; + } } - } } #endif // diff --git a/include/simhash.h b/include/simhash.h index d0d8ebd0..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 @@ -21,55 +21,55 @@ namespace alg { class SimHash { - private: - int V[32]; - public: - SimHash() { - memset(V, 0, sizeof(V)); - } + private: + int V[32]; + public: + SimHash() { + memset(V, 0, sizeof(V)); + } - /** - * hash a single word - */ - void AddWord(const char * word, uint32_t len) { - uint32_t hash = hash_fnv1a(word,len); - for(int i=0;i<32;i++) { - if (hash&(1< 0) { - hash|= (1< 0) { + hash|= (1< #include #include #include #include +#include -namespace alg -{ +namespace alg { template - class SkipList - { + class SkipList { private: struct SkipNode { KeyT key; // key @@ -36,15 +35,20 @@ namespace alg static const int SL_MAX_LEVEL = 6; + class NotFoundException: public std::exception { + public: + virtual const char * what() const throw() { + return "cannot find the element in skiplist"; + } + } excp_notfound; + public: - SkipList() - { + SkipList() { m_header = make_node(SL_MAX_LEVEL, 0, 0); m_level = 0; } - ~SkipList() - { + ~SkipList() { // TODO: free nodes } @@ -55,10 +59,9 @@ namespace alg public: /** * search the given key from the skip list - * if the key is not exist, return NULL + * if the key is not exist, throw exception */ - inline ValueT operator[] (KeyT key) const - { + inline ValueT operator[] (KeyT key) const { struct SkipNode* x = m_header; // travels down until level-0 @@ -70,14 +73,13 @@ namespace alg x = x->forward[0]; if(x != NULL && x->key == key) return x->value; - return NULL; + throw excp_notfound; } /** * insert a key->key pair into the list */ - void insert(KeyT key, ValueT value) - { + void insert(KeyT key, ValueT value) { struct SkipNode * x = m_header; struct SkipNode * update[SL_MAX_LEVEL + 1]; memset(update, 0, SL_MAX_LEVEL + 1); @@ -95,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++) { @@ -116,8 +118,7 @@ namespace alg /** * delete a node by it's key */ - void delete_key(KeyT key) - { + void delete_key(KeyT key) { struct SkipNode* x = m_header; struct SkipNode* update[SL_MAX_LEVEL + 1]; memset(update, 0, SL_MAX_LEVEL + 1); @@ -146,8 +147,7 @@ namespace alg } } - void print() - { + void print() { for(int i=m_level-1;i>=0;i--) { SkipNode* x = m_header->forward[i]; printf("{"); @@ -169,8 +169,7 @@ namespace alg /** * get the random promote level */ - int random_level() - { + int random_level() { int lvl = 0; // the possibility is 1/2 for each level while(rand_norm() < 0.5f && lvl < SL_MAX_LEVEL) @@ -182,8 +181,7 @@ namespace alg /** * make a node with specified level & key */ - SkipNode * make_node(int level, KeyT key, ValueT value) - { + SkipNode * make_node(int level, KeyT key, ValueT value) { SkipNode * n = new SkipNode; // the max forward entry for a key is : level + 1 @@ -193,7 +191,6 @@ namespace alg return n; } - }; } diff --git a/include/sol.h b/include/sol.h index cfca2e59..c8064fc8 100644 --- a/include/sol.h +++ b/include/sol.h @@ -16,33 +16,30 @@ * ******************************************************************************/ -#ifndef __SOL_H__ -#define __SOL_H__ +#ifndef ALGO_SOL_H__ +#define ALGO_SOL_H__ #include "double_linked_list.h" -namespace alg -{ +namespace alg { /** * Move a node to the front */ - static inline void list_mtf(struct list_head *entry, struct list_head *head) - { + 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); } /** * Move a node ahead one position */ - static inline void list_mao(struct list_head *entry, struct list_head * head) - { + static inline void list_mao(struct list_head *entry, struct list_head * head) { // 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/sort.h b/include/sort.h new file mode 100644 index 00000000..51e78d1b --- /dev/null +++ b/include/sort.h @@ -0,0 +1,296 @@ +#ifndef _SORT_H_ +#define _SORT_H_ + + +#include +#include + + +using namespace std; + +namespace alg{ + + template + class SortClass{ + public: + SortClass(vector& sort_list,bool(*comp)(T,T),void(*_swap)(T&,T&)){ + m_sort_list=&sort_list; + compre=comp; + swap=_swap; + } + + + ~SortClass(){ + + } + + // + // 插入排序法 + // + void insertSort(){ + int j; + T temp; + for(size_t i = 1; i < (*m_sort_list).size(); ++i) + { + temp=(*m_sort_list)[i]; + j=i-1; + while((j>=0) && (compre((*m_sort_list)[j],temp)==true)){ + (*m_sort_list)[j+1] = (*m_sort_list)[j]; + j--; + } + (*m_sort_list)[j+1] = temp; + /* code */ + } + + } + + + // + // 冒泡排序法 + // + void bubbleSort(){ + + for(size_t i = 0; i < (*m_sort_list).size(); ++i) + { + for(size_t j = i+1; j < (*m_sort_list).size(); ++j) + { + if(compre((*m_sort_list)[i],(*m_sort_list)[j])==true){ + + swap((*m_sort_list)[i],(*m_sort_list)[j]); + + } + + } + + } + + } + + + // + // 快速排序 + // + void quickSort(){ + _quickSort((*m_sort_list),0,(*m_sort_list).size()-1); + } + + + // + // 选择排序 + // + void selectionSort(){ + + int min_index; + + for(size_t i = 0; i < (*m_sort_list).size()-1; ++i) + { + min_index=i; + for(size_t j = i+1; j < (*m_sort_list).size(); ++j) + { + if ( compre((*m_sort_list)[min_index],(*m_sort_list)[j]) == true) + min_index=j; + + } + + if (i != min_index) + { + swap((*m_sort_list)[min_index],(*m_sort_list)[i]); + + } + } + + } + + + // + // 归并排序 + // + void mergeSort(){ + + _mergeSort(1); + + } + + + // + // 堆排序 + // + void heapSort(){ + + buildHeap(); + for(int i = (*m_sort_list).size()-1; i > 0; --i) + { + swap((*m_sort_list)[0],(*m_sort_list)[i]); + + adjHeap(0,i); + + } + } + + + + void displaySort(){ + + for(size_t i = 0; i < (*m_sort_list).size(); ++i) + { + cout << (*m_sort_list)[i] << ","; + + } + cout << endl; + + } + + + + + private: + vector *m_sort_list; + vector m_merge_list; + bool (*compre)(T,T); + void (*swap)(T&,T&); + + // + // 归并排序具体实现,双路归并 + // + void _mergeSort(int len){ + + if(len>(*m_sort_list).size()) + return; + + m_merge_list.clear(); + for(size_t i = 0; i < (*m_sort_list).size(); i+=len*2) + { + + int j=i; + int k=i+len; + int maxj = ( i+len >= (*m_sort_list).size() ) ? (*m_sort_list).size() : (i+len); + int maxk = ( i+2*len >= (*m_sort_list).size() ) ? (*m_sort_list).size() : (i+2*len); + + while((j= 0 ; --i) + { + adjHeap(i,(*m_sort_list).size()); + } + + + } + + + // + // 快速排序具体实现 + // + void _quickSort(vector& arr,int start,int end){ + + int i,j; + i = start; + j = end; + if((arr.size()==0)) + return; + + while(i1){ + _quickSort(arr,start,i-1); + } + + if(end-j>1){ + _quickSort(arr,j+1,end); + } + } + + }; + + +} + + +#endif \ No newline at end of file diff --git a/include/stack.h b/include/stack.h index 2af8b557..21ab1159 100644 --- a/include/stack.h +++ b/include/stack.h @@ -14,116 +14,109 @@ * ******************************************************************************/ -#ifndef __STACK_H__ -#define __STACK_H__ +#ifndef ALGO_STACK_H__ +#define ALGO_STACK_H__ #include #include #include -/** - * Stack has three properties. capacity stands for the maximum number of - * elements stack can hold. Size stands for the current size of the stack and elements - * is the array of elements - */ -template -class Stack -{ -private: - class StackEmptyException: public std::exception - { - public: - virtual const char * what() const throw() - { - return "stack is empty"; - } - }; - - class StackIndexOutOfBoundException: public std::exception - { - public: - virtual const char * what() const throw() - { - return "Index out of bound."; - } - }; - - uint32_t m_capacity; // the total capacity - uint32_t m_size; // current stack size - T * m_elements; // the elements - const StackEmptyException exp_empty; - const StackIndexOutOfBoundException exp_ioob; - -public: - /** - * capcity is the maximum elements the stack can hold. +namespace alg { + /** + * Stack has three properties. capacity stands for the maximum number of + * elements stack can hold. Size stands for the current size of the stack and elements + * is the array of elements */ - Stack(uint32_t capacity) { - this->m_capacity = capacity; - this->m_size = 0; - this->m_elements = new T[capacity]; - } - - ~Stack() { - delete [] m_elements; - } - - -private: - Stack(const Stack&); - Stack& operator=(const Stack&); - - -public: - /** - * test whether the stack is empty - */ - inline bool is_empty() const { return m_size==0?true:false; } - - /** - * pop stack - */ - inline void pop() - { - if(m_size!=0) m_size--; - return; - } - - /** - * get the top element - */ - inline const T& top() const - { - if (m_size==0) throw exp_empty; - return m_elements[m_size-1]; - } - - /** - * push an element into the stack - * returns false when stack is full. - */ - inline bool push(const T & value) - { - if(m_size==m_capacity) { return false; } - else { - m_elements[m_size++] = value; - return true; - } - } - - /** - * return the stack size count. - */ - inline uint32_t count() const { return m_size; } - - /** - * return value by index - */ - inline const T& operator[] (int idx) const - { - if (idx<0 || idx >= m_capacity) throw exp_ioob; - return m_elements[m_size-1-idx]; - } -}; + template + class Stack { + private: + class StackEmptyException: public std::exception { + public: + virtual const char * what() const throw() + { + return "stack is empty"; + } + } excp_empty; + + class StackIndexOutOfBoundException: public std::exception { + public: + virtual const char * what() const throw() + { + return "Index out of bound."; + } + } excp_ioob; + + uint32_t m_capacity; // the total capacity + uint32_t m_size; // current stack size + T * m_elements; // the elements + + public: + /** + * capcity is the maximum elements the stack can hold. + */ + Stack(uint32_t capacity) { + this->m_capacity = capacity; + this->m_size = 0; + this->m_elements = new T[capacity]; + } + + ~Stack() { + delete [] m_elements; + } + + + private: + Stack(const Stack&); + Stack& operator=(const Stack&); + + + public: + /** + * test whether the stack is empty + */ + inline bool is_empty() const { return m_size==0?true:false; } + + /** + * pop stack + */ + inline void pop() { + if(m_size!=0) m_size--; + return; + } + + /** + * get the top element + */ + inline const T& top() const { + if (m_size==0) throw excp_empty; + return m_elements[m_size-1]; + } + + /** + * push an element into the stack + * returns false when stack is full. + */ + inline bool push(const T & value) { + if(m_size==m_capacity) { return false; } + else { + m_elements[m_size++] = value; + return true; + } + } + + /** + * return the stack size count. + */ + inline uint32_t count() const { return m_size; } + + /** + * return value by index + */ + inline const T& operator[] (uint32_t idx) const { + if (idx >= m_capacity) throw excp_ioob; + return m_elements[m_size-1-idx]; + } + }; +} #endif // diff --git a/include/suffix_array.h b/include/suffix_array.h new file mode 100644 index 00000000..8c7e11fb --- /dev/null +++ b/include/suffix_array.h @@ -0,0 +1,103 @@ +/******************************************************************************* + * ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * SUFFIX ARRAY + * + * Features: + * suffix array can sort all the suffixs in time complexity O(n*log^2(n)), + * and use memory in O(n). And suffix array can get two suffixs' longest + * common prefix(lcp) in O(log(n)) complexity. + * + * You can test it by running suffix_array_demo.cpp + * Want to get more detailed information about suffix array? + * + * Please google SUFF_AR_ENG.pdf + * + * AUTHOR: nowerzt@gmail.com + ******************************************************************************/ + +#ifndef ALGO_SUFFIX_ARRAY_H__ +#define ALGO_SUFFIX_ARRAY_H__ + +#include +#include +#include +#include +#include + +using namespace std; + +namespace alg { + class SuffixArray { + private: + vector > bucket; + vector suffix; + int N, L, K; + const string& str; + void suffix_sort(); + void update_bucket(); + + bool less_than(int a, int b) { + if(K==0) return str[a]>1)=0 && x +//#include +#include +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::map; +using std::make_pair; +using std::cout; +using std::endl; +using std::out_of_range; +using std::ostream; +//typedef tr1::unordered_map map; + +// TODO: upgrade it to process trace. Rule: char-->elem string-->elem_list +class SuffixTree +{ +public: + // active point is initialized as (root, None, 0), remainder initialized as 1 + 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 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) + { + Iterator result = sub; + Node* node = &root; + Edge* edge = NULL; + int pos = 0; // the iter's pos at edge + int edge_len = -1; + bool flag = true; + + + while (flag) { + if (edge == NULL) { + edge = node->find_edge(*result); + if (edge == NULL) { + flag = false; + } + else { + result++; + pos = 1; // the second element of the edge + edge_len = edge->length(); + } + } + else { + if (pos >= edge_len) { + node = edge->endpoint; + edge = NULL; + edge_len = 0; + } + else { + if (*result == (*edge)[pos]) { + result++; + pos++; + } + else + flag = false; + } + } + } + + return result; + } + + struct 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; + // Is there a better way to find test_str? + string& test_node_str; + + Node * endpoint; + + Edge(unsigned int b, unsigned int e, string& str): + test_node_str(str) + { + begin = b; + end = e; + endpoint = NULL; + std::cout << "Edge initialized" << std::endl; + } + + void change_edge(unsigned int b, unsigned int e) + { + begin = b; + end = e; + } + + int length(void) + { + + if (end > test_node_str.size()) + return test_node_str.size() - begin; + else + return end - begin + 1; + } + + // needed by map + friend bool operator<(const Edge& me, const Edge& other) + { + return me.begin < other.begin; + } + + char operator[](unsigned int i) + { + i += begin; + if (i > end) + throw out_of_range("Edge [] out of range."); + + return test_node_str[i]; + } + + friend ostream& operator<<(ostream& os, Edge& edge) + { + unsigned int end = edge.test_node_str.size()-1; + if (end >= edge.end) + end = edge.end; + + char c; + for (unsigned int i=edge.begin; i<=end; i++) { + c = edge.test_node_str[i]; + os << c; + } + if (end != edge.end) + os << '#'; + + return os; + } + + bool is_none(void) { return begin == 0 && end == 0; } + }; + + struct Node{ + string& test_node_str; + map testmap; + map edges; + // find the edge quicky by storing the leading char of this edge + map findedges; + Node* suffix_link; + + friend class LinkState; + + Node(string& str) : + test_node_str(str), suffix_link(NULL) { edges.clear(); findedges.clear(); } + + void add_edge(Edge* edge) { + if (edge->endpoint == NULL) + edge->endpoint = new Node(test_node_str); + make_pair(edge, true); + edges.insert(make_pair(edge, true)); + findedges.insert(make_pair(test_node_str[edge->begin], edge)); + cout << "edge added. Now we have " << edges.size() << "edges." << endl; + } + + void del_edge(Edge* edge) { + map::iterator iter = edges.find(edge); + + if (iter == edges.end()) + throw out_of_range("edge don't exit"); + else { + // note we should erase the findedges too + edges.erase(edge); + cout << "delete" << (*edge)[0] << endl; + findedges.erase((*edge)[0]); + cout << "edge deleted. Now we have " << edges.size() << "edges." << endl; + } + + } + + // find edge by the first char + Edge* find_edge(char c) + { + cout << "finding edge char " << c; + map::iterator iter = findedges.find(c); + cout << " founded? "; + + if (iter != findedges.end()) { + cout << "yes." << endl; + return iter->second; + } + else { + cout << "no." << endl; + return NULL; + } + } + + bool isleaf() { return edges.empty(); } + + bool operator==(Node& other) + { + return (this) == (&other); + } + + friend ostream& operator<<(ostream& os, Node& node) + { + map::iterator iter; + map::iterator iter_f; + + for (iter=node.edges.begin(); iter!=node.edges.end(); ++iter) + os << iter->first << '\t'; + os << endl; + + for (iter_f=node.findedges.begin(); iter_f!=node.findedges.end(); ++iter_f) + os << iter_f->first << "-->" << iter_f->second << endl; + + return os; + } + }; + int print_tree(void); +private: + string test_str; + class ActivePoint{ + public: + Node* active_node; + char active_edge; + int active_length; + + ActivePoint(Node* node, char edge, int length): + active_node(node), active_edge(edge), active_length(length) { std::cout << "ActivePoint initialized" << std::endl; } + }; + + Node root; + ActivePoint active_point; + + Node* get_active_node(void) { return active_point.active_node; } + void set_active_node(Node* node) { active_point.active_node = node; cout << "Active node set as " << node << endl; } + char get_active_edge(void) + { + return test_str[active_e]; + } + + int get_active_length(void) { return active_point.active_length; } + void set_active_length(int len) { active_point.active_length = len; } + void inc_active_len() { active_point.active_length++; } + void dec_active_len() { active_point.active_length--; } + + // how many suffixes is to be inserted? + int remainder; + // how many characters inserted? + unsigned int pos; + 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(); + int insert_rule1(); + int insert_rule3(); + int print_node(Node* node, int level); + + + Node* separate_edge(Node * node, Edge* edge); + + // check if we can change active node + bool check_active_node(void) + { + Node* node = get_active_node(); + char a_char = get_active_edge(); + Edge* edge = node->find_edge(a_char); + + if (edge == NULL) + return false; + + unsigned int edge_size = edge->end - edge->begin + 1; + unsigned int length = get_active_length(); + + // update + if (length >= edge_size) { + set_active_node(edge->endpoint); + set_active_length(length-edge_size); + active_e += edge_size; + + return true; + } + return false; + } + + // this class indicate when shall we insert a suffix link + // ls should be a singleton + class LinkState + { + bool first; + + Node* prev, *curr; + + public: + LinkState() : first(true), prev(NULL), curr(NULL) {} + + void ins_link(Node* node) + { + prev = curr; + curr = node; + + if (first == false) { + prev->suffix_link = curr; + cout << "Suffix link added from prev " << prev << " to curr " << curr << endl; + } + + first = false; + } + + void clear(void) + { + first = true; + prev = curr = NULL; + } + }; + LinkState ls; +}; diff --git a/include/trie.h b/include/trie.h index efae60c3..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 @@ -20,107 +20,105 @@ namespace alg { const int NUMWORD = 26; - class Trie { - private: - class node { + private: + class node { + public: + int words; + int prefixes; + node *edges[NUMWORD]; + node():words(0),prefixes(0) { + memset(edges, 0, sizeof(edges)); + } + ~node() { + for (int i=0;iwords++; - } else { - n->prefixes++; - int index=str[0]-'a'; - if (n->edges[index]==NULL) { - n->edges[index] = new node; - } - _add(n->edges[index], ++str); - } - } - - int _count(node *n, char * str) { - if (str[0] == '\0') { - return n->words; - } else { - int index=str[0]-'a'; - if (n->edges[index]==NULL) { - return 0; - } + int Count(const char *str) { + char * _str = strdup(str); + _lowercase(_str); + + int cnt = _count(m_root, _str); + free(_str); + return cnt; + } + + int CountPrefix(const char *prefix) { + char * _str = strdup(prefix); + _lowercase(_str); + + int cnt = _count_prefix(m_root, _str); + free(_str); + return cnt; + } - return _count(n->edges[index], ++str); - } - } - - int _count_prefix(node *n, char * str) { - if (str[0] == '\0') { - return n->prefixes; - } else { - int index=str[0]-'a'; - if (n->edges[index]==NULL) { - return 0; + private: + void _lowercase(char *str) { + int i; + for (i=0;str[i];i++) { + str[i] = tolower(str[i]); } + } + + void _add(node *n, const char * str) { + if (str[0] == '\0') { + n->words++; + } else { + n->prefixes++; + int index=str[0]-'a'; + if (n->edges[index]==NULL) { + n->edges[index] = new node; + } - return _count_prefix(n->edges[index], ++str); - } - } + _add(n->edges[index], ++str); + } + } + + int _count(node *n, const char * str) { + if (str[0] == '\0') { + return n->words; + } else { + int index=str[0]-'a'; + if (n->edges[index]==NULL) { + return 0; + } + + return _count(n->edges[index], ++str); + } + } + + int _count_prefix(node *n, char * str) { + if (str[0] == '\0') { + return n->prefixes; + } else { + int index=str[0]-'a'; + if (n->edges[index]==NULL) { + return 0; + } + + return _count_prefix(n->edges[index], ++str); + } + } }; } diff --git a/include/undirected_graph.h b/include/undirected_graph.h index 3cc6d6cc..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 @@ -25,114 +25,134 @@ #include "graph_defs.h" #include "double_linked_list.h" -namespace alg -{ - class UndirectedGraph:public Graph - { - private: - /** - * delete a vertex from adjacent lists - */ - void delete_me(Adjacent * a) - { - Vertex * v,* vn; - - // for each connected-vertex - list_for_each_entry_safe(v, vn, &a->v_head, v_node){ - Adjacent * neigh = (*this)[v->id]; - neigh->delete_vertex(a->v.id); - num_edges--; - } - } - public: - /** - * create a new vertex and add to the graph, with specified id. - */ - inline bool add_vertex(uint32_t id) - { - if ((*this)[id]!=NULL) return false; - - // new empty adjacent list - Adjacent * a = new Adjacent(id); - INIT_LIST_HEAD(&a->v_head); - list_add_tail(&a->a_node, &a_head); - num_vertex++; - - return true; - } - - /** - * delete a vertex with specified id - */ - void delete_vertex(uint32_t id) - { - Adjacent * a = (*this)[id]; - if (a==NULL) return; - delete_me(a); - - // delete adjacent list itself. - num_vertex--; - list_del(&a->a_node); - delete a; - } - - /** - * add an edge for x<->y - */ - bool add_edge(uint32_t x, uint32_t y, int32_t weight) - { - struct Adjacent * a1 = (*this)[x]; - struct Adjacent * a2 = (*this)[y]; - - if (a1==NULL || a2==NULL) return false; - if (is_adjacent(a1, a2)) return false; - - // create new vertex & add to adjacent list - Vertex * n = new Vertex(y); - n->weight = weight; - list_add_tail(&n->v_node, &a1->v_head); - - n = new Vertex(x); - n->weight = weight; - list_add_tail(&n->v_node, &a2->v_head); - - num_edges++; - a1->num_neigh++; - a2->num_neigh++; - - return true; - } - - /** - * delete an edge for x<->y - */ - void delete_edge(uint32_t x, uint32_t y) - { - Adjacent * a1 = (*this)[x]; - Adjacent * a2 = (*this)[y]; - if (a1==NULL || a2==NULL) return ; - if (!is_adjacent(a1, a2)) return ; - - Vertex * v, *n; - // find x->.....y... - list_for_each_entry_safe(v, n, &a1->v_head, v_node){ - if (v->id == y) { - list_del(&v->v_node); - delete(v); +namespace alg { + class UndirectedGraph:public Graph { + private: + /** + * delete a vertex from adjacent lists + */ + void delete_me(Adjacent * a) { + Vertex * v,* vn; + + // for each connected-vertex + list_for_each_entry_safe(v, vn, &a->v_head, v_node){ + Adjacent * neigh = (*this)[v->id]; + neigh->delete_vertex(a->v.id); num_edges--; - a1->num_neigh--; } } + public: + /** + * create a new vertex and add to the graph, with specified id. + */ + inline bool add_vertex(uint32_t id) { + if ((*this)[id]!=NULL) return false; + + // new empty adjacent list + Adjacent * a = new Adjacent(id); + INIT_LIST_HEAD(&a->v_head); + list_add_tail(&a->a_node, &a_head); + num_vertex++; + + return true; + } + + /** + * delete a vertex with specified id + */ + void delete_vertex(uint32_t id) { + Adjacent * a = (*this)[id]; + if (a==NULL) return; + delete_me(a); + + // delete adjacent list itself. + num_vertex--; + list_del(&a->a_node); + delete a; + } + + /** + * add an edge for x<->y + */ + bool add_edge(uint32_t x, uint32_t y, int32_t weight) { + struct Adjacent * a1 = (*this)[x]; + struct Adjacent * a2 = (*this)[y]; + + if (a1==NULL || a2==NULL) return false; + if (is_adjacent(a1, a2)) return false; + + // create new vertex & add to adjacent list + Vertex * n = new Vertex(y); + n->weight = weight; + list_add_tail(&n->v_node, &a1->v_head); + + n = new Vertex(x); + n->weight = weight; + list_add_tail(&n->v_node, &a2->v_head); + + num_edges++; + a1->num_neigh++; + a2->num_neigh++; - // find y->.....x... - list_for_each_entry_safe(v, n, &a2->v_head, v_node){ - if (v->id == x) { - list_del(&v->v_node); - delete(v); - a2->num_neigh--; + return true; + } + + /** + * delete an edge for x<->y + */ + void delete_edge(uint32_t x, uint32_t y) { + Adjacent * a1 = (*this)[x]; + Adjacent * a2 = (*this)[y]; + if (a1==NULL || a2==NULL) return ; + if (!is_adjacent(a1, a2)) return ; + + Vertex * v, *n; + // find x->.....y... + list_for_each_entry_safe(v, n, &a1->v_head, v_node){ + if (v->id == y) { + list_del(&v->v_node); + delete(v); + num_edges--; + a1->num_neigh--; + } + } + + // find y->.....x... + list_for_each_entry_safe(v, n, &a2->v_head, v_node){ + if (v->id == x) { + list_del(&v->v_node); + delete(v); + a2->num_neigh--; + } + } + } + /** + * randomly generate a graph, for test purpose + * start from 1 + */ + static UndirectedGraph * randgraph(int nvertex) { + UndirectedGraph * g = new UndirectedGraph; + int i; + + for(i=1;i<=nvertex;i++) { + g->add_vertex(i); + } + + // random connect + for(i=1;i<=nvertex;i++) { + int j; + for(j=i+1;jadd_edge(i, j, w); + } + } } + + + return g; } - } }; } diff --git a/include/universal_hash.h b/include/universal_hash.h index 9b44e60c..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 @@ -26,8 +26,7 @@ #include "random.h" #include "integer.h" -namespace alg -{ +namespace alg { struct UHash { uint32_t a[KLEN]; uint32_t prime; @@ -36,8 +35,7 @@ namespace alg /** * init an universal hash struct */ - static inline void uhash_init(struct UHash * params, uint32_t max_element) - { + static inline void uhash_init(struct UHash * params, uint32_t max_element) { int i; // the size of the hash bucket is the prime larger than 2 * max_element for(i=max_element+1;;i++) { @@ -55,8 +53,7 @@ namespace alg /** * hash a key */ - static inline uint32_t uhash_integer(const struct UHash * params, uint64_t key) - { + static inline uint32_t uhash_integer(const struct UHash * params, uint64_t key) { uint32_t k[KLEN]; uint32_t sum; @@ -66,11 +63,10 @@ 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) - { + static uint32_t uhash_bigint(const struct UHash * params, uint32_t * key, uint32_t len) { // TODO : need a better algorithm, or NOT? return key[0]%params->prime; } diff --git a/include/word_seg.h b/include/word_seg.h index e8e2b335..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 @@ -32,8 +32,7 @@ #include "2darray.h" #endif//ALG_VLA_NOT_SUPPORTED -namespace alg -{ +namespace alg { /** * define a word in four state * which means a @@ -42,290 +41,281 @@ namespace alg * -- MIDDLE, a word is at the middle of the word, eg, '习' in '补习班' * -- END, a word is at the end of the word, eg, '物' in '有机物' */ - class WordSeg - { - public: - enum WORDSTATE { - SINGLE = 0, - BEGIN = 1, - MIDDLE = 2, - END = 3 - }; - - enum WORDTAG { - N=0, // 名词 - V, // 动词 - ADJ , // 形容词 - ADV , // 副词 - CLAS, // 量词 - ECHO, // 拟声词 - STRU, // 结构助词 - AUX , // 助词 - COOR, // 并列连词 - CONJ, // 连词 - SUFFIX, // 前缀 - PREFIX, // 后缀 - PREP , // 介词 - PRON , // 代词 - QUES , // 疑问词 - NUM , // 数词 - IDIOM // 成语 - }; - - /** - * the state transition probability matrix. - * the 2-d array is in the format of : - * SINGLE -> S B M E - * ... -> S B M E - */ - inline const float (&TP()const)[4][4] - { + class WordSeg { + public: + enum WORDSTATE { + SINGLE = 0, + BEGIN = 1, + MIDDLE = 2, + END = 3 + }; + + enum WORDTAG { + N=0, // 名词 + V, // 动词 + ADJ , // 形容词 + ADV , // 副词 + CLAS, // 量词 + ECHO, // 拟声词 + STRU, // 结构助词 + AUX , // 助词 + COOR, // 并列连词 + CONJ, // 连词 + SUFFIX, // 前缀 + PREFIX, // 后缀 + PREP , // 介词 + PRON , // 代词 + QUES , // 疑问词 + NUM , // 数词 + IDIOM // 成语 + }; + /** * the state transition probability matrix. * the 2-d array is in the format of : * SINGLE -> S B M E * ... -> S B M E - * A MORE SOPHISTICATED CALCULATION IS REQUIRED IN PRACTICE */ - static const float _TP[4][4] = { - {0.5138298266610544, 0.48617017333894563, 0.000001, 0.000001}, - {0.000001, 0.000001, 0.14817814348183422, 0.8518218565181658}, - {0.000001, 0.000001, 0.2835512540013088, 0.7164487459986911}, - {0.44551469488355755, 0.554485305116442, 0.000001, 0.000001} - }; + inline const float (&TP()const)[4][4] { + /** + * the state transition probability matrix. + * the 2-d array is in the format of : + * SINGLE -> S B M E + * ... -> S B M E + * A MORE SOPHISTICATED CALCULATION IS REQUIRED IN PRACTICE + */ + static const float _TP[4][4] = { + {0.5138298266610544, 0.48617017333894563, 0.000001, 0.000001}, + {0.000001, 0.000001, 0.14817814348183422, 0.8518218565181658}, + {0.000001, 0.000001, 0.2835512540013088, 0.7164487459986911}, + {0.44551469488355755, 0.554485305116442, 0.000001, 0.000001} + }; - return _TP; - } - /** - * the start probability of state - */ - inline const float (&SP()const)[4] - { + return _TP; + } /** * the start probability of state */ - static const float _SP[4] = {0.5f, 0.5f, 0.0f, 0.0f}; - return _SP; - } - /** - * word state definition - * record a single word emission probability in each state - */ - struct WordEP { - float EP[4]; // the emission probability in each state - uint64_t SC[4]; // the count of appearence in each state - WordEP() { - EP[0] = EP[1] = EP[2] = EP[3] = 0.0f; - SC[0] = SC[1] = SC[2] = SC[3] = 0; + inline const float (&SP()const)[4] { + /** + * the start probability of state + */ + static const float _SP[4] = {0.5f, 0.5f, 0.0f, 0.0f}; + return _SP; } - }; - - static const int GB18030_NR = 70244; - - /** - * The word segmentation structure. - */ - private: - HashTable wordht; // a WORD-> WordEP hashtable - uint32_t words[GB18030_NR]; // every char in GB18030 - - public: - WordSeg() : wordht(GB18030_NR){ } - - /** - * init a WordSeg struct by a given file - * format: - * WORD1 ..... - * WORD2 - * .... - * WORDN - */ - WordSeg(const char * path):wordht(GB18030_NR) { - FILE * fp; - char word[64]; // the longest word should be less than 64 char - - fp = fopen(path, "r"); - if (fp==NULL) { - perror(__func__); - } else { - while(!feof(fp)) { - fscanf(fp, "%s%*[^\n]", word); - // printf("read %s count %d\n", word, count); - add_word(word); + /** + * word state definition + * record a single word emission probability in each state + */ + struct WordEP { + float EP[4]; // the emission probability in each state + uint64_t SC[4]; // the count of appearence in each state + WordEP() { + EP[0] = EP[1] = EP[2] = EP[3] = 0.0f; + SC[0] = SC[1] = SC[2] = SC[3] = 0; } - } - fclose(fp); - - calc_all(); - } + }; - /** - * add a new word to the hashtable - */ - void add_word(const char * word) - { - int i=0; - int len = strlen(word); - int num_char = 0; + static const int GB18030_NR = 70244; - while(word[i]!='\0') { - uint32_t CH; - i+= gb18030_read(word, i, &CH); - num_char++; + /** + * The word segmentation structure. + */ + private: + HashTable wordht; // a WORD-> WordEP hashtable + public: + WordSeg() : wordht(GB18030_NR){ } - WordEP & wep = wordht[CH]; + /** + * init a WordSeg struct by a given file + * format: + * WORD1 ..... + * WORD2 + * .... + * WORDN + */ + WordSeg(const char * path):wordht(GB18030_NR) { + FILE * fp; + char word[64]; // the longest word should be less than 64 char - if (i==len && (num_char==1)) { // single word - wep.SC[SINGLE]+=1; + fp = fopen(path, "r"); + if (fp==NULL) { + perror(__func__); } else { - if (num_char==1) { // begin - wep.SC[BEGIN]+=1; + while(!feof(fp)) { + fscanf(fp, "%s%*[^\n]", word); + // printf("read %s count %d\n", word, count); + add_word(word); + } + } + fclose(fp); + + calc_all(); + } + + /** + * add a new word to the hashtable + */ + void add_word(const char * word) { + int i=0; + int len = strlen(word); + int num_char = 0; + + while(word[i]!='\0') { + uint32_t CH; + i+= gb18030_read(word, i, &CH); + num_char++; + + WordEP & wep = wordht[CH]; + + if (i==len && (num_char==1)) { // single word + wep.SC[SINGLE]+=1; } else { - if (i==len) { //end - wep.SC[END]+=1; - } else { // otherwise we are in middle - wep.SC[MIDDLE]+=1; + if (num_char==1) { // begin + wep.SC[BEGIN]+=1; + } else { + if (i==len) { //end + wep.SC[END]+=1; + } else { // otherwise we are in middle + wep.SC[MIDDLE]+=1; + } } } } - } - }; - - /** - * return the most possible B,E,M,S sequence(FIFO) for a sentence - * using The Viterbi algorithm - * - * you should strip the , . white-spaces first before entering this - * function - */ - Queue * run(const char * str) - { - // the position of string cursor - int pos = 0; - int len = strlen(str); - + }; + + /** + * return the most possible B,E,M,S sequence(FIFO) for a sentence + * using The Viterbi algorithm + * + * you should strip the , . white-spaces first before entering this + * function + */ + Queue * run(const char * str) { + // the position of string cursor + int pos = 0; + int len = strlen(str); + #ifdef ALG_VLA_NOT_SUPPORTED - alg::Array2D V(len, 4); - uint32_t CH; + alg::Array2D V(len, 4); + uint32_t CH; - // record the path - alg::Array2D<> path(4, len+1); - alg::Array2D<> newpath(4, len+1); + // record the path + alg::Array2D<> path(4, len+1); + alg::Array2D<> newpath(4, len+1); - path.clear(0); - newpath.clear(0); + path.clear(0); + newpath.clear(0); #else - double V[len][4]; - uint32_t CH; - - // record the path - char path[4][len+1]; - char newpath[4][len+1]; - - memset(path,0, sizeof(path)); - memset(newpath,0, sizeof(newpath)); + double V[len][4]; + uint32_t CH; + + // record the path + char path[4][len+1]; + char newpath[4][len+1]; + + memset(path,0, sizeof(path)); + memset(newpath,0, sizeof(newpath)); #endif - // Initialize base case. the first observation. - int i; - pos = gb18030_read(str, pos, &CH); - - for(i=0; i<4;i++) { - V[0][i] = SP()[i] * wordht[CH].EP[i]; - path[i][0] = i+'0'; - } + // Initialize base case. the first observation. + int i; + pos = gb18030_read(str, pos, &CH); - // Run Viterbi for observation > 1 - int wc=1; // word count; - while(pos prob_max) { - prob_max = prob; - state_max = k; - } - } - // update the maximum values - V[wc][j] = prob_max; - strcpy(newpath[j], path[state_max]); - newpath[j][wc] = j+'0'; + for(i=0; i<4;i++) { + V[0][i] = SP()[i] * wordht[CH].EP[i]; + path[i][0] = i+'0'; } - - // path update - for (j=0;j<4;j++) { - strcpy(path[j], newpath[j]); + + // Run Viterbi for observation > 1 + int wc=1; // word count; + while(pos prob_max) { + prob_max = prob; + state_max = k; + } + } + // update the maximum values + V[wc][j] = prob_max; + strcpy(newpath[j], path[state_max]); + newpath[j][wc] = j+'0'; + } + + // path update + for (j=0;j<4;j++) { + strcpy(path[j], newpath[j]); + } + + wc++; } - - wc++; - } - double prob_max = 0; - int state_max = 0; + double prob_max = 0; + int state_max = 0; - for(i=0;i<4;i++) { - if (V[wc-1][i] > prob_max) { - prob_max = V[wc-1][i]; - state_max = i; + for(i=0;i<4;i++) { + if (V[wc-1][i] > prob_max) { + prob_max = V[wc-1][i]; + state_max = i; + } } - } - - Queue * q = new Queue(wc); - - i=0; - while(path[state_max][i]!='\0') { - q->enqueue(path[state_max][i]); - i++; - } - return q; - } - - private: - /** - * calc a single word emission probability by its count in each state - */ - void calc_ep(WordEP & wep) - { - double sum = wep.SC[0]+wep.SC[1]+wep.SC[2]+wep.SC[3]; - wep.EP[SINGLE] = wep.SC[SINGLE]/sum; - wep.EP[BEGIN] = wep.SC[BEGIN]/sum; - wep.EP[END] = wep.SC[END]/sum; - wep.EP[MIDDLE] = wep.SC[MIDDLE]/sum; - }; - - /** - * calculate the emission probability for each word - */ - void calc_all() - { - unsigned char i, j, m, n; - - // for each char in gb18030 - for (i=0;i<=0x7f;i++) { calc_ep(wordht[i]); } - - for (i=0x81;i<=0xFE;i++) { - for(j=0x40;j<=0xFE;j++) { - uint32_t CH = (i << 8)|j; - calc_ep(wordht[CH]); + Queue * q = new Queue(wc); + + i=0; + while(path[state_max][i]!='\0') { + q->enqueue(path[state_max][i]); + i++; } - - for(j=0x30;j<=0x39;j++) { - for(m=0x81;m<=0xFE;m++) { - for(n=0x30;n<=0x39;n++) { - uint32_t CH = (i<<24)|(j<<16)|(m<<8)|n; - calc_ep(wordht[CH]); + + return q; + } + + private: + /** + * calc a single word emission probability by its count in each state + */ + void calc_ep(WordEP & wep) { + double sum = wep.SC[0]+wep.SC[1]+wep.SC[2]+wep.SC[3]; + wep.EP[SINGLE] = wep.SC[SINGLE]/sum; + wep.EP[BEGIN] = wep.SC[BEGIN]/sum; + wep.EP[END] = wep.SC[END]/sum; + wep.EP[MIDDLE] = wep.SC[MIDDLE]/sum; + }; + + /** + * calculate the emission probability for each word + */ + void calc_all() { + unsigned char i, j, m, n; + + // for each char in gb18030 + for (i=0;i<=0x7f;i++) { calc_ep(wordht[i]); } + + for (i=0x81;i<=0xFE;i++) { + for(j=0x40;j<=0xFE;j++) { + uint32_t CH = (i << 8)|j; + calc_ep(wordht[CH]); + } + + for(j=0x30;j<=0x39;j++) { + for(m=0x81;m<=0xFE;m++) { + for(n=0x30;n<=0x39;n++) { + uint32_t CH = (i<<24)|(j<<16)|(m<<8)|n; + calc_ep(wordht[CH]); + } } } } - } - }; + }; }; } diff --git a/msvc/alg_vs.h b/msvc/alg_vs.h index 623174db..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 @@ -8,11 +8,11 @@ #define strtok_r strtok_s -#if _MSC_VER <= 1700 -#define ALG_VLA_NOT_SUPPORTED 1 +#if _MSC_VER <= 1800 +#define ALG_VLA_NOT_SUPPORTED #endif #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/8queue_demo.cpp b/src/8queue_demo.cpp new file mode 100644 index 00000000..fc26016b --- /dev/null +++ b/src/8queue_demo.cpp @@ -0,0 +1,8 @@ +#include +#include <8queen.h> + +int main(void) { + alg::Queen8 q; + q.solve(); +} + diff --git a/src/LRU_cache_demo.cpp b/src/LRU_cache_demo.cpp new file mode 100644 index 00000000..24a853f9 --- /dev/null +++ b/src/LRU_cache_demo.cpp @@ -0,0 +1,35 @@ + +#include +#include "LRU_cache.h" + +using namespace std; +using namespace alg; + +int main() { + + + LRUCache Cache(5); + Cache.putValue("key1","value1"); + Cache.putValue("key2","value2"); + Cache.putValue("key3","value3"); + Cache.putValue("key4","value4"); + Cache.putValue("key5","value5"); + Cache.putValue("key6","value6"); + + + cout << "Display The LRU Cache...." << endl; + Cache.display(); + + cout << "Now,Visit the LRU Cache with \"key4\"" << endl; + cout << "The \"key4\" Value is : "<< Cache.getValue("key4") << endl; + cout << "The New LRU Cache is ... " << endl; + Cache.display(); + + cout << "Now, Update The LRU Cache with \"key5\" and new value is \"newValue5\" ... " << endl; + Cache.putValue("key5","newValue5"); + cout << "The New LRU Cache is ... " << endl; + Cache.display(); + Cache.getValue("aaa"); + + +} diff --git a/src/astar_demo.cpp b/src/astar_demo.cpp index b48d8325..cdc51f20 100644 --- a/src/astar_demo.cpp +++ b/src/astar_demo.cpp @@ -3,7 +3,7 @@ #include #include "astar.h" -#define N 40 +#define N 128 #define MARK 0xEE diff --git a/src/avl_demo.cpp b/src/avl_demo.cpp new file mode 100644 index 00000000..444185f0 --- /dev/null +++ b/src/avl_demo.cpp @@ -0,0 +1,66 @@ +#include +#include "avl.h" + +using namespace std; +using namespace alg; + +const unsigned N = 4096*32; +const unsigned N_ELEMS_TO_REMOVE = N-128; // Must be between 0 and N-1 + +template +void printTreeStatus(const AVL &t) { + cout << "----------------------------------------" << endl; + if (t.isEmpty()) cout << "The tree is empty" << endl; + else { + cout << "Tree root is: " << t.root() << endl; + cout << "Tree height is: " << t.height() << endl; + cout << "Tree contains " << t.size() << " elements" << endl; + } + cout << "----------------------------------------" << endl; +} + +int main() +{ + int values[N]; + + AVL avl; + + cout << "Populating the tree with " << N << " random values... "; + for (unsigned i = 0; i < N; ++i) { + values[i] = rand(); + avl.insert(values[i]); + } + cout << "Done" << endl; + + printTreeStatus(avl); + + for (unsigned i = 0; i < N; ++i) { + unsigned idx = rand() % N; + if (!avl.contains(values[idx])) + cout << "ERROR: Value " << values[idx] << " was inserted and not found!" << endl; + } + + cout << "Now removing a random element from the tree... "; + unsigned idx = rand() % N; + avl.erase(values[idx]); + cout << "Done" << endl; + + printTreeStatus(avl); + + cout << "Now removing the root of the tree " << N_ELEMS_TO_REMOVE << " times... "; + for (unsigned i = 0; i < N_ELEMS_TO_REMOVE; ++i) { + avl.erase(avl.root()); + } + cout << "Done" << endl; + + printTreeStatus(avl); + + // Outputting to cerr so the output can be redirected with ./avl_demo 2> .gvz + cout << "Do you want to output the GraphViz representation of the tree to the cerr stream (Y/n)? "; + char usrInput; + cin >> usrInput; + if (usrInput == 'Y' || usrInput == 'y') avl.toGraphViz(cerr, "AVL"); + + return 0; +} + diff --git a/src/base64_demo.cpp b/src/base64_demo.cpp new file mode 100644 index 00000000..3b0ad16c --- /dev/null +++ b/src/base64_demo.cpp @@ -0,0 +1,18 @@ +#include +#include "base64.h" +#include + +using namespace std; + +int main() { + const char *s = "Matthew 7:24-27 Therefore everyone who hears these words of mine and puts them into practice is like a wise man who built his house on the rock. 25 The rain came down, the streams rose, and the winds blew and beat against that house; yet it did not fall, because it had its foundation on the rock. 26 But everyone who hears these words of mine and does not put them into practice is like a foolish man who built his house on sand. 27 The rain came down, the streams rose, and the winds blew and beat against that house, and it fell with a great crash."; + cout << " INPUT: " << endl; + cout << s << endl << endl; + + string base=alg::CBase64::encodeBase64((unsigned char *) s, strlen(s)); + cout << " encodeBase64: " << endl; + cout << base << endl << endl; + + cout << " decodeBase64: " << endl; + cout << alg::CBase64::decodeBase64(base) << endl; +} diff --git a/src/bellman_ford_demo.cpp b/src/bellman_ford_demo.cpp index 5bd5b21e..432e00d9 100644 --- a/src/bellman_ford_demo.cpp +++ b/src/bellman_ford_demo.cpp @@ -8,45 +8,17 @@ #include "bellman_ford.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -DirectedGraph * randgraph(int nvertex) -{ - DirectedGraph * g = new DirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=3;iadd_edge(i, j, w); - } - } - } - - - return g; -} - int main(void) { srand(time(NULL)); - int NVERTEX = 50; - DirectedGraph * g = randgraph(NVERTEX); - g->print(); + int NVERTEX = 10; + DirectedGraph * g = DirectedGraph::randgraph(NVERTEX); + g->printdot(); BellmanFord bf(*g); printf("finding bellman-ford shortest path starting from 3: \n"); - std::auto_ptr > previous(bf.run(3)); + std::auto_ptr > previous(bf.run(3)); Graph::Adjacent * a; list_for_each_entry(a, &g->list(), a_node) { @@ -59,13 +31,17 @@ int main(void) printf("\nconstructing a negative cycle and run again\n"); // construct a negative cycle; - g->add_edge(0,1, -1); - g->add_edge(1,2, -1); - g->add_edge(2,0, -1); + g->add_vertex(100); + g->add_vertex(101); + g->add_vertex(102); + g->add_edge(100,101, -1); + g->add_edge(101,102, -1); + g->add_edge(102,100, -1); BellmanFord bf2(*g); - std::auto_ptr > previous2(bf2.run(0)); + std::auto_ptr > previous2(bf2.run(0)); + g->printdot(); printf("\nwe %s have negative weighted cycle.\n", bf2.has_negative_cycle()?"DO":"DON'T"); delete g; diff --git a/src/binary_search_tree_demo.cpp b/src/binary_search_tree_demo.cpp index 3b817868..3e4e1ea5 100644 --- a/src/binary_search_tree_demo.cpp +++ b/src/binary_search_tree_demo.cpp @@ -27,13 +27,16 @@ int main() t.insert(key[i], value[i]); } + t.print_helper(); + for(i = 0; i < MAX_ELEMENTS; i++){ - printf("getting %d->%d\n",key[i], t[key[i]]); + printf("getting %d->%d\n",key[i], t.find(key[i])->value); } for(i = 0; i < MAX_ELEMENTS; i++){ - int k = rand()%100; - printf("testing %d-> %s\n",k,t.contains(k)?"YES":"NO"); + t.deleteKey(key[i]); + t.print_helper(); + printf("deleted %d\n\n", key[i]); } return 0; diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp new file mode 100644 index 00000000..e26a8b21 --- /dev/null +++ b/src/btree_demo.cpp @@ -0,0 +1,25 @@ +#include +#include "btree.h" + +using namespace alg; +int main(void) { + BTree x("./btree.dat"); + int32_t i; + + for (i=0;i<1000;i++) { + x.Insert(i); + printf("insert %d\n", i); + BTree::Res r = x.Search(i); + if (r.idx == -1) { + printf("key[%d] insert failed\n", i); + } + } + + for (i=0;i<1000;i++) { + x.DeleteKey(i); + BTree::Res r = x.Search(i); + if (r.idx == -1) { + printf("key[%d] removed\n", i); + } + } +} diff --git a/src/bubble_sort_demo.cpp b/src/bubble_sort_demo.cpp new file mode 100644 index 00000000..37ca5072 --- /dev/null +++ b/src/bubble_sort_demo.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +#include "generic.h" +#include "bubble_sort.h" + +using namespace alg; +int main (int argc, char const *argv[]) { + const int MAX_ELEMENTS = 10; + int list[MAX_ELEMENTS]; + for(int i = 0; i < MAX_ELEMENTS; i++ ){ + list[i] = rand()%100; + } + printf("The list before sorting is:\n"); + printlist(list,MAX_ELEMENTS); + + alg::BubbleSort(list,0,MAX_ELEMENTS-1); + + printf("The list after sorting using bubble-sort algorithm:\n"); + printlist(list,MAX_ELEMENTS); + + return 0; +} diff --git a/src/dictionary_demo.cpp b/src/dictionary_demo.cpp new file mode 100644 index 00000000..d352cc88 --- /dev/null +++ b/src/dictionary_demo.cpp @@ -0,0 +1,49 @@ +#include "dictionary.h" +#include "hash_table.h" +#include "random.h" +#include + +using namespace alg; +using namespace std::chrono; + +int main(void) { + + Dictionary dict; + + dict.Add(0, 1); + dict.Add(1, 2); + dict.Add(5, 2); + dict.Add(3, 3); + dict.Remove(5); + dict.AddOrUpdate(3, 4); + + for (auto x : dict) + { + printf("%d - %d\n", x.Key, x.Value); + } + + static const uint32_t TEST_LENGTH = 1000000; + Dictionary d(TEST_LENGTH); + HashTable h(TEST_LENGTH); + + auto t0 = high_resolution_clock::now(); + + for (uint32_t i = 0; i < TEST_LENGTH; i++) + { + d.AddOrUpdate(alg::LCG(), alg::LCG()); + } + + auto t1 = high_resolution_clock::now(); + + for (uint32_t i = 0; i < TEST_LENGTH; i++) + { + h[alg::LCG()] = alg::LCG(); + } + + auto t2 = high_resolution_clock::now(); + + auto dt0 = duration_cast(t1 - t0).count(); + auto dt1 = duration_cast(t2 - t1).count(); + + printf("Dictionary: %lld ms, HashTable: %lld ms\n", dt0, dt1); +} diff --git a/src/dijkstra_demo.cpp b/src/dijkstra_demo.cpp index 61cc6374..a0873a8b 100644 --- a/src/dijkstra_demo.cpp +++ b/src/dijkstra_demo.cpp @@ -8,46 +8,18 @@ #include "dijkstra.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -DirectedGraph * randgraph(int nvertex) -{ - DirectedGraph * g = new DirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - return g; -} int main(void) { using namespace alg; srand(time(NULL)); - int NVERTEX = 50; - std::auto_ptr g(randgraph(NVERTEX)); - g->print(); + int NVERTEX = 10; + std::auto_ptr g(DirectedGraph::randgraph(NVERTEX)); + g->printdot(); - Dijkstra dijkstra(*g); Graph::Adjacent * a; - printf("finding Dijkstra shortest path starting from 0: \n"); - HashTable * result = dijkstra.run(0); + printf("finding Dijkstra shortest path starting from 1: \n"); + HashTable * result = Dijkstra::run(*g, 1); list_for_each_entry(a, &g->list(), a_node){ printf("previous of %u is ", a->v.id); @@ -57,9 +29,9 @@ int main(void) } delete result; - printf("finding Dijkstra shortest path starting from 10: \n"); + printf("finding Dijkstra shortest path starting from 2: \n"); - result = dijkstra.run(10); + result = Dijkstra::run(*g, 2); list_for_each_entry(a, &g->list(), a_node){ printf("previous of %u is ", a->v.id); int32_t pre = (*result)[a->v.id]; diff --git a/src/directed_graph_demo.cpp b/src/directed_graph_demo.cpp index 8a424ba5..77197457 100644 --- a/src/directed_graph_demo.cpp +++ b/src/directed_graph_demo.cpp @@ -5,40 +5,12 @@ #include "directed_graph.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -DirectedGraph * randgraph(int nvertex) -{ - DirectedGraph * g = new DirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - return g; -} - int main() { srand(time(NULL)); int NVERTEX = 20; - DirectedGraph * g = randgraph(NVERTEX); - g->print(); + DirectedGraph * g = DirectedGraph::randgraph(NVERTEX); + g->printdot(); printf("Random Delete Vertex:\n"); // random delete vertex @@ -49,7 +21,7 @@ int main() g->delete_vertex(n); } - g->print(); + g->printdot(); printf("Delete All Edges: \n"); for(i=0;iprint(); + g->printdot(); return 0; } diff --git a/src/disjoint-set_demo.cpp b/src/disjoint-set_demo.cpp new file mode 100644 index 00000000..6d0eb204 --- /dev/null +++ b/src/disjoint-set_demo.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +int main(void) { + alg::Set s1; + alg::Set s2; + alg::MakeSet(&s1); + alg::MakeSet(&s2); + + printf("before:\n"); + std::cout<< alg::FindSet(&s1) << std::endl; + std::cout<< alg::FindSet(&s2) << std::endl; + + printf("after:\n"); + alg::Union(&s1, &s2); + std::cout<< alg::FindSet(&s1) << std::endl; + std::cout<< alg::FindSet(&s2) << std::endl; +} diff --git a/src/edmonds_karp_demo.cpp b/src/edmonds_karp_demo.cpp index 427a091f..a5bb02c8 100644 --- a/src/edmonds_karp_demo.cpp +++ b/src/edmonds_karp_demo.cpp @@ -4,41 +4,13 @@ #include "edmonds_karp.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -DirectedGraph * randgraph(int nvertex) -{ - DirectedGraph * g = new DirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - return g; -} - int main(void) { using namespace alg; srand(time(NULL)); int NVERTEX = 6; - DirectedGraph * g = randgraph(NVERTEX); - g->print(); + DirectedGraph * g = DirectedGraph::randgraph(NVERTEX); + g->printdot(); printf("finding Maximal Flow from 0 to 5: \n"); EdmondsKarp ek(*g); 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/fib-heap_demo.cpp b/src/fib-heap_demo.cpp new file mode 100644 index 00000000..8aa765a4 --- /dev/null +++ b/src/fib-heap_demo.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include "fib-heap.h" + +int main(void) { + srand(time(NULL)); + alg::FibHeap heap; + int32_t i; + for (i=0;i<10;i++) { + heap.Insert(rand(), i); + } + + for (i=0;i<10;i++) { + alg::FibHeap::Node n; + n = heap.ExtractMin(); + if (n!= NULL) { + printf("%d %d\n", n->key, n->value); + } + } +} diff --git a/src/graph_search_demo.cpp b/src/graph_search_demo.cpp index 2d031d66..7db103f2 100644 --- a/src/graph_search_demo.cpp +++ b/src/graph_search_demo.cpp @@ -6,46 +6,19 @@ #include "directed_graph.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -DirectedGraph * randgraph(int nvertex) -{ - DirectedGraph * g = new DirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - return g; -} int main() { using namespace alg; srand(time(NULL)); int NVERTEX = 10; - Graph * g = randgraph(NVERTEX); - g->print(); + Graph * g = DirectedGraph::randgraph(NVERTEX); + g->printdot(); printf("breadth first search: \n"); - breadth_first_search(*g, 0); + BFS(*g, 0); printf("depth first search: \n"); - depth_first_search(*g, 0); + DFS(*g); delete g; return 0; diff --git a/src/hash_table_demo.cpp b/src/hash_table_demo.cpp index 5824c28e..90bb7f59 100644 --- a/src/hash_table_demo.cpp +++ b/src/hash_table_demo.cpp @@ -10,7 +10,7 @@ int main() const int MAX_ELEMENTS = 50; srand(time(NULL)); - HashTable ht(MAX_ELEMENTS); + HashTable ht(MAX_ELEMENTS); printf("Hash Table Demo: \n"); int i; diff --git a/src/heap_demo.cpp b/src/heap_demo.cpp index 7f75582f..ccae4aea 100644 --- a/src/heap_demo.cpp +++ b/src/heap_demo.cpp @@ -6,24 +6,28 @@ int main() { using namespace alg; - int MAXELEMENTS=50; + int MAXELEMENTS=10; Heap heap(MAXELEMENTS); - + int i; srand(time(NULL)); for (i=0;i < MAXELEMENTS; i++) { - int value = rand()%1000; - heap.insert(100-i, value); - printf("inserting: %d->%d\n", 100-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/huffman_demo.cpp b/src/huffman_demo.cpp index eb38e885..6c0786cf 100644 --- a/src/huffman_demo.cpp +++ b/src/huffman_demo.cpp @@ -14,11 +14,11 @@ int main(void) printf("encoding message: \n%s\n", STR); - printf("<<< before huffman coding : length:%d bytes\n", strlen(STR)); + printf("<<< before huffman coding : length:%lu bytes\n", strlen(STR)); memset(codes, 0, sizeof(codes)); length = tree.encode(STR, codes); - printf(">>> after huffman coding : length:%d bytes\n", length/8); + printf(">>> after huffman coding : length:%u bytes\n", length/8); printf("decoding messsage:\n"); tree.decode(codes, length); diff --git a/src/kmp_demo.cpp b/src/kmp_demo.cpp index 7b107bd6..b42d7f10 100644 --- a/src/kmp_demo.cpp +++ b/src/kmp_demo.cpp @@ -8,32 +8,33 @@ using namespace alg; int main(void) { srand(time(NULL)); - char * S = (char*)malloc(10000); - char * W = (char*)malloc(6); + char * S = (char*)malloc(1001); + char * W = (char*)malloc(5); - memset(S,0, 10000); - memset(W,0, 6); + memset(S,0, 1001); + memset(W,0, 5); // random genrate a pattern for A, G, C,T const char P[] = {'A', 'G','C','T'}; - for (int i=0;i<10000;i++) { + for (int i=0;i<1000;i++) { int k = rand()%4; S[i] = P[k]; } - for (int i=0;i<6;i++) { + for (int i=0;i<4;i++) { int k = rand()%4; W[i] = P[k]; } // do a search for W from S int pos = kmp_search(S, W); + printf("to be searched:%s\n", W); - printf("text:\n%s\n", S); if (pos > 0) { - printf("found %s from text, pos %d\n", W, pos); - } else { - printf("cannot found %s from text\n", W); + printf("found in pos:%d\n", pos); + printf("text:\n%.*s", pos, S); + printf("\033[31m%s\033[0m", W); + printf("%s\n",&S[pos + strlen(W)]); } } diff --git a/src/kruskal_mst_demo.cpp b/src/kruskal_mst_demo.cpp index f19b1516..18362ffb 100644 --- a/src/kruskal_mst_demo.cpp +++ b/src/kruskal_mst_demo.cpp @@ -7,43 +7,13 @@ #include "kruskal_mst.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -UndirectedGraph * randgraph(int nvertex) -{ - UndirectedGraph * g = new UndirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - - - return g; -} - int main(void) { using namespace alg; srand(time(NULL)); int NVERTEX = 10; - UndirectedGraph * g = randgraph(NVERTEX); - g->print(); + UndirectedGraph * g = UndirectedGraph::randgraph(NVERTEX); + g->printdot(); printf("Generating Kruskal's Graph: \n"); Kruskal pg(*g); pg.print(); @@ -51,7 +21,7 @@ int main(void) printf("Generating Minimal spanning tree: \n"); Graph * mst = pg.run(); - mst->print(); + mst->printdot(); delete mst; delete g; 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 "max_subarray.h" + +using namespace alg; +int main() { + int arr[] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}; + int arr2[] = {1,-1,-2,-3,-4}; + + int begin; + int end; + int i; + + printf("the array:\n"); + for (i=0;i + +int main() { + alg::palindrome("banana"); + alg::palindrome("abba"); + alg::palindrome("aaaaa"); +} diff --git a/src/prim_mst_demo.cpp b/src/prim_mst_demo.cpp index b71a3f83..2dc15319 100644 --- a/src/prim_mst_demo.cpp +++ b/src/prim_mst_demo.cpp @@ -5,50 +5,18 @@ #include "undirected_graph.h" #include "prim_mst.h" -using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -UndirectedGraph * randgraph(int nvertex) -{ - UndirectedGraph * g = new UndirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - return g; -} int main(void) { using namespace alg; srand(time(NULL)); int NVERTEX = 10; - UndirectedGraph * g = randgraph(NVERTEX); - g->print(); + alg::UndirectedGraph * g = alg::UndirectedGraph::randgraph(NVERTEX); + g->printdot(); printf("Generating Prim's Graph: \n"); - Prim pg(*g); - pg.print(); - - printf("Generating Minimal spanning tree: \n"); - Graph * mst = pg.run(); - mst->print(); - delete mst; + Graph * prim = alg::Prim::run(*g, 1); + prim->printdot(); + delete prim; delete g; return 0; } diff --git a/src/prime_test.cpp b/src/prime_demo.cpp similarity index 100% rename from src/prime_test.cpp rename to src/prime_demo.cpp diff --git a/src/queue_demo.cpp b/src/queue_demo.cpp index 5f27fc4a..6c73f08a 100644 --- a/src/queue_demo.cpp +++ b/src/queue_demo.cpp @@ -17,6 +17,8 @@ int main() Q.enqueue(value); } + printf("queue count:%u\n", Q.count()); + printf("> DEQUEUE\n"); while(!Q.is_empty()) { printf("dequeue %d\n",Q.front()); diff --git a/src/random_demo.cpp b/src/random_demo.cpp index 3c5788a5..d2df1d8c 100644 --- a/src/random_demo.cpp +++ b/src/random_demo.cpp @@ -1,9 +1,9 @@ -#include +#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 "edmonds_karp.h" +#include "relabel_to_front.h" +using namespace alg; + +int main(void) +{ + using namespace alg; + srand(time(NULL)); + int NVERTEX = 300; + + clock_t ek_start, ek_end, pr_start, pr_end; + + DirectedGraph * g = DirectedGraph::randgraph(NVERTEX); +// g->printdot(); + + printf("finding Maximal Flow from 0 to %d: \n", NVERTEX-1); + printf("The graph containing %d edges.\n", g->edge_count()); + + ek_start = clock(); + EdmondsKarp ek(*g); + uint32_t maxflow = ek.run(0, NVERTEX-1); + ek_end = clock(); + + printf("Max Flow calculated by edmonds-karp algorithm is %d\n", maxflow); +// printf("the residual network\n"); +// printf("\t"); +// for(uint32_t i=0;ivertex_count();i++) { +// printf("%d\t", ek2.rmap()[i]); +// } +// printf("\n"); + +// for(uint32_t i=0;ivertex_count();i++) { +// printf("%d\t",ek2.rmap()[i]); +// for(uint32_t j=0;jvertex_count();j++) { +// printf("%d\t", ek2.residual()(i,j)); +// } +// printf("\n"); +// } + + pr_start = clock(); + RelabelToFront pr2(*g); + uint32_t maxflow_pr = pr2.run(0, NVERTEX-1); + pr_end = clock(); + + printf("Max Flow calculated by push-relabel is %d\n", maxflow_pr); +// printf("the residual and preflow network\n"); +// printf("\t"); +// for(uint32_t i=0; ivertex_count(); i++) { +// printf("%d\t", pr2.rmap()[i]); +// } +// printf("\n"); + +// for (uint32_t i=0; ivertex_count(); i++){ +// printf("%d\t", pr2.rmap()[i]); +// for (uint32_t j=0; jvertex_count(); j++){ +// printf("%d\t", pr2.residual()(i,j)); +// } +// printf("\n"); +// } +// printf("\n"); + + long ek_time = ek_end - ek_start; + long pr_time = pr_end - pr_start; + + printf("The number of clock tick consumed by edmonds-karp is %ld\n", ek_time); + printf("--------------------------------- by push-relabel is %ld\n", pr_time); + + delete g; + + return 0; +} diff --git a/src/scc_demo.cpp b/src/scc_demo.cpp new file mode 100644 index 00000000..4b409b65 --- /dev/null +++ b/src/scc_demo.cpp @@ -0,0 +1,45 @@ +#include +#include +#include + +#include "directed_graph.h" +#include "graph_search.h" +#include "scc.h" + +using namespace alg; + +int main() +{ + using namespace alg; + srand(time(NULL)); + DirectedGraph * g = new DirectedGraph; + // construct 3 islands + int32_t i; + for (i=0;i<9;i++) { + g->add_vertex(i); + } + + g->add_edge(0,1,1); + g->add_edge(1,2,1); + g->add_edge(2,0,1); + + g->add_edge(3,4,1); + g->add_edge(4,5,1); + g->add_edge(5,3,1); + + g->add_edge(6,7,1); + g->add_edge(7,8,1); + g->add_edge(8,6,1); + + // connect island + g->add_edge(0,3,1); + g->add_edge(3,8,1); + + g->printdot(); + + printf("find strongly connected component\n"); + SCC(*g); + + delete g; + return 0; +} diff --git a/src/selection_sort_demo.cpp b/src/selection_sort_demo.cpp new file mode 100644 index 00000000..3968cf41 --- /dev/null +++ b/src/selection_sort_demo.cpp @@ -0,0 +1,28 @@ +#include + +#include "selection_sort.h" + +template +static void printlist(T & list,int count) { + int i; + for(i=0;i -#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/skip_list_demo.cpp b/src/skiplist_demo.cpp similarity index 81% rename from src/skip_list_demo.cpp rename to src/skiplist_demo.cpp index 39c70bdc..a9d26953 100644 --- a/src/skip_list_demo.cpp +++ b/src/skiplist_demo.cpp @@ -1,10 +1,8 @@ #include -#include "skip_list.h" +#include "skiplist.h" using namespace alg; - - int main() { @@ -25,7 +23,11 @@ int main() printf("Random get keys :\n"); for(i = 0; i < MAX_ELEMENTS; i++ ){ int r = rand()%100; - printf("get: %d->%d\n",r, ss[r]); + try { + printf("get: %d->%d\n",r, ss[r]); + } catch (std::exception &e) { + printf("%s\n", e.what()); + } } printf("random deleteion:\n"); diff --git a/src/sort_demo.cpp b/src/sort_demo.cpp new file mode 100644 index 00000000..3f50f7bd --- /dev/null +++ b/src/sort_demo.cpp @@ -0,0 +1,117 @@ + +#include +#include +#include "sort.h" + +using namespace std; +using namespace alg; + + +///////////////////////////// +// +// custom compare function +// +///////////////////////////// +bool comp(int a,int b){ + if (a>=b) + return true; + + return false; +} + +///////////////////////////// +// +// custom swap function +// +/////////////////////////////// +void swap(int &a,int &b){ + int tmp; + tmp=a; + a=b; + b=tmp; +} + + +//make rand data +void makeArray(vector& array,int num){ + + for(size_t i = 0; i < num; ++i) + { + array.push_back(rand()%100); + /* code */ + } + +} + + +int main (int argc, char const *argv[]) +{ + vector a; + + alg::SortClass sort(a,comp,swap); + makeArray(a,10); + cout << "############### quick sort ###############" << endl; + cout << "before sort::: " ; + sort.displaySort(); + sort.quickSort(); + cout << "after sort ::: "; + sort.displaySort(); + cout << endl; + + + a.clear(); + makeArray(a,11); + cout << "############### insertion sort ###############" << endl; + cout << "before sort::: " ; + sort.displaySort(); + sort.insertSort(); + cout << "after sort ::: "; + sort.displaySort(); + cout << endl; + + + a.clear(); + makeArray(a,10); + cout << "############### bubble sort ###############" << endl; + cout << "before sort::: " ; + sort.displaySort(); + sort.bubbleSort(); + cout << "after sort ::: "; + sort.displaySort(); + cout << endl; + + + a.clear(); + makeArray(a,10); + cout << "############### selection sort ###############" << endl; + cout << "before sort::: " ; + sort.displaySort(); + sort.selectionSort(); + cout << "after sort ::: "; + sort.displaySort(); + cout << endl; + + + a.clear(); + makeArray(a,10); + cout << "############### heap sort ###############" << endl; + cout << "before sort::: " ; + sort.displaySort(); + sort.heapSort(); + cout << "after sort ::: "; + sort.displaySort(); + cout << endl; + + a.clear(); + makeArray(a,10); + cout << "############### merge sort ###############" << endl; + cout << "before sort::: " ; + sort.displaySort(); + sort.mergeSort(); + cout << "after sort ::: "; + sort.displaySort(); + + + + return 0; +} diff --git a/src/stack_demo.cpp b/src/stack_demo.cpp index fac5be10..e69acce3 100644 --- a/src/stack_demo.cpp +++ b/src/stack_demo.cpp @@ -2,6 +2,7 @@ #include #include "stack.h" +using namespace alg; int main() { Stack S(4); diff --git a/src/suffix_array_demo.cpp b/src/suffix_array_demo.cpp new file mode 100644 index 00000000..a49a00b8 --- /dev/null +++ b/src/suffix_array_demo.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "suffix_array.h" + +using namespace std; +using namespace alg; + +void print(string::iterator b, string::iterator e) { + for(auto it=b;it!=e;++it) cout<<*it; +} + +int main() +{ + string str; + while(cin>>str) { + SuffixArray sa(str); + cout< + +int SuffixTree::search(string sub) +{ + Node* node = &root; + bool in_edge = false; // Are we searching in middle of an edge? + Edge* edge = NULL; + int edge_pos = 0, edge_len = 0; + + int result = -1; + + for (unsigned int i=0; ifind_edge(cur); // find an edge and search it + + if (edge == NULL) + return -1; + + // record match pos + if (i == 0) + result = edge->begin; + + edge_pos = 0; + edge_len = edge->length(); + } + + + if (cur != (*edge)[edge_pos]) + return -1; + + edge_pos++; + // reached the end of this edge, jump to next node + if (edge_pos >= edge_len) { + in_edge = false; + node = edge->endpoint; + edge = NULL; + edge_pos = 0; + } + } + + return result; +} + + +int SuffixTree::construct(void) +{ + // test_str shouldn't have '#' until now + test_str = test_str + "#"; + using std::numeric_limits; + + while (pos < test_str.size()) { + ls.clear(); + remainder++; + cout << "Char: " << test_str[pos] << endl; + + while (remainder) { + int length = get_active_length(); + if (length == 0) + active_e = pos; + + Node* node = active_point.active_node; + char a_char = get_active_edge(); + Edge* a_edge = node->find_edge(a_char); + + + if (a_edge == NULL) { + Edge* newedge = new Edge(pos, numeric_limits::max(), test_str); + node->add_edge(newedge); + ls.ins_link(node); + } + else { + if (check_active_node()) + continue; + + char expected_ele = (*a_edge)[get_active_length()]; + if (expected_ele == get_ele(pos)) { + inc_active_len(); + ls.ins_link(node); + break; + } + 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); + } + remainder--; + if (node == &root && get_active_length() > 0) { + dec_active_len(); + active_e = pos - remainder + 1; + } + else if (node->suffix_link) { + set_active_node(node->suffix_link); + } + else + set_active_node(&root); + } + + pos++; + } + return 0; +} + +SuffixTree::Node* SuffixTree::separate_edge(Node * node, Edge* a_edge) +{ + cout << "separate the old edge here: " << (*a_edge) << endl; + int new_begin = a_edge->begin + get_active_length(); + int new_end = a_edge->end; + + int old_begin = a_edge->begin; + int old_end = new_begin - 1; + + cout << (*node); + + node->del_edge(a_edge); + a_edge->change_edge(new_begin, new_end); + Edge* old_edge1 = new Edge(old_begin, old_end, test_str); + node->add_edge(old_edge1); + + old_edge1->endpoint->add_edge(a_edge); + + cout << "The old edge split as -- " << (*a_edge) << " and -- " << (*old_edge1) << endl; + + cout << "root " << (&root) << endl; + cout << node << endl; + Node* new_node = old_edge1->endpoint; + cout << node << endl; + + return new_node; +} + +int SuffixTree::print_tree() +{ + print_node(&root, 1); + + return 0; +} + +int SuffixTree::print_node(Node* node, int level) +{ + using namespace std; + if (level == 0) + cout << "Root " << endl; + + if (node->isleaf()) { + cout << "Leaf reached." << endl; + return 0; + } + + map::iterator iter; + for (iter = node->edges.begin(); iter!=node->edges.end(); iter++) { + int indent = level; + while (indent--) + cout << '\t'; + + int begin = iter->first->begin, end = (iter->first->end < test_str.size() - 1) ? iter->first->end : test_str.size() - 1; + cout << "--> (" << begin << ", " << end << ") "; + for (int i=begin; i<=end; i++) + cout << test_str[i]; + cout << endl; + + cout << "Node Add " << node << endl; + cout << "Edge printed " << iter->first << endl << endl; + print_node((iter->first->endpoint), level+1); + } + + cout << endl; + return 0; +} + +using namespace std; + +int main() +{ + cout << "Beginning" << endl; + SuffixTree st("mississippi"); + + cout << "Constructing..." << endl; + st.construct(); + + cout << "Printing..." << endl; + st.print_tree(); + + cout << "Search ANA:" << st.search("ANA") << endl; + cout << "Search NA:" << st.search("NA") << endl; + cout << "Search NAN:" << st.search("NAN") << endl; + cout << "Search B:" << st.search("B") << endl; + + cout << endl; + + cout << "Search BB:" << st.search("BB") << endl; + cout << "Search ANN:" << st.search("ANN") << endl; + cout << "Search b:" << st.search("b") << endl; + + return 0; +} diff --git a/src/undirected_graph_demo.cpp b/src/undirected_graph_demo.cpp index 3261b75a..6ecff464 100644 --- a/src/undirected_graph_demo.cpp +++ b/src/undirected_graph_demo.cpp @@ -5,40 +5,12 @@ #include "undirected_graph.h" using namespace alg; -/** - * randomly generate a graph, for test purpose - */ -UndirectedGraph * randgraph(int nvertex) -{ - UndirectedGraph * g = new UndirectedGraph; - int i; - - for(i=0;iadd_vertex(i); - } - - // random connect - for(i=0;iadd_edge(i, j, w); - } - } - } - - - return g; -} - int main() { srand(time(NULL)); int NVERTEX = 20; - UndirectedGraph * g = randgraph(NVERTEX); - g->print(); + UndirectedGraph * g = UndirectedGraph::randgraph(NVERTEX); + g->printdot(); printf("Random Delete Vertex:\n"); // random delete vertex @@ -49,7 +21,7 @@ int main() g->delete_vertex(n); } - g->print(); + g->printdot(); printf("Delete All Edges: \n"); for(i=0;iprint(); + g->printdot(); return 0; } 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