From 8b4f47f101b9d08ed349b720debb38caebfaf982 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 6 Sep 2013 15:40:07 +0800 Subject: [PATCH 001/217] update tabing --- include/kruskal_mst.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/kruskal_mst.h b/include/kruskal_mst.h index 0a5f00dc..714d7f58 100644 --- a/include/kruskal_mst.h +++ b/include/kruskal_mst.h @@ -133,8 +133,7 @@ namespace alg const Graph::Vertex * v; KruskalAdjacent * pa; uint32_t flag=0; //record the edge to be added into the mst - uint32_t total_nodes=num_vertex; //nodes of the Kruskal - + uint32_t total_nodes=num_vertex; //nodes of the Kruskal while(true) { int weight = INT_MAX; From 1e2a93aa8ec188d101987d9b8455b683703e3ac8 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 8 Sep 2013 14:55:16 +0800 Subject: [PATCH 002/217] add disjoint_set --- include/disjoint_set.h | 98 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 include/disjoint_set.h diff --git a/include/disjoint_set.h b/include/disjoint_set.h new file mode 100644 index 00000000..475d6b79 --- /dev/null +++ b/include/disjoint_set.h @@ -0,0 +1,98 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * DISJOINT-SET + * + * Features: + * 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 __DISJOINT_SET_H__ +#define __DISJOINT_SET_H__ +#include + +namespace alg { + class DisjointSet { + public: + class Set{ + public: + struct Set *parent; + int rank; + int value; + + void MakeSet(Set *x) { + x->parent = x; + } + + Set* Find(Set *x) { + // path compression when finding + if (x->parent == x) { + x->parent = Find(x->parent); + } + + return x->parent; + } + + void Union(Set *x, Set *y) { + Set * xRoot = Find(x); + Set * yRoot = Find(y); + + if (xRoot == yRoot) { + return; + } + + // x and y are not already in same set. Merge them. + // always attach the smaller tree to the root of the larger tree, + if (xRoot->rank < yRoot->rank) { + xRoot->parent = yRoot; + } else if (xRoot->rank > yRoot->rank) { + yRoot->parent = xRoot; + } else { // same rank + yRoot->parent = xRoot; + xRoot->rank++; + } + } + }; + + private: + DisjointSet(const DisjointSet &); + DisjointSet& operator=(const DisjointSet&); + + private: + Set *sets; + int cap; + int size; + public: + DisjointSet(int capacity) { + sets = new Set[capacity]; + cap = capacity; + size = 0; + } + + ~DisjointSet() { + delete []sets; + } + + //------------------------------------------------- new set + Set* AllocSet(int v) { + if (size > cap) return NULL; + sets[size].value = v; + size++; + return &sets[size-1]; + } + }; +} + +#endif // From a716eaa7389ce650c5ee7848b432700d2c5c76a7 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Thu, 12 Sep 2013 15:17:06 +0800 Subject: [PATCH 003/217] add LRU cache algorithm add LRU cache --- Makefile | 3 +- include/LRU_cache.h | 158 +++++++++++++++++++++++++++++++++++++++++ src/LRU_cache_demo.cpp | 49 +++++++++++++ 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 include/LRU_cache.h create mode 100644 src/LRU_cache_demo.cpp diff --git a/Makefile b/Makefile index beaa08cd..4931dec2 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,8 @@ PROGRAMS = m_based \ k-means_demo \ kmp_demo \ heap_sort_demo \ - kruskal_mst_demo + kruskal_mst_demo \ + LRU_cache_demo all: $(PROGRAMS) diff --git a/include/LRU_cache.h b/include/LRU_cache.h new file mode 100644 index 00000000..b0145c75 --- /dev/null +++ b/include/LRU_cache.h @@ -0,0 +1,158 @@ + + +#ifndef _LRUCACHE_ +#define _LRUCACHE_ + + +#include +#include +#include +#include +#include + +using namespace std; + +typedef struct _Node_{ + + int key; + int value; + + struct _Node_ *next; + struct _Node_ *pre; + +}CacheNode; + + + +class LRUCache{ + +public: + + LRUCache(int cache_size=10) + { + cache_size_=cache_size; + cache_real_size_=0; + 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; + } + + + int getValue(int key) + { + CacheNode *p=p_cache_list_head->next; + while(p->next!=NULL) + { + + if(p->key == key) //catch node + { + + detachNode(p); + addToFront(p); + return p->value; + } + p=p->next; + } + return -1; + } + + bool putValue(int key,int value) + { + CacheNode *p=p_cache_list_head->next; + while(p->next!=NULL) + { + + + if(p->key == key) //catch node + { + p->value=value; + getValue(key); + return true; + } + p=p->next; + } + + + if(cache_real_size_ >= cache_size_) + { + cout << "free" <pre->pre; + delete p->next; + p->next=p_cache_list_near; + p_cache_list_near->pre=p; + } + + p=new CacheNode();//(CacheNode *)malloc(sizeof(CacheNode)); + + if(p==NULL) + return false; + + addToFront(p); + p->key=key; + p->value=value; + + cache_real_size_++; + + return true; + } + void displayNodes() + { + CacheNode *p=p_cache_list_head->next; + + while(p->next!=NULL) + { + cout << " Key : " << p->key << " Value : " << p->value << endl; + p=p->next; + + } + cout << endl; + + } + + +private: + + int cache_size_; + int cache_real_size_; + CacheNode *p_cache_list_head; + CacheNode *p_cache_list_near; + + void detachNode(CacheNode *node) + { + node->pre->next=node->next; + node->next->pre=node->pre; + } + void addToFront(CacheNode *node) + { + + node->next=p_cache_list_head->next; + p_cache_list_head->next->pre=node; + p_cache_list_head->next=node; + node->pre=p_cache_list_head; + + } + +}; + + + +#endif + + + diff --git a/src/LRU_cache_demo.cpp b/src/LRU_cache_demo.cpp new file mode 100644 index 00000000..6a9b90fc --- /dev/null +++ b/src/LRU_cache_demo.cpp @@ -0,0 +1,49 @@ + +#include +#include "LRU_cache.h" + +int main() +{ + #if 1 + LRUCache *cache=new LRUCache(9); + + cache->putValue(1,1); + cache->putValue(2,2); + cache->putValue(3,3); + cache->putValue(4,3); + cache->putValue(5,2); + cache->displayNodes(); + + cout << cache->getValue(4) << endl; + cache->displayNodes(); + //cache->displayNodes(); + cout << cache->getValue(3) << endl; + cache->displayNodes(); + cout << cache->getValue(3) << endl; + cache->displayNodes(); + cout << cache->getValue(1) << endl; + cache->displayNodes(); + cout << cache->getValue(2) << endl; + cache->displayNodes(); + cout << cache->getValue(9) << endl; + + cache->displayNodes(); + + cache->putValue(4,9); + //cout << cache->getValue(2) << endl; + //cout << cache->getValue(3) << endl; + cache->displayNodes(); + cout << cache->getValue(4) << endl; + cache->displayNodes(); + cout << cache->getValue(2) << endl; + cache->displayNodes(); + + delete cache; + #endif + + + + return 1; +} + + From e4b86c3941192d84bdf351b67b183db250206d56 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Thu, 12 Sep 2013 15:55:49 +0800 Subject: [PATCH 004/217] add base64 encode and decode add base64 encode and decode --- Makefile | 3 +- include/base64.h | 141 ++++++++++++++++++++++++++++++++++++++++++++ src/base64_demo.cpp | 32 ++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 include/base64.h create mode 100644 src/base64_demo.cpp diff --git a/Makefile b/Makefile index 4931dec2..98de9173 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,8 @@ PROGRAMS = m_based \ kmp_demo \ heap_sort_demo \ kruskal_mst_demo \ - LRU_cache_demo + LRU_cache_demo \ + base64_demo all: $(PROGRAMS) diff --git a/include/base64.h b/include/base64.h new file mode 100644 index 00000000..1d590e64 --- /dev/null +++ b/include/base64.h @@ -0,0 +1,141 @@ + + + + +#ifndef _CBASE64_H_ +#define _CBASE64_H_ + + +#include +#include +#include + +using namespace std; + + +class CBase64 +{ + +public: + CBase64(); + ~CBase64(); + + + + static string encodeBase64(unsigned char *input , int input_len) + { + string code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned char input_char[3]; + char output_char[4]; + int output_num; + 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]='='; + } + + 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_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_str.append(output_char); + + + } + + //cout <<"encodeBase64 Res::: " << output_str << endl; + + + return output_str; + } + + static string decodeBase64(string input) + { + unsigned char input_char[4]; + unsigned char output_char[4]; + int output_num=0; + int k=0; + 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; + } + } + + //cout << "decodeBase64 ::: " < +#include "base64.h" +#include + + + +int main() +{ + char *s="Man is distinguished not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.."; + + cout << " INPUT: " << endl; + cout << s << endl; + cout << endl; + + string base=CBase64::encodeBase64((unsigned char *) s, strlen(s)); + cout << " encodeBase64: " < Date: Thu, 12 Sep 2013 17:06:19 +0800 Subject: [PATCH 005/217] fix bugs in base64 fix bugs in base64 --- include/base64.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/base64.h b/include/base64.h index 1d590e64..0cd46f09 100644 --- a/include/base64.h +++ b/include/base64.h @@ -26,7 +26,7 @@ class CBase64 { string code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned char input_char[3]; - char output_char[4]; + char output_char[5]; int output_num; string output_str=""; int near=input_len%3; @@ -48,6 +48,7 @@ class CBase64 output_char[1]=code[((output_num>>12) & 0x3f)]; output_char[2]='='; output_char[3]='='; + output_char[4]='\0'; } if(near==2) @@ -56,6 +57,7 @@ class CBase64 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); @@ -67,6 +69,7 @@ class CBase64 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); From 1d71a63a76f9ee8072116b7c0a61db1852e6dba8 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Thu, 12 Sep 2013 17:09:07 +0800 Subject: [PATCH 006/217] add index add index for fix bugs in base64 --- include/base64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/base64.h b/include/base64.h index 0cd46f09..0444f894 100644 --- a/include/base64.h +++ b/include/base64.h @@ -34,7 +34,7 @@ class CBase64 for(int i=0;i Date: Thu, 12 Sep 2013 17:25:16 +0800 Subject: [PATCH 007/217] update base64 for code formatting --- include/base64.h | 187 +++++++++++++++++++------------------------- src/base64_demo.cpp | 29 ++----- 2 files changed, 88 insertions(+), 128 deletions(-) diff --git a/include/base64.h b/include/base64.h index 0444f894..3b1d1684 100644 --- a/include/base64.h +++ b/include/base64.h @@ -1,6 +1,17 @@ - - - +/******************************************************************************* + * + * /\ | _ _ ._ 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_ @@ -10,59 +21,45 @@ #include #include -using namespace std; - - -class CBase64 -{ - -public: - CBase64(); - ~CBase64(); - - - - static string encodeBase64(unsigned char *input , int input_len) - { - string code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - unsigned char input_char[3]; - char output_char[5]; - int output_num; - 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; - } + if (i+3 <= input_len) { + memcpy(input_char,input+i,3); + } else { + memcpy(input_char,input+i,input_len-i); + output_num=((int)input_char[0]<<16)+((int)input_char[1]<<8)+(int)input_char[2]; + + if (near==1) { + output_char[0]=code[((output_num>>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)]; @@ -71,74 +68,50 @@ class CBase64 output_char[3]=code[((output_num) & 0x3f)]; output_char[4]='\0'; output_str.append(output_char); - - } - //cout <<"encodeBase64 Res::: " << output_str << endl; - + //cout <<"encodeBase64 Res::: " << output_str << endl; + return output_str; + } - 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=""; - static string decodeBase64(string input) - { - unsigned char input_char[4]; - unsigned char output_char[4]; - int output_num=0; - int k=0; - 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; - } + if (k==4) { + output_num= ((int)input_char[0]<<18)+((int)input_char[1]<<12)+((int)input_char[2]<<6)+((int)input_char[3]); + output_char[0]=(unsigned char)((output_num & 0x00FF0000 )>> 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; + } } - //cout << "decodeBase64 ::: " < #include "base64.h" #include +using namespace std; - -int main() -{ - char *s="Man is distinguished not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.."; +int main() { + const char *s="Man is distinguished not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.."; cout << " INPUT: " << endl; - cout << s << endl; - cout << endl; - - string base=CBase64::encodeBase64((unsigned char *) s, strlen(s)); - cout << " encodeBase64: " < Date: Thu, 12 Sep 2013 17:37:27 +0800 Subject: [PATCH 008/217] update readme --- README.md | 1 + include/base64.h | 14 ++++---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 5c137574..a14e0f28 100644 --- a/README.md +++ b/README.md @@ -79,3 +79,4 @@ Samana : for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST + wyh267: for base64, LRU diff --git a/include/base64.h b/include/base64.h index 3b1d1684..c3e89e1d 100644 --- a/include/base64.h +++ b/include/base64.h @@ -25,7 +25,7 @@ namespace alg { class CBase64 { public: static std::string encodeBase64(unsigned char *input , int input_len) { - std::string code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const char * code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned char input_char[3]; char output_char[5]; int output_num; @@ -70,7 +70,6 @@ namespace alg { output_str.append(output_char); } - //cout <<"encodeBase64 Res::: " << output_str << endl; return output_str; } @@ -95,18 +94,13 @@ namespace alg { } } - //cout << "decodeBase64 ::: " < Date: Thu, 12 Sep 2013 17:47:32 +0800 Subject: [PATCH 009/217] Update LRU_cache.h --- include/LRU_cache.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/LRU_cache.h b/include/LRU_cache.h index b0145c75..2d3f276c 100644 --- a/include/LRU_cache.h +++ b/include/LRU_cache.h @@ -1,4 +1,34 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ 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. + * + * Tow 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_ From d26af2ca4fed9d176b557bdf8130f443aa689069 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 13 Sep 2013 09:18:32 +0800 Subject: [PATCH 010/217] update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a14e0f28..c973836c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Bloom Filter SHA-1 Message Digest Algorithm MD5 + Base64 Graph data structure Prim's minimum spanning tree From fffed02de8ac343ebe2cfd19325d0bfd5a739ecb Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 13 Sep 2013 09:39:46 +0800 Subject: [PATCH 011/217] format LRU_cache --- include/LRU_cache.h | 173 ++++++++++++++++------------------------- src/LRU_cache_demo.cpp | 25 +++--- 2 files changed, 78 insertions(+), 120 deletions(-) diff --git a/include/LRU_cache.h b/include/LRU_cache.h index 2d3f276c..5d161b5c 100644 --- a/include/LRU_cache.h +++ b/include/LRU_cache.h @@ -1,81 +1,69 @@ - /******************************************************************************* - * DANIEL'S ALGORITHM IMPLEMENTAIONS * * /\ | _ _ ._ 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, + * 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. * - * Tow Interface: + * 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 + * 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 -using namespace std; - -typedef struct _Node_{ - - int key; - int value; - - struct _Node_ *next; - struct _Node_ *pre; - -}CacheNode; - - - -class LRUCache{ - -public: - - LRUCache(int cache_size=10) - { - cache_size_=cache_size; - cache_real_size_=0; - 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; - +namespace alg { + class LRUCache{ + typedef struct _Node_{ + int key; + int value; + + struct _Node_ *next; + struct _Node_ *pre; + + } CacheNode; + + public: + LRUCache(int cache_size=10) { + cache_size_ = cache_size; + cache_real_size_ = 0; + 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() - { + + ~LRUCache() { CacheNode *p; - p=p_cache_list_head->next; - while(p!=NULL) - { + p = p_cache_list_head->next; + while(p!=NULL) { delete p->pre; p=p->next; } @@ -83,16 +71,10 @@ class LRUCache{ delete p_cache_list_near; } - - int getValue(int key) - { + int getValue(int key) { CacheNode *p=p_cache_list_head->next; - while(p->next!=NULL) - { - - if(p->key == key) //catch node - { - + while (p->next!=NULL) { + if (p->key == key) { //catch node detachNode(p); addToFront(p); return p->value; @@ -102,87 +84,68 @@ class LRUCache{ return -1; } - bool putValue(int key,int value) - { + bool putValue(int key,int value) { CacheNode *p=p_cache_list_head->next; - while(p->next!=NULL) - { - - - if(p->key == key) //catch node - { + while (p->next!=NULL) { + if(p->key == key) { //catch node p->value=value; getValue(key); return true; } p=p->next; } - - - if(cache_real_size_ >= cache_size_) - { - cout << "free" <= cache_size_) { + std::cout << "free" <pre->pre; delete p->next; p->next=p_cache_list_near; p_cache_list_near->pre=p; } - - p=new CacheNode();//(CacheNode *)malloc(sizeof(CacheNode)); - - if(p==NULL) + + p = new CacheNode();//(CacheNode *)malloc(sizeof(CacheNode)); + + if (p==NULL) return false; addToFront(p); p->key=key; p->value=value; - + cache_real_size_++; - + return true; } - void displayNodes() - { + + void displayNodes() { CacheNode *p=p_cache_list_head->next; - - while(p->next!=NULL) - { - cout << " Key : " << p->key << " Value : " << p->value << endl; + + while(p->next!=NULL) { + std::cout << " Key : " << p->key << " Value : " << p->value << std::endl; p=p->next; - + } - cout << endl; - + std::cout << std::endl; } - - -private: - - int cache_size_; - int cache_real_size_; - CacheNode *p_cache_list_head; - CacheNode *p_cache_list_near; - - void detachNode(CacheNode *node) - { + + private: + int cache_size_; + int cache_real_size_; + CacheNode *p_cache_list_head; + CacheNode *p_cache_list_near; + + void detachNode(CacheNode *node) { node->pre->next=node->next; node->next->pre=node->pre; } - void addToFront(CacheNode *node) - { - + + void addToFront(CacheNode *node) { node->next=p_cache_list_head->next; p_cache_list_head->next->pre=node; p_cache_list_head->next=node; node->pre=p_cache_list_head; - } - -}; - - + }; +} #endif - - - diff --git a/src/LRU_cache_demo.cpp b/src/LRU_cache_demo.cpp index 6a9b90fc..b190b4ff 100644 --- a/src/LRU_cache_demo.cpp +++ b/src/LRU_cache_demo.cpp @@ -2,18 +2,18 @@ #include #include "LRU_cache.h" -int main() -{ - #if 1 - LRUCache *cache=new LRUCache(9); - +using namespace std; +int main() { +#if 1 + alg::LRUCache *cache=new alg::LRUCache(9); + cache->putValue(1,1); cache->putValue(2,2); cache->putValue(3,3); cache->putValue(4,3); cache->putValue(5,2); cache->displayNodes(); - + cout << cache->getValue(4) << endl; cache->displayNodes(); //cache->displayNodes(); @@ -26,9 +26,9 @@ int main() cout << cache->getValue(2) << endl; cache->displayNodes(); cout << cache->getValue(9) << endl; - + cache->displayNodes(); - + cache->putValue(4,9); //cout << cache->getValue(2) << endl; //cout << cache->getValue(3) << endl; @@ -37,13 +37,8 @@ int main() cache->displayNodes(); cout << cache->getValue(2) << endl; cache->displayNodes(); - - delete cache; - #endif - - + delete cache; +#endif return 1; } - - From d7278a248f9aca781a0204f2d1e2897801c71b15 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 16 Sep 2013 16:09:24 +0800 Subject: [PATCH 012/217] update comment for random_select --- include/random_select.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/random_select.h b/include/random_select.h index 45dd608d..6e3eee69 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -5,13 +5,15 @@ * /--\ | (_| (_) | | |_ | | | | | _> * _| * - * 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 * ******************************************************************************/ From bd7f1586b659456ce7b31259559306d7b6c027f5 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 16 Sep 2013 19:24:08 +0800 Subject: [PATCH 013/217] update random_select.h --- include/disjoint_set.h | 98 ----------------------------------------- include/random_select.h | 15 +++---- 2 files changed, 6 insertions(+), 107 deletions(-) delete mode 100644 include/disjoint_set.h diff --git a/include/disjoint_set.h b/include/disjoint_set.h deleted file mode 100644 index 475d6b79..00000000 --- a/include/disjoint_set.h +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * DANIEL'S ALGORITHM IMPLEMENTAIONS - * - * /\ | _ _ ._ o _|_ |_ ._ _ _ - * /--\ | (_| (_) | | |_ | | | | | _> - * _| - * - * DISJOINT-SET - * - * Features: - * 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 __DISJOINT_SET_H__ -#define __DISJOINT_SET_H__ -#include - -namespace alg { - class DisjointSet { - public: - class Set{ - public: - struct Set *parent; - int rank; - int value; - - void MakeSet(Set *x) { - x->parent = x; - } - - Set* Find(Set *x) { - // path compression when finding - if (x->parent == x) { - x->parent = Find(x->parent); - } - - return x->parent; - } - - void Union(Set *x, Set *y) { - Set * xRoot = Find(x); - Set * yRoot = Find(y); - - if (xRoot == yRoot) { - return; - } - - // x and y are not already in same set. Merge them. - // always attach the smaller tree to the root of the larger tree, - if (xRoot->rank < yRoot->rank) { - xRoot->parent = yRoot; - } else if (xRoot->rank > yRoot->rank) { - yRoot->parent = xRoot; - } else { // same rank - yRoot->parent = xRoot; - xRoot->rank++; - } - } - }; - - private: - DisjointSet(const DisjointSet &); - DisjointSet& operator=(const DisjointSet&); - - private: - Set *sets; - int cap; - int size; - public: - DisjointSet(int capacity) { - sets = new Set[capacity]; - cap = capacity; - size = 0; - } - - ~DisjointSet() { - delete []sets; - } - - //------------------------------------------------- new set - Set* AllocSet(int v) { - if (size > cap) return NULL; - sets[size].value = v; - size++; - return &sets[size-1]; - } - }; -} - -#endif // diff --git a/include/random_select.h b/include/random_select.h index 6e3eee69..144538e4 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -28,8 +28,7 @@ namespace alg * the random_select partition routine */ template - static int __partition(T list[],int begin, int end) - { + static int __partition(T list[],int begin, int end) { int pivot_idx = RANDOM(begin,end); T pivot = list[pivot_idx]; swap(list[begin],list[pivot_idx]); @@ -37,8 +36,7 @@ namespace alg int i = begin + 1; int j = end; - while(i <= j) - { + while(i <= j) { while((i <= end) && (list[i] <= pivot)) i++; while((j >= begin) && (list[j] > pivot)) @@ -55,20 +53,19 @@ namespace alg * 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) - { + 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 pivot_idx; if(k < human_idx) return random_select(list, begin, pivot_idx - 1, k); - if(k > human_idx) + else if(k > human_idx) return random_select(list, pivot_idx+1, end, k - human_idx); + + return pivot_idx; } } From 61b22b2f243dc5a544bcf4c88086f865034ec0ee Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 27 Sep 2013 09:43:04 +0800 Subject: [PATCH 014/217] update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c973836c..cf937405 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ 服务器端 (based on linux/gcc) 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. - (corret! and ease of use, one .header file per algorithm) + (correct! and ease of use, one .header file per algorithm) ####约定 ( Convention ): From 5d4dc67076ec5cf978a8ce028ce1afab82389362 Mon Sep 17 00:00:00 2001 From: fuli Date: Sat, 28 Sep 2013 14:26:19 +0800 Subject: [PATCH 015/217] add max subarray problem --- Makefile | 3 ++- include/max_subarray.h | 56 +++++++++++++++++++++++++++++++++++++++ src/max_subarray_demo.cpp | 32 ++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 include/max_subarray.h create mode 100644 src/max_subarray_demo.cpp diff --git a/Makefile b/Makefile index 98de9173..186814fd 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,8 @@ PROGRAMS = m_based \ heap_sort_demo \ kruskal_mst_demo \ LRU_cache_demo \ - base64_demo + base64_demo \ + max_subarray_demo all: $(PROGRAMS) diff --git a/include/max_subarray.h b/include/max_subarray.h new file mode 100644 index 00000000..c791df3b --- /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/src/max_subarray_demo.cpp b/src/max_subarray_demo.cpp new file mode 100644 index 00000000..012aef75 --- /dev/null +++ b/src/max_subarray_demo.cpp @@ -0,0 +1,32 @@ +#include +#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 Date: Sat, 28 Sep 2013 14:27:16 +0800 Subject: [PATCH 016/217] update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cf937405..43505a69 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ 2D Array Arbitary Integer Linear congruential generator + Maximum subarray problem Bit-Set data structure Queue data structure From 42582ec1f06bf28bf2798668f75b40161a9bd260 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 2 Oct 2013 21:59:51 +0800 Subject: [PATCH 017/217] update queue.count method --- include/queue.h | 2 +- src/queue_demo.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/queue.h b/include/queue.h index 7eace7ff..08d8ac5a 100644 --- a/include/queue.h +++ b/include/queue.h @@ -137,7 +137,7 @@ namespace alg /** * return the queue count. */ - inline int count() const { return m_size; }; + inline uint32_t count() const { return m_size; }; }; } #endif // 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()); From a6447c43f6a75bf732075b1e1831ec8d9aebce66 Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 3 Oct 2013 13:22:52 +0800 Subject: [PATCH 018/217] add capcity method for queue --- include/queue.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/queue.h b/include/queue.h index 08d8ac5a..ff4e2d59 100644 --- a/include/queue.h +++ b/include/queue.h @@ -138,6 +138,11 @@ namespace alg * return the queue count. */ inline uint32_t count() const { return m_size; }; + + /** + * return the queue capacity. + */ + inline uint32_t capcity() const { return m_capacity; }; }; } #endif // From 465e70290400699dd52509b554b9be107e418fdd Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 3 Oct 2013 15:02:24 +0800 Subject: [PATCH 019/217] rename skiplist, enhance error process --- Makefile | 2 +- include/skip_list.h | 200 ----------------------------------------- include/stack.h | 2 +- src/skip_list_demo.cpp | 42 --------- 4 files changed, 2 insertions(+), 244 deletions(-) delete mode 100644 include/skip_list.h delete mode 100644 src/skip_list_demo.cpp diff --git a/Makefile b/Makefile index 186814fd..a697f029 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,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 \ diff --git a/include/skip_list.h b/include/skip_list.h deleted file mode 100644 index 216fef09..00000000 --- a/include/skip_list.h +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************************* - * DANIEL'S ALGORITHM IMPLEMENTAIONS - * - * /\ | _ _ ._ o _|_ |_ ._ _ _ - * /--\ | (_| (_) | | |_ | | | | | _> - * _| - * - * SKIP LIST - * - * http://en.wikipedia.org/wiki/Skip_list - * - ******************************************************************************/ - -#ifndef __SKIP_LIST_H__ -#define __SKIP_LIST_H__ -#include -#include -#include -#include -#include - -namespace alg -{ - template - class SkipList - { - private: - struct SkipNode { - KeyT key; // key - ValueT value; // value - SkipNode ** forward; // pointers to different levels - }; - - struct SkipNode * m_header; // the header node, empty - int m_level; // the max level of skip list - - static const int SL_MAX_LEVEL = 6; - - public: - SkipList() - { - m_header = make_node(SL_MAX_LEVEL, 0, 0); - m_level = 0; - } - - ~SkipList() - { - // TODO: free nodes - } - - private: - SkipList(const SkipList &); - SkipList& operator=(const SkipList &); - - public: - /** - * search the given key from the skip list - * if the key is not exist, return NULL - */ - inline ValueT operator[] (KeyT key) const - { - struct SkipNode* x = m_header; - - // travels down until level-0 - for(int i = m_level; i >= 0; i--) { - while(x->forward[i] != NULL && x->forward[i]->key < key) { - x = x->forward[i]; - } - } - x = x->forward[0]; - if(x != NULL && x->key == key) - return x->value; - return NULL; - } - - /** - * insert a key->key pair into the list - */ - 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); - - // travels down the list until we found a proper node - for(int i = m_level; i >= 0; i--) { - while(x->forward[i] != NULL && x->forward[i]->key < key) { - x = x->forward[i]; - } - update[i] = x; - } - x = x->forward[0]; - - // if it's not the largest key or duplicated key (middle ones) - if(x == NULL || x->key != key) { - int lvl = random_level(); // random promotion - - // for nodes higer than current max level - // make 'header node' as it's prev - if(lvl > m_level) { - for(int i = m_level + 1; i <= lvl; i++) { - update[i] = m_header; - } - m_level = lvl; - } - x = make_node(lvl, key, value); - - // for each node travlling down, relink into the skiplist - for(int i = 0; i <= lvl; i++) { - x->forward[i] = update[i]->forward[i]; - update[i]->forward[i] = x; - } - } - } - - /** - * delete a node by it's 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); - - // find the node, and record it's level update info - for(int i = m_level; i >= 0; i--) { - while(x->forward[i] != NULL && x->forward[i]->key < key) { - x = x->forward[i]; - } - update[i] = x; - } - x = x->forward[0]; - - // delete every level's key - if(x != NULL && x->key == key) { - for(int i = 0; i <= m_level; i++) { - if(update[i]->forward[i] != x) - break; - update[i]->forward[i] = x->forward[i]; - } - free(x); - - while(m_level > 0 && m_header->forward[m_level] == NULL) { - m_level--; - } - } - } - - void print() - { - for(int i=m_level-1;i>=0;i--) { - SkipNode* x = m_header->forward[i]; - printf("{"); - while(x != NULL) { - printf("%d->%d", x->key, x->value); - x = x->forward[i]; - if(x != NULL) - printf(", "); - } - printf("}\n"); - } - } - private: - /** - * normalize to [0.0 1.0] - */ - inline float rand_norm() { return (float) rand() / RAND_MAX; } - - /** - * get the random promote level - */ - int random_level() - { - int lvl = 0; - // the possibility is 1/2 for each level - while(rand_norm() < 0.5f && lvl < SL_MAX_LEVEL) - lvl++; - - return lvl; - } - - /** - * make a node with specified level & key - */ - SkipNode * make_node(int level, KeyT key, ValueT value) - { - SkipNode * n = new SkipNode; - - // the max forward entry for a key is : level + 1 - n->forward = new struct SkipNode *[level + 1]; - n->key = key; - n->value = value; - - return n; - } - - }; -} - -#endif // diff --git a/include/stack.h b/include/stack.h index 2af8b557..bfcfaac1 100644 --- a/include/stack.h +++ b/include/stack.h @@ -119,7 +119,7 @@ class Stack /** * return value by index */ - inline const T& operator[] (int idx) const + inline const T& operator[] (uint32_t idx) const { if (idx<0 || idx >= m_capacity) throw exp_ioob; return m_elements[m_size-1-idx]; diff --git a/src/skip_list_demo.cpp b/src/skip_list_demo.cpp deleted file mode 100644 index 39c70bdc..00000000 --- a/src/skip_list_demo.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include "skip_list.h" - -using namespace alg; - - - -int main() -{ - - SkipList ss; - - const int MAX_ELEMENTS = 20; - - int i = 0; - srand(time(NULL)); - - for(i = 0; i < MAX_ELEMENTS; i++ ){ - ss.insert(i, rand()%100); - } - - printf("The skip list :\n"); - ss.print(); - - printf("Random get keys :\n"); - for(i = 0; i < MAX_ELEMENTS; i++ ){ - int r = rand()%100; - printf("get: %d->%d\n",r, ss[r]); - } - - printf("random deleteion:\n"); - for(i = 0; i < MAX_ELEMENTS; i++ ){ - int r = rand()%100; - printf("delete key :%d\n",r); - ss.delete_key(r); - } - - printf("The skip list after deletion:\n"); - - ss.print(); - return 0; -} From a96d91d736be7609532870f11d94fbddd9678173 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 5 Oct 2013 13:48:18 +0800 Subject: [PATCH 020/217] refactoring bst --- include/binary_search_tree.h | 119 ++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 28 deletions(-) diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 72a47678..4b242842 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -38,8 +38,9 @@ namespace alg { KeyT key; // key ValueT value; // data - treeNode *left; // left child - treeNode *right; // right child + treeNode *parent; // parent + treeNode *left; // left child + treeNode *right; // right child }; class BSTException: public std::exception @@ -58,13 +59,11 @@ namespace alg public: BST():m_root(NULL){}; - ~BST() - { + ~BST() { destruct(m_root); } - ValueT operator[] (const KeyT & key) - { + ValueT operator[] (const KeyT & key) { if (m_root == NULL) throw error; treeNode * tmp = m_root; @@ -83,8 +82,7 @@ namespace alg /** * test whether the key is in the tree */ - bool contains(const KeyT & key) - { + bool contains(const KeyT & key) { if (m_root == NULL) return false; treeNode * tmp = m_root; @@ -103,46 +101,111 @@ namespace alg /** * 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; + bool insert(const KeyT & key, const ValueT & value) { + treeNode *newnode = new treeNode; + newnode->key = key; + newnode->value = value; + newnode->left = newnode->right = newnode->parent = NULL; if (m_root == NULL){ - m_root = n; + m_root = newnode; return true; } - treeNode * tmp = m_root; - + + treeNode * n = m_root; while(true) { - if (key == tmp->key) { // already inserted - delete n; + if (key == n->key) { // already inserted + delete newnode; return false; } - else if(key < tmp->key) { - if (tmp->left == NULL) { - tmp->left = n; + else if(key < n->key) { + if (n->left == NULL) { + newnode->parent = n; + n->left = newnode; return true; - } else tmp = tmp->left; + } else n = n->left; } else { - if (tmp->right == NULL) { - tmp->right = n; + if (n->right == NULL) { + newnode->parent = n; + n->right = newnode; return true; - } else tmp = tmp->right; + } else n = n->right; + } + } + } + + /** + * delete a key from the binary search tree. + */ + bool deleteKey(const KeyT & key) { + treeNode * n = m_root; + treeNode * z = NULL; + + while(n!=NULL) { + if (key == n->key) { // found! + z = n; + break; + } + else if(key < n->key) { + n = n->left; + } else { + n = n->right; } } + + // delete the node + if (z==NULL) { + return false; + } + + if (z->left == NULL) { + transplant(z, z->right); + } else if (z->right == NULL) { + transplant(z, z->left); + } else { + treeNode *y = minimum(z->right); + if (y->parent != z) { + transplant(y, y->right); + y->right = z->right; + y->right->parent = y; + } + + transplant(z,y); + y->left = z->left; + y->left->parent = y; + } } + private: - void destruct(treeNode *n) - { + void destruct(treeNode *n) { if (n==NULL) return; destruct(n->left); destruct(n->right); delete n; } + void transplant(treeNode *u, treeNode *v) { + if (u->parent == NULL) { + m_root = u; + } else if (u == u->parent->left) { + u->parent->left = v; + } else { + u->parent->right = v; + } + + if (v!=NULL) { + v->parent = u->parent; + } + } + + treeNode * minimum(treeNode *x) { + while (x->left != NULL) { + x = x->left; + } + + return x; + } + private: BST(const BST&); BST& operator=(const BST&); From 83e076560db269e1cf500f6214236beef2022a3f Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 5 Oct 2013 17:13:21 +0800 Subject: [PATCH 021/217] refactoring bst --- Makefile | 2 +- include/binary_search_tree.h | 102 ++++++++++++++++---------------- src/binary_search_tree_demo.cpp | 10 ++++ 3 files changed, 62 insertions(+), 52 deletions(-) diff --git a/Makefile b/Makefile index a697f029..dc62743e 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CPP=g++ AR=ar RANLIB=ranlib -CFLAGS= -O2 -Wall -Wno-unused-function +CFLAGS= -g -O2 -Wall -Wno-unused-function SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 4b242842..dc8f1560 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -1,5 +1,5 @@ /******************************************************************************* - * DANIEL'S ALGORITHM IMPLEMENTAIONS + * ALGORITHM IMPLEMENTAIONS * * /\ | _ _ ._ o _|_ |_ ._ _ _ * /--\ | (_| (_) | | |_ | | | | | _> @@ -25,17 +25,14 @@ #include #include -namespace alg -{ +namespace alg { template - class BST - { + class BST { private: /** * binary search tree definiton. */ - struct treeNode - { + struct treeNode { KeyT key; // key ValueT value; // data treeNode *parent; // parent @@ -43,24 +40,24 @@ namespace alg treeNode *right; // right child }; - class BSTException: public std::exception - { + class BSTException: public std::exception { public: - virtual const char * what() const throw() - { + virtual const char * what() const throw() { return "key does not exist"; } }; private: - treeNode * m_root; + treeNode * m_root; // the root const BSTException error; - + private: + BST(const BST&); + BST& operator=(const BST&); public: BST():m_root(NULL){}; ~BST() { - destruct(m_root); + __destruct(m_root); } ValueT operator[] (const KeyT & key) { @@ -101,37 +98,31 @@ namespace alg /** * insert a new data into the binary search tree. */ - bool insert(const KeyT & key, const ValueT & value) { - treeNode *newnode = new treeNode; - newnode->key = key; - newnode->value = value; - newnode->left = newnode->right = newnode->parent = NULL; - - if (m_root == NULL){ - m_root = newnode; - return true; - } + 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; - while(true) { - if (key == n->key) { // already inserted - delete newnode; - return false; - } - else if(key < n->key) { - if (n->left == NULL) { - newnode->parent = n; - n->left = newnode; - return true; - } else n = n->left; + treeNode * y = NULL; + while(n!=NULL) { + y = n; + if(key < n->key) { + n = n->left; } else { - if (n->right == NULL) { - newnode->parent = n; - n->right = newnode; - return true; - } else n = n->right; + n = n->right; } } + + z->parent = y; + if (y==NULL) { + m_root = z; + } else if (key < y->key) { + y->left = z; + } else { + y->right = z; + } } /** @@ -145,8 +136,7 @@ namespace alg if (key == n->key) { // found! z = n; break; - } - else if(key < n->key) { + } else if(key < n->key) { n = n->left; } else { n = n->right; @@ -163,27 +153,38 @@ namespace alg } else if (z->right == NULL) { transplant(z, z->left); } else { - treeNode *y = minimum(z->right); + // 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; } private: - void destruct(treeNode *n) { + void __destruct(treeNode *n) { if (n==NULL) return; - destruct(n->left); - destruct(n->right); + __destruct(n->left); + __destruct(n->right); delete n; } + /** + * replace node u with v. + */ void transplant(treeNode *u, treeNode *v) { if (u->parent == NULL) { m_root = u; @@ -198,6 +199,9 @@ namespace alg } } + /** + * find the minimum element of the subtree + */ treeNode * minimum(treeNode *x) { while (x->left != NULL) { x = x->left; @@ -205,10 +209,6 @@ namespace alg return x; } - - private: - BST(const BST&); - BST& operator=(const BST&); }; } diff --git a/src/binary_search_tree_demo.cpp b/src/binary_search_tree_demo.cpp index 3b817868..05e2c271 100644 --- a/src/binary_search_tree_demo.cpp +++ b/src/binary_search_tree_demo.cpp @@ -36,5 +36,15 @@ int main() printf("testing %d-> %s\n",k,t.contains(k)?"YES":"NO"); } + for(i = 0; i < MAX_ELEMENTS; i++){ + t.deleteKey(key[i]); + printf("delete %d\n", key[i]); + } + + for(i = 0; i < MAX_ELEMENTS; i++){ + int k = rand()%100; + printf("testing %d-> %s\n",k,t.contains(k)?"YES":"NO"); + } + return 0; } From cfa466c2397d688c86b6fe179853ecf85d754e7d Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 5 Oct 2013 18:01:38 +0800 Subject: [PATCH 022/217] new binary search tree --- include/binary_search_tree.h | 75 +++++++++++++-------------------- src/binary_search_tree_demo.cpp | 15 ++----- 2 files changed, 34 insertions(+), 56 deletions(-) diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index dc8f1560..befca627 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace alg { template @@ -60,39 +61,20 @@ namespace alg { __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; - } - } - } - /** - * test whether the key is in the tree + * find key */ - 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; + treeNode * find(const KeyT & key) { + treeNode * n= m_root; + while (n!=NULL && key != n->key) { + if (key < n->key) { + n = n->left; } else { - if (tmp->right == NULL) return false; - tmp = tmp->right; + n = n->right; } } + + return n; } /** @@ -129,22 +111,8 @@ namespace alg { * delete a key from the binary search tree. */ bool deleteKey(const KeyT & key) { - treeNode * n = m_root; - treeNode * z = NULL; - - while(n!=NULL) { - if (key == n->key) { // found! - z = n; - break; - } else if(key < n->key) { - n = n->left; - } else { - n = n->right; - } - } - - // delete the node - if (z==NULL) { + treeNode *z = find(key); + if (z == NULL) { return false; } @@ -173,6 +141,23 @@ namespace alg { delete z; return true; } + + 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); + } + + void print_helper() { + print_tree(m_root, 0); + } private: void __destruct(treeNode *n) { @@ -187,7 +172,7 @@ namespace alg { */ void transplant(treeNode *u, treeNode *v) { if (u->parent == NULL) { - m_root = u; + m_root = v; } else if (u == u->parent->left) { u->parent->left = v; } else { diff --git a/src/binary_search_tree_demo.cpp b/src/binary_search_tree_demo.cpp index 05e2c271..3e4e1ea5 100644 --- a/src/binary_search_tree_demo.cpp +++ b/src/binary_search_tree_demo.cpp @@ -27,23 +27,16 @@ int main() t.insert(key[i], value[i]); } - for(i = 0; i < MAX_ELEMENTS; i++){ - printf("getting %d->%d\n",key[i], t[key[i]]); - } + t.print_helper(); for(i = 0; i < MAX_ELEMENTS; i++){ - int k = rand()%100; - printf("testing %d-> %s\n",k,t.contains(k)?"YES":"NO"); + printf("getting %d->%d\n",key[i], t.find(key[i])->value); } for(i = 0; i < MAX_ELEMENTS; i++){ t.deleteKey(key[i]); - printf("delete %d\n", key[i]); - } - - for(i = 0; i < MAX_ELEMENTS; i++){ - int k = rand()%100; - printf("testing %d-> %s\n",k,t.contains(k)?"YES":"NO"); + t.print_helper(); + printf("deleted %d\n\n", key[i]); } return 0; From 095a0bbdc6e20b9d5870f5967502600e66d4c727 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 5 Oct 2013 18:02:21 +0800 Subject: [PATCH 023/217] rename skiplist --- include/skiplist.h | 211 ++++++++++++++++++++++++++++++++++++++++++ src/skiplist_demo.cpp | 44 +++++++++ 2 files changed, 255 insertions(+) create mode 100644 include/skiplist.h create mode 100644 src/skiplist_demo.cpp diff --git a/include/skiplist.h b/include/skiplist.h new file mode 100644 index 00000000..2078aff2 --- /dev/null +++ b/include/skiplist.h @@ -0,0 +1,211 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * SKIP LIST + * + * http://en.wikipedia.org/wiki/Skip_list + * + ******************************************************************************/ + +#ifndef __SKIP_LIST_H__ +#define __SKIP_LIST_H__ +#include +#include +#include +#include +#include +#include + +namespace alg +{ + template + class SkipList + { + private: + struct SkipNode { + KeyT key; // key + ValueT value; // value + SkipNode ** forward; // pointers to different levels + }; + + struct SkipNode * m_header; // the header node, empty + int m_level; // the max level of skip list + + 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"; + } + }; + const NotFoundException excp_notfound; + + public: + SkipList() + { + m_header = make_node(SL_MAX_LEVEL, 0, 0); + m_level = 0; + } + + ~SkipList() + { + // TODO: free nodes + } + + private: + SkipList(const SkipList &); + SkipList& operator=(const SkipList &); + + public: + /** + * search the given key from the skip list + * if the key is not exist, throw exception + */ + inline ValueT operator[] (KeyT key) const + { + struct SkipNode* x = m_header; + + // travels down until level-0 + for(int i = m_level; i >= 0; i--) { + while(x->forward[i] != NULL && x->forward[i]->key < key) { + x = x->forward[i]; + } + } + x = x->forward[0]; + if(x != NULL && x->key == key) + return x->value; + throw excp_notfound; + } + + /** + * insert a key->key pair into the list + */ + 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); + + // travels down the list until we found a proper node + for(int i = m_level; i >= 0; i--) { + while(x->forward[i] != NULL && x->forward[i]->key < key) { + x = x->forward[i]; + } + update[i] = x; + } + x = x->forward[0]; + + // if it's not the largest key or duplicated key (middle ones) + if(x == NULL || x->key != key) { + int lvl = random_level(); // random promotion + + // for nodes higer than current max level + // make 'header node' as it's prev + if(lvl > m_level) { + for(int i = m_level + 1; i <= lvl; i++) { + update[i] = m_header; + } + m_level = lvl; + } + x = make_node(lvl, key, value); + + // for each node travlling down, relink into the skiplist + for(int i = 0; i <= lvl; i++) { + x->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = x; + } + } + } + + /** + * delete a node by it's 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); + + // find the node, and record it's level update info + for(int i = m_level; i >= 0; i--) { + while(x->forward[i] != NULL && x->forward[i]->key < key) { + x = x->forward[i]; + } + update[i] = x; + } + x = x->forward[0]; + + // delete every level's key + if(x != NULL && x->key == key) { + for(int i = 0; i <= m_level; i++) { + if(update[i]->forward[i] != x) + break; + update[i]->forward[i] = x->forward[i]; + } + free(x); + + while(m_level > 0 && m_header->forward[m_level] == NULL) { + m_level--; + } + } + } + + void print() + { + for(int i=m_level-1;i>=0;i--) { + SkipNode* x = m_header->forward[i]; + printf("{"); + while(x != NULL) { + printf("%d->%d", x->key, x->value); + x = x->forward[i]; + if(x != NULL) + printf(", "); + } + printf("}\n"); + } + } + private: + /** + * normalize to [0.0 1.0] + */ + inline float rand_norm() { return (float) rand() / RAND_MAX; } + + /** + * get the random promote level + */ + int random_level() + { + int lvl = 0; + // the possibility is 1/2 for each level + while(rand_norm() < 0.5f && lvl < SL_MAX_LEVEL) + lvl++; + + return lvl; + } + + /** + * make a node with specified level & key + */ + SkipNode * make_node(int level, KeyT key, ValueT value) + { + SkipNode * n = new SkipNode; + + // the max forward entry for a key is : level + 1 + n->forward = new struct SkipNode *[level + 1]; + n->key = key; + n->value = value; + + return n; + } + + }; +} + +#endif // diff --git a/src/skiplist_demo.cpp b/src/skiplist_demo.cpp new file mode 100644 index 00000000..a9d26953 --- /dev/null +++ b/src/skiplist_demo.cpp @@ -0,0 +1,44 @@ +#include +#include "skiplist.h" + +using namespace alg; + +int main() +{ + + SkipList ss; + + const int MAX_ELEMENTS = 20; + + int i = 0; + srand(time(NULL)); + + for(i = 0; i < MAX_ELEMENTS; i++ ){ + ss.insert(i, rand()%100); + } + + printf("The skip list :\n"); + ss.print(); + + printf("Random get keys :\n"); + for(i = 0; i < MAX_ELEMENTS; i++ ){ + int r = rand()%100; + try { + printf("get: %d->%d\n",r, ss[r]); + } catch (std::exception &e) { + printf("%s\n", e.what()); + } + } + + printf("random deleteion:\n"); + for(i = 0; i < MAX_ELEMENTS; i++ ){ + int r = rand()%100; + printf("delete key :%d\n",r); + ss.delete_key(r); + } + + printf("The skip list after deletion:\n"); + + ss.print(); + return 0; +} From e557bbb09be057f63c6c6a3716753a4a4fbd077c Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 9 Oct 2013 16:12:43 +0800 Subject: [PATCH 024/217] add disjoint-set --- Makefile | 3 +- include/disjoint-set.h | 65 +++++++++++++++++++++++++++++++++++++++ src/disjoint-set_demo.cpp | 19 ++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 include/disjoint-set.h create mode 100644 src/disjoint-set_demo.cpp diff --git a/Makefile b/Makefile index dc62743e..25f5c0e9 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,8 @@ PROGRAMS = m_based \ kruskal_mst_demo \ LRU_cache_demo \ base64_demo \ - max_subarray_demo + max_subarray_demo \ + disjoint-set_demo all: $(PROGRAMS) diff --git a/include/disjoint-set.h b/include/disjoint-set.h new file mode 100644 index 00000000..7c3afc1b --- /dev/null +++ b/include/disjoint-set.h @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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 __DISJOINTSET_H__ +#define __DISJOINTSET_H__ + +namespace alg { + template + struct Set{ + Set* parent; + T element; + 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/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; +} From 40d303e9e1f05a835b7b4565d7d511b090ee10f6 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 9 Oct 2013 16:13:16 +0800 Subject: [PATCH 025/217] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 43505a69..f1c6df86 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ A* algorithm K-Means Knuth–Morris–Pratt algorithm + Disjoint-Set ####贡献者 ( Contributors ) : Samana : for heavy work of MSVC compatability From 395f4ae325a2bef44be4da4e9d9b240c5db5a361 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 9 Oct 2013 16:25:34 +0800 Subject: [PATCH 026/217] update demo --- src/disjoint-set_demo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/disjoint-set_demo.cpp b/src/disjoint-set_demo.cpp index 6d0eb204..8685433d 100644 --- a/src/disjoint-set_demo.cpp +++ b/src/disjoint-set_demo.cpp @@ -5,6 +5,8 @@ int main(void) { alg::Set s1; alg::Set s2; + s1.element = 1; + s2.element = 2; alg::MakeSet(&s1); alg::MakeSet(&s2); From 5f8f4c967f4f731299dba65b241e7caef94de95f Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 9 Oct 2013 16:44:05 +0800 Subject: [PATCH 027/217] update disjoint-set --- include/disjoint-set.h | 1 - src/disjoint-set_demo.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/disjoint-set.h b/include/disjoint-set.h index 7c3afc1b..340bf08c 100644 --- a/include/disjoint-set.h +++ b/include/disjoint-set.h @@ -25,7 +25,6 @@ namespace alg { template struct Set{ Set* parent; - T element; int rank; }; diff --git a/src/disjoint-set_demo.cpp b/src/disjoint-set_demo.cpp index 8685433d..6d0eb204 100644 --- a/src/disjoint-set_demo.cpp +++ b/src/disjoint-set_demo.cpp @@ -5,8 +5,6 @@ int main(void) { alg::Set s1; alg::Set s2; - s1.element = 1; - s2.element = 2; alg::MakeSet(&s1); alg::MakeSet(&s2); From 352fca25e7e38d37c7ccea1d5073b35b6dfb1656 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Thu, 10 Oct 2013 23:02:20 +0800 Subject: [PATCH 028/217] push-relabel maxflow algorithm --- include/push_relabel.h | 196 ++++++++++++++++++++++++++++++++++++++ src/push_relabel_demo.cpp | 115 ++++++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 include/push_relabel.h create mode 100644 src/push_relabel_demo.cpp diff --git a/include/push_relabel.h b/include/push_relabel.h new file mode 100644 index 00000000..74b8b08c --- /dev/null +++ b/include/push_relabel.h @@ -0,0 +1,196 @@ +/* + * Push-Relabel algorithm + * + * Features: This maxflow algorithm runs in O(V2 E) time, faster than Edmonds-Karp in theory. + * But the funny thing is, in practice, this method is often 5 times slower than Edmonds-Karp. + * You can test it by changing NVERTEX in push_relabel.cpp. + * + * http://en.wikipedia.org/wiki/Push%E2%80%93relabel_maximum_flow_algorithm + * + * */ + +#ifndef __PUSH_RELABEL_H__ +#define __PUSH_RELABEL_H__ + +#include +#include +#include + +#include "directed_graph.h" +#include "hash_table.h" +#include "2darray.h" + +namespace alg +{ + class PushRelabel + { + protected: + 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: + PushRelabel(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); + } + } + } + + ~PushRelabel() + { + 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(uint32_t src, uint32_t dst) + { + //c f (u, v) = c(u, v) - preflow(u, v) + int from = m_map[src], to = m_map[dst]; + + 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(uint32_t u, int height) + { + int from = m_map[u]; + h[from] = height + 1; + } + + void relabel(uint32_t u) + { + int min_height = INT_MAX; + int from = m_map[u]; + Graph::Adjacent * a = (* possible_residual_edge)[from]; + Graph::Vertex * v; + + list_for_each_entry(v, &a->v_head, v_node){ + int to = v->id; + 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; + } + + uint32_t run(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 to = v->id; + 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){ + int id_to = m_rmap[to]; + push(id_from, id_to); + } + } + } + } + if (need_relabel && residual_edge){ + relabel(id_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/src/push_relabel_demo.cpp b/src/push_relabel_demo.cpp new file mode 100644 index 00000000..c13fef5b --- /dev/null +++ b/src/push_relabel_demo.cpp @@ -0,0 +1,115 @@ +#include +#include +#include + +#include "edmonds_karp.h" +#include "push_relabel.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 = 500; + + clock_t ek_start, ek_end, pr_start, pr_end; + + DirectedGraph * g = randgraph(NVERTEX); +// g->print(); + + printf("finding Maximal Flow from 0 to nvertex-1: \n"); + + ek_start = clock(); + EdmondsKarp ek2(*g); + uint32_t maxflow = ek2.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(); + PushRelabel 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"); + +// printf("the excess flow\n\t"); +// for (uint32_t i=0; ivertex_count(); i++){ +// printf("%d\t", pr2.excess()[i]); +// } +// printf("\n"); + +// printf("the height\n\t"); +// for (uint32_t i=0; ivertex_count(); i++){ +// printf("%d\t", pr2.height()[i]); +// } +// 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; +} From 21dba98af89761e31af05b3adbf572f0e256c5f4 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Thu, 10 Oct 2013 23:12:07 +0800 Subject: [PATCH 029/217] change makefile --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dc62743e..73650239 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,8 @@ PROGRAMS = m_based \ kruskal_mst_demo \ LRU_cache_demo \ base64_demo \ - max_subarray_demo + max_subarray_demo \ + push_relabel_demo all: $(PROGRAMS) From e12d6c4029c782809a56cc46db4eba438c0ed3c6 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Sun, 13 Oct 2013 21:23:23 +0800 Subject: [PATCH 030/217] Relabel-To-Front Maxflow algorithm --- include/relabel_to_front.h | 254 ++++++++++++++++++++++++++++++++++ src/relabel_to_front_demo.cpp | 104 ++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 include/relabel_to_front.h create mode 100644 src/relabel_to_front_demo.cpp diff --git a/include/relabel_to_front.h b/include/relabel_to_front.h new file mode 100644 index 00000000..a7b5c54f --- /dev/null +++ b/include/relabel_to_front.h @@ -0,0 +1,254 @@ +/* + * 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 __RELABEL_TO_FRONT_H__ +#define __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/src/relabel_to_front_demo.cpp b/src/relabel_to_front_demo.cpp new file mode 100644 index 00000000..0184d136 --- /dev/null +++ b/src/relabel_to_front_demo.cpp @@ -0,0 +1,104 @@ +#include +#include +#include + +#include "edmonds_karp.h" +#include "relabel_to_front.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 = 300; + + clock_t ek_start, ek_end, pr_start, pr_end; + + DirectedGraph * g = randgraph(NVERTEX); +// g->print(); + + 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; +} From 631afe5914a7348a9cdfddef0e3fdd50f4626a76 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Sun, 13 Oct 2013 21:30:21 +0800 Subject: [PATCH 031/217] Relabel-ToFront MaxFlow algorithm --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 73650239..715e9bf6 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ PROGRAMS = m_based \ LRU_cache_demo \ base64_demo \ max_subarray_demo \ - push_relabel_demo + relabel_to_front_demo all: $(PROGRAMS) From 9c94ebf33192982e96ca3b38e09512037cc91b8a Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Sun, 13 Oct 2013 21:35:23 +0800 Subject: [PATCH 032/217] Remove redundant push_relabel algorithm --- include/push_relabel.h | 196 -------------------------------------- src/push_relabel_demo.cpp | 115 ---------------------- 2 files changed, 311 deletions(-) delete mode 100644 include/push_relabel.h delete mode 100644 src/push_relabel_demo.cpp diff --git a/include/push_relabel.h b/include/push_relabel.h deleted file mode 100644 index 74b8b08c..00000000 --- a/include/push_relabel.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Push-Relabel algorithm - * - * Features: This maxflow algorithm runs in O(V2 E) time, faster than Edmonds-Karp in theory. - * But the funny thing is, in practice, this method is often 5 times slower than Edmonds-Karp. - * You can test it by changing NVERTEX in push_relabel.cpp. - * - * http://en.wikipedia.org/wiki/Push%E2%80%93relabel_maximum_flow_algorithm - * - * */ - -#ifndef __PUSH_RELABEL_H__ -#define __PUSH_RELABEL_H__ - -#include -#include -#include - -#include "directed_graph.h" -#include "hash_table.h" -#include "2darray.h" - -namespace alg -{ - class PushRelabel - { - protected: - 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: - PushRelabel(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); - } - } - } - - ~PushRelabel() - { - 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(uint32_t src, uint32_t dst) - { - //c f (u, v) = c(u, v) - preflow(u, v) - int from = m_map[src], to = m_map[dst]; - - 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(uint32_t u, int height) - { - int from = m_map[u]; - h[from] = height + 1; - } - - void relabel(uint32_t u) - { - int min_height = INT_MAX; - int from = m_map[u]; - Graph::Adjacent * a = (* possible_residual_edge)[from]; - Graph::Vertex * v; - - list_for_each_entry(v, &a->v_head, v_node){ - int to = v->id; - 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; - } - - uint32_t run(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 to = v->id; - 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){ - int id_to = m_rmap[to]; - push(id_from, id_to); - } - } - } - } - if (need_relabel && residual_edge){ - relabel(id_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/src/push_relabel_demo.cpp b/src/push_relabel_demo.cpp deleted file mode 100644 index c13fef5b..00000000 --- a/src/push_relabel_demo.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include -#include - -#include "edmonds_karp.h" -#include "push_relabel.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 = 500; - - clock_t ek_start, ek_end, pr_start, pr_end; - - DirectedGraph * g = randgraph(NVERTEX); -// g->print(); - - printf("finding Maximal Flow from 0 to nvertex-1: \n"); - - ek_start = clock(); - EdmondsKarp ek2(*g); - uint32_t maxflow = ek2.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(); - PushRelabel 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"); - -// printf("the excess flow\n\t"); -// for (uint32_t i=0; ivertex_count(); i++){ -// printf("%d\t", pr2.excess()[i]); -// } -// printf("\n"); - -// printf("the height\n\t"); -// for (uint32_t i=0; ivertex_count(); i++){ -// printf("%d\t", pr2.height()[i]); -// } -// 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; -} From 0c10f2cbf81f1a455e71ef8f9b5b28776abcd47c Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 14 Oct 2013 09:02:08 +0800 Subject: [PATCH 033/217] update readme.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f1c6df86..ac33df57 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Dijkstra's algorithm Bellman-Ford algorithm Edmonds-Karp Maximal Flow + Push–Relabel algorithm Huffman Coding Word segementation(CHN/GB18030) using HMM and viterbi algorithm. @@ -83,3 +84,4 @@ wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST wyh267: for base64, LRU + ZhangYou0122 : Push-Relabel algorithm From fbdf59475d7ae414503c0017ba7328e034232508 Mon Sep 17 00:00:00 2001 From: fuli Date: Tue, 15 Oct 2013 12:51:19 +0800 Subject: [PATCH 034/217] adding btree.h --- include/btree.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 include/btree.h diff --git a/include/btree.h b/include/btree.h new file mode 100644 index 00000000..637fb2c0 --- /dev/null +++ b/include/btree.h @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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. + * + * http://en.wikipedia.org/wiki/B-tree + ******************************************************************************/ + +#ifndef __BTREE_H__ +#define __BTREE_H__ +#include +namespace alg { + class BTree { + private: + // 4K node, 4080 bytes + typedef struct node_t { + int16_t leaf; // is leaf? + int16_t n; // num keys + int32_t keys[509]; // keys + int32_t c[510]; // childs pointers(file offsets) + } *node; + private: + node m_root; + private: + BTree(const BTree &); + BTree& operator=(const BTree&); + public: + BTree() { + node x = allocate_node(); + x->leaf = true; + x->n = 0; + } + + private: + node allocate_node() { + node x = new node_t; + return x; + } + }; +} +#endif // From f738e6a162189af2930e36f533bf7f9443b4f8f8 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 16 Oct 2013 09:56:29 +0800 Subject: [PATCH 035/217] save btree --- include/btree.h | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/include/btree.h b/include/btree.h index 637fb2c0..75244e53 100644 --- a/include/btree.h +++ b/include/btree.h @@ -21,16 +21,24 @@ #ifndef __BTREE_H__ #define __BTREE_H__ #include +#include namespace alg { class BTree { private: // 4K node, 4080 bytes + // t = 255 typedef struct node_t { int16_t leaf; // is leaf? int16_t n; // num keys int32_t keys[509]; // keys - int32_t c[510]; // childs pointers(file offsets) + int32_t c[510]; // childs pointers (file offsets) + node_t* pc[510]; // childs pointers (memory pointers) } *node; + + struct search_r { + node n; + int32_t i; + }; private: node m_root; private: @@ -41,13 +49,39 @@ namespace alg { node x = allocate_node(); x->leaf = true; x->n = 0; + memset(x->keys, 0, sizeof(x->keys)); + memset(x->c, 0, sizeof(x->c)); + } + + /** + * search a key, returns node and index + */ + search_r Search(node x, int32_t k) { + int i = 1; + search_r ret; + while (i<=x->n && k > x->keys[i]) i++; + + if (i <= x->n && k == x->keys[i]) { + ret.n = x, ret.i = i; + return ret; + } else if (x->leaf) { + ret.n = NULL, ret.i = i; + return ret; + } else { + disk_read(x, i); + return Search(x->pc[i], k); + } } private: + // disk ops node allocate_node() { node x = new node_t; return x; } + + void disk_read(node x, int32_t i) { + } }; } #endif // From c1e95e74dbba0c30386c08f6df01d966320aab90 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 09:08:52 +0800 Subject: [PATCH 036/217] using basic disk io --- include/btree.h | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/include/btree.h b/include/btree.h index 75244e53..010a147f 100644 --- a/include/btree.h +++ b/include/btree.h @@ -20,19 +20,26 @@ #ifndef __BTREE_H__ #define __BTREE_H__ + #include +#include #include +#include +#include + +#define BLOCKSIZE 4096 namespace alg { class BTree { private: - // 4K node, 4080 bytes + // 4K node, 4096 bytes to write // t = 255 - typedef struct node_t { + typedef struct __attribute__ ((packed)) node_t { int16_t leaf; // is leaf? int16_t n; // num keys int32_t keys[509]; // keys - int32_t c[510]; // childs pointers (file offsets) - node_t* pc[510]; // childs pointers (memory pointers) + int32_t c[510]; // childs pointers (file offsets related to 0) + char padding[16]; // padding to 4096 + void *pc[510]; // memory } *node; struct search_r { @@ -41,16 +48,26 @@ namespace alg { }; private: node m_root; + void * map; + int fd; private: BTree(const BTree &); BTree& operator=(const BTree&); public: - BTree() { + BTree(const char * path) { + fd = open(path, O_RDWR); + if (fd == -1) + return; node x = allocate_node(); x->leaf = true; x->n = 0; memset(x->keys, 0, sizeof(x->keys)); memset(x->c, 0, sizeof(x->c)); + memset(x->pc, 0, sizeof(x->pc)); + } + + ~BTree() { + close(fd); } /** @@ -69,7 +86,7 @@ namespace alg { return ret; } else { disk_read(x, i); - return Search(x->pc[i], k); + return Search((node)x->pc[i], k); } } @@ -81,6 +98,13 @@ namespace alg { } void disk_read(node x, int32_t i) { + if (x->pc[i] != NULL) { + return; + } + + x->pc[i] = malloc(sizeof(node_t)); + lseek(fd, x->c[i], SEEK_SET); + read(fd, x->pc[i], BLOCKSIZE); } }; } From bfcda4e2c679f3466b5193e88012406ba6fa09bc Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 11:35:48 +0800 Subject: [PATCH 037/217] add split-child method --- include/btree.h | 84 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/include/btree.h b/include/btree.h index 010a147f..d2ef9dc9 100644 --- a/include/btree.h +++ b/include/btree.h @@ -28,6 +28,7 @@ #include #define BLOCKSIZE 4096 +#define T 255 namespace alg { class BTree { private: @@ -35,11 +36,12 @@ namespace alg { // t = 255 typedef struct __attribute__ ((packed)) node_t { int16_t leaf; // is leaf? - int16_t n; // num keys - int32_t keys[509]; // keys + int16_t n; // num key + int32_t offset; // block offset + int32_t key[509]; // key int32_t c[510]; // childs pointers (file offsets related to 0) - char padding[16]; // padding to 4096 - void *pc[510]; // memory + char padding[12]; // padding to 4096 + void *pc[510]; // memory } *node; struct search_r { @@ -58,12 +60,8 @@ namespace alg { fd = open(path, O_RDWR); if (fd == -1) return; - node x = allocate_node(); + node x = (node)allocate_node(); x->leaf = true; - x->n = 0; - memset(x->keys, 0, sizeof(x->keys)); - memset(x->c, 0, sizeof(x->c)); - memset(x->pc, 0, sizeof(x->pc)); } ~BTree() { @@ -76,36 +74,90 @@ namespace alg { search_r Search(node x, int32_t k) { int i = 1; search_r ret; - while (i<=x->n && k > x->keys[i]) i++; + while (i<=x->n && k > x->key[i]) i++; - if (i <= x->n && k == x->keys[i]) { + if (i <= x->n && k == x->key[i]) { ret.n = x, ret.i = i; return ret; } else if (x->leaf) { ret.n = NULL, ret.i = i; return ret; } else { - disk_read(x, i); + READ(x, i); return Search((node)x->pc[i], k); } } private: // disk ops - node allocate_node() { - node x = new node_t; + void * allocate_node() { + node x = (node)malloc(sizeof(node_t)); + x->leaf = false; + x->n = 0; + x->offset = -1; + memset(x->key, 0, sizeof(x->key)); + memset(x->c, 0, sizeof(x->c)); + memset(x->pc, 0, sizeof(x->pc)); return x; } + + void split_child(node x, int32_t i) { + node z = (node)allocate_node(); + node y = (node)x->pc[i]; + z->leaf = y->leaf; + z->n = T - 1; + + int j; + for (j=1;j<=T-1;j++) { // init z + z->key[j] = y->key[j+T]; + } + + if (y->leaf == false) { + for (j=1;j<=T;j++) { + z->c[j] = y->c[j+T]; + z->pc[j] = y->pc[j+T]; // copy mem ref also + } + } + + y->n = T-1; // splited y + WRITE(y); + WRITE(z); + + for (j=x->n+1;j>=i+1;j--) { + x->c[j+1] = x->c[j]; // shift + x->pc[j+1] = x->pc[j]; + } + + // relocate z + x->c[i+1] = z->offset; + x->pc[i+1] = z; + + for (j=x->n;j>=i;j--) { + x->key[j+1] = x->key[j]; + } + x->key[i] = y->key[T]; + x->n = x->n +1; + WRITE(x); + } - void disk_read(node x, int32_t i) { + void READ(node x, int32_t i) { if (x->pc[i] != NULL) { return; } - x->pc[i] = malloc(sizeof(node_t)); + x->pc[i] = allocate_node(); lseek(fd, x->c[i], SEEK_SET); read(fd, x->pc[i], BLOCKSIZE); } + + void WRITE(node x) { + if (x->offset !=-1) { + lseek(fd, x->offset, SEEK_SET); + } else { + x->offset = lseek(fd,0, SEEK_END); + } + write(fd, x, BLOCKSIZE); + } }; } #endif // From c073d84ddc2d3ec50b849ab69874b217fe77d6a7 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 12:59:58 +0800 Subject: [PATCH 038/217] save --- Makefile | 3 ++- include/btree.h | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 7fc346ba..47c0d4e2 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,8 @@ PROGRAMS = m_based \ base64_demo \ max_subarray_demo \ disjoint-set_demo \ - relabel_to_front_demo + relabel_to_front_demo \ + btree_demo all: $(PROGRAMS) diff --git a/include/btree.h b/include/btree.h index d2ef9dc9..3c2debde 100644 --- a/include/btree.h +++ b/include/btree.h @@ -50,18 +50,22 @@ namespace alg { }; private: node m_root; - void * map; int fd; private: BTree(const BTree &); BTree& operator=(const BTree&); public: BTree(const char * path) { - fd = open(path, O_RDWR); + fd = open(path, O_RDWR|O_CREAT, 0640); if (fd == -1) return; node x = (node)allocate_node(); - x->leaf = true; + int n = read(fd,x,BLOCKSIZE); + if (n != BLOCKSIZE) { // init new btree + x->leaf = true; + WRITE(x); + } + m_root = (node)x; } ~BTree() { @@ -88,7 +92,29 @@ namespace alg { } } + void Insert(int32_t k) { + node r = m_root; + if (r->n == 2*T - 1) { + node s = (node)allocate_node(); + // replace old root + m_root->offset = -1; + WRITE(m_root); + // new root + s->offset = 0; + s->n = 0; + s->c[1] = m_root->offset; + m_root = s; + split_child(s, 1); + insert_nonfull(s, k); + } else { + insert_nonfull(r, k); + } + } + private: + void insert_nonfull(node s, int32_t k) { + } + // disk ops void * allocate_node() { node x = (node)malloc(sizeof(node_t)); @@ -139,7 +165,7 @@ namespace alg { x->n = x->n +1; WRITE(x); } - + void READ(node x, int32_t i) { if (x->pc[i] != NULL) { return; From 3fadc24632cad7f62b4062611fa2479a5511f79f Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 13:26:46 +0800 Subject: [PATCH 039/217] update btree --- include/btree.h | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/include/btree.h b/include/btree.h index 3c2debde..fb546909 100644 --- a/include/btree.h +++ b/include/btree.h @@ -96,13 +96,14 @@ namespace alg { node r = m_root; if (r->n == 2*T - 1) { node s = (node)allocate_node(); - // replace old root + // re-place the old root m_root->offset = -1; WRITE(m_root); // new root s->offset = 0; s->n = 0; s->c[1] = m_root->offset; + s->pc[1] = m_root; m_root = s; split_child(s, 1); insert_nonfull(s, k); @@ -112,7 +113,29 @@ namespace alg { } private: - void insert_nonfull(node s, int32_t k) { + void insert_nonfull(node x, int32_t k) { + int32_t i = x->n; + if (x->leaf) { + while (i>=1 && k <=x->key[i]) { + x->key[i+1] = x->key[i]; + i = i - 1; + } + x->key[i+1] = k; + x->n = x->n + 1; + } else { + while(i>=1 && k <= x->key[i]) { + i = i-1; + } + i=i+1; + READ(x, i); + if (((node)x->pc[i])->n == 2*T-1) { + split_child(x, i); + if (k > x->key[i]) { + i = i+1; + } + } + insert_nonfull((node)x->pc[i], k); + } } // disk ops @@ -138,7 +161,7 @@ namespace alg { z->key[j] = y->key[j+T]; } - if (y->leaf == false) { + if (!y->leaf) { for (j=1;j<=T;j++) { z->c[j] = y->c[j+T]; z->pc[j] = y->pc[j+T]; // copy mem ref also From 83717ec1c579e1fbcb0f44e2676f19d5c27171f6 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 13:53:46 +0800 Subject: [PATCH 040/217] update btree --- include/btree.h | 51 ++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/include/btree.h b/include/btree.h index fb546909..33a335cc 100644 --- a/include/btree.h +++ b/include/btree.h @@ -34,16 +34,18 @@ namespace alg { private: // 4K node, 4096 bytes to write // t = 255 - typedef struct __attribute__ ((packed)) node_t { + struct node_t { int16_t leaf; // is leaf? int16_t n; // num key - int32_t offset; // block offset + int32_t offset; // block offset (8 byte head) int32_t key[509]; // key int32_t c[510]; // childs pointers (file offsets related to 0) char padding[12]; // padding to 4096 void *pc[510]; // memory - } *node; + } __attribute__ ((packed)); + typedef struct node_t *node; + public: struct search_r { node n; int32_t i; @@ -71,25 +73,9 @@ namespace alg { ~BTree() { close(fd); } - - /** - * search a key, returns node and index - */ - search_r Search(node x, int32_t k) { - int i = 1; - search_r ret; - while (i<=x->n && k > x->key[i]) i++; - - if (i <= x->n && k == x->key[i]) { - ret.n = x, ret.i = i; - return ret; - } else if (x->leaf) { - ret.n = NULL, ret.i = i; - return ret; - } else { - READ(x, i); - return Search((node)x->pc[i], k); - } + + search_r Search(int32_t x) { + return search(m_root, x); } void Insert(int32_t k) { @@ -113,6 +99,26 @@ namespace alg { } private: + /** + * search a key, returns node and index + */ + search_r search(node x, int32_t k) { + int i = 1; + search_r ret; + while (i<=x->n && k > x->key[i]) i++; + + if (i <= x->n && k == x->key[i]) { + ret.n = x, ret.i = i; + return ret; + } else if (x->leaf) { + ret.n = NULL, ret.i = i; + return ret; + } else { + READ(x, i); + return search((node)x->pc[i], k); + } + } + void insert_nonfull(node x, int32_t k) { int32_t i = x->n; if (x->leaf) { @@ -122,6 +128,7 @@ namespace alg { } x->key[i+1] = k; x->n = x->n + 1; + WRITE(x); } else { while(i>=1 && k <= x->key[i]) { i = i-1; From d307c38f26c59603f8aa81171446569329cca051 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 14:23:14 +0800 Subject: [PATCH 041/217] update btree_demo --- include/btree.h | 50 ++++++++++++++++++++++------------------------ src/btree_demo.cpp | 17 ++++++++++++++++ 2 files changed, 41 insertions(+), 26 deletions(-) create mode 100644 src/btree_demo.cpp diff --git a/include/btree.h b/include/btree.h index 33a335cc..f766a6f7 100644 --- a/include/btree.h +++ b/include/btree.h @@ -26,6 +26,7 @@ #include #include #include +#include #define BLOCKSIZE 4096 #define T 255 @@ -41,11 +42,13 @@ namespace alg { int32_t key[509]; // key int32_t c[510]; // childs pointers (file offsets related to 0) char padding[12]; // padding to 4096 - void *pc[510]; // memory } __attribute__ ((packed)); typedef struct node_t *node; public: + /** + * search result + */ struct search_r { node n; int32_t i; @@ -82,14 +85,13 @@ namespace alg { node r = m_root; if (r->n == 2*T - 1) { node s = (node)allocate_node(); - // re-place the old root + // place the old root node to the end of the file m_root->offset = -1; - WRITE(m_root); + WRITE(m_root); // new root s->offset = 0; s->n = 0; s->c[1] = m_root->offset; - s->pc[1] = m_root; m_root = s; split_child(s, 1); insert_nonfull(s, k); @@ -114,15 +116,18 @@ namespace alg { ret.n = NULL, ret.i = i; return ret; } else { - READ(x, i); - return search((node)x->pc[i], k); + std::auto_ptr xi(READ(x, i)); + return search(xi.get(), k); } } + /** + * insert into non-full node + */ void insert_nonfull(node x, int32_t k) { int32_t i = x->n; if (x->leaf) { - while (i>=1 && k <=x->key[i]) { + while (i>=1 && k key[i]) { x->key[i+1] = x->key[i]; i = i - 1; } @@ -130,18 +135,18 @@ namespace alg { x->n = x->n + 1; WRITE(x); } else { - while(i>=1 && k <= x->key[i]) { + while(i>=1 && k < x->key[i]) { i = i-1; } i=i+1; - READ(x, i); - if (((node)x->pc[i])->n == 2*T-1) { + std::auto_ptr xi(READ(x, i)); + if (xi->n == 2*T-1) { split_child(x, i); if (k > x->key[i]) { i = i+1; } } - insert_nonfull((node)x->pc[i], k); + insert_nonfull(xi.get(), k); } } @@ -153,13 +158,12 @@ namespace alg { x->offset = -1; memset(x->key, 0, sizeof(x->key)); memset(x->c, 0, sizeof(x->c)); - memset(x->pc, 0, sizeof(x->pc)); return x; } void split_child(node x, int32_t i) { - node z = (node)allocate_node(); - node y = (node)x->pc[i]; + std::auto_ptr z((node)allocate_node()); + std::auto_ptr y(READ(x, i)); z->leaf = y->leaf; z->n = T - 1; @@ -171,22 +175,19 @@ namespace alg { if (!y->leaf) { for (j=1;j<=T;j++) { z->c[j] = y->c[j+T]; - z->pc[j] = y->pc[j+T]; // copy mem ref also } } y->n = T-1; // splited y - WRITE(y); - WRITE(z); + WRITE(y.get()); + WRITE(z.get()); for (j=x->n+1;j>=i+1;j--) { x->c[j+1] = x->c[j]; // shift - x->pc[j+1] = x->pc[j]; } // relocate z x->c[i+1] = z->offset; - x->pc[i+1] = z; for (j=x->n;j>=i;j--) { x->key[j+1] = x->key[j]; @@ -196,14 +197,11 @@ namespace alg { WRITE(x); } - void READ(node x, int32_t i) { - if (x->pc[i] != NULL) { - return; - } - - x->pc[i] = allocate_node(); + node READ(node x, int32_t i) { + void *xi = allocate_node(); lseek(fd, x->c[i], SEEK_SET); - read(fd, x->pc[i], BLOCKSIZE); + read(fd, xi, BLOCKSIZE); + return (node)xi; } void WRITE(node x) { diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp new file mode 100644 index 00000000..6bcaee23 --- /dev/null +++ b/src/btree_demo.cpp @@ -0,0 +1,17 @@ +#include +#include "btree.h" + +using namespace alg; +int main(void) { + BTree x("./btree.dat"); + int32_t i; + + for (i=0;i<510;i++) { + x.Insert(i); + } + + for(i=0;i<509;i++) { + BTree::search_r r = x.Search(i); + printf("block[%x] idx[%d]\n", r.n, r.i); + } +} From 4187938712c892e1827c3f79d89657dfb259bb4c Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 14:32:10 +0800 Subject: [PATCH 042/217] update btree.h --- include/btree.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/btree.h b/include/btree.h index f766a6f7..7557c903 100644 --- a/include/btree.h +++ b/include/btree.h @@ -91,9 +91,9 @@ namespace alg { // new root s->offset = 0; s->n = 0; - s->c[1] = m_root->offset; + s->c[0] = m_root->offset; m_root = s; - split_child(s, 1); + split_child(s, 0); insert_nonfull(s, k); } else { insert_nonfull(r, k); @@ -105,11 +105,11 @@ namespace alg { * search a key, returns node and index */ search_r search(node x, int32_t k) { - int i = 1; + int i = 0; search_r ret; - while (i<=x->n && k > x->key[i]) i++; + while (in && k > x->key[i]) i++; - if (i <= x->n && k == x->key[i]) { + if (i < x->n && k == x->key[i]) { ret.n = x, ret.i = i; return ret; } else if (x->leaf) { @@ -125,9 +125,9 @@ namespace alg { * insert into non-full node */ void insert_nonfull(node x, int32_t k) { - int32_t i = x->n; + int32_t i = x->n-1; if (x->leaf) { - while (i>=1 && k key[i]) { + while (i>=0 && k key[i]) { x->key[i+1] = x->key[i]; i = i - 1; } @@ -135,7 +135,7 @@ namespace alg { x->n = x->n + 1; WRITE(x); } else { - while(i>=1 && k < x->key[i]) { + while(i>=0 && k < x->key[i]) { i = i-1; } i=i+1; @@ -168,12 +168,12 @@ namespace alg { z->n = T - 1; int j; - for (j=1;j<=T-1;j++) { // init z + for (j=0;jkey[j] = y->key[j+T]; } if (!y->leaf) { - for (j=1;j<=T;j++) { + for (j=0;jc[j] = y->c[j+T]; } } @@ -182,14 +182,14 @@ namespace alg { WRITE(y.get()); WRITE(z.get()); - for (j=x->n+1;j>=i+1;j--) { + for (j=x->n;j>=i+1;j--) { x->c[j+1] = x->c[j]; // shift } // relocate z x->c[i+1] = z->offset; - for (j=x->n;j>=i;j--) { + for (j=x->n-1;j>=i;j--) { x->key[j+1] = x->key[j]; } x->key[i] = y->key[T]; From 5dbfa029503987c502f36197bc0b44c1f2fd8ed9 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 14:33:53 +0800 Subject: [PATCH 043/217] fixed a leak in btree --- include/btree.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/btree.h b/include/btree.h index 7557c903..a4e4d7a2 100644 --- a/include/btree.h +++ b/include/btree.h @@ -92,6 +92,7 @@ namespace alg { s->offset = 0; s->n = 0; s->c[0] = m_root->offset; + free(m_root); m_root = s; split_child(s, 0); insert_nonfull(s, k); From e2a09aa3d4ae592b30261837fdd026cad757c257 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 14:42:00 +0800 Subject: [PATCH 044/217] update comments for btree --- include/btree.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/include/btree.h b/include/btree.h index a4e4d7a2..c2f27487 100644 --- a/include/btree.h +++ b/include/btree.h @@ -151,7 +151,9 @@ namespace alg { } } - // disk ops + /** + * allocate empty node struct + */ void * allocate_node() { node x = (node)malloc(sizeof(node_t)); x->leaf = false; @@ -162,6 +164,9 @@ namespace alg { return x; } + /** + * split a node into 2. + */ void split_child(node x, int32_t i) { std::auto_ptr z((node)allocate_node()); std::auto_ptr y(READ(x, i)); @@ -198,6 +203,9 @@ namespace alg { WRITE(x); } + /** + * Read a 4K-block from disk, and returns the node struct. + */ node READ(node x, int32_t i) { void *xi = allocate_node(); lseek(fd, x->c[i], SEEK_SET); @@ -205,6 +213,9 @@ namespace alg { return (node)xi; } + /** + * update a node struct to file, create if offset is -1. + */ void WRITE(node x) { if (x->offset !=-1) { lseek(fd, x->offset, SEEK_SET); From e72721a5d579483a056250f89d790b56174c8019 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 16:02:03 +0800 Subject: [PATCH 045/217] update btree --- include/btree.h | 54 +++++++++++++++++++++++++--------------------- src/btree_demo.cpp | 6 ++++-- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/include/btree.h b/include/btree.h index c2f27487..e1467321 100644 --- a/include/btree.h +++ b/include/btree.h @@ -30,18 +30,21 @@ #define BLOCKSIZE 4096 #define T 255 +#define LEAF 0x0001 +#define ONDISK 0x0002 + namespace alg { class BTree { private: // 4K node, 4096 bytes to write // t = 255 struct node_t { - int16_t leaf; // is leaf? - int16_t n; // num key - int32_t offset; // block offset (8 byte head) - int32_t key[509]; // key - int32_t c[510]; // childs pointers (file offsets related to 0) - char padding[12]; // padding to 4096 + uint16_t n; // num key + uint16_t flag; // flags + uint32_t offset; // block offset (8 byte head) + char padding[12]; // padding to 4096 + int32_t key[509]; // key + int32_t c[510]; // childs pointers (file offsets related to 0) } __attribute__ ((packed)); typedef struct node_t *node; @@ -67,7 +70,7 @@ namespace alg { node x = (node)allocate_node(); int n = read(fd,x,BLOCKSIZE); if (n != BLOCKSIZE) { // init new btree - x->leaf = true; + x->flag |= LEAF; WRITE(x); } m_root = (node)x; @@ -86,13 +89,14 @@ namespace alg { if (r->n == 2*T - 1) { node s = (node)allocate_node(); // place the old root node to the end of the file - m_root->offset = -1; - WRITE(m_root); + m_root->flag &= ~ONDISK; + WRITE(m_root); // new root + s->flag &= ~LEAF; s->offset = 0; s->n = 0; s->c[0] = m_root->offset; - free(m_root); + //free(m_root); m_root = s; split_child(s, 0); insert_nonfull(s, k); @@ -106,14 +110,14 @@ namespace alg { * search a key, returns node and index */ search_r search(node x, int32_t k) { - int i = 0; + uint16_t i = 0; search_r ret; while (in && k > x->key[i]) i++; - if (i < x->n && k == x->key[i]) { + if (in && k == x->key[i]) { ret.n = x, ret.i = i; return ret; - } else if (x->leaf) { + } else if (x->flag & LEAF) { ret.n = NULL, ret.i = i; return ret; } else { @@ -127,7 +131,7 @@ namespace alg { */ void insert_nonfull(node x, int32_t k) { int32_t i = x->n-1; - if (x->leaf) { + if (x->flag & LEAF) { while (i>=0 && k key[i]) { x->key[i+1] = x->key[i]; i = i - 1; @@ -140,14 +144,15 @@ namespace alg { i = i-1; } i=i+1; - std::auto_ptr xi(READ(x, i)); + node xi = READ(x, i); if (xi->n == 2*T-1) { split_child(x, i); if (k > x->key[i]) { i = i+1; } } - insert_nonfull(xi.get(), k); + insert_nonfull(xi, k); + free(xi); } } @@ -156,9 +161,9 @@ namespace alg { */ void * allocate_node() { node x = (node)malloc(sizeof(node_t)); - x->leaf = false; x->n = 0; - x->offset = -1; + x->offset = 0; + x->flag = 0; memset(x->key, 0, sizeof(x->key)); memset(x->c, 0, sizeof(x->c)); return x; @@ -170,15 +175,15 @@ namespace alg { void split_child(node x, int32_t i) { std::auto_ptr z((node)allocate_node()); std::auto_ptr y(READ(x, i)); - z->leaf = y->leaf; + z->flag |= (y->flag & LEAF); z->n = T - 1; - int j; + uint16_t j; for (j=0;jkey[j] = y->key[j+T]; } - if (!y->leaf) { + if (!(y->flag & LEAF)) { for (j=0;jc[j] = y->c[j+T]; } @@ -192,13 +197,13 @@ namespace alg { x->c[j+1] = x->c[j]; // shift } - // relocate z + // save z x->c[i+1] = z->offset; for (j=x->n-1;j>=i;j--) { x->key[j+1] = x->key[j]; } - x->key[i] = y->key[T]; + x->key[i] = y->key[T-1]; x->n = x->n +1; WRITE(x); } @@ -217,11 +222,12 @@ namespace alg { * update a node struct to file, create if offset is -1. */ void WRITE(node x) { - if (x->offset !=-1) { + 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); } }; diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 6bcaee23..4bb77903 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,12 +6,14 @@ int main(void) { BTree x("./btree.dat"); int32_t i; - for (i=0;i<510;i++) { + for (i=0;i<100000;i++) { x.Insert(i); } - for(i=0;i<509;i++) { + /* + for(i=0;i<100000;i++) { BTree::search_r r = x.Search(i); printf("block[%x] idx[%d]\n", r.n, r.i); } + */ } From 4b042974433ba47c4e77297429054599a27520a4 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 17:22:33 +0800 Subject: [PATCH 046/217] update btree.h --- include/btree.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/btree.h b/include/btree.h index e1467321..72dabe4d 100644 --- a/include/btree.h +++ b/include/btree.h @@ -87,16 +87,15 @@ namespace alg { void Insert(int32_t k) { node r = m_root; if (r->n == 2*T - 1) { - node s = (node)allocate_node(); // place the old root node to the end of the file m_root->flag &= ~ONDISK; WRITE(m_root); // new root + node s = (node)allocate_node(); s->flag &= ~LEAF; - s->offset = 0; - s->n = 0; s->c[0] = m_root->offset; - //free(m_root); + // free old & set new + free(m_root); m_root = s; split_child(s, 0); insert_nonfull(s, k); @@ -110,7 +109,7 @@ namespace alg { * search a key, returns node and index */ search_r search(node x, int32_t k) { - uint16_t i = 0; + int32_t i = 0; search_r ret; while (in && k > x->key[i]) i++; @@ -178,7 +177,7 @@ namespace alg { z->flag |= (y->flag & LEAF); z->n = T - 1; - uint16_t j; + int32_t j; for (j=0;jkey[j] = y->key[j+T]; } @@ -204,7 +203,7 @@ namespace alg { x->key[j+1] = x->key[j]; } x->key[i] = y->key[T-1]; - x->n = x->n +1; + x->n = x->n+1; WRITE(x); } From 6bf147e6a458e607550faa987fd6168cb313fbbe Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 18:25:27 +0800 Subject: [PATCH 047/217] debuging btree --- include/btree.h | 23 ++++++++--------------- src/btree_demo.cpp | 12 ++++++------ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/include/btree.h b/include/btree.h index 72dabe4d..ef97db45 100644 --- a/include/btree.h +++ b/include/btree.h @@ -48,14 +48,6 @@ namespace alg { } __attribute__ ((packed)); typedef struct node_t *node; - public: - /** - * search result - */ - struct search_r { - node n; - int32_t i; - }; private: node m_root; int fd; @@ -80,7 +72,7 @@ namespace alg { close(fd); } - search_r Search(int32_t x) { + int32_t Search(int32_t x) { return search(m_root, x); } @@ -108,17 +100,14 @@ namespace alg { /** * search a key, returns node and index */ - search_r search(node x, int32_t k) { + int32_t search(node x, int32_t k) { int32_t i = 0; - search_r ret; while (in && k > x->key[i]) i++; if (in && k == x->key[i]) { - ret.n = x, ret.i = i; - return ret; + return i; } else if (x->flag & LEAF) { - ret.n = NULL, ret.i = i; - return ret; + return -1; } else { std::auto_ptr xi(READ(x, i)); return search(xi.get(), k); @@ -174,7 +163,11 @@ namespace alg { void split_child(node x, int32_t i) { std::auto_ptr z((node)allocate_node()); std::auto_ptr y(READ(x, i)); + z->flag &= ~LEAF; z->flag |= (y->flag & LEAF); + printf("leafz:%x\n", z->flag); + printf("leafy:%x\n", y->flag); + printf("leafx:%x offset:%x\n", x->flag, x->offset); z->n = T - 1; int32_t j; diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 4bb77903..edeb89a4 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,14 +6,14 @@ int main(void) { BTree x("./btree.dat"); int32_t i; - for (i=0;i<100000;i++) { + /* + for (i=0;i<1024;i++) { x.Insert(i); } + */ - /* - for(i=0;i<100000;i++) { - BTree::search_r r = x.Search(i); - printf("block[%x] idx[%d]\n", r.n, r.i); + for(i=0;i<1024;i++) { + int32_t r = x.Search(i); + printf("idx[%d]\n", r); } - */ } From 2ea1ea33a5563fc7acf2ef6ac449ef8a6236d0fa Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 17 Oct 2013 18:27:51 +0800 Subject: [PATCH 048/217] fixed a bug in btree --- include/btree.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/btree.h b/include/btree.h index ef97db45..e2be5586 100644 --- a/include/btree.h +++ b/include/btree.h @@ -85,6 +85,8 @@ namespace alg { // new root node s = (node)allocate_node(); s->flag &= ~LEAF; + s->flag |= ONDISK; // write to offset 0 + s->offset = 0; s->c[0] = m_root->offset; // free old & set new free(m_root); From 39b1dc20c983c8b9af4a5ee693ff5e1cd24b9954 Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 17 Oct 2013 23:06:47 +0800 Subject: [PATCH 049/217] add debug info --- include/btree.h | 23 +++++++++-------------- src/btree_demo.cpp | 4 +--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/include/btree.h b/include/btree.h index e2be5586..19577bf3 100644 --- a/include/btree.h +++ b/include/btree.h @@ -29,7 +29,7 @@ #include #define BLOCKSIZE 4096 -#define T 255 +#define T 255 #define LEAF 0x0001 #define ONDISK 0x0002 @@ -104,11 +104,16 @@ namespace alg { */ int32_t search(node x, int32_t k) { int32_t i = 0; - while (in && k > x->key[i]) i++; + while (in && (k > x->key[i])) i++; if (in && k == x->key[i]) { return i; } else if (x->flag & LEAF) { + int c; + for (c=0;cn;c++) { + printf("%d ", x->key[c]); + } + printf("[%d]\n", x->key[i]); return -1; } else { std::auto_ptr xi(READ(x, i)); @@ -151,11 +156,7 @@ namespace alg { */ void * allocate_node() { node x = (node)malloc(sizeof(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, 0, sizeof(node_t)); return x; } @@ -165,11 +166,7 @@ namespace alg { void split_child(node x, int32_t i) { std::auto_ptr z((node)allocate_node()); std::auto_ptr y(READ(x, i)); - z->flag &= ~LEAF; z->flag |= (y->flag & LEAF); - printf("leafz:%x\n", z->flag); - printf("leafy:%x\n", y->flag); - printf("leafx:%x offset:%x\n", x->flag, x->offset); z->n = T - 1; int32_t j; @@ -188,10 +185,8 @@ namespace alg { WRITE(z.get()); for (j=x->n;j>=i+1;j--) { - x->c[j+1] = x->c[j]; // shift + x->c[j+1] = x->c[j]; // right shift } - - // save z x->c[i+1] = z->offset; for (j=x->n-1;j>=i;j--) { diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index edeb89a4..63c5f24c 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,11 +6,9 @@ int main(void) { BTree x("./btree.dat"); int32_t i; - /* for (i=0;i<1024;i++) { - x.Insert(i); + x.Insert(i); } - */ for(i=0;i<1024;i++) { int32_t r = x.Search(i); From 15785958282d0d639db506ae7598d89072c9e675 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 18 Oct 2013 09:34:26 +0800 Subject: [PATCH 050/217] add comment for btree --- include/btree.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/include/btree.h b/include/btree.h index e2be5586..c2966f2b 100644 --- a/include/btree.h +++ b/include/btree.h @@ -106,12 +106,12 @@ namespace alg { int32_t i = 0; while (in && k > x->key[i]) i++; - if (in && k == x->key[i]) { + if (in && k == x->key[i]) { // search in [0,n-1] return i; - } else if (x->flag & LEAF) { + } else if (x->flag & LEAF) { // leaf, no more childs return -1; } else { - std::auto_ptr xi(READ(x, i)); + std::auto_ptr xi(READ(x, i)); // in last child return search(xi.get(), k); } } @@ -121,8 +121,8 @@ namespace alg { */ void insert_nonfull(node x, int32_t k) { int32_t i = x->n-1; - if (x->flag & LEAF) { - while (i>=0 && k key[i]) { + if (x->flag & LEAF) { // insert into leaf + while (i>=0 && k < x->key[i]) { // shift from right to left, when k < key[i] x->key[i+1] = x->key[i]; i = i - 1; } @@ -173,28 +173,26 @@ namespace alg { z->n = T - 1; int32_t j; - for (j=0;jkey[j] = y->key[j+T]; } - if (!(y->flag & LEAF)) { + if (!(y->flag & LEAF)) { // if not leaf, copy childs too. for (j=0;jc[j] = y->c[j+T]; } } - y->n = T-1; // splited y + y->n = T-1; // shrink y to t-1 elements WRITE(y.get()); WRITE(z.get()); - for (j=x->n;j>=i+1;j--) { - x->c[j+1] = x->c[j]; // shift + for (j=x->n;j>=i+1;j--) { // make place for the new child in x + x->c[j+1] = x->c[j]; } - // save z - x->c[i+1] = z->offset; - - for (j=x->n-1;j>=i;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]; From 21646dd4d8e96ea59181ecb474fbd33c24081d28 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 18 Oct 2013 12:38:35 +0800 Subject: [PATCH 051/217] fixed a bug in btree. --- include/btree.h | 9 ++++----- src/btree_demo.cpp | 5 ----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/include/btree.h b/include/btree.h index c2966f2b..6d153f54 100644 --- a/include/btree.h +++ b/include/btree.h @@ -87,6 +87,7 @@ namespace alg { s->flag &= ~LEAF; s->flag |= ONDISK; // write to offset 0 s->offset = 0; + s->n = 0; s->c[0] = m_root->offset; // free old & set new free(m_root); @@ -141,6 +142,7 @@ namespace alg { i = i+1; } } + xi = READ(x, i); // reload x[i] insert_nonfull(xi, k); free(xi); } @@ -167,9 +169,6 @@ namespace alg { std::auto_ptr y(READ(x, i)); z->flag &= ~LEAF; z->flag |= (y->flag & LEAF); - printf("leafz:%x\n", z->flag); - printf("leafy:%x\n", y->flag); - printf("leafx:%x offset:%x\n", x->flag, x->offset); z->n = T - 1; int32_t j; @@ -195,7 +194,7 @@ namespace alg { 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]; + x->key[i] = y->key[T-1]; // copy the middle element of y into x x->n = x->n+1; WRITE(x); } @@ -209,7 +208,7 @@ namespace alg { read(fd, xi, BLOCKSIZE); return (node)xi; } - + /** * update a node struct to file, create if offset is -1. */ diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index edeb89a4..042b31ab 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,13 +6,8 @@ int main(void) { BTree x("./btree.dat"); int32_t i; - /* for (i=0;i<1024;i++) { x.Insert(i); - } - */ - - for(i=0;i<1024;i++) { int32_t r = x.Search(i); printf("idx[%d]\n", r); } From e3577f0147cc5645fe1680a7a3b3473ebed70d77 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 18 Oct 2013 12:39:26 +0800 Subject: [PATCH 052/217] update demo --- src/btree_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 042b31ab..a6ac106b 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,7 +6,7 @@ int main(void) { BTree x("./btree.dat"); int32_t i; - for (i=0;i<1024;i++) { + for (i=0;i<100000;i++) { x.Insert(i); int32_t r = x.Search(i); printf("idx[%d]\n", r); From 81474a350f1ab569047b7698a451644482c895e3 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 18 Oct 2013 16:05:46 +0800 Subject: [PATCH 053/217] update readme.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ac33df57..6e11c789 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Interval tree Prefix Tree(Trie) *Suffix Tree(未实现)* + B-Tree Hash by multiplication Hash table From d9f1e7eaf75e441d32918148e915c56ce326ffe0 Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 18 Oct 2013 16:16:45 +0800 Subject: [PATCH 054/217] optimize btree.h --- include/btree.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/btree.h b/include/btree.h index 6d153f54..c6ac1102 100644 --- a/include/btree.h +++ b/include/btree.h @@ -141,8 +141,9 @@ namespace alg { if (k > x->key[i]) { i = i+1; } + // reload x[i] after split_child(will modify child x[i]) + xi = READ(x, i); } - xi = READ(x, i); // reload x[i] insert_nonfull(xi, k); free(xi); } From 49f09d190ff0b4d5ec96cca5863130f27709897f Mon Sep 17 00:00:00 2001 From: fuli Date: Fri, 18 Oct 2013 18:13:14 +0800 Subject: [PATCH 055/217] updating btree --- include/btree.h | 75 +++++++++++++++++++++++++++++++++++++++++++--- src/btree_demo.cpp | 4 +-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/include/btree.h b/include/btree.h index c6ac1102..85f38069 100644 --- a/include/btree.h +++ b/include/btree.h @@ -48,6 +48,12 @@ namespace alg { } __attribute__ ((packed)); typedef struct node_t *node; + public: + // node and index + struct nr { + uint32_t offset; + int32_t idx; + }; private: node m_root; int fd; @@ -72,7 +78,7 @@ namespace alg { close(fd); } - int32_t Search(int32_t x) { + nr Search(int32_t x) { return search(m_root, x); } @@ -99,18 +105,28 @@ namespace alg { } } + void DeleteKey(int32_t k) { + node x = m_root; + delete_op(m_root, k); + } + private: /** * search a key, returns node and index */ - int32_t search(node x, int32_t k) { + nr search(node x, int32_t k) { int32_t i = 0; + nr ret; while (in && k > x->key[i]) i++; if (in && k == x->key[i]) { // search in [0,n-1] - return i; + ret.offset = x->offset; + ret.idx = i; + return ret; } else if (x->flag & LEAF) { // leaf, no more childs - return -1; + ret.offset = 0; + ret.idx = -1; + return ret; } else { std::auto_ptr xi(READ(x, i)); // in last child return search(xi.get(), k); @@ -200,6 +216,57 @@ namespace alg { WRITE(x); } + /** + * recursion deletion + */ + void delete_op(node x, int32_t k) { + int32_t i; + for (i=0;in;i++) { + if (x->key[i] == k) { // leaf node, case1 + break; + } + } + + if (in && (x->flag & LEAF)) { + int j; + for (j = i;jn-1;j++) { // shift copy + x->key[j] = x->key[j+1]; + } + WRITE(x); + } else if (x->key[i] == k) { // non-leaf + if (i = x->n-1 || i == 0) { // outside, case 2c + delete_case3(x); + } else { + node y= READ(x, i-1); + if (y->n >= T) { // case 2a + x->key[i] = y->key[y->n-1]; // subsitute the key with predecessor + delete_op(y, x->key[i]); + free(y); + return; + } + + node z = READ(x, i+1); + if (z->n >= T) { // case 2b + x->key[i] = z->key[0]; + delete_op(z, x->key[i]); + return; + } + + // case 2c: + if (y->n == T-1 && z->n == T-1) { + + } + delete_case3(x); + } + } + } + + /** + * delete case3 + */ + void delete_case3(node x) { + } + /** * Read a 4K-block from disk, and returns the node struct. */ diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index a6ac106b..7cade81f 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -8,7 +8,7 @@ int main(void) { for (i=0;i<100000;i++) { x.Insert(i); - int32_t r = x.Search(i); - printf("idx[%d]\n", r); + BTree::nr r = x.Search(i); + printf("offset[%x] idx[%d]\n", r.offset, r.idx); } } From b17fed84bb87d61d155a91be191b22eca4b258ce Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 19 Oct 2013 08:39:52 +0800 Subject: [PATCH 056/217] Revert "add debug info" This reverts commit 39b1dc20c983c8b9af4a5ee693ff5e1cd24b9954. --- include/btree.h | 23 ++++++++++++++--------- src/btree_demo.cpp | 4 +++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/btree.h b/include/btree.h index 19577bf3..e2be5586 100644 --- a/include/btree.h +++ b/include/btree.h @@ -29,7 +29,7 @@ #include #define BLOCKSIZE 4096 -#define T 255 +#define T 255 #define LEAF 0x0001 #define ONDISK 0x0002 @@ -104,16 +104,11 @@ namespace alg { */ int32_t search(node x, int32_t k) { int32_t i = 0; - while (in && (k > x->key[i])) i++; + while (in && k > x->key[i]) i++; if (in && k == x->key[i]) { return i; } else if (x->flag & LEAF) { - int c; - for (c=0;cn;c++) { - printf("%d ", x->key[c]); - } - printf("[%d]\n", x->key[i]); return -1; } else { std::auto_ptr xi(READ(x, i)); @@ -156,7 +151,11 @@ namespace alg { */ void * allocate_node() { node x = (node)malloc(sizeof(node_t)); - memset(x, 0, sizeof(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)); return x; } @@ -166,7 +165,11 @@ namespace alg { void split_child(node x, int32_t i) { std::auto_ptr z((node)allocate_node()); std::auto_ptr y(READ(x, i)); + z->flag &= ~LEAF; z->flag |= (y->flag & LEAF); + printf("leafz:%x\n", z->flag); + printf("leafy:%x\n", y->flag); + printf("leafx:%x offset:%x\n", x->flag, x->offset); z->n = T - 1; int32_t j; @@ -185,8 +188,10 @@ namespace alg { WRITE(z.get()); for (j=x->n;j>=i+1;j--) { - x->c[j+1] = x->c[j]; // right shift + x->c[j+1] = x->c[j]; // shift } + + // save z x->c[i+1] = z->offset; for (j=x->n-1;j>=i;j--) { diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 63c5f24c..edeb89a4 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,9 +6,11 @@ int main(void) { BTree x("./btree.dat"); int32_t i; + /* for (i=0;i<1024;i++) { - x.Insert(i); + x.Insert(i); } + */ for(i=0;i<1024;i++) { int32_t r = x.Search(i); From 787da1d071e7ba8340c6d7bd3ff21948bd3c3618 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 19 Oct 2013 19:23:16 +0800 Subject: [PATCH 057/217] adding btree delete --- include/btree.h | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/include/btree.h b/include/btree.h index 85f38069..4acf9d04 100644 --- a/include/btree.h +++ b/include/btree.h @@ -29,9 +29,10 @@ #include #define BLOCKSIZE 4096 -#define T 255 -#define LEAF 0x0001 -#define ONDISK 0x0002 +#define T 255 +#define LEAF 0x0001 +#define ONDISK 0x0002 +#define MARKFREE 0x0004 namespace alg { class BTree { @@ -217,7 +218,7 @@ namespace alg { } /** - * recursion deletion + * recursive deletion. */ void delete_op(node x, int32_t k) { int32_t i; @@ -240,22 +241,53 @@ namespace alg { node y= READ(x, i-1); if (y->n >= T) { // case 2a x->key[i] = y->key[y->n-1]; // subsitute the key with predecessor + WRITE(x); + delete_op(y, x->key[i]); free(y); return; } + free(y); node z = READ(x, i+1); if (z->n >= T) { // case 2b x->key[i] = z->key[0]; + WRITE(x); delete_op(z, x->key[i]); return; } + free(z); // case 2c: if (y->n == T-1 && z->n == T-1) { + // merge k & z into y + y->key[y->n] = k; + int j; + for (j=0;jn;j++) { // merge n keys, k already in + y->key[y->n+j+1] = z->key[j]; + } + for (j=0;jn+1;j++) { // merge n+1 childs + y->c[y->n+j+1] = z->key[j]; + } + // mark free this node + z->flag |= MARKFREE; + y->n = y->n + z->n + 1; // size after merge + WRITE(z); + WRITE(y); + + // shift x + for (j=i;jn-1;j++) { + x->key[i] = x->key[i+1]; + } + x->n = x->n - 1; + WRITE(x); + + // recursive delete k + delete_op(y, k); + return; } + delete_case3(x); } } From 5ccbfa5721e497907e6df5c1046ba69477dc7356 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 19 Oct 2013 23:00:49 +0800 Subject: [PATCH 058/217] updating btree --- include/btree.h | 565 ++++++++++++++++++++++++++---------------------- 1 file changed, 309 insertions(+), 256 deletions(-) diff --git a/include/btree.h b/include/btree.h index 4acf9d04..5cd1759a 100644 --- a/include/btree.h +++ b/include/btree.h @@ -36,291 +36,344 @@ 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; // block offset (8 byte head) - char padding[12]; // padding to 4096 - int32_t key[509]; // key - int32_t c[510]; // childs pointers (file offsets related to 0) - } __attribute__ ((packed)); - typedef struct node_t *node; - - public: - // node and index - struct nr { - uint32_t offset; - int32_t idx; - }; - private: - node m_root; - 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)allocate_node(); - int n = read(fd,x,BLOCKSIZE); - if (n != BLOCKSIZE) { // init new btree - x->flag |= LEAF; - WRITE(x); + private: + // 4K node, 4096 bytes to write + // t = 255 + struct node_t { + uint16_t n; // num key + uint16_t flag; // flags + uint32_t offset; // block offset (8 byte head) + char padding[12]; // padding to 4096 + int32_t key[509]; // key + int32_t c[510]; // childs pointers (file offsets related to 0) + } __attribute__ ((packed)); + typedef struct node_t *node; + + public: + // node and index + struct nr { + uint32_t offset; + int32_t idx; + }; + private: + node m_root; + 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)allocate_node(); + int n = read(fd,x,BLOCKSIZE); + if (n != BLOCKSIZE) { // init new btree + x->flag |= LEAF; + WRITE(x); + } + m_root = (node)x; } - m_root = (node)x; - } - - ~BTree() { - close(fd); - } - - nr Search(int32_t x) { - return search(m_root, x); - } - - void Insert(int32_t k) { - node r = m_root; - if (r->n == 2*T - 1) { - // place the old root node to the end of the file - m_root->flag &= ~ONDISK; - WRITE(m_root); - // new root - node s = (node)allocate_node(); - s->flag &= ~LEAF; - s->flag |= ONDISK; // write to offset 0 - s->offset = 0; - s->n = 0; - s->c[0] = m_root->offset; - // free old & set new - free(m_root); - m_root = s; - split_child(s, 0); - insert_nonfull(s, k); - } else { - insert_nonfull(r, k); + + ~BTree() { + close(fd); } - } - - void DeleteKey(int32_t k) { - node x = m_root; - delete_op(m_root, k); - } - - private: - /** - * search a key, returns node and index - */ - nr search(node x, int32_t k) { - int32_t i = 0; - nr 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)); // in last child - return search(xi.get(), k); + + nr Search(int32_t x) { + return search(m_root, x); } - } - - /** - * 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 leaf - while (i>=0 && k < x->key[i]) { // shift from right to left, when k < key[i] - x->key[i+1] = x->key[i]; - i = i - 1; + + void Insert(int32_t k) { + node r = m_root; + if (r->n == 2*T - 1) { + // place the old root node to the end of the file + m_root->flag &= ~ONDISK; + WRITE(m_root); + // new root + node s = (node)allocate_node(); + s->flag &= ~LEAF; + s->flag |= ONDISK; // write to offset 0 + s->offset = 0; + s->n = 0; + s->c[0] = m_root->offset; + // free old & set new + free(m_root); + m_root = s; + split_child(s, 0); + insert_nonfull(s, k); + } else { + insert_nonfull(r, k); } - x->key[i+1] = k; - x->n = x->n + 1; - WRITE(x); - } else { - while(i>=0 && k < x->key[i]) { - i = i-1; + } + + void DeleteKey(int32_t k) { + node x = m_root; + delete_op(m_root, k); + } + + private: + /** + * search a key, returns node and index + */ + nr search(node x, int32_t k) { + int32_t i = 0; + nr 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)); // in last child + return search(xi.get(), k); } - i=i+1; - node xi = READ(x, i); - if (xi->n == 2*T-1) { - split_child(x, i); - if (k > x->key[i]) { - i = i+1; + } + + /** + * 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 leaf + while (i>=0 && k < x->key[i]) { // shift from right to left, when k < key[i] + x->key[i+1] = x->key[i]; + i = i - 1; } - // reload x[i] after split_child(will modify child x[i]) - xi = READ(x, i); + 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); + if (xi->n == 2*T-1) { + split_child(x, i); + if (k > x->key[i]) { + i = i+1; + } + // reload x[i] after split_child(will modify child x[i]) + xi = READ(x, i); + } + insert_nonfull(xi, k); + free(xi); } - insert_nonfull(xi, k); - free(xi); } - } - - /** - * allocate empty node struct - */ - void * allocate_node() { - node x = (node)malloc(sizeof(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)); - return x; - } - - /** - * split a node into 2. - */ - void split_child(node x, int32_t i) { - std::auto_ptr z((node)allocate_node()); - 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]; + + /** + * allocate empty node struct + */ + void * allocate_node() { + node x = (node)malloc(sizeof(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)); + return x; } - if (!(y->flag & LEAF)) { // if not leaf, copy childs too. - for (j=0;jc[j] = y->c[j+T]; + /** + * split a node into 2. + */ + void split_child(node x, int32_t i) { + std::auto_ptr z((node)allocate_node()); + 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]; } - } - y->n = T-1; // shrink y to t-1 elements - WRITE(y.get()); - WRITE(z.get()); + if (!(y->flag & LEAF)) { // if not leaf, copy childs too. + for (j=0;jc[j] = y->c[j+T]; + } + } - for (j=x->n;j>=i+1;j--) { // make place for the new child in x - x->c[j+1] = x->c[j]; - } + y->n = T-1; // shrink y to t-1 elements + WRITE(y.get()); + WRITE(z.get()); - 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; - for (i=0;in;i++) { - if (x->key[i] == k) { // leaf node, case1 - break; + for (j=x->n;j>=i+1;j--) { // make place for the new child in x + x->c[j+1] = x->c[j]; } - } - - if (in && (x->flag & LEAF)) { - int j; - for (j = i;jn-1;j++) { // shift copy - x->key[j] = x->key[j+1]; + + 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); - } else if (x->key[i] == k) { // non-leaf - if (i = x->n-1 || i == 0) { // outside, case 2c - delete_case3(x); - } else { - node y= READ(x, i-1); - if (y->n >= T) { // case 2a - x->key[i] = y->key[y->n-1]; // subsitute the key with predecessor - WRITE(x); + } - delete_op(y, x->key[i]); - free(y); - return; - } - free(y); - - node z = READ(x, i+1); - if (z->n >= T) { // case 2b - x->key[i] = z->key[0]; - WRITE(x); - delete_op(z, x->key[i]); - return; - } - free(z); + /** + * recursive deletion. + */ + void delete_op(node x, int32_t k) { + int32_t i; + if (x->n == 0) { // emtpy node + return; + } + + i = x->n - 1; + while (i>=0 && k < x->key[i]) { // search the key. + i = i - 1; + } - // case 2c: - if (y->n == T-1 && z->n == T-1) { - // merge k & z into y - y->key[y->n] = k; - + if (x->key[i] == k) { // key in this node. + if (x->flag & LEAF) { // if it's a leaf node. case 1. int j; - for (j=0;jn;j++) { // merge n keys, k already in - y->key[y->n+j+1] = z->key[j]; + for (j = i;jn-1;j++) { // shift copy + x->key[j] = x->key[j+1]; } - for (j=0;jn+1;j++) { // merge n+1 childs - y->c[y->n+j+1] = z->key[j]; + WRITE(x); + return; + } else { // in non-leaf node + node y, z; + if (i-1 >= 0) { // case 2a + y = READ(x, i-1); + std::auto_ptr _y(y); + if (y->n >= T) { + x->key[i] = y->key[y->n-1]; + WRITE(x); + delete_op(y, x->key[i]); + return; + } } - // mark free this node - z->flag |= MARKFREE; - y->n = y->n + z->n + 1; // size after merge - WRITE(z); - WRITE(y); - - // shift x - for (j=i;jn-1;j++) { - x->key[i] = x->key[i+1]; + + if (i+1 < x->n) { // case 2b + z = READ(x, i+1); + std::auto_ptr _z(z); + if (z->n >= T) { + x->key[i] = z->key[0]; + WRITE(x); + delete_op(z, x->key[i]); + return; + } + } + + if (y->n == T-1 && z->n == T-1) { // case 2c + // merge k & z into y + y->key[y->n] = k; + + int j; + for (j=0;jn;j++) { // merge n keys, k already in + y->key[y->n+j+1] = z->key[j]; + } + for (j=0;jn+1;j++) { // merge n+1 childs + y->c[y->n+j+1] = z->key[j]; + } + // mark free this node + z->flag |= MARKFREE; + y->n = y->n + z->n + 1; // size after merge + WRITE(z); + WRITE(y); + + // shift x + for (j=i;jn-1;j++) { + x->key[i] = x->key[i+1]; + } + x->n = x->n - 1; + WRITE(x); + + // recursive delete k + delete_op(y, k); + return; } - x->n = x->n - 1; - WRITE(x); - // recursive delete k - delete_op(y, k); - return; } + } else { // case 3 + i = i+1; // child to search + std::auto_ptr ci(READ(x, i)); + + if (ci->n == T-1) { // case 3a. + if (i-1>=0) { + std::auto_ptr left(READ(x, i-1)); // left sibling + if (left->n > T) { + int j; + for (j=ci->n-2;j>=0;j++) { // right shift ci keys + ci->key[j+1] = ci->key[j]; + } + + for (j=ci->n-1;j>=0;j++) { // right shift ci childs + ci->c[j+1] = ci->c[j]; + } + ci->n = ci->n+1; + ci->key[0] = x->key[i]; // copy key from x[i] to ci[0] + ci->c[0] = left->c[left->n]; // copy child pointer from left last child + x->key[i] = left->key[left->n-1]; // copy from left last key + left->n = left->n-1; // decrease left num keys + + WRITE(ci.get()); + WRITE(x); + WRITE(left.get()); + delete_op(ci.get(), k); + } + } + + if (i+1n) { + std::auto_ptr right(READ(x, i+1)); // right sibling + if (right->n > T) { + ci->key[ci->n-1] = x->key[i]; + ci->c[ci->n] = right->c[0]; + ci->n = ci->n+1; + x->key[i] = right->key[0]; - delete_case3(x); + int j; + for (j=0;jn-1;j++) { // left shift sibling keys + right->key[j] = right->key[j+1]; + } + + for (j=0;jn;j++) { // left shift ci childs + right->c[j] = right->c[j+1]; + } + + WRITE(ci.get()); + WRITE(x); + WRITE(right.get()); + delete_op(ci.get(), k); + } + } + } } + + return; + } + + + /** + * Read a 4K-block from disk, and returns the node struct. + */ + node READ(node x, int32_t i) { + void *xi = allocate_node(); + lseek(fd, x->c[i], SEEK_SET); + read(fd, xi, BLOCKSIZE); + return (node)xi; } - } - - /** - * delete case3 - */ - void delete_case3(node x) { - } - - /** - * Read a 4K-block from disk, and returns the node struct. - */ - node READ(node x, int32_t i) { - void *xi = allocate_node(); - 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); + + /** + * 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); } - x->flag |= ONDISK; - write(fd, x, BLOCKSIZE); - } }; } #endif // From aac5c9a2ebeb257c096f15cd7419a6b01fa11791 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 19 Oct 2013 23:06:54 +0800 Subject: [PATCH 059/217] updating btree delete --- include/btree.h | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/include/btree.h b/include/btree.h index 5cd1759a..ced3baf9 100644 --- a/include/btree.h +++ b/include/btree.h @@ -240,27 +240,20 @@ namespace alg { WRITE(x); return; } else { // in non-leaf node - node y, z; - if (i-1 >= 0) { // case 2a - y = READ(x, i-1); - std::auto_ptr _y(y); - if (y->n >= T) { - x->key[i] = y->key[y->n-1]; - WRITE(x); - delete_op(y, x->key[i]); - return; - } + std::auto_ptr y(READ(x, i)); + if (y->n >= T) { // case 2a. + x->key[i] = y->key[y->n-1]; + WRITE(x); + delete_op(y.get(), x->key[i]); + return; } - if (i+1 < x->n) { // case 2b - z = READ(x, i+1); - std::auto_ptr _z(z); - if (z->n >= T) { - x->key[i] = z->key[0]; - WRITE(x); - delete_op(z, x->key[i]); - return; - } + std::auto_ptr z(READ(x, i+1)); + if (z->n >= T) { // case 2b. + x->key[i] = z->key[0]; + WRITE(x); + delete_op(z.get(), x->key[i]); + return; } if (y->n == T-1 && z->n == T-1) { // case 2c @@ -277,8 +270,8 @@ namespace alg { // mark free this node z->flag |= MARKFREE; y->n = y->n + z->n + 1; // size after merge - WRITE(z); - WRITE(y); + WRITE(z.get()); + WRITE(y.get()); // shift x for (j=i;jn-1;j++) { @@ -288,7 +281,7 @@ namespace alg { WRITE(x); // recursive delete k - delete_op(y, k); + delete_op(y.get(), k); return; } From 0e6e367667657e69ea97d1d0b0eac40afa5eb83e Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 09:54:03 +0800 Subject: [PATCH 060/217] update btree, case 3 --- include/btree.h | 156 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 108 insertions(+), 48 deletions(-) diff --git a/include/btree.h b/include/btree.h index ced3baf9..6d974fb9 100644 --- a/include/btree.h +++ b/include/btree.h @@ -225,7 +225,7 @@ namespace alg { if (x->n == 0) { // emtpy node return; } - + i = x->n - 1; while (i>=0 && k < x->key[i]) { // search the key. i = i - 1; @@ -289,59 +289,119 @@ namespace alg { } else { // case 3 i = i+1; // child to search std::auto_ptr ci(READ(x, i)); - - if (ci->n == T-1) { // case 3a. - if (i-1>=0) { - std::auto_ptr left(READ(x, i-1)); // left sibling - if (left->n > T) { - int j; - for (j=ci->n-2;j>=0;j++) { // right shift ci keys - ci->key[j+1] = ci->key[j]; - } - - for (j=ci->n-1;j>=0;j++) { // right shift ci childs - ci->c[j+1] = ci->c[j]; - } - ci->n = ci->n+1; - ci->key[0] = x->key[i]; // copy key from x[i] to ci[0] - ci->c[0] = left->c[left->n]; // copy child pointer from left last child - x->key[i] = left->key[left->n-1]; // copy from left last key - left->n = left->n-1; // decrease left num keys - - WRITE(ci.get()); - WRITE(x); - WRITE(left.get()); - delete_op(ci.get(), k); + + // case 3a. left sibling + if (ci->n == T-1) { + std::auto_ptr left(READ(x, i-1)); + if (i-1>=0 && left->n > T) { + int j; + for (j=ci->n-2;j>=0;j++) { // right shift ci keys + ci->key[j+1] = ci->key[j]; + } + + for (j=ci->n-1;j>=0;j++) { // right shift ci childs + ci->c[j+1] = ci->c[j]; + } + ci->n = ci->n+1; + ci->key[0] = x->key[i]; // copy key from x[i] to ci[0] + ci->c[0] = left->c[left->n]; // copy child pointer from left last child + x->key[i] = left->key[left->n-1]; // copy from left last key + left->n = left->n-1; // decrease left num keys + + 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+1n && right->n > T) { + ci->key[ci->n-1] = x->key[i]; + ci->c[ci->n] = right->c[0]; + ci->n = ci->n+1; + x->key[i] = right->key[0]; + + int j; + for (j=0;jn-1;j++) { // left shift sibling keys + right->key[j] = right->key[j+1]; + } + + for (j=0;jn;j++) { // left shift ci childs + right->c[j] = right->c[j+1]; } + + WRITE(ci.get()); + WRITE(x); + WRITE(right.get()); + delete_op(ci.get(), k); + return; } - - if (i+1n) { - std::auto_ptr right(READ(x, i+1)); // right sibling - if (right->n > T) { - ci->key[ci->n-1] = x->key[i]; - ci->c[ci->n] = right->c[0]; - ci->n = ci->n+1; - x->key[i] = right->key[0]; - - int j; - for (j=0;jn-1;j++) { // left shift sibling keys - right->key[j] = right->key[j+1]; - } - - for (j=0;jn;j++) { // left shift ci childs - right->c[j] = right->c[j+1]; - } - - WRITE(ci.get()); - WRITE(x); - WRITE(right.get()); - delete_op(ci.get(), k); + + // case 3b. + if (left->n == T-1) { + // copy x[i] to left + left->key[left->n] = x->key[i]; + left->n = left->n + 1; + + // shift x + int j; + for (j=i;jn-1;j++) { + x->key[j] = x->key[j+1]; + } + + for (j=i+1;jn;j++) { // always overwrite right child + x->c[j] = x->c[j+1]; + } + + // append ci into left sibling + for (j=0;jn;j++) { + left->key[j+left->n] = ci->key[j]; + } + + for (j=0;jn+1;j++) { + left->c[j+left->n] = ci->c[j]; + } + left->n += ci->n; // left became 2T-1 + ci->flag |= MARKFREE; // free ci + WRITE(ci.get()); + WRITE(x); + WRITE(left.get()); + delete_op(left.get(), k); + } else { + // copy x[i] to ci + ci->key[ci->n] = x->key[i]; + ci->n = ci->n + 1; + + // shift x + int j; + for (j=i;jn-1;j++) { + x->key[j] = x->key[j+1]; + } + + for (j=i+1;jn;j++) { // always overwrite right child + x->c[j] = x->c[j+1]; } + + // append right sibling into ci + 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]; + } + right->flag |= MARKFREE; + WRITE(ci.get()); + WRITE(x); + WRITE(right.get()); + delete_op(ci.get(),k); } } - } - return; + return; + } } From 7ea936f3eef867e6366b6a159c67f3cdd2075322 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 12:46:00 +0800 Subject: [PATCH 061/217] add comment for btree --- include/btree.h | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/include/btree.h b/include/btree.h index 6d974fb9..50be2ccf 100644 --- a/include/btree.h +++ b/include/btree.h @@ -231,32 +231,52 @@ namespace alg { i = i - 1; } - if (x->key[i] == k) { // key in this node. - if (x->flag & LEAF) { // if it's a leaf node. case 1. + if (x->key[i] == k) { // key exists in this node. + // case 1. + // If the key k is in node x and x is a leaf, delete the key k from x. + if (x->flag & LEAF) { int j; - for (j = i;jn-1;j++) { // shift copy + for (j = i;jn-1;j++) { // shifting the keys. x->key[j] = x->key[j+1]; } WRITE(x); return; - } else { // in non-leaf node + } else { + // 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) { // case 2a. - x->key[i] = y->key[y->n-1]; + if (y->n >= T) { + int32_t k0 = y->key[y->n-1]; + x->key[i] = k0; WRITE(x); - delete_op(y.get(), x->key[i]); + 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) { // case 2b. - x->key[i] = z->key[0]; + if (z->n >= T) { + int32_t k0 = z->key[0]; + x->key[i] = k0; WRITE(x); - delete_op(z.get(), x->key[i]); + delete_op(z.get(), k0); return; } - if (y->n == T-1 && z->n == T-1) { // case 2c + // case 2c: + // Otherwise, if both y and ´ have only t 2 1 keys, + // merge k and all of ´ into y, so that x loses both k and the + // pointer to ´, and y now contains 2t c 1 keys. + // Then free ´ and recursively delete k from y. + if (y->n == T-1 && z->n == T-1) { // merge k & z into y y->key[y->n] = k; From 70e568820bacef8b6dbfadc9c0b5a07583b5b374 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 12:51:58 +0800 Subject: [PATCH 062/217] check btree --- include/btree.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/include/btree.h b/include/btree.h index 50be2ccf..55135273 100644 --- a/include/btree.h +++ b/include/btree.h @@ -272,31 +272,35 @@ namespace alg { } // case 2c: - // Otherwise, if both y and ´ have only t 2 1 keys, - // merge k and all of ´ into y, so that x loses both k and the - // pointer to ´, and y now contains 2t c 1 keys. - // Then free ´ and recursively delete k from y. + // 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) { // merge k & z into y y->key[y->n] = k; int j; - for (j=0;jn;j++) { // merge n keys, k already in + for (j=0;jn;j++) { // merge keys of z y->key[y->n+j+1] = z->key[j]; } - for (j=0;jn+1;j++) { // merge n+1 childs - y->c[y->n+j+1] = z->key[j]; + for (j=0;jn+1;j++) { // merge childs of z + y->c[y->n+j+1] = z->c[j]; } - // mark free this node + + // mark free z z->flag |= MARKFREE; y->n = y->n + z->n + 1; // size after merge WRITE(z.get()); WRITE(y.get()); - // shift x - for (j=i;jn-1;j++) { + for (j=i;jn-1;j++) { // delete k from node x x->key[i] = x->key[i+1]; } + + for (j=i+1;jn;j++){ // delete pointer to z --> (i+1)th + x->c[i] = x->c[i+1]; + } x->n = x->n - 1; WRITE(x); From 502da5fb276f8e079c92ce8c73180e5a32c281a5 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 14:30:50 +0800 Subject: [PATCH 063/217] adding comment --- include/btree.h | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/include/btree.h b/include/btree.h index 55135273..974c8dca 100644 --- a/include/btree.h +++ b/include/btree.h @@ -232,9 +232,9 @@ namespace alg { } if (x->key[i] == k) { // key exists in this node. - // case 1. - // If the key k is in node x and x is a leaf, delete the key k from x. if (x->flag & LEAF) { + // case 1. + // If the key k is in node x and x is a leaf, delete the key k from x. int j; for (j = i;jn-1;j++) { // shifting the keys. x->key[j] = x->key[j+1]; @@ -310,27 +310,33 @@ namespace alg { } } - } else { // case 3 - i = i+1; // child to search + } else { + i = i+1; // child ci std::auto_ptr ci(READ(x, i)); - // case 3a. left sibling + // 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]. if (ci->n == T-1) { std::auto_ptr left(READ(x, i-1)); if (i-1>=0 && left->n > T) { + // 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-2;j>=0;j++) { // right shift ci keys - ci->key[j+1] = ci->key[j]; + for (j=ci->n-1;j>0;j++) { + ci->key[j] = ci->key[j-1]; } - for (j=ci->n-1;j>=0;j++) { // right shift ci childs - ci->c[j+1] = ci->c[j]; + 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]; // copy key from x[i] to ci[0] - ci->c[0] = left->c[left->n]; // copy child pointer from left last child - x->key[i] = left->key[left->n-1]; // copy from left last key - left->n = left->n-1; // decrease left num keys + ci->key[0] = x->key[i]; // copy key from x[i] 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); @@ -342,24 +348,25 @@ namespace alg { // case 3a. right sibling std::auto_ptr right(READ(x, i+1)); if (i+1n && right->n > T) { - ci->key[ci->n-1] = x->key[i]; - ci->c[ci->n] = right->c[0]; + 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]; + x->key[i] = right->key[0]; // subsitute key in x int j; - for (j=0;jn-1;j++) { // left shift sibling keys + for (j=0;jn-1;j++) { // remove key[0] from right sibling right->key[j] = right->key[j+1]; } - for (j=0;jn;j++) { // left shift ci childs + 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); + delete_op(ci.get(), k); // recursive delete key in x.c[i] return; } From d4da5f1596b234bb2c3e12e313794c0edcd9fa35 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 14:52:18 +0800 Subject: [PATCH 064/217] add comments --- include/btree.h | 54 +++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/include/btree.h b/include/btree.h index 974c8dca..4e999394 100644 --- a/include/btree.h +++ b/include/btree.h @@ -371,24 +371,30 @@ namespace alg { } // case 3b. - if (left->n == T-1) { + // 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 (left->n == T-1 && right->n == T-1) { // copy x[i] to left left->key[left->n] = x->key[i]; left->n = left->n + 1; - - // shift x + + // remove key[i] from x and also the child int j; for (j=i;jn-1;j++) { x->key[j] = x->key[j+1]; } - for (j=i+1;jn;j++) { // always overwrite right child + for (j=i;jn;j++) { x->c[j] = x->c[j+1]; } - // append ci into left sibling + // point child-0 to left + x->c[0] = left->offset; + + // append x.c[i] into left sibling for (j=0;jn;j++) { - left->key[j+left->n] = ci->key[j]; + left->key[left->n + j] = ci->key[j]; } for (j=0;jn+1;j++) { @@ -398,36 +404,18 @@ namespace alg { ci->flag |= MARKFREE; // free ci WRITE(ci.get()); WRITE(x); - WRITE(left.get()); - delete_op(left.get(), k); - } else { - // copy x[i] to ci - ci->key[ci->n] = x->key[i]; - ci->n = ci->n + 1; - // shift x - int j; - for (j=i;jn-1;j++) { - x->key[j] = x->key[j+1]; - } - - for (j=i+1;jn;j++) { // always overwrite right child - x->c[j] = x->c[j+1]; - } - - // append right sibling into ci - for (j=0;jn;j++) { - ci->key[ci->n+j] = right->key[j]; + // root check + if (x->n == 0) { + m_root = left.get(); // free the old block , and + left->flag |= MARKFREE; // make root the first block of the file + WRITE(left.get()); + left->flag &= ~MARKFREE; + left->offset = 0; } - for (j=0;jn+1;j++) { - ci->c[ci->n+j] = right->c[j]; - } - right->flag |= MARKFREE; - WRITE(ci.get()); - WRITE(x); - WRITE(right.get()); - delete_op(ci.get(),k); + WRITE(left.get()); + delete_op(left.get(), k); } } From f7b646b49ff7b608c8519b64b0c7429a29ec2483 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 16:55:25 +0800 Subject: [PATCH 065/217] tmp save --- README.md | 1 + include/btree.h | 177 ++++++++++++++++++++++++++++++++------------- src/btree_demo.cpp | 7 +- 3 files changed, 133 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 6e11c789..d7536a4f 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ 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 ####已实现 ( Implemented ): diff --git a/include/btree.h b/include/btree.h index 4e999394..c7069c92 100644 --- a/include/btree.h +++ b/include/btree.h @@ -21,6 +21,8 @@ #ifndef __BTREE_H__ #define __BTREE_H__ +#include +#include #include #include #include @@ -107,7 +109,6 @@ namespace alg { } void DeleteKey(int32_t k) { - node x = m_root; delete_op(m_root, k); } @@ -240,6 +241,7 @@ namespace alg { x->key[j] = x->key[j+1]; } WRITE(x); + printf("case1"); return; } else { // case 2a: @@ -249,13 +251,14 @@ namespace alg { // (We can find k0 and delete it in a single downward pass.) std::auto_ptr y(READ(x, i)); if (y->n >= T) { + printf("case2a"); int32_t k0 = y->key[y->n-1]; 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, @@ -264,6 +267,7 @@ namespace alg { // and delete it in a single downward pass.) std::auto_ptr z(READ(x, i+1)); if (z->n >= T) { + printf("case2b"); int32_t k0 = z->key[0]; x->key[i] = k0; WRITE(x); @@ -277,6 +281,7 @@ namespace alg { // 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; @@ -308,6 +313,7 @@ namespace alg { delete_op(y.get(), k); return; } + printf("other in case2"); } } else { @@ -321,15 +327,17 @@ namespace alg { // appropriate child pointer from the sibling into x.c[i]. if (ci->n == T-1) { std::auto_ptr left(READ(x, i-1)); - if (i-1>=0 && left->n > T) { + printf("case 3a: %d %d\n", left->n, 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++) { + for (j=ci->n-1;j>0;j--) { ci->key[j] = ci->key[j-1]; } - for (j=ci->n;j>0;j++) { + for (j=ci->n;j>0;j--) { ci->c[j] = ci->c[j-1]; } ci->n = ci->n+1; @@ -347,7 +355,9 @@ namespace alg { // case 3a. right sibling std::auto_ptr right(READ(x, i+1)); - if (i+1n && right->n > T) { + printf("case 3a-r: %d %d\n", right->n, 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; @@ -374,63 +384,128 @@ namespace alg { // 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 (left->n == T-1 && right->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 - int j; - for (j=i;jn-1;j++) { - x->key[j] = x->key[j+1]; - } - - for (j=i;jn;j++) { - x->c[j] = x->c[j+1]; + if ((i-1<0 ||left->n == T-1) && (i+1 <=x->n || right->n == T-1)) { + std::cerr << "case3b in"; + if (left->n == T-1) { + std::cerr<<"case3b, left"; + // 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 + int j; + for (j=i;jn-1;j++) { + x->key[j] = x->key[j+1]; + } + + for (j=i;jn;j++) { + x->c[j] = x->c[j+1]; + } + x->n = x->n - 1; + x->c[0] = left->offset; + + // 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 + WRITE(ci.get()); + WRITE(x); + + // root check + if (x->n == 0 && x == m_root) { + left->flag |= MARKFREE; + WRITE(left.get()); + left->flag &= ~MARKFREE; + left->offset = 0; // set to the first block + WRITE(left.get()); + free(m_root); + m_root = DUP(left.get()); + } else { + WRITE(left.get()); + } + + delete_op(left.get(), k); + return; + } else if (right->n == T-1) { + std::cerr<<"case3b, right"; + // copy x[i] to x.c[i] + ci->key[x->n] = x->key[i]; + ci->n = x->n + 1; + + // remove key[i] from x and also the child + // shrink the size & set the child-0 to ci + int j; + for (j=i;jn-1;j++) { + x->key[j] = x->key[j+1]; + } + + for (j=i;jn;j++) { + x->c[j] = x->c[j+1]; + } + x->n = x->n - 1; + x->c[0] = ci->offset; + + // 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 + WRITE(right.get()); + WRITE(x); + + // root check, + // free the old block , and make root the first block of the file + if (x->n == 0 && x == m_root) { + ci->flag |= MARKFREE; + WRITE(ci.get()); + ci->flag &= ~MARKFREE; + ci->offset = 0; + WRITE(ci.get()); + free(m_root); + m_root = DUP(ci.get()); + } else { + WRITE(ci.get()); + } + + delete_op(ci.get(), k); + return; } - - // point child-0 to left - x->c[0] = left->offset; - - // 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[j+left->n] = ci->c[j]; - } - left->n += ci->n; // left became 2T-1 - ci->flag |= MARKFREE; // free ci - WRITE(ci.get()); - WRITE(x); - - // root check - if (x->n == 0) { - m_root = left.get(); // free the old block , and - left->flag |= MARKFREE; // make root the first block of the file - WRITE(left.get()); - left->flag &= ~MARKFREE; - left->offset = 0; - } - - WRITE(left.get()); - delete_op(left.get(), k); } } - - return; } } + /** + * duplicate the node + */ + node DUP(node x) { + void *n = allocate_node(); + memcpy(n, x, BLOCKSIZE); + return (node)n; + } + /** * Read a 4K-block from disk, and returns the node struct. */ node READ(node x, int32_t i) { void *xi = allocate_node(); - lseek(fd, x->c[i], SEEK_SET); - read(fd, xi, BLOCKSIZE); + if (i >=0 || i <= x->n) { + lseek(fd, x->c[i], SEEK_SET); + read(fd, xi, BLOCKSIZE); + } return (node)xi; } diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 7cade81f..df8553cd 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -9,6 +9,11 @@ int main(void) { for (i=0;i<100000;i++) { x.Insert(i); BTree::nr r = x.Search(i); - printf("offset[%x] idx[%d]\n", r.offset, r.idx); + } + + for (i=0;i<100000;i++) { + x.DeleteKey(i); + BTree::nr r = x.Search(i); + printf("key[%d] offset[%x] idx[%d]\n", i, r.offset, r.idx); } } From e62428bbdc877a2deda2beef4c75aae4ee736c68 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 20:55:36 +0800 Subject: [PATCH 066/217] debug btree --- include/btree.h | 454 ++++++++++++++++++++++----------------------- src/btree_demo.cpp | 1 - 2 files changed, 225 insertions(+), 230 deletions(-) diff --git a/include/btree.h b/include/btree.h index c7069c92..d54b7d6f 100644 --- a/include/btree.h +++ b/include/btree.h @@ -58,7 +58,6 @@ namespace alg { int32_t idx; }; private: - node m_root; int fd; private: BTree(const BTree &); @@ -74,7 +73,6 @@ namespace alg { x->flag |= LEAF; WRITE(x); } - m_root = (node)x; } ~BTree() { @@ -82,26 +80,24 @@ namespace alg { } nr Search(int32_t x) { - return search(m_root, x); + node root = ROOT(); + return search(root, x); } void Insert(int32_t k) { - node r = m_root; + node r = ROOT(); if (r->n == 2*T - 1) { // place the old root node to the end of the file - m_root->flag &= ~ONDISK; - WRITE(m_root); + r->flag &= ~ONDISK; + WRITE(r); // new root node s = (node)allocate_node(); s->flag &= ~LEAF; s->flag |= ONDISK; // write to offset 0 s->offset = 0; s->n = 0; - s->c[0] = m_root->offset; - // free old & set new - free(m_root); - m_root = s; - split_child(s, 0); + s->c[0] = r->offset; + split_child(s, 0); // split_child with write s insert_nonfull(s, k); } else { insert_nonfull(r, k); @@ -109,7 +105,8 @@ namespace alg { } void DeleteKey(int32_t k) { - delete_op(m_root, k); + node root = ROOT(); + delete_op(root, k); } private: @@ -124,6 +121,12 @@ namespace alg { if (in && k == x->key[i]) { // search in [0,n-1] ret.offset = x->offset; ret.idx = i; + /* + int t; + for (t=0;tn;t++) { + printf("%d ",x->key[t]); + } + */ return ret; } else if (x->flag & LEAF) { // leaf, no more childs ret.offset = 0; @@ -163,7 +166,7 @@ namespace alg { xi = READ(x, i); } insert_nonfull(xi, k); - free(xi); + delete xi; } } @@ -171,7 +174,7 @@ namespace alg { * allocate empty node struct */ void * allocate_node() { - node x = (node)malloc(sizeof(node_t)); + node x = new node_t; x->n = 0; x->offset = 0; x->flag = 0; @@ -232,7 +235,8 @@ namespace alg { i = i - 1; } - if (x->key[i] == k) { // key exists in this node. + if (i >= 0 && x->key[i] == k) { // key exists in this node. + printf("in case 1 & 2 [%d] [%d]\n", i,x->n); if (x->flag & LEAF) { // case 1. // If the key k is in node x and x is a leaf, delete the key k from x. @@ -241,249 +245,231 @@ namespace alg { x->key[j] = x->key[j+1]; } WRITE(x); - printf("case1"); + printf("deleted %d offset %x\n", k, x); return; } else { - // 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) { - printf("case2a"); - int32_t k0 = y->key[y->n-1]; - x->key[i] = k0; - WRITE(x); - delete_op(y.get(), k0); - return; - } + case2(x, i, k); + } + } else { + // case 3. on x.c[i+1] + case3(x, i+1, k); + } + } - // 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) { - printf("case2b"); - int32_t k0 = z->key[0]; - x->key[i] = k0; - WRITE(x); - delete_op(z.get(), k0); - return; - } + 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; + printf("key[i] %d\n", k0, x->key[i]); + WRITE(x); + delete_op(y.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; + // 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; + } - int j; - for (j=0;jn;j++) { // merge keys of z - y->key[y->n+j+1] = z->key[j]; - } - for (j=0;jn+1;j++) { // merge childs of z - y->c[y->n+j+1] = z->c[j]; - } + // 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+j+1] = z->key[j]; + } + for (j=0;jn+1;j++) { // merge childs of z + y->c[y->n+j+1] = 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()); + // 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[i] = x->key[i+1]; - } + for (j=i;jn-1;j++) { // delete k from node x + x->key[i] = x->key[i+1]; + } - for (j=i+1;jn;j++){ // delete pointer to z --> (i+1)th - x->c[i] = x->c[i+1]; - } - x->n = x->n - 1; - WRITE(x); + for (j=i+1;jn;j++){ // delete pointer to z --> (i+1)th + x->c[i] = x->c[i+1]; + } + x->n = x->n - 1; + WRITE(x); - // recursive delete k - delete_op(y.get(), k); - return; + // recursive delete k + delete_op(y.get(), k); + return; + } + printf("other in case2"); + } + + void case3(node x, int32_t i, int32_t k) { + std::auto_ptr ci(READ(x, i)); + // 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]. + if (ci->n == T-1) { + 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]; } - printf("other in case2"); + 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; } - } else { - i = i+1; // child ci - std::auto_ptr ci(READ(x, i)); - - // 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]. - if (ci->n == T-1) { - std::auto_ptr left(READ(x, i-1)); - printf("case 3a: %d %d\n", left->n, 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 + + // 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)) { + std::cerr << "case3b in"; + if (left->n == T-1) { + std::cerr<<"case3b, left"; + // 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 int j; - for (j=ci->n-1;j>0;j--) { - ci->key[j] = ci->key[j-1]; + for (j=i;jn-1;j++) { + x->key[j] = x->key[j+1]; } - for (j=ci->n;j>0;j--) { - ci->c[j] = ci->c[j-1]; + for (j=i;jn;j++) { + x->c[j] = x->c[j+1]; } - ci->n = ci->n+1; - ci->key[0] = x->key[i]; // copy key from x[i] 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 + x->n = x->n - 1; + x->c[0] = left->offset; + // 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 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)); - printf("case 3a-r: %d %d\n", right->n, 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 + delete_op(left.get(), k); + return; + } else if (right->n == T-1) { + std::cerr<<"case3b, right"; + // copy x[i] to x.c[i] + ci->key[x->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 int j; - for (j=0;jn-1;j++) { // remove key[0] from right sibling - right->key[j] = right->key[j+1]; + for (j=i;jn-1;j++) { + x->key[j] = x->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]; + for (j=i;jn;j++) { + x->c[j] = x->c[j+1]; } - right->n = right->n - 1; // reduce the size of the right sibling. + x->n = x->n - 1; + x->c[i] = ci->offset; - WRITE(ci.get()); - WRITE(x); - WRITE(right.get()); - delete_op(ci.get(), k); // recursive delete key in x.c[i] - return; - } + // append right sibling into x.c[i] + for (j=0;jn;j++) { + ci->key[ci->n + j] =right->key[j]; + } - // 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)) { - std::cerr << "case3b in"; - if (left->n == T-1) { - std::cerr<<"case3b, left"; - // 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 - int j; - for (j=i;jn-1;j++) { - x->key[j] = x->key[j+1]; - } - - for (j=i;jn;j++) { - x->c[j] = x->c[j+1]; - } - x->n = x->n - 1; - x->c[0] = left->offset; - - // 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 - WRITE(ci.get()); - WRITE(x); - - // root check - if (x->n == 0 && x == m_root) { - left->flag |= MARKFREE; - WRITE(left.get()); - left->flag &= ~MARKFREE; - left->offset = 0; // set to the first block - WRITE(left.get()); - free(m_root); - m_root = DUP(left.get()); - } else { - WRITE(left.get()); - } - - delete_op(left.get(), k); - return; - } else if (right->n == T-1) { - std::cerr<<"case3b, right"; - // copy x[i] to x.c[i] - ci->key[x->n] = x->key[i]; - ci->n = x->n + 1; - - // remove key[i] from x and also the child - // shrink the size & set the child-0 to ci - int j; - for (j=i;jn-1;j++) { - x->key[j] = x->key[j+1]; - } - - for (j=i;jn;j++) { - x->c[j] = x->c[j+1]; - } - x->n = x->n - 1; - x->c[0] = ci->offset; - - // 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 - WRITE(right.get()); - WRITE(x); - - // root check, - // free the old block , and make root the first block of the file - if (x->n == 0 && x == m_root) { - ci->flag |= MARKFREE; - WRITE(ci.get()); - ci->flag &= ~MARKFREE; - ci->offset = 0; - WRITE(ci.get()); - free(m_root); - m_root = DUP(ci.get()); - } else { - WRITE(ci.get()); - } - - delete_op(ci.get(), k); - return; + 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 + WRITE(right.get()); + WRITE(x); + WRITE(ci.get()); + delete_op(ci.get(), k); + return; } } + } else { + int t; + printf("key[%d]\n",k); + delete_op(ci.get(), k); } } @@ -497,12 +483,22 @@ namespace alg { return (node)n; } + /** + * Load the root block + */ + node ROOT() { + void *root = allocate_node(); + 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 = allocate_node(); - if (i >=0 || i <= x->n) { + if (i >=0 && i <= x->n) { lseek(fd, x->c[i], SEEK_SET); read(fd, xi, BLOCKSIZE); } diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index df8553cd..4f6e36cb 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -8,7 +8,6 @@ int main(void) { for (i=0;i<100000;i++) { x.Insert(i); - BTree::nr r = x.Search(i); } for (i=0;i<100000;i++) { From d0e4d7fe990150907c339a77a5a58be0a539e0c4 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 20 Oct 2013 23:00:11 +0800 Subject: [PATCH 067/217] finish test with btree. --- include/btree.h | 83 +++++++++++++++++++++++++++------------------- src/btree_demo.cpp | 4 +-- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/include/btree.h b/include/btree.h index d54b7d6f..c2dc307b 100644 --- a/include/btree.h +++ b/include/btree.h @@ -226,6 +226,15 @@ namespace alg { */ 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; } @@ -234,20 +243,13 @@ namespace alg { 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. - printf("in case 1 & 2 [%d] [%d]\n", i,x->n); if (x->flag & LEAF) { - // case 1. - // If the key k is in node x and x is a leaf, delete the key k from x. - int j; - for (j = i;jn-1;j++) { // shifting the keys. - x->key[j] = x->key[j+1]; - } - WRITE(x); - printf("deleted %d offset %x\n", k, x); - return; + 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 { @@ -256,6 +258,17 @@ namespace alg { } } + void case1(node x, int32_t i, int32_t k) { + // case 1. + // If the key k is in node x and x is a leaf, delete the key k from x. + int j; + for (j = i;jn-1;j++) { // shifting the keys. + 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 @@ -301,10 +314,10 @@ namespace alg { int j; for (j=0;jn;j++) { // merge keys of z - y->key[y->n+j+1] = z->key[j]; + y->key[y->n+1+j] = z->key[j]; } for (j=0;jn+1;j++) { // merge childs of z - y->c[y->n+j+1] = z->c[j]; + y->c[y->n+1+j] = z->c[j]; } // mark free z @@ -314,11 +327,11 @@ namespace alg { WRITE(y.get()); for (j=i;jn-1;j++) { // delete k from node x - x->key[i] = x->key[i+1]; + x->key[j] = x->key[j+1]; } for (j=i+1;jn;j++){ // delete pointer to z --> (i+1)th - x->c[i] = x->c[i+1]; + x->c[j] = x->c[j+1]; } x->n = x->n - 1; WRITE(x); @@ -332,6 +345,7 @@ namespace alg { void case3(node x, int32_t i, int32_t k) { std::auto_ptr ci(READ(x, i)); + // 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 @@ -409,11 +423,10 @@ namespace alg { x->key[j] = x->key[j+1]; } - for (j=i;jn;j++) { + for (j=i+1;jn;j++) { x->c[j] = x->c[j+1]; } x->n = x->n - 1; - x->c[0] = left->offset; // append x.c[i] into left sibling for (j=0;jn;j++) { @@ -425,16 +438,23 @@ namespace alg { } 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) { std::cerr<<"case3b, right"; // copy x[i] to x.c[i] - ci->key[x->n] = x->key[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 @@ -443,15 +463,14 @@ namespace alg { x->key[j] = x->key[j+1]; } - for (j=i;jn;j++) { + for (j=i+1;jn;j++) { x->c[j] = x->c[j+1]; } x->n = x->n - 1; - x->c[i] = ci->offset; // append right sibling into x.c[i] for (j=0;jn;j++) { - ci->key[ci->n + j] =right->key[j]; + ci->key[ci->n + j] = right->key[j]; } for (j=0;jn+1;j++) { @@ -459,30 +478,26 @@ namespace alg { } 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; } } } else { - int t; - printf("key[%d]\n",k); delete_op(ci.get(), k); } } - - /** - * duplicate the node - */ - node DUP(node x) { - void *n = allocate_node(); - memcpy(n, x, BLOCKSIZE); - return (node)n; - } - /** * Load the root block */ diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 4f6e36cb..4a8e22b4 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -6,11 +6,11 @@ int main(void) { BTree x("./btree.dat"); int32_t i; - for (i=0;i<100000;i++) { + for (i=0;i<1000;i++) { x.Insert(i); } - for (i=0;i<100000;i++) { + for (i=0;i<1000;i++) { x.DeleteKey(i); BTree::nr r = x.Search(i); printf("key[%d] offset[%x] idx[%d]\n", i, r.offset, r.idx); From a95d61a3f461d7f7417eb455176971afb889c4fc Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 09:18:21 +0800 Subject: [PATCH 068/217] update btree demo & comments --- include/btree.h | 30 +++++++++++------------------- src/btree_demo.cpp | 5 ++++- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/include/btree.h b/include/btree.h index c2dc307b..586eff52 100644 --- a/include/btree.h +++ b/include/btree.h @@ -22,7 +22,7 @@ #define __BTREE_H__ #include -#include +#include #include #include #include @@ -121,12 +121,6 @@ namespace alg { if (in && k == x->key[i]) { // search in [0,n-1] ret.offset = x->offset; ret.idx = i; - /* - int t; - for (t=0;tn;t++) { - printf("%d ",x->key[t]); - } - */ return ret; } else if (x->flag & LEAF) { // leaf, no more childs ret.offset = 0; @@ -246,10 +240,10 @@ namespace alg { 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); + //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); + //printf("in case 2 [%d] [%d]\n", i,x->n); case2(x, i, k); } } else { @@ -278,9 +272,8 @@ namespace alg { 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]); + //printf("case2a %d %d\n", k0, x->key[i]); x->key[i] = k0; - printf("key[i] %d\n", k0, x->key[i]); WRITE(x); delete_op(y.get(), k0); return; @@ -295,7 +288,7 @@ namespace alg { 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]); + //printf("case2b %d %d\n", k0, x->key[i]); x->key[i] = k0; WRITE(x); delete_op(z.get(), k0); @@ -308,7 +301,7 @@ namespace alg { // 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"); + //printf("case2c"); // merge k & z into y y->key[y->n] = k; @@ -340,7 +333,9 @@ namespace alg { delete_op(y.get(), k); return; } - printf("other in case2"); + + // cannot reach here + assert(false); } void case3(node x, int32_t i, int32_t k) { @@ -354,7 +349,7 @@ namespace alg { if (ci->n == T-1) { std::auto_ptr left(READ(x, i-1)); if (i-1>=0 && left->n >= T) { - printf("case3a, left"); + // printf("case3a, left"); // right shift keys and childs of x.c[i] to make place for a key // right shift ci childs int j; @@ -381,7 +376,7 @@ namespace alg { // case 3a. right sibling std::auto_ptr right(READ(x, i+1)); if (i+1<=x->n && right->n >= T) { - printf("case3a, right"); + // 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; @@ -409,9 +404,7 @@ namespace alg { // 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)) { - std::cerr << "case3b in"; if (left->n == T-1) { - std::cerr<<"case3b, left"; // copy x[i] to left left->key[left->n] = x->key[i]; left->n = left->n + 1; @@ -452,7 +445,6 @@ namespace alg { delete_op(left.get(), k); return; } else if (right->n == T-1) { - std::cerr<<"case3b, right"; // copy x[i] to x.c[i] ci->key[ci->n] = x->key[i]; ci->n = ci->n + 1; diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 4a8e22b4..7f692631 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -8,11 +8,14 @@ int main(void) { for (i=0;i<1000;i++) { x.Insert(i); + printf("insert %d\n", i); } for (i=0;i<1000;i++) { x.DeleteKey(i); BTree::nr r = x.Search(i); - printf("key[%d] offset[%x] idx[%d]\n", i, r.offset, r.idx); + if (r.idx == -1) { + printf("key[%d] removed\n", i); + } } } From 94a9b3803f637a834fc5e89fe575cc1d8c465907 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 09:37:31 +0800 Subject: [PATCH 069/217] update btree -- add procedure --- include/btree.h | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/include/btree.h b/include/btree.h index 586eff52..e39751be 100644 --- a/include/btree.h +++ b/include/btree.h @@ -411,16 +411,9 @@ namespace alg { // remove key[i] from x and also the child // shrink the size & set the child-0 to left - 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; + 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]; @@ -450,16 +443,9 @@ namespace alg { ci->n = ci->n + 1; // remove key[i] from x and also the child // shrink the size & set the child-0 to ci - 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; + 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]; @@ -490,6 +476,21 @@ namespace alg { } } + /** + * delete ith node + */ + 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; + } + /** * Load the root block */ From cb8fc2a29468a2de81815effa1b7a8b13363949a Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 09:39:34 +0800 Subject: [PATCH 070/217] update btree --- include/btree.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/btree.h b/include/btree.h index e39751be..104117e7 100644 --- a/include/btree.h +++ b/include/btree.h @@ -340,7 +340,6 @@ namespace alg { void case3(node x, int32_t i, int32_t k) { std::auto_ptr ci(READ(x, i)); - // 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 From f2188b69a6b4afca1fce6043332434050a138e9f Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 11:23:07 +0800 Subject: [PATCH 071/217] change struct name nr -> Res --- include/btree.h | 8 ++++---- src/btree_demo.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/btree.h b/include/btree.h index 104117e7..630911d3 100644 --- a/include/btree.h +++ b/include/btree.h @@ -53,7 +53,7 @@ namespace alg { public: // node and index - struct nr { + struct Res { uint32_t offset; int32_t idx; }; @@ -79,7 +79,7 @@ namespace alg { close(fd); } - nr Search(int32_t x) { + Res Search(int32_t x) { node root = ROOT(); return search(root, x); } @@ -113,9 +113,9 @@ namespace alg { /** * search a key, returns node and index */ - nr search(node x, int32_t k) { + Res search(node x, int32_t k) { int32_t i = 0; - nr ret; + Res ret; while (in && k > x->key[i]) i++; if (in && k == x->key[i]) { // search in [0,n-1] diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 7f692631..36c38c53 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -13,7 +13,7 @@ int main(void) { for (i=0;i<1000;i++) { x.DeleteKey(i); - BTree::nr r = x.Search(i); + BTree::Res r = x.Search(i); if (r.idx == -1) { printf("key[%d] removed\n", i); } From 61fe124701d932ed68656b04ab16c8cd1a7b41e7 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 11:32:09 +0800 Subject: [PATCH 072/217] add comments for btree --- include/btree.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/btree.h b/include/btree.h index 630911d3..df3f10a8 100644 --- a/include/btree.h +++ b/include/btree.h @@ -15,6 +15,12 @@ * 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 ******************************************************************************/ From 9c0d63dcd923a29017d0c12aba7aeab644cd4363 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 13:24:36 +0800 Subject: [PATCH 073/217] update comment --- include/btree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/btree.h b/include/btree.h index df3f10a8..d3888ef9 100644 --- a/include/btree.h +++ b/include/btree.h @@ -133,7 +133,7 @@ namespace alg { ret.idx = -1; return ret; } else { - std::auto_ptr xi(READ(x, i)); // in last child + std::auto_ptr xi(READ(x, i)); // search in a child return search(xi.get(), k); } } From a794d8e0ff4842ff07a0bc416acf0fd92c1ef169 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 13:45:12 +0800 Subject: [PATCH 074/217] refactor btree impl. --- include/btree.h | 275 +++++++++++++++++++++++---------------------- src/btree_demo.cpp | 4 + 2 files changed, 143 insertions(+), 136 deletions(-) diff --git a/include/btree.h b/include/btree.h index d3888ef9..a22c3fbb 100644 --- a/include/btree.h +++ b/include/btree.h @@ -73,7 +73,7 @@ namespace alg { fd = open(path, O_RDWR|O_CREAT, 0640); if (fd == -1) return; - node x = (node)allocate_node(); + node x = (node)ALLOCBLK(); int n = read(fd,x,BLOCKSIZE); if (n != BLOCKSIZE) { // init new btree x->flag |= LEAF; @@ -97,7 +97,7 @@ namespace alg { r->flag &= ~ONDISK; WRITE(r); // new root - node s = (node)allocate_node(); + node s = (node)ALLOCBLK(); s->flag &= ~LEAF; s->flag |= ONDISK; // write to offset 0 s->offset = 0; @@ -143,9 +143,9 @@ namespace alg { */ void insert_nonfull(node x, int32_t k) { int32_t i = x->n-1; - if (x->flag & LEAF) { // insert into leaf - while (i>=0 && k < x->key[i]) { // shift from right to left, when k < key[i] - x->key[i+1] = x->key[i]; + 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; @@ -156,13 +156,14 @@ namespace alg { i = i-1; } i=i+1; - node xi = READ(x, i); + 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; } - // reload x[i] after split_child(will modify child x[i]) + // NOTICE! + // reload x[i] after split_child. xi = READ(x, i); } insert_nonfull(xi, k); @@ -170,24 +171,11 @@ namespace alg { } } - /** - * allocate empty node struct - */ - void * allocate_node() { - 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)); - return x; - } - /** * split a node into 2. */ void split_child(node x, int32_t i) { - std::auto_ptr z((node)allocate_node()); + std::auto_ptr z((node)ALLOCBLK()); std::auto_ptr y(READ(x, i)); z->flag &= ~LEAF; z->flag |= (y->flag & LEAF); @@ -258,11 +246,13 @@ namespace alg { } } + /** + * 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) { - // case 1. - // If the key k is in node x and x is a leaf, delete the key k from x. int j; - for (j = i;jn-1;j++) { // shifting the keys. + 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; @@ -346,138 +336,139 @@ namespace alg { 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]. - if (ci->n == T-1) { - 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 + 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; - for (j=ci->n-1;j>0;j--) { - ci->key[j] = ci->key[j-1]; + // append x.c[i] into left sibling + for (j=0;jn;j++) { + left->key[left->n + j] = ci->key[j]; } - for (j=ci->n;j>0;j--) { - ci->c[j] = ci->c[j-1]; + for (j=0;jn+1;j++) { + left->c[left->n + j] = ci->c[j]; } - 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 - + 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(ci.get(), k); + delete_op(left.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 + } 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; - for (j=0;jn-1;j++) { // remove key[0] from right sibling - right->key[j] = right->key[j+1]; + // append right sibling into x.c[i] + for (j=0;jn;j++) { + ci->key[ci->n + j] = right->key[j]; } - for (j=0;jn;j++) { // and also the child c[0] of the right sibling. - right->c[j] = right->c[j+1]; + for (j=0;jn+1;j++) { + ci->c[ci->n + j] = right->c[j]; } - right->n = right->n - 1; // reduce the size of the right sibling. - - WRITE(ci.get()); - WRITE(x); + ci->n += right->n; // ci became 2T-1 + right->flag |= MARKFREE; // free right + right->n = 0; 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(x); + // root check + if (x->n == 0 && x->offset ==0) { + ci->flag |= MARKFREE; WRITE(ci.get()); - delete_op(ci.get(), k); - return; + ci->flag &= ~MARKFREE; + ci->offset = 0; } + WRITE(ci.get()); + delete_op(ci.get(), k); + return; } - } else { - delete_op(ci.get(), k); } } @@ -496,11 +487,23 @@ namespace alg { x->n = x->n - 1; } + /** + * allocate empty node struct + */ + 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)); + return x; + } /** * Load the root block */ node ROOT() { - void *root = allocate_node(); + void *root = ALLOCBLK(); lseek(fd, 0, SEEK_SET); read(fd, root, BLOCKSIZE); return (node)root; @@ -510,7 +513,7 @@ namespace alg { * Read a 4K-block from disk, and returns the node struct. */ node READ(node x, int32_t i) { - void *xi = allocate_node(); + void *xi = ALLOCBLK(); if (i >=0 && i <= x->n) { lseek(fd, x->c[i], SEEK_SET); read(fd, xi, BLOCKSIZE); diff --git a/src/btree_demo.cpp b/src/btree_demo.cpp index 36c38c53..e26a8b21 100644 --- a/src/btree_demo.cpp +++ b/src/btree_demo.cpp @@ -9,6 +9,10 @@ int main(void) { 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++) { From 34aaa4e58ed0a92dada2bd162f70b7d983480ca5 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 13:50:40 +0800 Subject: [PATCH 075/217] update btree padding content --- include/btree.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/btree.h b/include/btree.h index a22c3fbb..c6bdde3d 100644 --- a/include/btree.h +++ b/include/btree.h @@ -497,6 +497,7 @@ namespace alg { 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; } /** From d376ce8ee1eea4dd48e6ea1a59f954b90562a784 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 14:03:07 +0800 Subject: [PATCH 076/217] update comment in btree.h --- include/btree.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/btree.h b/include/btree.h index c6bdde3d..a671667e 100644 --- a/include/btree.h +++ b/include/btree.h @@ -50,10 +50,10 @@ namespace alg { struct node_t { uint16_t n; // num key uint16_t flag; // flags - uint32_t offset; // block offset (8 byte head) + 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 (file offsets related to 0) + int32_t c[510]; // childs pointers (represented as file offsets) } __attribute__ ((packed)); typedef struct node_t *node; @@ -473,7 +473,7 @@ namespace alg { } /** - * delete ith node + * delete ith key & child. */ void delete_i(node x, int32_t i) { int j; @@ -488,7 +488,10 @@ namespace alg { } /** - * allocate empty node struct + * 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; @@ -500,6 +503,7 @@ namespace alg { memset(x->padding, 0xcc, sizeof(x->padding)); return x; } + /** * Load the root block */ From 648b1155f91425b0bc7ced6040cfcb3ecb5f5e2b Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 21 Oct 2013 14:06:11 +0800 Subject: [PATCH 077/217] update comments --- include/btree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/btree.h b/include/btree.h index a671667e..ac835910 100644 --- a/include/btree.h +++ b/include/btree.h @@ -489,8 +489,8 @@ namespace alg { /** * 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. + * 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() { From 494678893859623c8dc5cd77a73667e095320625 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 28 Oct 2013 16:39:47 +0800 Subject: [PATCH 078/217] implementing fib-heap --- include/fib-heap.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 include/fib-heap.h diff --git a/include/fib-heap.h b/include/fib-heap.h new file mode 100644 index 00000000..b8022e21 --- /dev/null +++ b/include/fib-heap.h @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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 __FIB_HEAP_H__ +#define __FIB_HEAP_H__ +#include +namespace alg { + template + class FibHeap { + public: + typedef _Key key_type; + typedef _Val value_type; + typedef struct node_t { + int32_t degree; + node_t * parent; + node_t * child; + bool mark; + key_type key; + value_type value; + } *Node; + private: + FibHeap(const FibHeap &); + FibHeap& operator=(const FibHeap&); + private: + int32_t n; + Node min; + public: + FibHeap() { + } + }; +} + +#endif // From de365ad28c18a358ba4ee1a3d6860c99fb683c74 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Tue, 29 Oct 2013 16:09:03 +0800 Subject: [PATCH 079/217] =?UTF-8?q?=E4=BF=AE=E6=94=B9LRU=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.使用模板来表述key和value 2.使用hash来查询数据,提高效率 --- include/LRU_cache.h | 161 ++++++++++++++++++++++++----------------- src/LRU_cache_demo.cpp | 63 +++++++--------- 2 files changed, 123 insertions(+), 101 deletions(-) diff --git a/include/LRU_cache.h b/include/LRU_cache.h index 5d161b5c..624dab54 100644 --- a/include/LRU_cache.h +++ b/include/LRU_cache.h @@ -36,30 +36,37 @@ #include #include #include +#include + +using namespace std; namespace alg { - class LRUCache{ + + template + class LRUCache + { typedef struct _Node_{ - int key; - int value; + K key; + V value; struct _Node_ *next; struct _Node_ *pre; } CacheNode; - - public: + + public: LRUCache(int cache_size=10) { cache_size_ = cache_size; - cache_real_size_ = 0; 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; @@ -69,82 +76,106 @@ namespace alg { } delete p_cache_list_near; + cache_hash.clear(); } - - int getValue(int key) { - CacheNode *p=p_cache_list_head->next; - while (p->next!=NULL) { - if (p->key == key) { //catch node - detachNode(p); - addToFront(p); - return p->value; - } - p=p->next; + + + + 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(); } - return -1; - } - bool putValue(int key,int value) { - CacheNode *p=p_cache_list_head->next; - while (p->next!=NULL) { - if(p->key == key) { //catch node - p->value=value; - getValue(key); - return true; - } - p=p->next; - } + } + + + + + 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(); + } + - if (cache_real_size_ >= cache_size_) { - std::cout << "free" <pre->pre; - delete p->next; - p->next=p_cache_list_near; - p_cache_list_near->pre=p; } - - p = new CacheNode();//(CacheNode *)malloc(sizeof(CacheNode)); - - if (p==NULL) - return false; - - addToFront(p); - p->key=key; - p->value=value; - - cache_real_size_++; - + return true; } - - void displayNodes() { + + + + + + void display(){ CacheNode *p=p_cache_list_head->next; - while(p->next!=NULL) { - std::cout << " Key : " << p->key << " Value : " << p->value << std::endl; + std::cout << " KEY[" << p->key << "]<==>VALUE[" << p->value <<"]" << std::endl; p=p->next; - } - std::cout << std::endl; + std::cout << std::endl; } - - private: + + private: int cache_size_; - int cache_real_size_; CacheNode *p_cache_list_head; CacheNode *p_cache_list_near; - - void detachNode(CacheNode *node) { + mapcache_hash; + + + void detachNode(CacheNode *node){ node->pre->next=node->next; - node->next->pre=node->pre; + node->next->pre=node->pre; } - - void addToFront(CacheNode *node) { - node->next=p_cache_list_head->next; - p_cache_list_head->next->pre=node; - p_cache_list_head->next=node; - node->pre=p_cache_list_head; + + + 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); + } + }; } diff --git a/src/LRU_cache_demo.cpp b/src/LRU_cache_demo.cpp index b190b4ff..24a853f9 100644 --- a/src/LRU_cache_demo.cpp +++ b/src/LRU_cache_demo.cpp @@ -3,42 +3,33 @@ #include "LRU_cache.h" using namespace std; -int main() { -#if 1 - alg::LRUCache *cache=new alg::LRUCache(9); - - cache->putValue(1,1); - cache->putValue(2,2); - cache->putValue(3,3); - cache->putValue(4,3); - cache->putValue(5,2); - cache->displayNodes(); - - cout << cache->getValue(4) << endl; - cache->displayNodes(); - //cache->displayNodes(); - cout << cache->getValue(3) << endl; - cache->displayNodes(); - cout << cache->getValue(3) << endl; - cache->displayNodes(); - cout << cache->getValue(1) << endl; - cache->displayNodes(); - cout << cache->getValue(2) << endl; - cache->displayNodes(); - cout << cache->getValue(9) << endl; +using namespace alg; - cache->displayNodes(); - - cache->putValue(4,9); - //cout << cache->getValue(2) << endl; - //cout << cache->getValue(3) << endl; - cache->displayNodes(); - cout << cache->getValue(4) << endl; - cache->displayNodes(); - cout << cache->getValue(2) << endl; - cache->displayNodes(); +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"); + - delete cache; -#endif - return 1; } From e42bf35bd26f20cf43583bf69506b318c67ad564 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 30 Oct 2013 14:31:13 +0800 Subject: [PATCH 080/217] updating fib-heap --- include/fib-heap.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index b8022e21..16f28925 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -20,6 +20,8 @@ #ifndef __FIB_HEAP_H__ #define __FIB_HEAP_H__ #include +#include +#include "double_linked_list.h" namespace alg { template class FibHeap { @@ -33,6 +35,7 @@ namespace alg { bool mark; key_type key; value_type value; + struct list_head node; // list data struct } *Node; private: FibHeap(const FibHeap &); @@ -40,8 +43,28 @@ namespace alg { private: int32_t n; Node min; + struct list_head rootlist; public: - FibHeap() { + FibHeap():n(0),min(0){ + INIT_LIST_HEAD(&rootlist); + } + + void Insert(key_type key, value_type value) { + Node x = new node_t; + x->degree = 0; + x->p = NULL; + x->child = NULL; + x->mark = false; + if (min == NULL) { + min = x; + list_add(&x->node, &rootlist); + } else { + list_add(&x->node, &rootlist); + if (x->key < min->key) { + min = x; + } + } + n = n+1; } }; } From bc6189505316161c5e4180ead69dc0c17941e58c Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 30 Oct 2013 15:47:18 +0800 Subject: [PATCH 081/217] implementing fib-heap --- include/fib-heap.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/fib-heap.h b/include/fib-heap.h index 16f28925..c6287fee 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -49,6 +49,9 @@ namespace alg { INIT_LIST_HEAD(&rootlist); } + /** + * insert a value into the Fibonacci Heap + */ void Insert(key_type key, value_type value) { Node x = new node_t; x->degree = 0; @@ -66,6 +69,37 @@ namespace alg { } n = n+1; } + + /** + * Union 2 Fibonacci-Heap + */ + static FibHeap* Union(FibHeap *H1, FibHeap *H2) { + FibHeap * H = new FibHeap(); + H->min = H1->min; + H->rootlist = H1->rootlist; + list_splice(&H->rootlist, &H1->rootlist); // concat 2 root-list + list_splice(&H->rootlist, &H2->rootlist); + 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 n, ns; + // for each child x of z, add x to the root list of H + list_for_each_entry_safe(n,ns, z->child, node){ + list_add(&n->node, &rootlist); + n->parent = NULL; + } + } + } }; } From 83e98abd80c5a50ae26fdbeb9f7b82aedbc1f6bf Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 30 Oct 2013 15:54:45 +0800 Subject: [PATCH 082/217] temp save --- include/fib-heap.h | 157 ++++++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 72 deletions(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index c6287fee..db282b1c 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -24,83 +24,96 @@ #include "double_linked_list.h" namespace alg { template - class FibHeap { - public: - typedef _Key key_type; - typedef _Val value_type; - typedef struct node_t { - int32_t degree; - node_t * parent; - node_t * child; - bool mark; - key_type key; - value_type value; - struct list_head node; // list data struct - } *Node; - private: - FibHeap(const FibHeap &); - FibHeap& operator=(const FibHeap&); - private: - int32_t n; - Node min; - struct list_head rootlist; - public: - FibHeap():n(0),min(0){ - INIT_LIST_HEAD(&rootlist); - } + class FibHeap { + public: + typedef _Key key_type; + typedef _Val value_type; + typedef struct node_t { + int32_t degree; + node_t * parent; + node_t * child; + bool mark; + key_type key; + value_type value; + struct list_head node; // list data struct + } *Node; + private: + FibHeap(const FibHeap &); + FibHeap& operator=(const FibHeap&); + private: + int32_t n; + Node min; + struct list_head rootlist; + public: + FibHeap():n(0),min(0){ + INIT_LIST_HEAD(&rootlist); + } + + /** + * insert a value into the Fibonacci Heap + */ + void Insert(key_type key, value_type value) { + Node x = new node_t; + x->degree = 0; + x->p = NULL; + x->child = NULL; + x->mark = false; + if (min == NULL) { + min = x; + list_add(&x->node, &rootlist); + } else { + list_add(&x->node, &rootlist); + if (x->key < min->key) { + min = x; + } + } + n = n+1; + } - /** - * insert a value into the Fibonacci Heap - */ - void Insert(key_type key, value_type value) { - Node x = new node_t; - x->degree = 0; - x->p = NULL; - x->child = NULL; - x->mark = false; - if (min == NULL) { - min = x; - list_add(&x->node, &rootlist); - } else { - list_add(&x->node, &rootlist); - if (x->key < min->key) { - min = x; + /** + * Union 2 Fibonacci-Heap + */ + static FibHeap* Union(FibHeap *H1, FibHeap *H2) { + FibHeap * H = new FibHeap(); + H->min = H1->min; + H->rootlist = H1->rootlist; + list_splice(&H->rootlist, &H1->rootlist); // concat 2 root-list + list_splice(&H->rootlist, &H2->rootlist); + 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; } - } - n = n+1; - } - /** - * Union 2 Fibonacci-Heap - */ - static FibHeap* Union(FibHeap *H1, FibHeap *H2) { - FibHeap * H = new FibHeap(); - H->min = H1->min; - H->rootlist = H1->rootlist; - list_splice(&H->rootlist, &H1->rootlist); // concat 2 root-list - list_splice(&H->rootlist, &H2->rootlist); - 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 n, ns; + // for each child x of z, add x to the root list of H + list_for_each_entry_safe(n,ns, z->child, node){ + list_add(&n->node, &rootlist); + n->parent = NULL; + } + + // remove z from the root list of H + list_del(&z->node, &rootlist); + if (z == z->next) { // the only node on the root list + min = NULL; + } else { + min = z->right; + Consolidate(); + } + n = n + 1; + } + } - /** - * Extract Min Element - */ - Node * ExtractMin() { - Node z = min; - if (z != NULL) { - Node n, ns; - // for each child x of z, add x to the root list of H - list_for_each_entry_safe(n,ns, z->child, node){ - list_add(&n->node, &rootlist); - n->parent = NULL; + void Consolidate() { } - } - } - }; + }; } #endif // From d38e7490359ab8225544d878d03bf896bc30e645 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 30 Oct 2013 17:53:47 +0800 Subject: [PATCH 083/217] update fib-heap.h --- include/fib-heap.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/fib-heap.h b/include/fib-heap.h index db282b1c..62bb07ed 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -19,6 +19,7 @@ #ifndef __FIB_HEAP_H__ #define __FIB_HEAP_H__ +#include #include #include #include "double_linked_list.h" @@ -113,6 +114,10 @@ namespace alg { void Consolidate() { } + + int32_t D(int32_t n) { + return int32_t(ceil(log(n))); + } }; } From be8fcfd49b260ca2c2da11ab047427ba30b08eb1 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 4 Nov 2013 09:07:00 +0800 Subject: [PATCH 084/217] updating fib-heap --- include/fib-heap.h | 52 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index 62bb07ed..0d8f182f 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -95,7 +95,7 @@ namespace alg { if (z != NULL) { Node n, ns; // for each child x of z, add x to the root list of H - list_for_each_entry_safe(n,ns, z->child, node){ + list_for_each_entry_safe(n,ns, &z->child.node, node){ list_add(&n->node, &rootlist); n->parent = NULL; } @@ -113,11 +113,59 @@ namespace alg { } void Consolidate() { + int32_t dn = D(n); + Node A[dn]; // let A[0..D(H.n)] to be a new array + int32_t i; + for (i=0;idegree; + while (A[d] != NULL) { + Node y = A[d]; // another node with the same degree as x + if (x->key > y->key) { + Node tmp = x; + x = y; + y = tmp; + } + Link(y,x); + A[d] = NULL; + d = d + 1; + } + A[d] = x; + } + min = NULL; + for (i=0;inode, &rootlist); + min = A[i]; + } else { + list_add(&A[i]->node, &rootlist); + if (A[i]->key < min->key) { + min = A[i]; + } + } + } + } } - + private: int32_t D(int32_t n) { return int32_t(ceil(log(n))); } + + void Link(Node y, Node x) { + list_del(&y->node, &rootlist); + y->parent = x; + x->degree = x->degree + 1; + y->mark = false; + } }; } From f1043d6342f9c7a307ccaefe25ac855b0ca47b1a Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 4 Nov 2013 17:04:05 +0800 Subject: [PATCH 085/217] debug fib-heap insert --- Makefile | 5 +++-- include/fib-heap.h | 40 ++++++++++++++++++++++++---------------- src/fib-heap_demo.cpp | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 src/fib-heap_demo.cpp diff --git a/Makefile b/Makefile index 47c0d4e2..febb7b84 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CPP=g++ AR=ar RANLIB=ranlib -CFLAGS= -g -O2 -Wall -Wno-unused-function +CFLAGS= -g -Wall -Wno-unused-function SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = @@ -60,7 +60,8 @@ PROGRAMS = m_based \ max_subarray_demo \ disjoint-set_demo \ relabel_to_front_demo \ - btree_demo + btree_demo \ + fib-heap_demo all: $(PROGRAMS) diff --git a/include/fib-heap.h b/include/fib-heap.h index 0d8f182f..34a44c00 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -32,10 +32,10 @@ namespace alg { typedef struct node_t { int32_t degree; node_t * parent; - node_t * child; bool mark; key_type key; value_type value; + struct list_head child; struct list_head node; // list data struct } *Node; private: @@ -56,9 +56,10 @@ namespace alg { void Insert(key_type key, value_type value) { Node x = new node_t; x->degree = 0; - x->p = NULL; - x->child = NULL; + x->parent = NULL; x->mark = false; + INIT_LIST_HEAD(&x->node); + INIT_LIST_HEAD(&x->child); if (min == NULL) { min = x; list_add(&x->node, &rootlist); @@ -90,33 +91,35 @@ namespace alg { /** * Extract Min Element */ - Node * ExtractMin() { + Node ExtractMin() { Node z = min; if (z != NULL) { - Node n, ns; + Node x, xs; // for each child x of z, add x to the root list of H - list_for_each_entry_safe(n,ns, &z->child.node, node){ - list_add(&n->node, &rootlist); - n->parent = NULL; + list_for_each_entry_safe(x,xs, &z->child, node){ + list_del(&x->node); + list_add(&x->node, &rootlist); + x->parent = NULL; } // remove z from the root list of H - list_del(&z->node, &rootlist); - if (z == z->next) { // the only node on the root list + list_del(&z->node); + if (z == right(z)) { // the only node on the root list min = NULL; } else { - min = z->right; + min = right(z); Consolidate(); } n = n + 1; } + return z; } void Consolidate() { int32_t dn = D(n); - Node A[dn]; // let A[0..D(H.n)] to be a new array + Node A[dn+1]; // let A[0..D(H.n)] to be a new array int32_t i; - for (i=0;idegree; while (A[d] != NULL) { Node y = A[d]; // another node with the same degree as x - if (x->key > y->key) { + if (x->key > y->key) { // exchange x with y Node tmp = x; x = y; y = tmp; @@ -139,7 +142,7 @@ namespace alg { A[d] = x; } min = NULL; - for (i=0;inode.next, node_t, node); + } + void Link(Node y, Node x) { - list_del(&y->node, &rootlist); + list_del(&y->node); y->parent = x; + list_add(&y->node, &x->child); x->degree = x->degree + 1; y->mark = false; } diff --git a/src/fib-heap_demo.cpp b/src/fib-heap_demo.cpp new file mode 100644 index 00000000..86e905ae --- /dev/null +++ b/src/fib-heap_demo.cpp @@ -0,0 +1,17 @@ +#include +#include +#include "fib-heap.h" + +int main(void) { + alg::FibHeap heap; + int32_t i; + for (i=0;i<100;i++) { + heap.Insert(rand(),0); + } + + for (i=0;i<100;i++) { + alg::FibHeap::Node n; + n = heap.ExtractMin(); + printf("%d\n", n->key); + } +} From f3da16ae7a44e5a037ce1a697630bc072879af65 Mon Sep 17 00:00:00 2001 From: fuli Date: Mon, 4 Nov 2013 18:08:20 +0800 Subject: [PATCH 086/217] update fib-heap --- include/fib-heap.h | 23 +++++++++++++++++------ src/fib-heap_demo.cpp | 3 +-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index 34a44c00..527064f7 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -58,6 +58,8 @@ namespace alg { x->degree = 0; x->parent = NULL; x->mark = false; + x->key = key; + x->value = value; INIT_LIST_HEAD(&x->node); INIT_LIST_HEAD(&x->child); if (min == NULL) { @@ -69,6 +71,11 @@ namespace alg { min = x; } } + + Node m,mm; + list_for_each_entry_safe(m,mm, &rootlist, node){ + printf("%d %d\n", m->key, m->value); + } n = n+1; } @@ -96,20 +103,24 @@ namespace alg { 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, node){ - list_del(&x->node); + list_for_each_entry_safe(x,xs, &z->child, child){ + list_del(&x->child); list_add(&x->node, &rootlist); x->parent = NULL; } - - // remove z from the root list of H - list_del(&z->node); if (z == right(z)) { // the only node on the root list min = NULL; } else { + list_for_each_entry_safe(x,xs,&z->node, node){ + printf("%d %d\n", x->key, x->value); + } min = right(z); - Consolidate(); + //Consolidate(); } + /* + // remove z from the root list of H + list_del(&z->node); + */ n = n + 1; } return z; diff --git a/src/fib-heap_demo.cpp b/src/fib-heap_demo.cpp index 86e905ae..8b73308e 100644 --- a/src/fib-heap_demo.cpp +++ b/src/fib-heap_demo.cpp @@ -6,12 +6,11 @@ int main(void) { alg::FibHeap heap; int32_t i; for (i=0;i<100;i++) { - heap.Insert(rand(),0); + heap.Insert(rand(), i); } for (i=0;i<100;i++) { alg::FibHeap::Node n; n = heap.ExtractMin(); - printf("%d\n", n->key); } } From 7b46da4e34ffd6f203abf6465d0a0280aaacaf52 Mon Sep 17 00:00:00 2001 From: fuli Date: Tue, 5 Nov 2013 14:45:40 +0800 Subject: [PATCH 087/217] update fib-heap --- include/fib-heap.h | 78 +++++++++++++++++++------------------------ src/fib-heap_demo.cpp | 7 +++- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index 527064f7..3baee623 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -24,30 +24,31 @@ #include #include "double_linked_list.h" namespace alg { - template + template class FibHeap { public: typedef _Key key_type; typedef _Val value_type; - typedef struct node_t { + struct node_t { int32_t degree; node_t * parent; bool mark; key_type key; value_type value; - struct list_head child; - struct list_head node; // list data struct - } *Node; + 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 rootlist; + struct list_head m_root; // root list public: - FibHeap():n(0),min(0){ - INIT_LIST_HEAD(&rootlist); + FibHeap():n(0),min(NULL){ + INIT_LIST_HEAD(&m_root); } /** @@ -60,22 +61,16 @@ namespace alg { x->mark = false; x->key = key; x->value = value; - INIT_LIST_HEAD(&x->node); - INIT_LIST_HEAD(&x->child); + INIT_LIST_HEAD(&x->child_head); if (min == NULL) { min = x; - list_add(&x->node, &rootlist); + list_add(&x->node, &m_root); } else { - list_add(&x->node, &rootlist); + list_add(&x->node, &m_root); if (x->key < min->key) { min = x; } } - - Node m,mm; - list_for_each_entry_safe(m,mm, &rootlist, node){ - printf("%d %d\n", m->key, m->value); - } n = n+1; } @@ -85,9 +80,9 @@ namespace alg { static FibHeap* Union(FibHeap *H1, FibHeap *H2) { FibHeap * H = new FibHeap(); H->min = H1->min; - H->rootlist = H1->rootlist; - list_splice(&H->rootlist, &H1->rootlist); // concat 2 root-list - list_splice(&H->rootlist, &H2->rootlist); + 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; } @@ -103,24 +98,24 @@ namespace alg { 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, child){ - list_del(&x->child); - list_add(&x->node, &rootlist); + list_for_each_entry_safe(x, xs, &z->child_head, node) { + list_del(&x->node); + list_add(&x->node, &m_root); x->parent = NULL; } - if (z == right(z)) { // the only node on the root list + + if (z->node.next != &m_root) { // pick one sibling + min = list_entry(z->node.next, node_t, node); + list_del(&z->node); + Consolidate(); + } else if (z->node.prev != &m_root ) { + min = list_entry(z->node.prev, node_t, node); + list_del(&z->node); + Consolidate(); + } else { // the only node on the root list min = NULL; - } else { - list_for_each_entry_safe(x,xs,&z->node, node){ - printf("%d %d\n", x->key, x->value); - } - min = right(z); - //Consolidate(); } - /* // remove z from the root list of H - list_del(&z->node); - */ n = n + 1; } return z; @@ -136,8 +131,9 @@ namespace alg { Node w, ws; // for each node w in the root list of H - list_for_each_entry_safe(w,ws, &rootlist, node){ + list_for_each_entry_safe(w, ws, &m_root, node){ Node x = w; + printf("%d %d\n", x->degree, x->key); int32_t d = x->degree; while (A[d] != NULL) { Node y = A[d]; // another node with the same degree as x @@ -156,12 +152,11 @@ namespace alg { 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(&rootlist); - list_add(&A[i]->node, &rootlist); + // insert into rootlist + list_add(&A[i]->node, &m_root); min = A[i]; } else { - list_add(&A[i]->node, &rootlist); + list_add(&A[i]->node, &m_root); if (A[i]->key < min->key) { min = A[i]; } @@ -174,14 +169,9 @@ namespace alg { return int32_t(ceil(log(n))); } - Node right(Node x) { - return list_entry(x->node.next, node_t, node); - } - void Link(Node y, Node x) { - list_del(&y->node); y->parent = x; - list_add(&y->node, &x->child); + list_add(&y->node, &x->child_head); x->degree = x->degree + 1; y->mark = false; } diff --git a/src/fib-heap_demo.cpp b/src/fib-heap_demo.cpp index 8b73308e..da1aecc0 100644 --- a/src/fib-heap_demo.cpp +++ b/src/fib-heap_demo.cpp @@ -1,16 +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<100;i++) { heap.Insert(rand(), i); } - for (i=0;i<100;i++) { + for (i=0;i<99;i++) { alg::FibHeap::Node n; n = heap.ExtractMin(); + if (n!= NULL) { + printf("%d %d", n->key, n->value); + } } } From c20014e1fedffb914aa0f0240625de02b5556257 Mon Sep 17 00:00:00 2001 From: fuli Date: Tue, 5 Nov 2013 17:25:35 +0800 Subject: [PATCH 088/217] complete fib-heap Insert --- include/fib-heap.h | 21 ++++++++++----------- src/fib-heap_demo.cpp | 6 +++--- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index 3baee623..f086f3e3 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -104,13 +104,9 @@ namespace alg { x->parent = NULL; } - if (z->node.next != &m_root) { // pick one sibling - min = list_entry(z->node.next, node_t, node); - list_del(&z->node); - Consolidate(); - } else if (z->node.prev != &m_root ) { - min = list_entry(z->node.prev, node_t, node); - list_del(&z->node); + list_del(&z->node); + if (!list_empty(&m_root)) { + min = list_entry(m_root.next, node_t, node); Consolidate(); } else { // the only node on the root list min = NULL; @@ -131,9 +127,8 @@ namespace alg { Node w, ws; // for each node w in the root list of H - list_for_each_entry_safe(w, ws, &m_root, node){ + list_for_each_entry_safe(w, ws, &m_root, node) { Node x = w; - printf("%d %d\n", x->degree, x->key); int32_t d = x->degree; while (A[d] != NULL) { Node y = A[d]; // another node with the same degree as x @@ -152,7 +147,8 @@ namespace alg { for (i=0;i<=dn;i++) { if (A[i]!=NULL) { if (min == NULL) { - // insert into rootlist + // 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 { @@ -166,7 +162,10 @@ namespace alg { } private: int32_t D(int32_t n) { - return int32_t(ceil(log(n))); + float p1 = logf(n); + float p2 = logf(1.61803); + //printf("D(n) = %f\n", floor(p1/p2)); + return int32_t(floor(p1/p2)); } void Link(Node y, Node x) { diff --git a/src/fib-heap_demo.cpp b/src/fib-heap_demo.cpp index da1aecc0..8aa765a4 100644 --- a/src/fib-heap_demo.cpp +++ b/src/fib-heap_demo.cpp @@ -7,15 +7,15 @@ int main(void) { srand(time(NULL)); alg::FibHeap heap; int32_t i; - for (i=0;i<100;i++) { + for (i=0;i<10;i++) { heap.Insert(rand(), i); } - for (i=0;i<99;i++) { + for (i=0;i<10;i++) { alg::FibHeap::Node n; n = heap.ExtractMin(); if (n!= NULL) { - printf("%d %d", n->key, n->value); + printf("%d %d\n", n->key, n->value); } } } From e0340f869926cc87a0b59dfa801980c049967c6c Mon Sep 17 00:00:00 2001 From: fuli Date: Tue, 5 Nov 2013 17:29:52 +0800 Subject: [PATCH 089/217] add .gitignore & rename --- .gitignore | 2 ++ Makefile | 4 ++-- src/{m_based.cpp => m_based_demo.cpp} | 0 src/{prime_test.cpp => prime_demo.cpp} | 0 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 .gitignore rename src/{m_based.cpp => m_based_demo.cpp} (100%) rename src/{prime_test.cpp => prime_demo.cpp} (100%) 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/Makefile b/Makefile index febb7b84..6ec7e8a8 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = LIBS = -lm -PROGRAMS = m_based \ +PROGRAMS = m_based_demo \ integer_demo \ insertion_sort_demo \ radix_sort_demo \ @@ -22,7 +22,7 @@ PROGRAMS = m_based \ stack_demo \ queue_demo \ priority_queue_demo \ - prime_test \ + prime_demo \ universal_hash_demo \ perfect_hash_demo \ binary_search_tree_demo \ diff --git a/src/m_based.cpp b/src/m_based_demo.cpp similarity index 100% rename from src/m_based.cpp rename to src/m_based_demo.cpp 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 From 6cb60f375337c5e728c4b8d3c699ee275c172fc1 Mon Sep 17 00:00:00 2001 From: fuli Date: Tue, 5 Nov 2013 18:01:45 +0800 Subject: [PATCH 090/217] add decrease-key --- include/fib-heap.h | 64 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/include/fib-heap.h b/include/fib-heap.h index f086f3e3..8eaf77c6 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -106,8 +106,8 @@ namespace alg { list_del(&z->node); if (!list_empty(&m_root)) { - min = list_entry(m_root.next, node_t, node); - Consolidate(); + min = list_entry(m_root.next, node_t, node); // is this necessary? + CONSOLIDATE(); } else { // the only node on the root list min = NULL; } @@ -117,7 +117,49 @@ namespace alg { return z; } - void Consolidate() { + /** + * 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; @@ -137,7 +179,7 @@ namespace alg { x = y; y = tmp; } - Link(y,x); + LINK(y,x); A[d] = NULL; d = d + 1; } @@ -160,15 +202,21 @@ namespace alg { } } } - private: + int32_t D(int32_t n) { float p1 = logf(n); - float p2 = logf(1.61803); + float p2 = logf(1.61803); // golden ratio //printf("D(n) = %f\n", floor(p1/p2)); return int32_t(floor(p1/p2)); } - - void Link(Node y, Node x) { + + /** + * 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; From 4f2479ee08fd1a302527d05373b06185d9be0c62 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 6 Nov 2013 14:34:57 +0800 Subject: [PATCH 091/217] update heap indent --- include/heap.h | 320 ++++++++++++++++++++++++------------------------- 1 file changed, 155 insertions(+), 165 deletions(-) diff --git a/include/heap.h b/include/heap.h index b5734910..b81acea8 100644 --- a/include/heap.h +++ b/include/heap.h @@ -28,177 +28,167 @@ #include #include -namespace alg -{ +namespace alg { /** - * define binary heap structure. - */ + * 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; - }; - - ~Heap() - { - delete [] m_kvs; - }; - - private: - Heap(const Heap &); - Heap& operator=(const Heap&); - - public: - - inline int min_key() const { return m_kvs[1].key; }; - inline const T & min_value() const { return m_kvs[1].value; }; - - // for loop through the kvs - inline uint32_t count() const { return m_size; }; - inline const T & operator[] (uint32_t idx) const { return m_kvs[idx+1].value; }; - - /** - * insert a 'key'->'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. + 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; + }; + + ~Heap() { + delete [] m_kvs; + }; + + private: + Heap(const Heap &); + Heap& operator=(const Heap&); + + public: + + inline int min_key() const { return m_kvs[1].key; }; + inline const T & min_value() const { return m_kvs[1].value; }; + + // for loop through the kvs + inline uint32_t count() const { return m_size; }; + inline const T & operator[] (uint32_t idx) const { return m_kvs[idx+1].value; }; + + /** + * insert a 'key'->'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; } - // 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]; + + /** + * 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; } - else { // It fits there - break; + + /** + * 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. + } + // 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]; + } + else { // It fits there + break; + } + } + + m_kvs[now].key = lastKey; + m_kvs[now].value= lastValue; } - } - - m_kvs[now].key = lastKey; - m_kvs[now].value= lastValue; - } - - /** - * so called DECREASE KEY operation. - * step 1. find the value - * step 2. decrease the key to the newkey - */ - void decrease_key(const T & value, int newkey) - { - uint32_t index = m_size+1; - for (uint32_t i=1;i<=m_size;i++) { - if (m_kvs[i].value == value) { - index = i; - break; + + /** + * so called DECREASE KEY operation. + * step 1. find the value + * step 2. decrease the key to the newkey + */ + void decrease_key(const T & value, int newkey) { + uint32_t index = m_size+1; + for (uint32_t i=1;i<=m_size;i++) { + if (m_kvs[i].value == value) { + index = i; + break; + } + } + + if (index > 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; } - } - - if (index > 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; - } - }; + }; } #endif // From 7504093c3b6b93d3b4fa98f81b440d2dd13dc851 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 6 Nov 2013 14:58:15 +0800 Subject: [PATCH 092/217] indent files --- include/2darray.h | 104 ++++--- include/LRU_cache.h | 221 +++++++-------- include/bellman_ford.h | 114 ++++---- include/binary_search_tree.h | 326 +++++++++++----------- include/bitset.h | 144 +++++----- include/btree.h | 16 +- include/dijkstra.h | 106 ++++---- include/directed_graph.h | 164 ++++++----- include/disjoint-set.h | 50 ++-- include/dos_tree.h | 338 +++++++++++------------ include/edmonds_karp.h | 170 ++++++------ include/generic.h | 63 +++-- include/graph_defs.h | 251 +++++++++-------- include/graph_search.h | 15 +- include/hash_multi.h | 11 +- include/hash_string.h | 9 +- include/hash_table.h | 237 ++++++++-------- include/heap.h | 4 +- include/heap_sort.h | 52 ++-- include/huffman.h | 360 ++++++++++++------------- include/imath.h | 25 +- include/insertion_sort.h | 26 +- include/integer.h | 508 +++++++++++++++++------------------ include/interval_tree.h | 372 +++++++++++++------------ include/k-means.h | 197 ++++++-------- include/kmp.h | 2 +- 26 files changed, 1850 insertions(+), 2035 deletions(-) diff --git a/include/2darray.h b/include/2darray.h index 2fb0b999..1383e242 100644 --- a/include/2darray.h +++ b/include/2darray.h @@ -15,71 +15,67 @@ #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 - 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; + 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; } - 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(); + ~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(); } - } - - - - - 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_){ + 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_){ + } 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; } - - 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; + + 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; } - 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; + + 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); } - } - - - - 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/bellman_ford.h b/include/bellman_ford.h index 13d42a30..37e1d4f0 100644 --- a/include/bellman_ford.h +++ b/include/bellman_ford.h @@ -59,78 +59,74 @@ // 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 befca627..c1f332bc 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -28,173 +28,173 @@ namespace alg { template - class BST { - private: - /** - * binary search tree definiton. - */ - struct treeNode { - KeyT key; // key - ValueT value; // data - treeNode *parent; // parent - treeNode *left; // left child - treeNode *right; // right child - }; - - class BSTException: public std::exception { + class BST { + private: + /** + * binary search tree definiton. + */ + 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"; + } + }; + + private: + treeNode * m_root; // the root + const BSTException error; + private: + BST(const BST&); + BST& operator=(const BST&); public: - virtual const char * what() const throw() { - return "key does not exist"; - } - }; - - private: - treeNode * m_root; // the root - const BSTException error; - private: - BST(const BST&); - BST& operator=(const BST&); - public: - 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; + 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; } - } - - 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; + + 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); + } + + 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; } - } - - 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 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; + } } - - // replace z with y - transplant(z,y); - y->left = z->left; - y->left->parent = y; - } - - delete z; - return true; - } - - 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); - } - - 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; - } - - /** - * 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; - } - }; + + /** + * find the minimum element of the subtree + */ + treeNode * minimum(treeNode *x) { + while (x->left != NULL) { + x = x->left; + } + + return x; + } + }; } #endif // diff --git a/include/bitset.h b/include/bitset.h index 0e66ad1c..83171c12 100644 --- a/include/bitset.h +++ b/include/bitset.h @@ -19,85 +19,77 @@ #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/btree.h b/include/btree.h index ac835910..bec96048 100644 --- a/include/btree.h +++ b/include/btree.h @@ -215,13 +215,13 @@ namespace alg { 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"); - */ + 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; @@ -231,7 +231,7 @@ namespace alg { 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); diff --git a/include/dijkstra.h b/include/dijkstra.h index 3dbeec33..e5722b00 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -33,74 +33,72 @@ #include "stack.h" #include "hash_table.h" -namespace alg -{ +namespace alg { /** * the dijkstra algorithm workspace */ 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), + 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()); - Q.clear(); - dist.clear(); + // 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()); - // source - Graph::Adjacent * source = g[src_id]; - Q.insert(0, source->v.id); // weight->id binary heap - dist[source->v.id] = 0; + Q.clear(); + dist.clear(); - // 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 + // source + Graph::Adjacent * source = g[src_id]; + Q.insert(0, source->v.id); // weight->id binary heap + dist[source->v.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; } - (*previous)[a->v.id] = UNDEFINED; - } - while(!Q.is_empty()) { // The main loop - Graph::Adjacent * u = g[Q.min_value()]; - int dist_u = Q.min_key(); - Q.delete_min(); + while(!Q.is_empty()) { // The main loop + Graph::Adjacent * u = g[Q.min_value()]; + int dist_u = Q.min_key(); + Q.delete_min(); - 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; + 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; + } } } - } - - return previous; - }; + + return previous; + }; }; } diff --git a/include/directed_graph.h b/include/directed_graph.h index 9f41e874..cc2c2068 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -28,101 +28,99 @@ 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--; + 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: - /** - * 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; + 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; + } - // new empty adjacent list - Adjacent * a = new Adjacent(id); - list_add_tail(&a->a_node, &a_head); - num_vertex++; + /** + * create a new vertex and add to the graph, with specified id. + */ + bool add_vertex(uint32_t id) + { + if ((*this)[id]!=NULL) return false; - return true; - } + // new empty adjacent list + Adjacent * a = new Adjacent(id); + list_add_tail(&a->a_node, &a_head); + num_vertex++; - /** - * 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]; + return true; + } - // make sure both vertex exists & not connected from x->y - if (a1==NULL || a2==NULL) return false; - if (is_adjacent(a1, a2)) return false; + /** + * 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]; - // 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++; + // make sure both vertex exists & not connected from x->y + if (a1==NULL || a2==NULL) return false; + if (is_adjacent(a1, a2)) return false; - return true; - } + // create new vertex & add to adjacent list + Vertex * n = new Vertex(y); + n->weight = weight; + list_add_tail(&n->v_node, &a1->v_head); - /** - * 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--; - } + 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--; + } + } + } }; } diff --git a/include/disjoint-set.h b/include/disjoint-set.h index 340bf08c..c13a002e 100644 --- a/include/disjoint-set.h +++ b/include/disjoint-set.h @@ -23,42 +23,42 @@ namespace alg { template - struct Set{ - Set* parent; - int rank; - }; + struct Set{ + Set* parent; + int rank; + }; template - void MakeSet(T *s){ - s->parent = s; - s->rank = 0; - } + void MakeSet(T *s){ + s->parent = s; + s->rank = 0; + } template - void Union(T *x, T *y) { - Link(FindSet(x), FindSet(y)); - } + 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; + 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); - } + T* FindSet(T *x) { + if (x != x->parent) { + x->parent = FindSet(x->parent); + } - return x->parent; - } + return x->parent; + } } #endif // diff --git a/include/dos_tree.h b/include/dos_tree.h index f0838411..a45b88ca 100644 --- a/include/dos_tree.h +++ b/include/dos_tree.h @@ -27,200 +27,188 @@ #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); + // copy child value if exists + if (child != NULL) { + DOSNODE(n)->key = DOSNODE(child)->key; + DOSNODE(n)->size = DOSNODE(child)->size; + } + if (n->parent == NULL && child != NULL) + 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); + } + } + 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); } - replace_node(n, child); - // copy child value if exists - if (child != NULL) { - DOSNODE(n)->key = DOSNODE(child)->key; - DOSNODE(n)->size = DOSNODE(child)->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; } - 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; + + void rotate_right_callback(rbtree_node n, rbtree_node parent) { + rotate_left_callback(n,parent); } - if (n->right != NULL) { - print_helper(n->right, 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); } - 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); + + 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/edmonds_karp.h b/include/edmonds_karp.h index bdbeb044..a485798e 100644 --- a/include/edmonds_karp.h +++ b/include/edmonds_karp.h @@ -33,29 +33,26 @@ #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), - m_residual(g.vertex_count(), g.vertex_count()), - m_pre(g.vertex_count()), - m_map(g.vertex_count()), m_rmap(g.vertex_count()) - { + 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 @@ -66,7 +63,7 @@ namespace alg m_rmap[id] = a->v.id; id++; } - + // init residual network m_residual.clear(0); @@ -80,83 +77,80 @@ namespace alg } } - ~EdmondsKarp() - { - delete [] m_visits; - } + ~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)); - } + /** + * 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)); + } - // 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; + // 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; + } + + maxflow += delta; } - maxflow += delta; + return maxflow; } - 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;} - - private: - /** - * find a augument path. using breadth first search - */ - bool find_path(uint32_t _src, uint32_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==_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(uint32_t _src, uint32_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==_sink) { // nice, we've got to sink point. + return true; + } + Q.enqueue(i); } - Q.enqueue(i); } } - } - return false; - } + return false; + } }; } diff --git a/include/generic.h b/include/generic.h index b936c76a..c55487c6 100644 --- a/include/generic.h +++ b/include/generic.h @@ -8,7 +8,7 @@ * GENERIC METHODS FOR ALGORITHMS * ******************************************************************************/ - + #ifndef __ALG_INC_H__ #define __ALG_INC_H__ #include @@ -26,57 +26,54 @@ #define RANDOM_INIT() srand(time(NULL)) #define RANDOM(L, R) (L + rand() % ((R) - (L))) // 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; } - } + }; + + /** + * Adjacent Lists. + */ + struct Adjacent { + struct Vertex v; + struct list_head v_head; // vertex list header + struct list_head a_node; + uint32_t num_neigh; // num of neighbours - const Vertex & vertex() const { return v;} + Adjacent(uint32_t id):v(id) { + INIT_LIST_HEAD(&v_head); + num_neigh = 0; + } - 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() { + 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: + 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); + + 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("}\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..9d2be927 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -32,10 +32,8 @@ #include "directed_graph.h" #include "hash_table.h" -namespace alg -{ - static void breadth_first_search(const Graph & g, uint32_t source) - { +namespace alg { + static void breadth_first_search(const Graph & g, uint32_t source) { static const uint32_t MARK = 0xDEAD; Graph::Adjacent * root = g[source]; @@ -47,7 +45,7 @@ namespace alg Queue Q(g.vertex_count()); Q.enqueue(root->v.id); ht[root->v.id] = MARK; - + while(!Q.is_empty()) { uint32_t t = Q.front(); printf("%d->", t); @@ -65,8 +63,7 @@ namespace alg printf("\n"); } - static void depth_first_search(const Graph & g, uint32_t source) - { + static void depth_first_search(const Graph & g, uint32_t source) { static const uint32_t MARK = 0xDEAD; Graph::Adjacent * root = g[source]; @@ -78,7 +75,7 @@ namespace alg 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); @@ -92,7 +89,7 @@ namespace alg } } } - + printf("\n"); } } diff --git a/include/hash_multi.h b/include/hash_multi.h index d8a98f57..bc75cb37 100644 --- a/include/hash_multi.h +++ b/include/hash_multi.h @@ -23,21 +23,19 @@ #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; @@ -50,8 +48,7 @@ namespace alg /** * 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)); int i; diff --git a/include/hash_string.h b/include/hash_string.h index 75f60857..52d1b7cf 100644 --- a/include/hash_string.h +++ b/include/hash_string.h @@ -17,14 +17,12 @@ #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 - 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; + 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; 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(uint32_t key) const { + // hash the key using a hash function. + uint32_t hash = multi_hash(m_multi, 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(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; + } + } + + 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 T& operator[] (uint32_t key) const { + // hash the key using a hash function. + uint32_t hash = multi_hash(m_multi, 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 [] + */ + 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; + } + } } - } - } - }; + }; } #endif // diff --git a/include/heap.h b/include/heap.h index b81acea8..0aa8cc10 100644 --- a/include/heap.h +++ b/include/heap.h @@ -30,8 +30,8 @@ namespace alg { /** - * define binary heap structure. - */ + * define binary heap structure. + */ template class Heap { private: diff --git a/include/heap_sort.h b/include/heap_sort.h index 585bcbc4..7c4d3455 100644 --- a/include/heap_sort.h +++ b/include/heap_sort.h @@ -9,7 +9,7 @@ * * 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 + it has the advantage of a more favorable worst-case O(n log n) runtime * * http://en.wikipedia.org/wiki/Heapsort * @@ -20,38 +20,34 @@ #include -namespace alg -{ - - +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 heap(number_of_elements); + int i; + + // In order to build a heap structure from input array + for(i=0;i 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..6a23ab52 100644 --- a/include/imath.h +++ b/include/imath.h @@ -8,7 +8,7 @@ * COMMON MATH OPS * ******************************************************************************/ - + #ifndef __IMATH_H__ #define __IMATH_H__ @@ -16,13 +16,11 @@ #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..82594b23 100644 --- a/include/insertion_sort.h +++ b/include/insertion_sort.h @@ -16,27 +16,25 @@ #ifndef __INSERTION_SORT_H__ #define __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) + 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..f177d5ad 100644 --- a/include/integer.h +++ b/include/integer.h @@ -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..8d8336a2 100644 --- a/include/interval_tree.h +++ b/include/interval_tree.h @@ -27,230 +27,218 @@ #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; - - /* 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); - - 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; - } + /** + * 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; + } - if (n->parent == NULL && child != NULL) - child->color = BLACK; + // fixup the 'm' value until m is not the max value of the path. + fixup_m(n); - delete(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); + } - void print() { - print_helper(IVLNODE(get_root()), 0); - puts(""); - } + 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; + } - void print_helper(ivltree_node n, int indent) { - int i; + if (n->parent == NULL && child != NULL) + child->color = BLACK; - if (n == NULL) { - fputs("", stdout); - return; + delete(n); } - if (n->right != NULL) { - print_helper(IVLNODE(n->right), indent + INDENT_STEP); + void print() { + print_helper(IVLNODE(get_root()), 0); + puts(""); } - 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())); - } - private: + void print_helper(ivltree_node n, int indent) { + int i; - void destruct(ivltree_node n) - { - if (n==NULL) return; - destruct(IVLNODE(n->left)); - destruct(IVLNODE(n->right)); - delete n; - } + if (n == NULL) { + fputs("", stdout); + 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))); - } + 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); + } + } - void rotate_right_callback(rbtree_node n, rbtree_node parent) - { - rotate_left_callback(n, parent); - } + ~IntervalTree() { + destruct(IVLNODE(get_root())); + } - /** - * 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..953430de 100644 --- a/include/k-means.h +++ b/include/k-means.h @@ -11,7 +11,7 @@ * First Contributor: * https://github.com/wycg1984 ******************************************************************************/ - + #ifndef __KMEANS_H__ #define __KMEANS_H__ #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..ada982a1 100644 --- a/include/kmp.h +++ b/include/kmp.h @@ -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) { From e63e01473251a46c83c33df61c1a17dacf944ec7 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 6 Nov 2013 15:10:34 +0800 Subject: [PATCH 093/217] indent files --- include/kruskal_mst.h | 256 ++++++++++--------- include/lcs.h | 89 ++++--- include/merge_sort.h | 50 ++-- include/perfect_hash.h | 279 +++++++++++---------- include/prim_mst.h | 280 +++++++++++---------- include/prime.h | 40 ++- include/priority_queue.h | 194 +++++++-------- include/queue.h | 212 ++++++++-------- include/quick_sort.h | 55 ++--- include/radix_sort.h | 12 +- include/random.h | 2 +- include/random_select.h | 63 +++-- include/rbtree.h | 296 +++++++++++----------- include/rbtree_defs.h | 471 +++++++++++++++++------------------ include/relabel_to_front.h | 39 +-- include/shuffle.h | 26 +- include/simhash.h | 78 +++--- include/skiplist.h | 37 +-- include/sol.h | 9 +- include/stack.h | 201 ++++++++------- include/trie.h | 183 +++++++------- include/undirected_graph.h | 197 ++++++++------- include/universal_hash.h | 12 +- include/word_seg.h | 486 ++++++++++++++++++------------------- src/stack_demo.cpp | 1 + 25 files changed, 1705 insertions(+), 1863 deletions(-) diff --git a/include/kruskal_mst.h b/include/kruskal_mst.h index 714d7f58..e5305868 100644 --- a/include/kruskal_mst.h +++ b/include/kruskal_mst.h @@ -34,124 +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.insert(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); @@ -161,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); @@ -175,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..3b65a532 100644 --- a/include/lcs.h +++ b/include/lcs.h @@ -18,70 +18,67 @@ #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, 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); + } } - } } #endif // diff --git a/include/merge_sort.h b/include/merge_sort.h index f0effe15..8a45aece 100644 --- a/include/merge_sort.h +++ b/include/merge_sort.h @@ -35,57 +35,49 @@ #ifndef __MERGE_SORT_H__ #define __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 - 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"; + } + }; + + // Level-2 Slot definition + class 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; + } + }; - // Level-2 Slot definition - class SlotL2 { - public: - uint32_t cnt; // collison count - uint32_t key; //key - T value; // value - }; + struct SlotL1 * slots; // level 1 slots + struct UHash params; // 1st level + uint32_t num_slots; + const PerfHTException error; - // Level-1 Slot definition - struct SlotL1 { - public: - uint32_t cnt; // collison count - struct UHash params; // 2nd level - struct SlotL2 * lv2_slots; // level 2 slots + public: + PerfHT(uint32_t keys[], uint32_t len) { + // remove duplicate keys + uint32_t newlen = remove_dup(keys, len); - uint32_t key; // key - T value; // value + // 1-level hashing + uhash_init(&this->params, newlen); - ~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); - }; + 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); + }; + + ~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; + } + } + + throw error; + } - ~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..bf9b8bc5 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -31,161 +31,153 @@ #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); +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; + + ~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 + 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;} + + /** + * 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; } - - 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 - - // 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; + 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 + + // 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(); } - break; - } else { - pa->heap.delete_min(); } } - } - 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; - }; + 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); + 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); + } + printf("}\n"); } - printf("}\n"); } - } }; } diff --git a/include/prime.h b/include/prime.h index 64bf1538..8780dfd3 100644 --- a/include/prime.h +++ b/include/prime.h @@ -18,28 +18,26 @@ #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; + for (unsigned int i = 2; i <= sqrtn; ++i) { + 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..4a8dbe28 100644 --- a/include/priority_queue.h +++ b/include/priority_queue.h @@ -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 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); + 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 ff4e2d59..bb099207 100644 --- a/include/queue.h +++ b/include/queue.h @@ -20,129 +20,119 @@ #include #include -namespace alg -{ +namespace alg { /** * Queue Definition */ template - class Queue - { - private: - class QueueEmptyException: public std::exception - { - public: - virtual const char * what() const throw() - { - return "Queue is empty."; - } - }; + class Queue { + private: + class QueueEmptyException: public std::exception { + public: + virtual const char * what() const throw() { + return "Queue is 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 + 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 - const QueueEmptyException exp_empty; + const QueueEmptyException exp_empty; - 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; - }; + 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; + }; - ~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; - }; + ~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; + }; - /** - * return the front element. - */ - inline const T& front() const - { - if (m_size==0) throw exp_empty; - return m_elements[m_front]; - }; + /** + * return the front element. + */ + inline const T& front() const { + if (m_size==0) throw exp_empty; + return m_elements[m_front]; + }; - /** - * test weather the queue is empty - */ - inline bool is_empty() const - { - if (m_size ==0) return true; - return false; - }; + /** + * test weather the queue is empty + */ + inline bool is_empty() const { + if (m_size ==0) return true; + return false; + }; - /** - * 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; - } - }; + /** + * 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 count. - */ - inline uint32_t count() const { return m_size; }; + /** + * return the queue count. + */ + inline uint32_t count() const { return m_size; }; - /** - * return the queue capacity. - */ - inline uint32_t capcity() const { return m_capacity; }; - }; + /** + * return the queue capacity. + */ + inline uint32_t capcity() const { return m_capacity; }; + }; } #endif // diff --git a/include/quick_sort.h b/include/quick_sort.h index 633e63d2..b8962216 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -20,48 +20,43 @@ #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..4272ce48 100644 --- a/include/radix_sort.h +++ b/include/radix_sort.h @@ -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,8 +49,7 @@ 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); @@ -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..456ab698 100644 --- a/include/random.h +++ b/include/random.h @@ -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 144538e4..3577bdd9 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -22,51 +22,50 @@ #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; - 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); + int pivot_idx = __partition(list, begin, end); + int human_idx = pivot_idx - begin + 1; - return pivot_idx; - } + 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); + + return pivot_idx; + } } #endif // diff --git a/include/rbtree.h b/include/rbtree.h index ae558ec8..21b2f2a6 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -22,173 +22,165 @@ #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); + } + + /** + * contain test + */ + bool contains(KeyT key) { + if (lookup_node(key)) + return true; + return false; } - 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; - } + /** + * 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; + } - /** - * 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; - } + /** + * 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; + } - 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); - } + 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); + } - 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); - } - } + 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 * 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) { + 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..5eaf16fc 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -20,276 +20,243 @@ #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 index a7b5c54f..6b988ffb 100644 --- a/include/relabel_to_front.h +++ b/include/relabel_to_front.h @@ -20,10 +20,8 @@ #include "hash_table.h" #include "2darray.h" -namespace alg -{ - class RelabelToFront - { +namespace alg { + class RelabelToFront { private: const Graph & g; DirectedGraph * possible_residual_edge; // record possible residual edges @@ -41,8 +39,7 @@ namespace alg 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()) - { + e(g.vertex_count()), h(g.vertex_count()) { Graph::Adjacent * a; int id=0; list_for_each_entry(a, &g.list(), a_node){ @@ -71,13 +68,11 @@ namespace alg } } - ~RelabelToFront() - { + ~RelabelToFront() { delete possible_residual_edge; } - void initialize_preflow(uint32_t src) - { + 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; @@ -99,8 +94,7 @@ namespace alg } } - void push(int from, int to) - { + 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; @@ -108,13 +102,11 @@ namespace alg e[to] += delta; } - void relabel(int from, int height) - { + void relabel(int from, int height) { h[from] = height + 1; } - void relabel(int from) - { + void relabel(int from) { int min_height = INT_MAX; Graph::Adjacent * a = (* possible_residual_edge)[from]; Graph::Vertex * v; @@ -134,8 +126,7 @@ namespace alg h[from] = min_height + 1; } - void discharge(int from) - { + void discharge(int from) { if (e[from] <= 0){ return; } @@ -164,8 +155,7 @@ namespace alg } } - int run(uint32_t src, uint32_t sink) - { + int run(uint32_t src, uint32_t sink) { initialize_preflow(src); DirectedGraph * VertexList = new DirectedGraph; @@ -197,19 +187,16 @@ namespace alg /* * 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) - { + 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) - { + if (e[from] > 0) { overflow = true; bool need_relabel = true, residual_edge = false; int min_height = INT_MAX; diff --git a/include/shuffle.h b/include/shuffle.h index 49d2ae3e..fe8b97ab 100644 --- a/include/shuffle.h +++ b/include/shuffle.h @@ -21,26 +21,24 @@ #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..f68e9e58 100644 --- a/include/simhash.h +++ b/include/simhash.h @@ -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 -namespace alg -{ +namespace alg { template - class SkipList - { + class SkipList { private: struct SkipNode { KeyT key; // key @@ -37,25 +35,21 @@ namespace alg static const int SL_MAX_LEVEL = 6; - class NotFoundException: public std::exception - { + class NotFoundException: public std::exception { public: - virtual const char * what() const throw() - { + virtual const char * what() const throw() { return "cannot find the element in skiplist"; } }; const NotFoundException excp_notfound; public: - SkipList() - { + SkipList() { m_header = make_node(SL_MAX_LEVEL, 0, 0); m_level = 0; } - ~SkipList() - { + ~SkipList() { // TODO: free nodes } @@ -68,8 +62,7 @@ namespace alg * search the given key from the skip list * 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 @@ -87,8 +80,7 @@ namespace alg /** * 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); @@ -127,8 +119,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); @@ -157,8 +148,7 @@ namespace alg } } - void print() - { + void print() { for(int i=m_level-1;i>=0;i--) { SkipNode* x = m_header->forward[i]; printf("{"); @@ -180,8 +170,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) @@ -193,8 +182,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 @@ -204,7 +192,6 @@ namespace alg return n; } - }; } diff --git a/include/sol.h b/include/sol.h index cfca2e59..070ee4c5 100644 --- a/include/sol.h +++ b/include/sol.h @@ -20,13 +20,11 @@ #define __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); @@ -36,8 +34,7 @@ namespace alg /** * 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; diff --git a/include/stack.h b/include/stack.h index bfcfaac1..362d04f9 100644 --- a/include/stack.h +++ b/include/stack.h @@ -21,109 +21,104 @@ #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[] (uint32_t 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"; + } + }; + + 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. + */ + 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[] (uint32_t idx) const { + if (idx<0 || idx >= m_capacity) throw exp_ioob; + return m_elements[m_size-1-idx]; + } + }; +} #endif // diff --git a/include/trie.h b/include/trie.h index efae60c3..d79486e5 100644 --- a/include/trie.h +++ b/include/trie.h @@ -20,107 +20,106 @@ 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(char *str) { + char * _str = strdup(str); + _lowercase(_str); + + int cnt = _count(m_root, _str); + free(_str); + return cnt; + } + + int CountPrefix(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, 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, 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..43cbc40e 100644 --- a/include/undirected_graph.h +++ b/include/undirected_graph.h @@ -25,114 +25,107 @@ #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++; + + 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--; + // 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--; + } } } - } }; } diff --git a/include/universal_hash.h b/include/universal_hash.h index 9b44e60c..29afcf7d 100644 --- a/include/universal_hash.h +++ b/include/universal_hash.h @@ -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; @@ -69,8 +66,7 @@ namespace alg * hash an arbitary 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..21d52384 100644 --- a/include/word_seg.h +++ b/include/word_seg.h @@ -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,283 @@ 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(); - } + static const int GB18030_NR = 70244; - /** - * add a new word to the hashtable - */ - void add_word(const char * word) - { - int i=0; - int len = strlen(word); - int num_char = 0; + /** + * The word segmentation structure. + */ + private: + HashTable wordht; // a WORD-> WordEP hashtable + uint32_t words[GB18030_NR]; // every char in GB18030 - while(word[i]!='\0') { - uint32_t CH; - i+= gb18030_read(word, i, &CH); - num_char++; + 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/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); From b706137d4f49e1b23c3d33af8bf8c1590025b296 Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 6 Nov 2013 17:58:20 +0800 Subject: [PATCH 094/217] indent file --- include/astar.h | 232 ++++++++++++++++++++++++------------------------ 1 file changed, 114 insertions(+), 118 deletions(-) diff --git a/include/astar.h b/include/astar.h index d376546e..c15b2981 100644 --- a/include/astar.h +++ b/include/astar.h @@ -30,138 +30,134 @@ #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; + 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) : m_grid(grid), 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++; - } + /** + * 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]; + as->path = new int[2*as->num_nodes]; - 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; + 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; } - return as; - } - 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; - } - - // 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); + 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; + } + + // 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); + } } } } } + 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)); } - 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)); - } }; } From 89805546109d6de78cb0e48575aa98d30359213f Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 7 Nov 2013 10:58:04 +0800 Subject: [PATCH 095/217] update hash_table --- include/dijkstra.h | 6 ++--- include/hash_table.h | 60 +++++++++++++++++++++++++++++++++-------- src/dijkstra_demo.cpp | 2 +- src/hash_table_demo.cpp | 2 +- 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index e5722b00..759e4ecc 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -41,7 +41,7 @@ namespace alg { private: const Graph & g; Heap Q; // a binary heap - HashTable dist; // distance hash table + HashTable dist; // distance hash table public: static const int UNDEFINED = -1; /** @@ -52,9 +52,9 @@ namespace alg { dist(g.vertex_count()) {} // run dijkstra algorithm, and return the previous table - HashTable * run(uint32_t src_id) { + HashTable * run(uint32_t src_id) { // previous vertex hash table - HashTable * previous = new HashTable(g.vertex_count()); + HashTable * previous = new HashTable(g.vertex_count()); Q.clear(); dist.clear(); diff --git a/include/hash_table.h b/include/hash_table.h index ce81e925..fcf40881 100644 --- a/include/hash_table.h +++ b/include/hash_table.h @@ -18,24 +18,62 @@ #define __HASH_TABLE_H__ #include +#include #include #include #include "double_linked_list.h" #include "hash_multi.h" +#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; + } + }; + + /** * definition of a hash table. */ - template + template > class HashTable { + typedef _Key key_type; + typedef _Value value_type; + typedef _HashCode hash_code_fn; private: /** * definiton of Key-Value pair. */ struct HashKV { - uint32_t key; // 32-bit key - T value; // value + key_type key; // 32-bit key + value_type value; // value struct list_head node; // KV is a list element. }; @@ -79,9 +117,9 @@ namespace alg { /** * test if the hash table has the key */ - bool contains(uint32_t key) const { + bool contains(key_type key) const { // hash the key using a hash function. - uint32_t hash = multi_hash(m_multi, key); + uint32_t hash = multi_hash(m_multi, hash_code_fn()(key)); // we iterate through the list. HashKV * kv; @@ -96,9 +134,9 @@ namespace alg { /** * delete by key */ - bool delete_key(uint32_t key) { + bool delete_key(key_type key) { // hash the key using a hash function. - uint32_t hash = multi_hash(m_multi, key); + 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) { @@ -113,9 +151,9 @@ namespace alg { } // const version of operator [] - const T& operator[] (uint32_t key) const { + const value_type& operator[] (key_type key) const { // hash the key using a hash function. - uint32_t hash = multi_hash(m_multi, key); + uint32_t hash = multi_hash(m_multi, hash_code_fn()(key)); // we iterate through the list. HashKV * kv; @@ -136,8 +174,8 @@ namespace alg { /** * operator [] */ - T& operator[] (uint32_t key) { - return const_cast(static_cast(*this)[key]); + value_type& operator[] (key_type key) { + return const_cast(static_cast(*this)[key]); } void clear() { diff --git a/src/dijkstra_demo.cpp b/src/dijkstra_demo.cpp index 61cc6374..65790b04 100644 --- a/src/dijkstra_demo.cpp +++ b/src/dijkstra_demo.cpp @@ -47,7 +47,7 @@ int main(void) Dijkstra dijkstra(*g); Graph::Adjacent * a; printf("finding Dijkstra shortest path starting from 0: \n"); - HashTable * result = dijkstra.run(0); + HashTable * result = dijkstra.run(0); list_for_each_entry(a, &g->list(), a_node){ printf("previous of %u is ", a->v.id); 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; From f8b7ee9041ca4218c2871c9b607dadc853869870 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 7 Nov 2013 11:04:16 +0800 Subject: [PATCH 096/217] using new hash_table --- include/astar.h | 2 +- include/bellman_ford.h | 7 +++---- include/edmonds_karp.h | 10 +++++----- include/graph_search.h | 4 ++-- include/huffman.h | 2 +- include/relabel_to_front.h | 16 ++++++++-------- include/word_seg.h | 2 +- src/bellman_ford_demo.cpp | 4 ++-- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/include/astar.h b/include/astar.h index c15b2981..9dd67df5 100644 --- a/include/astar.h +++ b/include/astar.h @@ -84,7 +84,7 @@ namespace alg { openset.insert(0, x1*ncol+y1); // The map of navigated nodes. - HashTable came_from(nrow*ncol); + HashTable came_from(nrow*ncol); g_score(x1,y1) = 0.0f; f_score(x1,y1) = g_score(x1,y1) + estimate(x1,y1,x2,y2); diff --git a/include/bellman_ford.h b/include/bellman_ford.h index 37e1d4f0..2d6df417 100644 --- a/include/bellman_ford.h +++ b/include/bellman_ford.h @@ -62,7 +62,7 @@ namespace alg { class BellmanFord { private: - HashTable dist; // hash table for distance. + HashTable dist; // hash table for distance. bool has_neg_cycle; // negative weighted cycle mark. const Graph & g; public: @@ -72,10 +72,9 @@ namespace alg { /** * Bellman-Ford algorithm */ - HashTable * run(uint32_t source) - { + HashTable * run(uint32_t source) { // hash table for previous vertex - HashTable * previous = new HashTable(g.vertex_count()); + HashTable * previous = new HashTable(g.vertex_count()); // source vertex dist[source] = 0; diff --git a/include/edmonds_karp.h b/include/edmonds_karp.h index a485798e..7223a78c 100644 --- a/include/edmonds_karp.h +++ b/include/edmonds_karp.h @@ -41,11 +41,11 @@ namespace alg { private: const Graph & g; Array2D m_residual; // residual network , 2d array - HashTable m_pre; // pre node of current node + 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. + HashTable m_map; // vertex id to ordinary row/col number mapping + HashTable m_rmap; // reverse mapping of map. public: EdmondsKarp(const Graph & graph): @@ -114,8 +114,8 @@ namespace alg { } 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 & map() const { return m_map;} + inline const HashTable & rmap() const { return m_rmap;} private: /** diff --git a/include/graph_search.h b/include/graph_search.h index 9d2be927..e378b100 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -37,7 +37,7 @@ namespace alg { static const uint32_t MARK = 0xDEAD; Graph::Adjacent * root = g[source]; - HashTable ht(g.vertex_count()); + HashTable ht(g.vertex_count()); if (root==NULL) return; @@ -67,7 +67,7 @@ namespace alg { static const uint32_t MARK = 0xDEAD; Graph::Adjacent * root = g[source]; - HashTable ht(g.vertex_count()); + HashTable ht(g.vertex_count()); if (root==NULL) return; diff --git a/include/huffman.h b/include/huffman.h index b940a23e..b47a4d12 100644 --- a/include/huffman.h +++ b/include/huffman.h @@ -54,7 +54,7 @@ namespace alg { }; private: - HashTable m_symbol; // hash table for encoding + 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 diff --git a/include/relabel_to_front.h b/include/relabel_to_front.h index 6b988ffb..c8a4d950 100644 --- a/include/relabel_to_front.h +++ b/include/relabel_to_front.h @@ -28,11 +28,11 @@ namespace alg { Array2D m_residual; - HashTable m_map; - HashTable m_rmap; + HashTable m_map; + HashTable m_rmap; - HashTable e; //excess flow - HashTable h; //value of height function + HashTable e; //excess flow + HashTable h; //value of height function public: RelabelToFront(const Graph & graph): @@ -231,10 +231,10 @@ namespace alg { } 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; } + 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; } }; } diff --git a/include/word_seg.h b/include/word_seg.h index 21d52384..623f0e82 100644 --- a/include/word_seg.h +++ b/include/word_seg.h @@ -122,7 +122,7 @@ namespace alg { * The word segmentation structure. */ private: - HashTable wordht; // a WORD-> WordEP hashtable + HashTable wordht; // a WORD-> WordEP hashtable uint32_t words[GB18030_NR]; // every char in GB18030 public: diff --git a/src/bellman_ford_demo.cpp b/src/bellman_ford_demo.cpp index 5bd5b21e..9814e699 100644 --- a/src/bellman_ford_demo.cpp +++ b/src/bellman_ford_demo.cpp @@ -46,7 +46,7 @@ int main(void) 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) { @@ -64,7 +64,7 @@ int main(void) g->add_edge(2,0, -1); BellmanFord bf2(*g); - std::auto_ptr > previous2(bf2.run(0)); + std::auto_ptr > previous2(bf2.run(0)); printf("\nwe %s have negative weighted cycle.\n", bf2.has_negative_cycle()?"DO":"DON'T"); From f28a328f06928354f0ad342ad2042a2475f1d1af Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 7 Nov 2013 11:12:55 +0800 Subject: [PATCH 097/217] update edmonds_karp --- include/edmonds_karp.h | 69 +++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/include/edmonds_karp.h b/include/edmonds_karp.h index 7223a78c..396c9fbc 100644 --- a/include/edmonds_karp.h +++ b/include/edmonds_karp.h @@ -40,42 +40,41 @@ namespace alg { class EdmondsKarp { private: const Graph & g; - Array2D m_residual; // residual network , 2d array - HashTable m_pre; // pre node of current node + 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. + 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++; - } + 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); + // 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; + 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; @@ -85,10 +84,10 @@ namespace alg { * edmonds karp algorithm for maximal flow * returns the maxflow from src to sink */ - uint32_t run(uint32_t src, uint32_t sink) { + uint32_t run(int32_t src, int32_t sink) { // find augument path repeatedly. - int _src = m_map[src]; - int _sink = m_map[sink]; + int32_t _src = m_map[src]; + int32_t _sink = m_map[sink]; uint32_t maxflow = 0; @@ -114,14 +113,14 @@ namespace alg { } 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 & 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(uint32_t _src, uint32_t _sink) { + bool find_path(int32_t _src, int32_t _sink) { Queue Q(g.vertex_count()); // clear visit flag & path @@ -141,7 +140,7 @@ namespace alg { m_pre[i] = p; m_visits[i] = true; - if (i==_sink) { // nice, we've got to sink point. + if (i==uint32_t(_sink)) { // nice, we've got to sink point. return true; } Q.enqueue(i); From 97bafa3b9ad0114d8578df6f25b0ff5349b6bfee Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 7 Nov 2013 13:07:30 +0800 Subject: [PATCH 098/217] update some type mismatch --- include/heap.h | 19 ++++++++++--------- include/trie.h | 11 +++++------ src/huffman_demo.cpp | 4 ++-- src/max_subarray_demo.cpp | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/heap.h b/include/heap.h index 0aa8cc10..252f6dcd 100644 --- a/include/heap.h +++ b/include/heap.h @@ -40,13 +40,14 @@ namespace alg { */ struct KV { public: - int key; + int32_t key; T value; }; - uint32_t m_size; // current heap size. - uint32_t m_max; // max heap size. + int32_t m_size; // current heap size. + int32_t m_max; // max heap size. KV * m_kvs; // key value pairs. + //HashTable public: Heap(int max) { m_size = 0; @@ -108,7 +109,7 @@ namespace alg { * contains test */ bool contains(const T & value) { - for(uint32_t i=1;i<=m_size;i++) { + for(int32_t i=1;i<=m_size;i++) { if(m_kvs[i].value == value) return true; } @@ -125,9 +126,9 @@ namespace alg { // 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; + int32_t lastKey; T lastValue; - uint32_t child,now; + int32_t child,now; // empty heap, just return if (m_size == 0) return; @@ -166,9 +167,9 @@ namespace alg { * step 1. find the value * step 2. decrease the key to the newkey */ - void decrease_key(const T & value, int newkey) { - uint32_t index = m_size+1; - for (uint32_t i=1;i<=m_size;i++) { + void decrease_key(const T & value, int32_t newkey) { + int32_t index = m_size+1; + for (int32_t i=1;i<=m_size;i++) { if (m_kvs[i].value == value) { index = i; break; diff --git a/include/trie.h b/include/trie.h index d79486e5..c9990f28 100644 --- a/include/trie.h +++ b/include/trie.h @@ -54,7 +54,7 @@ namespace alg { _add(m_root, str); } - int Count(char *str) { + int Count(const char *str) { char * _str = strdup(str); _lowercase(_str); @@ -63,7 +63,7 @@ namespace alg { return cnt; } - int CountPrefix(char *prefix) { + int CountPrefix(const char *prefix) { char * _str = strdup(prefix); _lowercase(_str); @@ -73,15 +73,14 @@ namespace alg { } private: - void _lowercase(char *str) - { + void _lowercase(char *str) { int i; for (i=0;str[i];i++) { str[i] = tolower(str[i]); } } - void _add(node *n, char * str) { + void _add(node *n, const char * str) { if (str[0] == '\0') { n->words++; } else { @@ -95,7 +94,7 @@ namespace alg { } } - int _count(node *n, char * str) { + int _count(node *n, const char * str) { if (str[0] == '\0') { return n->words; } else { 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/max_subarray_demo.cpp b/src/max_subarray_demo.cpp index 012aef75..1ef7aa06 100644 --- a/src/max_subarray_demo.cpp +++ b/src/max_subarray_demo.cpp @@ -11,7 +11,7 @@ int main() { int i; printf("the array:\n"); - for (i=0;i Date: Thu, 7 Nov 2013 13:15:17 +0800 Subject: [PATCH 099/217] seperate hash_code into different file --- include/hash_code.h | 37 +++++++++++++++++++++++++++++++++++++ include/hash_table.h | 35 +---------------------------------- 2 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 include/hash_code.h diff --git a/include/hash_code.h b/include/hash_code.h new file mode 100644 index 00000000..3a6daae6 --- /dev/null +++ b/include/hash_code.h @@ -0,0 +1,37 @@ +#ifndef __HASH_CODE_H__ +#define __HASH_CODE_H__ +#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_table.h b/include/hash_table.h index fcf40881..0fcdb713 100644 --- a/include/hash_table.h +++ b/include/hash_table.h @@ -22,43 +22,10 @@ #include #include #include "double_linked_list.h" +#include "hash_code.h" #include "hash_multi.h" -#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; - } - }; - - /** * definition of a hash table. */ From 7f94591ddb414005bf350666b76b84c475db82f7 Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 7 Nov 2013 18:13:42 +0800 Subject: [PATCH 100/217] update heap --- include/hash_code.h | 1 + include/heap.h | 32 ++++++++++++++++---------------- src/heap_demo.cpp | 6 +++--- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/include/hash_code.h b/include/hash_code.h index 3a6daae6..89f22b2b 100644 --- a/include/hash_code.h +++ b/include/hash_code.h @@ -1,5 +1,6 @@ #ifndef __HASH_CODE_H__ #define __HASH_CODE_H__ +#include #include "hash_string.h" namespace alg { /** diff --git a/include/heap.h b/include/heap.h index 252f6dcd..59856d6b 100644 --- a/include/heap.h +++ b/include/heap.h @@ -27,6 +27,8 @@ #include #include #include +#include "hash_code.h" +#include "hash_table.h" namespace alg { /** @@ -43,21 +45,24 @@ namespace alg { int32_t key; T value; }; - int32_t m_size; // current heap size. + int32_t m_size; // current heap size. int32_t m_max; // max heap size. KV * m_kvs; // key value pairs. - //HashTable + HashTable * m_idx; // key -> idx + public: Heap(int max) { m_size = 0; m_max = max+1; m_kvs = new KV[m_max]; m_kvs[0].key = INT_MIN; + m_idx = new HashTable(m_max); }; ~Heap() { delete [] m_kvs; + delete m_idx; }; private: @@ -83,16 +88,19 @@ namespace alg { m_size++; m_kvs[m_size].key = key; m_kvs[m_size].value = value; + (*m_idx)[key] = m_size; // Adjust its position int now = m_size; while(m_kvs[now/2].key > key) { m_kvs[now] = m_kvs[now/2]; + (*m_idx)[m_kvs[now/2].key] = now; now /= 2; } m_kvs[now].key = key; m_kvs[now].value = value; + (*m_idx)[key] = now; } /** @@ -144,14 +152,14 @@ namespace alg { 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) { + if(child != m_size && m_kvs[child+1].key < m_kvs[child].key) { child++; // choose the minium one. } // To check if the last key fits or not it suffices to check // if the last key is less than the minimum key among both the children if(lastKey > m_kvs[child].key) { m_kvs[now] = m_kvs[child]; + (*m_idx)[child] = now; // record index } else { // It fits there break; @@ -160,6 +168,7 @@ namespace alg { m_kvs[now].key = lastKey; m_kvs[now].value= lastValue; + (*m_idx)[lastKey] = now; // record index } /** @@ -167,17 +176,9 @@ namespace alg { * step 1. find the value * step 2. decrease the key to the newkey */ - void decrease_key(const T & value, int32_t newkey) { - int32_t index = m_size+1; - for (int32_t i=1;i<=m_size;i++) { - if (m_kvs[i].value == value) { - index = i; - break; - } - } - - if (index > m_size) return; // value not found - + void decrease_key(int32_t oldkey, int32_t newkey) { + int32_t index = (*m_idx)[oldkey]; + if (index > m_size || index == 0) return; // value not found if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning. int now = index; @@ -187,7 +188,6 @@ namespace alg { } m_kvs[now].key = newkey; - m_kvs[now].value= value; } }; } diff --git a/src/heap_demo.cpp b/src/heap_demo.cpp index 7f75582f..70a5d6ee 100644 --- a/src/heap_demo.cpp +++ b/src/heap_demo.cpp @@ -8,12 +8,12 @@ int main() using namespace alg; int MAXELEMENTS=50; Heap heap(MAXELEMENTS); - - int i; + + int32_t i; srand(time(NULL)); for (i=0;i < MAXELEMENTS; i++) { int value = rand()%1000; - heap.insert(100-i, value); + heap.insert(i, value); printf("inserting: %d->%d\n", 100-i, value); } From 0e48b81e95794693251535d26a5c85eea83232b3 Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 7 Nov 2013 22:13:16 +0800 Subject: [PATCH 101/217] update dijkstra --- include/dijkstra.h | 63 +++++++++++++++---------------------------- src/dijkstra_demo.cpp | 5 ++-- 2 files changed, 24 insertions(+), 44 deletions(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index 759e4ecc..195dea14 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -34,65 +34,46 @@ #include "hash_table.h" namespace alg { - /** - * the dijkstra algorithm workspace - */ 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) { + static HashTable * run(const struct Graph & g, uint32_t src_id) { + // a binary heap + Heap Q(g.vertex_count()); + // distance hash table + HashTable dist(g.vertex_count()); // previous vertex hash table - HashTable * previous = new HashTable(g.vertex_count()); - - Q.clear(); - dist.clear(); - - // source - Graph::Adjacent * source = g[src_id]; - Q.insert(0, source->v.id); // weight->id binary heap - dist[source->v.id] = 0; + HashTable * previous = new HashTable(g.vertex_count()); + // record whether the vertex is visited + HashTable visited(g.vertex_count()); - // other vertices + // all 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; + dist[a->v.id] = INT_MAX; // set inital distance to each vertex as INT_MAX + (*previous)[a->v.id] = UNDEFINED; // clear path to UNDEFINED + visited[a->v.id] = false; // all vertices are not visited } - while(!Q.is_empty()) { // The main loop - Graph::Adjacent * u = g[Q.min_value()]; - int dist_u = Q.min_key(); - Q.delete_min(); + // source vertex, the first vertex in Heap-Q + Q.insert(0, src_id); + dist[src_id] = 0; - if (dist_u == INT_MAX) { - break; - } + while(!Q.is_empty()) { // for every un-visited vertex, try relaxing the path + Graph::Adjacent * u = g[Q.min_value()]; // the vertex to process + int dist_u = dist[Q.min_value()]; // current known shortest distance to u + visited[Q.min_value()] = true; // mark the vertex as visited. + Q.delete_min(); // remove u from Q 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) { + if (alt < dist_v && !visited[v->id]) { dist[v->id] = alt; - Q.decrease_key(v->id, alt); (*previous)[v->id] = u->v.id; + Q.insert(alt, v->id); } } } diff --git a/src/dijkstra_demo.cpp b/src/dijkstra_demo.cpp index 65790b04..30d5118e 100644 --- a/src/dijkstra_demo.cpp +++ b/src/dijkstra_demo.cpp @@ -44,10 +44,9 @@ int main(void) std::auto_ptr g(randgraph(NVERTEX)); g->print(); - Dijkstra dijkstra(*g); Graph::Adjacent * a; printf("finding Dijkstra shortest path starting from 0: \n"); - HashTable * result = dijkstra.run(0); + HashTable * result = Dijkstra::run(*g, 0); list_for_each_entry(a, &g->list(), a_node){ printf("previous of %u is ", a->v.id); @@ -59,7 +58,7 @@ int main(void) printf("finding Dijkstra shortest path starting from 10: \n"); - result = dijkstra.run(10); + result = Dijkstra::run(*g, 10); list_for_each_entry(a, &g->list(), a_node){ printf("previous of %u is ", a->v.id); int32_t pre = (*result)[a->v.id]; From 9c20b1dafc1bacdc5ca52136f65075cf19849a99 Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 7 Nov 2013 23:11:36 +0800 Subject: [PATCH 102/217] update dijkstra --- include/dijkstra.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index 195dea14..998eb164 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -61,10 +61,15 @@ namespace alg { dist[src_id] = 0; while(!Q.is_empty()) { // for every un-visited vertex, try relaxing the path - Graph::Adjacent * u = g[Q.min_value()]; // the vertex to process - int dist_u = dist[Q.min_value()]; // current known shortest distance to u - visited[Q.min_value()] = true; // mark the vertex as visited. - Q.delete_min(); // remove u from Q + int32_t id = Q.min_value(); + Q.delete_min(); // remove u from Q + if (visited[id]) { // jump visited vertex + continue; + } + + Graph::Adjacent * u = g[id]; // the vertex to process + int dist_u = dist[id]; // current known shortest distance to u + visited[id] = true; // mark the vertex as visited. Graph::Vertex * v; list_for_each_entry(v, &u->v_head, v_node){ From eff43fa36ce88f5ee8491618469d591f2223c5a1 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 8 Nov 2013 10:12:58 +0800 Subject: [PATCH 103/217] update heap decrease-key --- include/heap.h | 5 ++++- src/heap_demo.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/heap.h b/include/heap.h index 59856d6b..d3d0bab4 100644 --- a/include/heap.h +++ b/include/heap.h @@ -159,7 +159,7 @@ namespace alg { // if the last key is less than the minimum key among both the children if(lastKey > m_kvs[child].key) { m_kvs[now] = m_kvs[child]; - (*m_idx)[child] = now; // record index + (*m_idx)[m_kvs[now].key] = now; // record index } else { // It fits there break; @@ -180,14 +180,17 @@ namespace alg { int32_t index = (*m_idx)[oldkey]; if (index > m_size || index == 0) return; // value not found if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning. + T oldvalue = m_kvs[index].value; int now = index; while(m_kvs[now/2].key > newkey) { m_kvs[now] = m_kvs[now/2]; + (*m_idx)[m_kvs[now].key] = now; // record index now /= 2; } m_kvs[now].key = newkey; + m_kvs[now].value = oldvalue; } }; } diff --git a/src/heap_demo.cpp b/src/heap_demo.cpp index 70a5d6ee..aa4d3ea3 100644 --- a/src/heap_demo.cpp +++ b/src/heap_demo.cpp @@ -6,18 +6,18 @@ int main() { using namespace alg; - int MAXELEMENTS=50; + int MAXELEMENTS=10; Heap heap(MAXELEMENTS); int32_t i; srand(time(NULL)); for (i=0;i < MAXELEMENTS; i++) { - int value = rand()%1000; + int32_t value = i; heap.insert(i, value); - printf("inserting: %d->%d\n", 100-i, value); + printf("inserting: %d->%d\n", i, value); } - int index = 20; + int index = 9; printf("decrease a key[%d] to %d\n", index, -1); heap.decrease_key(index, -1); while(!heap.is_empty()) { From 776260b9b730da72ce9a2bf21f3422eec8d44a93 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 8 Nov 2013 10:15:42 +0800 Subject: [PATCH 104/217] update dijkstra heap max value --- include/dijkstra.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index 998eb164..d91bf48f 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -40,7 +40,7 @@ namespace alg { // run dijkstra algorithm, and return the previous table static HashTable * run(const struct Graph & g, uint32_t src_id) { // a binary heap - Heap Q(g.vertex_count()); + Heap Q(g.vertex_count() + g.edge_count()); // distance hash table HashTable dist(g.vertex_count()); // previous vertex hash table From e42bd77ccb7ce0dd5abe60714163eb7d656c1f00 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 8 Nov 2013 13:00:12 +0800 Subject: [PATCH 105/217] add some print to dijkstra --- include/dijkstra.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index d91bf48f..c3a41af4 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -63,7 +63,8 @@ namespace alg { while(!Q.is_empty()) { // for every un-visited vertex, try relaxing the path int32_t id = Q.min_value(); Q.delete_min(); // remove u from Q - if (visited[id]) { // jump visited vertex + if (visited[id]) { // jump visited vertex, it means a closer vertex has found + // printf("visted:%d %d\n", id, dist[id]); continue; } @@ -76,6 +77,14 @@ namespace alg { uint32_t alt = dist_u + v->weight; uint32_t dist_v = dist[v->id]; if (alt < dist_v && !visited[v->id]) { + /* + uint32_t tmp = dist[v->id]; + if (tmp != INT_MAX) { + printf("old %d %d\n", v->id, tmp); + printf("new %d %d\n", v->id, dist[v->id]); + } + */ + dist[v->id] = alt; (*previous)[v->id] = u->v.id; Q.insert(alt, v->id); From 680cfba026029e65d2388210bee2b8fedecb873c Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 9 Nov 2013 11:24:10 +0800 Subject: [PATCH 106/217] output generic dot format --- include/directed_graph.h | 26 ++++++++++++++++++++++++++ include/graph_defs.h | 16 ++++++++++++++++ src/bellman_ford_demo.cpp | 2 +- src/dijkstra_demo.cpp | 12 ++++++------ 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/include/directed_graph.h b/include/directed_graph.h index cc2c2068..5c7cc7fd 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -46,6 +46,32 @@ namespace alg } } } + 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 diff --git a/include/graph_defs.h b/include/graph_defs.h index 213ba051..015d006d 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -125,6 +125,22 @@ namespace alg { } } + /** + * print a graph as graphviz '.dot' format + */ + void printdot() const { + Adjacent * a; + printf("digraph G {\n"); + printf("\tnode [shape = circle];\n"); + list_for_each_entry(a, &a_head, a_node){ + Vertex * v; + 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 diff --git a/src/bellman_ford_demo.cpp b/src/bellman_ford_demo.cpp index 9814e699..5a043287 100644 --- a/src/bellman_ford_demo.cpp +++ b/src/bellman_ford_demo.cpp @@ -41,7 +41,7 @@ int main(void) srand(time(NULL)); int NVERTEX = 50; DirectedGraph * g = randgraph(NVERTEX); - g->print(); + g->printdot(); BellmanFord bf(*g); diff --git a/src/dijkstra_demo.cpp b/src/dijkstra_demo.cpp index 30d5118e..50479691 100644 --- a/src/dijkstra_demo.cpp +++ b/src/dijkstra_demo.cpp @@ -24,8 +24,8 @@ DirectedGraph * randgraph(int nvertex) for(i=0;iadd_edge(i, j, w); } @@ -40,9 +40,9 @@ int main(void) { using namespace alg; srand(time(NULL)); - int NVERTEX = 50; + int NVERTEX = 10; std::auto_ptr g(randgraph(NVERTEX)); - g->print(); + g->printdot(); Graph::Adjacent * a; printf("finding Dijkstra shortest path starting from 0: \n"); @@ -56,9 +56,9 @@ int main(void) } delete result; - printf("finding Dijkstra shortest path starting from 10: \n"); + printf("finding Dijkstra shortest path starting from 1: \n"); - result = Dijkstra::run(*g, 10); + result = Dijkstra::run(*g, 1); list_for_each_entry(a, &g->list(), a_node){ printf("previous of %u is ", a->v.id); int32_t pre = (*result)[a->v.id]; From 193715acf3d1fee318388d570159624cf518413a Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 9 Nov 2013 11:50:37 +0800 Subject: [PATCH 107/217] output Graphviz Dot graph in demo --- include/directed_graph.h | 5 +++-- include/undirected_graph.h | 26 +++++++++++++++++++++++++ src/bellman_ford_demo.cpp | 32 ++----------------------------- src/dijkstra_demo.cpp | 29 +--------------------------- src/directed_graph_demo.cpp | 36 ++++------------------------------- src/edmonds_karp_demo.cpp | 32 ++----------------------------- src/graph_search_demo.cpp | 31 ++---------------------------- src/kruskal_mst_demo.cpp | 36 +++-------------------------------- src/prim_mst_demo.cpp | 32 +++---------------------------- src/relabel_to_front_demo.cpp | 33 ++------------------------------ src/undirected_graph_demo.cpp | 36 ++++------------------------------- 11 files changed, 52 insertions(+), 276 deletions(-) diff --git a/include/directed_graph.h b/include/directed_graph.h index 5c7cc7fd..2cd3c733 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -62,8 +62,9 @@ namespace alg for(i=0;iadd_edge(i, j, w); } diff --git a/include/undirected_graph.h b/include/undirected_graph.h index 43cbc40e..2d2afadb 100644 --- a/include/undirected_graph.h +++ b/include/undirected_graph.h @@ -126,6 +126,32 @@ namespace alg { } } } + /** + * randomly generate a graph, for test purpose + */ + static 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; + } }; } diff --git a/src/bellman_ford_demo.cpp b/src/bellman_ford_demo.cpp index 5a043287..00dffc71 100644 --- a/src/bellman_ford_demo.cpp +++ b/src/bellman_ford_demo.cpp @@ -8,39 +8,11 @@ #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); + int NVERTEX = 10; + DirectedGraph * g = DirectedGraph::randgraph(NVERTEX); g->printdot(); BellmanFord bf(*g); diff --git a/src/dijkstra_demo.cpp b/src/dijkstra_demo.cpp index 50479691..bb43d956 100644 --- a/src/dijkstra_demo.cpp +++ b/src/dijkstra_demo.cpp @@ -8,40 +8,13 @@ #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 = 10; - std::auto_ptr g(randgraph(NVERTEX)); + std::auto_ptr g(DirectedGraph::randgraph(NVERTEX)); g->printdot(); Graph::Adjacent * a; 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/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/graph_search_demo.cpp b/src/graph_search_demo.cpp index 2d031d66..67ca4b88 100644 --- a/src/graph_search_demo.cpp +++ b/src/graph_search_demo.cpp @@ -6,41 +6,14 @@ #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); 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/prim_mst_demo.cpp b/src/prim_mst_demo.cpp index b71a3f83..a51da33c 100644 --- a/src/prim_mst_demo.cpp +++ b/src/prim_mst_demo.cpp @@ -6,48 +6,22 @@ #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(); + UndirectedGraph * g = 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(); + mst->printdot(); delete mst; delete g; return 0; diff --git a/src/relabel_to_front_demo.cpp b/src/relabel_to_front_demo.cpp index 0184d136..85d32f41 100644 --- a/src/relabel_to_front_demo.cpp +++ b/src/relabel_to_front_demo.cpp @@ -5,35 +5,6 @@ #include "edmonds_karp.h" #include "relabel_to_front.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) { @@ -43,8 +14,8 @@ int main(void) clock_t ek_start, ek_end, pr_start, pr_end; - DirectedGraph * g = randgraph(NVERTEX); -// g->print(); + 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()); 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; } From 3e79e1b43fa46a0d1bf81c8f461b57bba6b79cc0 Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Sat, 9 Nov 2013 12:00:30 +0800 Subject: [PATCH 108/217] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d7536a4f..fe6d7941 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ 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 + 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.) ####已实现 ( Implemented ): From 071b4ed8ab64af756a5637d1295a41da5f6438c3 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 10 Nov 2013 10:40:26 +0800 Subject: [PATCH 109/217] remove a unnecessary assignment in rbtree --- include/dos_tree.h | 8 -------- include/interval_tree.h | 9 --------- include/rbtree.h | 4 +--- include/rbtree_defs.h | 2 +- src/rbtree_demo.cpp | 4 ++-- 5 files changed, 4 insertions(+), 23 deletions(-) diff --git a/include/dos_tree.h b/include/dos_tree.h index a45b88ca..7dc809e9 100644 --- a/include/dos_tree.h +++ b/include/dos_tree.h @@ -124,14 +124,6 @@ namespace alg { delete_case1(n); } replace_node(n, child); - // copy child value if exists - if (child != NULL) { - DOSNODE(n)->key = DOSNODE(child)->key; - DOSNODE(n)->size = DOSNODE(child)->size; - } - if (n->parent == NULL && child != NULL) - child->color = BLACK; - delete (DOSNODE(n)); } diff --git a/include/interval_tree.h b/include/interval_tree.h index 8d8336a2..b4f5ccd4 100644 --- a/include/interval_tree.h +++ b/include/interval_tree.h @@ -132,15 +132,6 @@ namespace alg { } 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; - } - - if (n->parent == NULL && child != NULL) - child->color = BLACK; - delete(n); } diff --git a/include/rbtree.h b/include/rbtree.h index 21b2f2a6..02afe01e 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -12,7 +12,7 @@ * 2. O(logn) lookup performance * * http://en.wikipedia.org/wiki/Red_black_tree - * + * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ #ifndef __RBTREE_H__ @@ -124,8 +124,6 @@ namespace alg { delete_case1(n); } replace_node(n, child); - if (n->parent == NULL && child != NULL) - child->color = BLACK; delete(n); } diff --git a/include/rbtree_defs.h b/include/rbtree_defs.h index 5eaf16fc..68a9f8f8 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -12,7 +12,7 @@ * 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__ diff --git a/src/rbtree_demo.cpp b/src/rbtree_demo.cpp index 23d7251d..59e7f343 100644 --- a/src/rbtree_demo.cpp +++ b/src/rbtree_demo.cpp @@ -46,7 +46,7 @@ int main() { int MAXELEMENT = 50; printf("Inserting: \t"); for(i=0; i Date: Mon, 11 Nov 2013 12:28:33 +0800 Subject: [PATCH 110/217] add demo_dot.svg --- demo_dot.svg | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 demo_dot.svg diff --git a/demo_dot.svg b/demo_dot.svg new file mode 100644 index 00000000..1a5e94da --- /dev/null +++ b/demo_dot.svg @@ -0,0 +1,154 @@ + + + + + + +G + + +0 + +0 + + +4 + +4 + + +0->4 + + +5 + + +5 + +5 + + +0->5 + + +7 + + +9 + +9 + + +0->9 + + +20 + + +7 + +7 + + +5->7 + + +29 + + +6 + +6 + + +5->6 + + +21 + + +1 + +1 + + +1->4 + + +87 + + +1->9 + + +38 + + +1->7 + + +28 + + +8 + +8 + + +1->8 + + +6 + + +7->8 + + +60 + + +3 + +3 + + +3->4 + + +48 + + +3->5 + + +54 + + +3->8 + + +3 + + +6->9 + + +40 + + +6->7 + + +61 + + +6->8 + + +14 + + + From c3a7adf9841f5c06454d21d6708ec15cac492185 Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Mon, 11 Nov 2013 12:30:43 +0800 Subject: [PATCH 111/217] Update README.md --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fe6d7941..4a41dfcf 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,15 @@ ####约定 ( Convention ): - 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.) + 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: + ![Architecture](/demo_dot.svg) ####已实现 ( Implemented ): From 40531ce8b7f2c48de2bf96d716bcc12dd8256814 Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Mon, 11 Nov 2013 12:35:22 +0800 Subject: [PATCH 112/217] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a41dfcf..5744da11 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ 5. Graph的输出格式为 [Graphviz](http://www.graphviz.org/) Dot格式. (the output format of the graph is in dot of graphviz.) eg: - ![Architecture](/demo_dot.svg) + ![demosvg](https://raw.github.com/xtaci/algorithms/master/demo_dot.svg) ####已实现 ( Implemented ): From b7c981ec385649e8aabca316b5e07638905a70a5 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 12:38:14 +0800 Subject: [PATCH 113/217] add demo_graph.png --- demo_dot.svg | 154 ------------------------------------------------- demo_graph.png | Bin 0 -> 54010 bytes 2 files changed, 154 deletions(-) delete mode 100644 demo_dot.svg create mode 100644 demo_graph.png diff --git a/demo_dot.svg b/demo_dot.svg deleted file mode 100644 index 1a5e94da..00000000 --- a/demo_dot.svg +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - -G - - -0 - -0 - - -4 - -4 - - -0->4 - - -5 - - -5 - -5 - - -0->5 - - -7 - - -9 - -9 - - -0->9 - - -20 - - -7 - -7 - - -5->7 - - -29 - - -6 - -6 - - -5->6 - - -21 - - -1 - -1 - - -1->4 - - -87 - - -1->9 - - -38 - - -1->7 - - -28 - - -8 - -8 - - -1->8 - - -6 - - -7->8 - - -60 - - -3 - -3 - - -3->4 - - -48 - - -3->5 - - -54 - - -3->8 - - -3 - - -6->9 - - -40 - - -6->7 - - -61 - - -6->8 - - -14 - - - diff --git a/demo_graph.png b/demo_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..86c8ac97d29fd3233dc4d543056b7fe85d672e96 GIT binary patch literal 54010 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 o*!tTUC}_&Rmo*Fhe-4zu^8f$< literal 0 HcmV?d00001 From eece9a5a74a8eae7746cc66dee67eb8e66beb802 Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Mon, 11 Nov 2013 12:38:51 +0800 Subject: [PATCH 114/217] Update README.md --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 5744da11..ba078ec6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ 5. Graph的输出格式为 [Graphviz](http://www.graphviz.org/) Dot格式. (the output format of the graph is in dot of graphviz.) eg: - ![demosvg](https://raw.github.com/xtaci/algorithms/master/demo_dot.svg) + ![demograph](demo_graph.png) ####已实现 ( Implemented ): @@ -29,7 +29,7 @@ 2D Array Arbitary Integer Linear congruential generator - Maximum subarray problem + Maximum subarray problem Bit-Set data structure Queue data structure @@ -53,7 +53,7 @@ Interval tree Prefix Tree(Trie) *Suffix Tree(未实现)* - B-Tree + B-Tree Hash by multiplication Hash table @@ -65,29 +65,29 @@ Bloom Filter SHA-1 Message Digest Algorithm MD5 - Base64 +Base64 Graph data structure Prim's minimum spanning tree - Kruskal MST + Kruskal MST Directed/Undirected graph ops Breadth First Search Depth First Search Dijkstra's algorithm Bellman-Ford algorithm Edmonds-Karp Maximal Flow - Push–Relabel algorithm + Push–Relabel algorithm Huffman Coding Word segementation(CHN/GB18030) using HMM and viterbi algorithm. A* algorithm K-Means Knuth–Morris–Pratt algorithm - Disjoint-Set + Disjoint-Set ####贡献者 ( Contributors ) : Samana : for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST - wyh267: for base64, LRU - ZhangYou0122 : Push-Relabel algorithm + wyh267: for base64, LRU + ZhangYou0122 : Push-Relabel algorithm From 924dcdbaabfb53f7ec1866a91fdd7600238ca9dc Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Mon, 11 Nov 2013 12:39:51 +0800 Subject: [PATCH 115/217] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba078ec6..667267bf 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Bloom Filter SHA-1 Message Digest Algorithm MD5 -Base64 + Base64 Graph data structure Prim's minimum spanning tree From 49e7cce5db8de570b5d2d3295e7827773d191e7f Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Mon, 11 Nov 2013 12:41:21 +0800 Subject: [PATCH 116/217] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 667267bf..875de2bc 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ ####目标 ( goal ) : - 经典的算法实现 - (classical algorithms implementations) - 服务器端 - (based on linux/gcc) - 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. - (correct! and ease of use, one .header file per algorithm) + 1. 经典的算法实现 + (classical algorithms implementations) + 2. 服务器端 + (based on linux/gcc) + 3. 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. + (correct! and ease of use, one .header file per algorithm) ####约定 ( Convention ): From 49ed617df8d636b1448c0576083833a9bb6a018f Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 12:42:56 +0800 Subject: [PATCH 117/217] update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 875de2bc..7bfe3078 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,12 @@ Linear congruential generator Maximum subarray problem - Bit-Set data structure - Queue data structure - Stack data structure - Binary heap data structure - Priority queue + Bit-Set + Queue + Stack + Binary Heap + Fibonacci Heap + Priority Queue (list based) Insertion sort Radix sort From 46b9fbd3faca04a9cfacb8aedf98f44978515a62 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 12:45:55 +0800 Subject: [PATCH 118/217] add better .dot printing --- include/graph_defs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/graph_defs.h b/include/graph_defs.h index 015d006d..c0c268e7 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -130,6 +130,7 @@ namespace alg { */ 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){ @@ -139,6 +140,7 @@ namespace alg { } } printf("}\n"); + printf("==== END OF DOT ====\n"); } const list_head & list() const {return a_head; } From 0d3073731ab0a96abcb83d53eeb5d3df9efa98c5 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 13:34:17 +0800 Subject: [PATCH 119/217] update kmp_demo --- src/kmp_demo.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) 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)]); } } From ed40839a45e976643a813d961f7d3fa928e4bee7 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 13:42:45 +0800 Subject: [PATCH 120/217] update demo of bellman-ford --- src/bellman_ford_demo.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bellman_ford_demo.cpp b/src/bellman_ford_demo.cpp index 00dffc71..432e00d9 100644 --- a/src/bellman_ford_demo.cpp +++ b/src/bellman_ford_demo.cpp @@ -31,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)); + g->printdot(); printf("\nwe %s have negative weighted cycle.\n", bf2.has_negative_cycle()?"DO":"DON'T"); delete g; From b7a6b216ac5234551610802c28af51833c03deac Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 13:56:57 +0800 Subject: [PATCH 121/217] update demo of base64 --- src/base64_demo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/base64_demo.cpp b/src/base64_demo.cpp index 3afe3757..3b0ad16c 100644 --- a/src/base64_demo.cpp +++ b/src/base64_demo.cpp @@ -5,8 +5,7 @@ using namespace std; int main() { - const char *s="Man is distinguished not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.."; - + 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; From 6132cfe53638f2af5d730af1927e735bd00993b2 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 11 Nov 2013 16:12:22 +0800 Subject: [PATCH 122/217] revert rbtree for root property --- include/dos_tree.h | 2 ++ include/interval_tree.h | 2 ++ include/rbtree.h | 3 +++ 3 files changed, 7 insertions(+) diff --git a/include/dos_tree.h b/include/dos_tree.h index 7dc809e9..7440990f 100644 --- a/include/dos_tree.h +++ b/include/dos_tree.h @@ -124,6 +124,8 @@ namespace alg { delete_case1(n); } replace_node(n, child); + if (n->parent == NULL && child != NULL) // root + child->color = BLACK; delete (DOSNODE(n)); } diff --git a/include/interval_tree.h b/include/interval_tree.h index b4f5ccd4..c4edca19 100644 --- a/include/interval_tree.h +++ b/include/interval_tree.h @@ -132,6 +132,8 @@ namespace alg { } replace_node(n, child); + if (n->parent == NULL && child != NULL) // root + child->color = BLACK; delete(n); } diff --git a/include/rbtree.h b/include/rbtree.h index 02afe01e..c9b8a318 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -124,6 +124,9 @@ namespace alg { delete_case1(n); } replace_node(n, child); + + if (n->parent == NULL && child != NULL) // root + child->color = BLACK; delete(n); } From 559a789e35ad169057992c447cb67a7aa85d3bd7 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 17 Nov 2013 10:51:29 +0800 Subject: [PATCH 123/217] indent rbtree defs --- include/rbtree_defs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/rbtree_defs.h b/include/rbtree_defs.h index 68a9f8f8..ab5ef4ea 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -241,7 +241,8 @@ namespace alg { sibling(n)->color = RED; sibling(n)->right->color = BLACK; rotate_left(sibling(n)); - } delete_case6(n); + } + delete_case6(n); } void delete_case6(rbtree_node n) { From 84ae6f5601134627f4b137382c8b017a6d9368bc Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 17 Nov 2013 11:53:29 +0800 Subject: [PATCH 124/217] update BFS & DFS, using CLRS method --- include/graph_defs.h | 8 ++++ include/graph_search.h | 94 ++++++++++++++++++++++----------------- src/graph_search_demo.cpp | 4 +- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/include/graph_defs.h b/include/graph_defs.h index c0c268e7..849adda5 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -23,11 +23,16 @@ namespace alg { } }; + enum VertexColor { GRAY, WHITE, BLACK }; + /** * 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 @@ -78,6 +83,8 @@ namespace alg { 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; @@ -135,6 +142,7 @@ namespace alg { printf("\tnode [shape = circle];\n"); list_for_each_entry(a, &a_head, a_node){ Vertex * v; + 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); } diff --git a/include/graph_search.h b/include/graph_search.h index e378b100..c1b87ebf 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -33,64 +33,76 @@ #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; + /** + * 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); 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]; + if (v->color == Graph::WHITE) { + 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; - - Graph::Adjacent * root = g[source]; - HashTable ht(g.vertex_count()); + 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; + } - if (root==NULL) return; + // for each vertex + g.graph_tick = 0; + list_for_each_entry(a, &g.list(), a_node) { + if (a->color == Graph::WHITE) { + _DFS_VISIT(g, a); + } + } + } - // init - Stack S(g.vertex_count()); - S.push(root->v.id); - ht[root->v.id] = MARK; + 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; - 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::Adjacent * v; + list_for_each_entry(v, &g.list(), a_node) { // explore edge (u, v) + if (v->color == Graph::WHITE) { + _DFS_VISIT(g, v); } } - - printf("\n"); + printf("%d->", u->v.id); + u->color = Graph::BLACK; + u->f = ++g.graph_tick; } } diff --git a/src/graph_search_demo.cpp b/src/graph_search_demo.cpp index 67ca4b88..7db103f2 100644 --- a/src/graph_search_demo.cpp +++ b/src/graph_search_demo.cpp @@ -16,9 +16,9 @@ int main() 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; From 258c35fddf4d85e2997a15b8e0b0627d909d0122 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 17 Nov 2013 15:33:58 +0800 Subject: [PATCH 125/217] update graph_search for tidying --- include/graph_search.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/graph_search.h b/include/graph_search.h index c1b87ebf..6c86073e 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -51,13 +51,13 @@ namespace alg { while(!Q.is_empty()) { uint32_t id = Q.front(); - printf("%d->", id); + printf("%d->", id); // output discovered id Q.dequeue(); Graph::Vertex * _v; Graph::Adjacent * u = g[id]; list_for_each_entry(_v, &u->v_head, v_node) { - Graph::Adjacent * v = g[_v->id]; - if (v->color == Graph::WHITE) { + 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); @@ -65,7 +65,6 @@ namespace alg { } u->color = Graph::BLACK; } - printf("\n"); } @@ -87,8 +86,12 @@ namespace alg { _DFS_VISIT(g, a); } } + printf("\n"); } + /** + * 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; From 95faee57b9d796013c51dc1d415b323c4a83326c Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 19 Nov 2013 13:02:08 +0800 Subject: [PATCH 126/217] update DFS printing --- include/graph_search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/graph_search.h b/include/graph_search.h index 6c86073e..b8600b04 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -103,9 +103,9 @@ namespace alg { _DFS_VISIT(g, v); } } - printf("%d->", u->v.id); u->color = Graph::BLACK; u->f = ++g.graph_tick; + printf("%d(d:%d, f:%d) -> ", u->v.id, u->d, u->f); } } From 4dcf7e63f3bf6b366867b40341641c459c269c30 Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 19 Nov 2013 14:04:29 +0800 Subject: [PATCH 127/217] add transpose of a directed graph --- include/directed_graph.h | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/include/directed_graph.h b/include/directed_graph.h index 2cd3c733..113013d7 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -26,15 +26,13 @@ #include "graph_defs.h" #include "double_linked_list.h" -namespace alg -{ +namespace alg { class DirectedGraph:public Graph { private: /** * delete a vertex from adjacent lists */ - void delete_me(uint32_t id) - { + 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){ @@ -77,8 +75,7 @@ namespace alg /** * delete a vertex with specified id */ - void delete_vertex(uint32_t id) - { + void delete_vertex(uint32_t id) { Adjacent * a = (*this)[id]; if (a==NULL) return; delete_me(id); @@ -92,8 +89,7 @@ namespace alg /** * create a new vertex and add to the graph, with specified id. */ - bool add_vertex(uint32_t id) - { + bool add_vertex(uint32_t id) { if ((*this)[id]!=NULL) return false; // new empty adjacent list @@ -107,8 +103,7 @@ namespace alg /** * add an edge for x -> y */ - bool add_edge(uint32_t x, uint32_t y, int32_t weight) - { + bool add_edge(uint32_t x, uint32_t y, int32_t weight) { struct Adjacent * a1 = (*this)[x]; struct Adjacent * a2 = (*this)[y]; @@ -130,8 +125,7 @@ namespace alg /** * delete an edge for x -> y */ - void delete_edge(uint32_t x, uint32_t 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 ; @@ -148,6 +142,24 @@ namespace alg } } } + + /** + * create the transpose of a directed-graph + */ + DirectedGraph * tranpose() { + 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; + } }; } From 9d3edd6f6c8b016b368e1b466d77f38f37de4ed6 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Tue, 19 Nov 2013 19:37:37 +0800 Subject: [PATCH 128/217] add some sort alg --- include/sort.h | 296 ++++++++++++++++++++++++++++++++++++++++++++++ src/sort_demo.cpp | 117 ++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 include/sort.h create mode 100644 src/sort_demo.cpp 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/src/sort_demo.cpp b/src/sort_demo.cpp new file mode 100644 index 00000000..758faee4 --- /dev/null +++ b/src/sort_demo.cpp @@ -0,0 +1,117 @@ + + +#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; +} \ No newline at end of file From b0fcbf33ed9d17543d3e4b96dbc85463bb82cf84 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Tue, 19 Nov 2013 19:37:51 +0800 Subject: [PATCH 129/217] modify makefile --- Makefile | 47 +---------------------------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/Makefile b/Makefile index 47c0d4e2..19cdd3f4 100644 --- a/Makefile +++ b/Makefile @@ -15,52 +15,7 @@ PROGRAMS = m_based \ 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 \ - universal_hash_demo \ - perfect_hash_demo \ - binary_search_tree_demo \ - rbtree_demo \ - heap_demo \ - interval_tree_demo \ - dos_tree_demo \ - skiplist_demo \ - lcs_demo \ - prim_mst_demo \ - directed_graph_demo \ - undirected_graph_demo \ - dijkstra_demo \ - bellman_ford_demo \ - graph_search_demo \ - edmonds_karp_demo \ - astar_demo \ - hash_string_demo \ - bitset_demo \ - bloom_filter_demo \ - sha1_demo \ - huffman_demo \ - word_seg_demo \ - md5_demo \ - trie_demo \ - simhash_demo \ - imath_demo \ - 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 all: $(PROGRAMS) From fe93cf4a8b1e5ae86e7bf4c70d88d03bb3b0d654 Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Tue, 19 Nov 2013 19:39:43 +0800 Subject: [PATCH 130/217] Update Makefile --- Makefile | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 19cdd3f4..769d634d 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,52 @@ INCLUDEDIR = -I./include -I. DEPS = LIBS = -lm PROGRAMS = m_based \ - 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 \ + - universal_hash_demo \ + - perfect_hash_demo \ + - binary_search_tree_demo \ + - rbtree_demo \ + - heap_demo \ + - interval_tree_demo \ + - dos_tree_demo \ + - skiplist_demo \ + - lcs_demo \ + - prim_mst_demo \ + - directed_graph_demo \ + - undirected_graph_demo \ + - dijkstra_demo \ + - bellman_ford_demo \ + - graph_search_demo \ + - edmonds_karp_demo \ + - astar_demo \ + - hash_string_demo \ + - bitset_demo \ + - bloom_filter_demo \ + - sha1_demo \ + - huffman_demo \ + - word_seg_demo \ + - md5_demo \ + - trie_demo \ + - simhash_demo \ + - imath_demo \ + - 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 all: $(PROGRAMS) From 20ec8d3e9c884edb736c021159d2c7eb1738a26a Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 20 Nov 2013 10:38:13 +0800 Subject: [PATCH 131/217] update graph print --- include/graph_defs.h | 14 ++++++++++++-- include/insertion_sort.h | 6 ++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/graph_defs.h b/include/graph_defs.h index 849adda5..8860c9b1 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -84,7 +84,7 @@ namespace alg { struct list_head a_head; // list header public: int32_t graph_tick; // for counting discover & finish time - + Graph() { num_vertex = 0; num_edges = 0; @@ -142,7 +142,17 @@ namespace alg { printf("\tnode [shape = circle];\n"); list_for_each_entry(a, &a_head, a_node){ Vertex * v; - printf("\t%d;\n", a->v.id); + 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); } diff --git a/include/insertion_sort.h b/include/insertion_sort.h index 82594b23..42427e4b 100644 --- a/include/insertion_sort.h +++ b/include/insertion_sort.h @@ -23,12 +23,10 @@ namespace alg { template static void insertion_sort(T *array , int number_of_elements) { int iter,jter; - for(iter=1;iter=0 && array[jter] > current_element) - { + while(jter>=0 && array[jter] > current_element) { array[jter+1] = array[jter]; jter--; } From 5aa45c18e0c3f6d78d2aa33a6bfdf939bc7b2785 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 20 Nov 2013 13:18:50 +0800 Subject: [PATCH 132/217] fixed a bug in DFS, Add strongly connected componnets ALG --- Makefile | 3 +- include/directed_graph.h | 2 +- include/graph_search.h | 7 +++-- include/scc.h | 67 ++++++++++++++++++++++++++++++++++++++++ src/scc_demo.cpp | 45 +++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 include/scc.h create mode 100644 src/scc_demo.cpp diff --git a/Makefile b/Makefile index bc78af80..f02c8639 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,8 @@ PROGRAMS = m_based_demo \ relabel_to_front_demo \ btree_demo \ sort_demo \ - fib-heap_demo + fib-heap_demo \ + scc_demo all: $(PROGRAMS) diff --git a/include/directed_graph.h b/include/directed_graph.h index 113013d7..0eb8e56e 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -146,7 +146,7 @@ namespace alg { /** * create the transpose of a directed-graph */ - DirectedGraph * tranpose() { + DirectedGraph * transpose() { DirectedGraph * trans = new DirectedGraph; Adjacent * a; list_for_each_entry(a, &a_head, a_node){ diff --git a/include/graph_search.h b/include/graph_search.h index b8600b04..438ea660 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -83,7 +83,9 @@ namespace alg { 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"); @@ -97,8 +99,9 @@ namespace alg { u->d = ++g.graph_tick; u->color = Graph::GRAY; - Graph::Adjacent * v; - list_for_each_entry(v, &g.list(), a_node) { // explore edge (u, v) + 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); } diff --git a/include/scc.h b/include/scc.h new file mode 100644 index 00000000..381cc81f --- /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 __SCC_H__ +#define __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.insert(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()) { + int32_t key = Q.min_key(); + int32_t id = Q.min_value(); + Q.delete_min(); + 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/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; +} From 5edc0c6c189f599ef3db1e601f3ea058b0c1d0a4 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 20 Nov 2013 13:22:33 +0800 Subject: [PATCH 133/217] update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7bfe3078..fe3e9288 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Base64 Graph data structure + Strongly Connected Components(SCC) Prim's minimum spanning tree Kruskal MST Directed/Undirected graph ops From 91493ecac1f7fa3ccc7d4025dc4e9e177333af03 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 20 Nov 2013 20:49:55 +0800 Subject: [PATCH 134/217] fix compatiblity with clang --- include/astar.h | 2 +- include/binary_search_tree.h | 3 +-- include/dijkstra.h | 2 +- include/fib-heap.h | 2 +- include/lcs.h | 2 +- include/perfect_hash.h | 8 +++----- include/queue.h | 6 ++---- include/skiplist.h | 3 +-- include/stack.h | 10 ++++------ include/word_seg.h | 2 -- 10 files changed, 15 insertions(+), 25 deletions(-) diff --git a/include/astar.h b/include/astar.h index 9dd67df5..391352a7 100644 --- a/include/astar.h +++ b/include/astar.h @@ -49,7 +49,6 @@ namespace alg { }; static const unsigned char WALL = 0xFF; - static const float SQRT2 = 1.414213562373095; private: const Array2D & m_grid; @@ -72,6 +71,7 @@ namespace alg { * 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(); m_closedset.clear(false); diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index c1f332bc..21ff297a 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -46,11 +46,10 @@ namespace alg { virtual const char * what() const throw() { return "key does not exist"; } - }; + } excp_key; private: treeNode * m_root; // the root - const BSTException error; private: BST(const BST&); BST& operator=(const BST&); diff --git a/include/dijkstra.h b/include/dijkstra.h index c3a41af4..c7b9c9c3 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -38,7 +38,7 @@ namespace alg { public: static const int UNDEFINED = -1; // run dijkstra algorithm, and return the previous table - static HashTable * run(const struct Graph & g, uint32_t src_id) { + static HashTable * run(const Graph & g, uint32_t src_id) { // a binary heap Heap Q(g.vertex_count() + g.edge_count()); // distance hash table diff --git a/include/fib-heap.h b/include/fib-heap.h index 8eaf77c6..68100b8b 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -83,7 +83,7 @@ namespace alg { 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)) { + if (H1->min == NULL || (H2->min != NULL && H2->min.key < H1->min.key)) { H->min = H2->min; } H->n = H1->n + H2->n; diff --git a/include/lcs.h b/include/lcs.h index 3b65a532..a3c3e9d9 100644 --- a/include/lcs.h +++ b/include/lcs.h @@ -64,7 +64,7 @@ namespace alg { * pass an empty stack, pop out the result in sequential order. */ template - static void lcs_backtrack(Stack & S, struct Array2D & A, + 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; diff --git a/include/perfect_hash.h b/include/perfect_hash.h index bfdfb027..52dd9801 100644 --- a/include/perfect_hash.h +++ b/include/perfect_hash.h @@ -29,10 +29,10 @@ namespace alg { virtual const char * what() const throw() { return "key does not exist"; } - }; + } excp_key; // Level-2 Slot definition - class SlotL2 { + struct SlotL2 { public: uint32_t cnt; // collison count uint32_t key; //key @@ -57,8 +57,6 @@ namespace alg { 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 @@ -105,7 +103,7 @@ namespace alg { } } - throw error; + throw excp_key; } /** diff --git a/include/queue.h b/include/queue.h index bb099207..1de7b292 100644 --- a/include/queue.h +++ b/include/queue.h @@ -32,7 +32,7 @@ namespace alg { virtual const char * what() const throw() { return "Queue is empty."; } - }; + } excp_empty; private: uint32_t m_capacity; // queue capacity @@ -41,8 +41,6 @@ namespace alg { uint32_t m_rear; // index of the last element T * m_elements; // the elements - const QueueEmptyException exp_empty; - public: /** * constructor takes argument the maximum number of elements the Queue @@ -88,7 +86,7 @@ namespace alg { * return the front element. */ inline const T& front() const { - if (m_size==0) throw exp_empty; + if (m_size==0) throw excp_empty; return m_elements[m_front]; }; diff --git a/include/skiplist.h b/include/skiplist.h index 04809f9d..1c330ba7 100644 --- a/include/skiplist.h +++ b/include/skiplist.h @@ -40,8 +40,7 @@ namespace alg { virtual const char * what() const throw() { return "cannot find the element in skiplist"; } - }; - const NotFoundException excp_notfound; + } excp_notfound; public: SkipList() { diff --git a/include/stack.h b/include/stack.h index 362d04f9..acc75414 100644 --- a/include/stack.h +++ b/include/stack.h @@ -36,7 +36,7 @@ namespace alg { { return "stack is empty"; } - }; + } excp_empty; class StackIndexOutOfBoundException: public std::exception { public: @@ -44,13 +44,11 @@ namespace alg { { 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 - const StackEmptyException exp_empty; - const StackIndexOutOfBoundException exp_ioob; public: /** @@ -90,7 +88,7 @@ namespace alg { * get the top element */ inline const T& top() const { - if (m_size==0) throw exp_empty; + if (m_size==0) throw excp_empty; return m_elements[m_size-1]; } @@ -115,7 +113,7 @@ namespace alg { * return value by index */ inline const T& operator[] (uint32_t idx) const { - if (idx<0 || idx >= m_capacity) throw exp_ioob; + if (idx >= m_capacity) throw excp_ioob; return m_elements[m_size-1-idx]; } }; diff --git a/include/word_seg.h b/include/word_seg.h index 623f0e82..eb0f65c7 100644 --- a/include/word_seg.h +++ b/include/word_seg.h @@ -123,8 +123,6 @@ namespace alg { */ private: HashTable wordht; // a WORD-> WordEP hashtable - uint32_t words[GB18030_NR]; // every char in GB18030 - public: WordSeg() : wordht(GB18030_NR){ } From 0bfbeeb74e6f8c23cb4eb4e95ebabbe15779124a Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Mon, 25 Nov 2013 16:33:15 +0800 Subject: [PATCH 135/217] add bubble sort --- Makefile | 3 ++- include/bubble_sort.h | 51 ++++++++++++++++++++++++++++++++++++++++ src/bubble_sort_demo.cpp | 29 +++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 include/bubble_sort.h create mode 100644 src/bubble_sort_demo.cpp diff --git a/Makefile b/Makefile index 19cdd3f4..f33a5b0b 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ PROGRAMS = m_based \ shuffle_demo \ quick_sort_demo \ merge_sort_demo \ - sort_demo + sort_demo \ + bubble_sort_demo all: $(PROGRAMS) diff --git a/include/bubble_sort.h b/include/bubble_sort.h new file mode 100644 index 00000000..e1b37cad --- /dev/null +++ b/include/bubble_sort.h @@ -0,0 +1,51 @@ + + + +#ifndef _bubble_sort_h_ +#define _bubble_sort_h_ + + +#include +#include +#include +#include + + +using namespace std; + +namespace aglo{ + + template + static void BubbleSort(T list[],int start,int end){ + + + T tmp; + if(start < end){ + for(size_t i = start; i <= end; ++i) + { + for(size_t j = i+1; j <= end; ++j) + { + if(list[i]>=list[j]){ + + tmp=list[i]; + list[i]=list[j]; + list[j]=tmp; + + } + + } + + } + + } + + } + + + + + +} + + +#endif \ No newline at end of file diff --git a/src/bubble_sort_demo.cpp b/src/bubble_sort_demo.cpp new file mode 100644 index 00000000..16f4f8fb --- /dev/null +++ b/src/bubble_sort_demo.cpp @@ -0,0 +1,29 @@ +#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); + + // sort the list using quicksort + aglo::BubbleSort(list,0,MAX_ELEMENTS-1); + + // print the result + printf("The list after sorting using quicksort algorithm:\n"); + printlist(list,MAX_ELEMENTS); + + return 0; +} \ No newline at end of file From 3f7fda8dc09b5013ec0dc58cf446e6ee6b5af18c Mon Sep 17 00:00:00 2001 From: Wu Yinghao Date: Mon, 25 Nov 2013 16:57:35 +0800 Subject: [PATCH 136/217] add selection sort --- Makefile | 54 +++---------------------------------- include/selection_sort.h | 46 +++++++++++++++++++++++++++++++ src/selection_sort_demo.cpp | 38 ++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 51 deletions(-) create mode 100644 include/selection_sort.h create mode 100644 src/selection_sort_demo.cpp diff --git a/Makefile b/Makefile index c631d1db..52294615 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,6 @@ INCLUDEDIR = -I./include -I. DEPS = LIBS = -lm PROGRAMS = m_based \ -<<<<<<< HEAD integer_demo \ insertion_sort_demo \ radix_sort_demo \ @@ -17,56 +16,9 @@ PROGRAMS = m_based \ quick_sort_demo \ merge_sort_demo \ sort_demo \ - bubble_sort_demo -======= - random_select_demo \ - - hash_multi_demo \ - - hash_table_demo \ - - double_linked_list_demo \ - - stack_demo \ - - queue_demo \ - - priority_queue_demo \ - - prime_test \ - - universal_hash_demo \ - - perfect_hash_demo \ - - binary_search_tree_demo \ - - rbtree_demo \ - - heap_demo \ - - interval_tree_demo \ - - dos_tree_demo \ - - skiplist_demo \ - - lcs_demo \ - - prim_mst_demo \ - - directed_graph_demo \ - - undirected_graph_demo \ - - dijkstra_demo \ - - bellman_ford_demo \ - - graph_search_demo \ - - edmonds_karp_demo \ - - astar_demo \ - - hash_string_demo \ - - bitset_demo \ - - bloom_filter_demo \ - - sha1_demo \ - - huffman_demo \ - - word_seg_demo \ - - md5_demo \ - - trie_demo \ - - simhash_demo \ - - imath_demo \ - - 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 ->>>>>>> fe93cf4a8b1e5ae86e7bf4c70d88d03bb3b0d654 + bubble_sort_demo \ + selection_sort_demo + all: $(PROGRAMS) diff --git a/include/selection_sort.h b/include/selection_sort.h new file mode 100644 index 00000000..2ef7a3fe --- /dev/null +++ b/include/selection_sort.h @@ -0,0 +1,46 @@ +#ifndef _selection_sort_h_ +#define _selection_sort_h_ + + + +namespace aglo{ + + template + static void SelectionSort(T list[],int start,int end){ + + int min_index; + T tmp; + + if(start < end){ + + for(size_t i = start; i <= end-1; ++i) + { + min_index=i; + for(size_t j = i+1; j <= end; ++j) + { + if ( list[i] >= list[j]) + min_index=j; + + } + + if (i != min_index) + { + tmp=list[i]; + list[i]=list[min_index]; + list[min_index]=tmp; + + } + } + + } + + + + } + +} + + + + +#endif \ No newline at end of file diff --git a/src/selection_sort_demo.cpp b/src/selection_sort_demo.cpp new file mode 100644 index 00000000..50f1b585 --- /dev/null +++ b/src/selection_sort_demo.cpp @@ -0,0 +1,38 @@ + +#include +#include +#include + +#include "generic.h" +#include "selection_sort.h" + + +template +static void printlist(T & list,int count) +{ + int i; + for(i=0;i Date: Mon, 25 Nov 2013 18:05:18 +0800 Subject: [PATCH 137/217] update bubble-sort --- include/bubble_sort.h | 47 ++++++++++++---------------------------- src/bubble_sort_demo.cpp | 13 ++++------- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/include/bubble_sort.h b/include/bubble_sort.h index e1b37cad..42f2b28b 100644 --- a/include/bubble_sort.h +++ b/include/bubble_sort.h @@ -1,8 +1,5 @@ - - - -#ifndef _bubble_sort_h_ -#define _bubble_sort_h_ +#ifndef _BUBBLE_SORT_H_ +#define _BUBBLE_SORT_H_ #include @@ -13,39 +10,23 @@ using namespace std; -namespace aglo{ - +namespace alg { template - static void BubbleSort(T list[],int start,int end){ - - - T tmp; - if(start < end){ - for(size_t i = start; i <= end; ++i) - { - for(size_t j = i+1; j <= end; ++j) - { - if(list[i]>=list[j]){ - - tmp=list[i]; - list[i]=list[j]; - list[j]=tmp; - + static void BubbleSort(T list[],int start,int end){ + T tmp; + if(start < end){ + for(size_t i = start; i <= end; ++i) { + for(size_t j = i+1; j <= end; ++j) { + if(list[i]>=list[j]){ + tmp=list[i]; + list[i]=list[j]; + list[j]=tmp; + } } - } - } - } - - } - - - - - } -#endif \ No newline at end of file +#endif // _BUBBLE_SORT_H_ diff --git a/src/bubble_sort_demo.cpp b/src/bubble_sort_demo.cpp index 16f4f8fb..37ca5072 100644 --- a/src/bubble_sort_demo.cpp +++ b/src/bubble_sort_demo.cpp @@ -5,11 +5,8 @@ #include "generic.h" #include "bubble_sort.h" - - using namespace alg; -int main (int argc, char const *argv[]) -{ +int main (int argc, char const *argv[]) { const int MAX_ELEMENTS = 10; int list[MAX_ELEMENTS]; for(int i = 0; i < MAX_ELEMENTS; i++ ){ @@ -18,12 +15,10 @@ int main (int argc, char const *argv[]) printf("The list before sorting is:\n"); printlist(list,MAX_ELEMENTS); - // sort the list using quicksort - aglo::BubbleSort(list,0,MAX_ELEMENTS-1); + alg::BubbleSort(list,0,MAX_ELEMENTS-1); - // print the result - printf("The list after sorting using quicksort algorithm:\n"); + printf("The list after sorting using bubble-sort algorithm:\n"); printlist(list,MAX_ELEMENTS); return 0; -} \ No newline at end of file +} From 2533f02e84a0b8d5995b201e2df5a4a6e1a23fb1 Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 25 Nov 2013 18:37:42 +0800 Subject: [PATCH 138/217] update selection sort --- include/selection_sort.h | 59 +++++++++++++------------------------ src/selection_sort_demo.cpp | 16 ++++------ 2 files changed, 25 insertions(+), 50 deletions(-) diff --git a/include/selection_sort.h b/include/selection_sort.h index 2ef7a3fe..c0b0ae8f 100644 --- a/include/selection_sort.h +++ b/include/selection_sort.h @@ -1,46 +1,27 @@ -#ifndef _selection_sort_h_ -#define _selection_sort_h_ +#ifndef __SELECTION_SORT_H__ +#define __SELECTION_SORT_H__ - - -namespace aglo{ - +namespace alg { template - static void SelectionSort(T list[],int start,int end){ - - int min_index; - T tmp; - - if(start < end){ - - for(size_t i = start; i <= end-1; ++i) - { - min_index=i; - for(size_t j = i+1; j <= end; ++j) - { - if ( list[i] >= list[j]) - min_index=j; - - } - - if (i != min_index) - { - tmp=list[i]; - list[i]=list[min_index]; - list[min_index]=tmp; - + static void SelectionSort(T list[],int start,int end){ + int min_index; + T tmp; + if(start < end){ + for(size_t i = start; i <= end-1; ++i) { + min_index=i; + for(size_t j = i+1; j <= end; ++j) { + if ( list[i] >= list[j]) + min_index=j; + } + + if (i != min_index) { + tmp=list[i]; + list[i]=list[min_index]; + list[min_index]=tmp; + } } } - } - - - - } - } - - - -#endif \ No newline at end of file +#endif //__SELECTION_SORT_H__ diff --git a/src/selection_sort_demo.cpp b/src/selection_sort_demo.cpp index 50f1b585..dbe2b7b5 100644 --- a/src/selection_sort_demo.cpp +++ b/src/selection_sort_demo.cpp @@ -1,4 +1,3 @@ - #include #include #include @@ -6,10 +5,8 @@ #include "generic.h" #include "selection_sort.h" - template -static void printlist(T & list,int count) -{ +static void printlist(T & list,int count) { int i; for(i=0;i Date: Mon, 25 Nov 2013 18:38:46 +0800 Subject: [PATCH 139/217] update readme.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fe3e9288..25a6eb8b 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ Fibonacci Heap Priority Queue (list based) + Bubble sort + Selection sort Insertion sort Radix sort Quick sort @@ -91,5 +93,5 @@ Samana : for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST - wyh267: for base64, LRU + wyh267: for base64, LRU, bubble sort, selection sort ZhangYou0122 : Push-Relabel algorithm From eb35a77cd0b7a669954ada746dc41778649f8f8b Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 26 Nov 2013 10:11:55 +0800 Subject: [PATCH 140/217] update selection sort --- include/selection_sort.h | 53 +++++++++++++++++++++++++++---------- src/selection_sort_demo.cpp | 4 --- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/include/selection_sort.h b/include/selection_sort.h index c0b0ae8f..a956ad9a 100644 --- a/include/selection_sort.h +++ b/include/selection_sort.h @@ -1,25 +1,50 @@ +/******************************************************************************* + * 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 __SELECTION_SORT_H__ #define __SELECTION_SORT_H__ +#include +#include + namespace alg { template - static void SelectionSort(T list[],int start,int end){ - int min_index; - T tmp; - if(start < end){ - for(size_t i = start; i <= end-1; ++i) { - min_index=i; - for(size_t j = i+1; j <= end; ++j) { - if ( list[i] >= list[j]) - min_index=j; - } + static void SelectionSort(T list[], int start, int end) { + int i,j; + int iMin; - if (i != min_index) { - tmp=list[i]; - list[i]=list[min_index]; - list[min_index]=tmp; + 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]); + } } } } diff --git a/src/selection_sort_demo.cpp b/src/selection_sort_demo.cpp index dbe2b7b5..3968cf41 100644 --- a/src/selection_sort_demo.cpp +++ b/src/selection_sort_demo.cpp @@ -1,8 +1,5 @@ #include -#include -#include -#include "generic.h" #include "selection_sort.h" template @@ -13,7 +10,6 @@ static void printlist(T & list,int count) { printf("\n"); } - int main (int argc, char const *argv[]) { const int MAX_ELEMENTS = 10; int list[MAX_ELEMENTS]; From f79745f87f16797c486af0d2cc107cad11393506 Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 26 Nov 2013 10:32:24 +0800 Subject: [PATCH 141/217] update bubble sort --- include/bubble_sort.h | 57 ++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/include/bubble_sort.h b/include/bubble_sort.h index 42f2b28b..ca194ced 100644 --- a/include/bubble_sort.h +++ b/include/bubble_sort.h @@ -1,30 +1,49 @@ +/******************************************************************************* + * 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 -#include -#include - - -using namespace std; +#include +#include namespace alg { template - static void BubbleSort(T list[],int start,int end){ - T tmp; - if(start < end){ - for(size_t i = start; i <= end; ++i) { - for(size_t j = i+1; j <= end; ++j) { - if(list[i]>=list[j]){ - tmp=list[i]; - list[i]=list[j]; - list[j]=tmp; - } + 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); } } From 80a849f1b842cddfee9c8004c6290bae4f369575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-David=20Be=CC=81langer?= Date: Thu, 12 Dec 2013 17:10:26 -0500 Subject: [PATCH 142/217] fix astar bug with x,y vs col,row --- include/astar.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/astar.h b/include/astar.h index 391352a7..b3663071 100644 --- a/include/astar.h +++ b/include/astar.h @@ -86,8 +86,8 @@ namespace alg { // 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); + g_score(y1,x1) = 0.0f; + f_score(y1,x1) = g_score(y1,x1) + estimate(x1,y1,x2,y2); AStarResult * as = new AStarResult; as->path = NULL; @@ -117,7 +117,7 @@ namespace alg { } openset.delete_min(); - m_closedset(cx, cy) = true; + m_closedset(cy, cx) = true; // for each neighbor int nx, ny; @@ -127,13 +127,13 @@ namespace alg { if (ny<0 || ny>=(int)nrow) continue; // except the wall; - if(m_grid(nx,ny) == WALL) continue; + if(m_grid(ny,nx) == WALL) continue; // except the cur itself if(nx == cx && ny==cy) continue; // if neighbour in the closed set - if(m_closedset(nx,ny)) continue; + if(m_closedset(ny,nx)) continue; - float tentative = g_score(cx,cy); + float tentative = g_score(cy,cx); if (nx == cx || ny == cy) { tentative += 1; } else { @@ -141,12 +141,12 @@ namespace alg { } // if neighbour not in the openset or dist < g_score[neighbour] - if (!openset.contains(nx*ncol+ny) || tentative < g_score(nx,ny)) { + if (!openset.contains(nx*ncol+ny) || tentative < g_score(ny,nx)) { 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); + g_score(ny,nx) = tentative; + f_score(ny,nx) = tentative + estimate(nx,ny,x2,y2); if (!openset.contains(nx*ncol+ny)) { - openset.insert(f_score(nx,ny), nx*ncol+ny); + openset.insert(f_score(ny,nx), nx*ncol+ny); } } } From 62252c005e325f31b6d8c9206a6cee485e2f359a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-David=20Be=CC=81langer?= Date: Thu, 12 Dec 2013 17:17:35 -0500 Subject: [PATCH 143/217] allow astar to use grid weight instead of a fix value (1 and SQRT2) --- include/astar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/astar.h b/include/astar.h index b3663071..b9f93ecb 100644 --- a/include/astar.h +++ b/include/astar.h @@ -135,9 +135,9 @@ namespace alg { float tentative = g_score(cy,cx); if (nx == cx || ny == cy) { - tentative += 1; + tentative += 1 + m_grid(ny,nx); } else { - tentative += SQRT2; + tentative += (1 + m_grid(ny,nx)) * SQRT2; } // if neighbour not in the openset or dist < g_score[neighbour] From 8edf1e34ae5ce8d2029e239e9725ee28eb4bc889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-David=20Be=CC=81langer?= Date: Fri, 13 Dec 2013 13:53:24 -0500 Subject: [PATCH 144/217] Always returns start and end nodes when a path is found in astar --- include/astar.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/astar.h b/include/astar.h index 391352a7..f9faa074 100644 --- a/include/astar.h +++ b/include/astar.h @@ -100,6 +100,7 @@ namespace alg { if(cx == (int)x2 && cy==(int)y2) { // we reached (x2,y2) // reconstruct path & return + as->num_nodes = 2; uint32_t tmp = x2*ncol+y2; while((tmp=came_from[tmp]) != x1*ncol+y1) { as->num_nodes++; @@ -109,10 +110,14 @@ namespace alg { 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; } From c061a910eec7a7060252d757dc2b6005e427d5b2 Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 17 Dec 2013 10:52:51 +0800 Subject: [PATCH 145/217] update prim alg --- include/heap.h | 20 ++--- include/prim_mst.h | 159 +++++++++---------------------------- include/undirected_graph.h | 7 +- src/dijkstra_demo.cpp | 8 +- src/heap_demo.cpp | 5 +- src/prim_mst_demo.cpp | 14 +--- 6 files changed, 63 insertions(+), 150 deletions(-) diff --git a/include/heap.h b/include/heap.h index d3d0bab4..3462660a 100644 --- a/include/heap.h +++ b/include/heap.h @@ -49,7 +49,7 @@ namespace alg { int32_t m_max; // max heap size. KV * m_kvs; // key value pairs. - HashTable * m_idx; // key -> idx + HashTable * m_idx; // key -> idx public: Heap(int max) { @@ -57,7 +57,7 @@ namespace alg { m_max = max+1; m_kvs = new KV[m_max]; m_kvs[0].key = INT_MIN; - m_idx = new HashTable(m_max); + m_idx = new HashTable(m_max); }; ~Heap() { @@ -88,19 +88,19 @@ namespace alg { m_size++; m_kvs[m_size].key = key; m_kvs[m_size].value = value; - (*m_idx)[key] = m_size; + (*m_idx)[value] = m_size; // Adjust its position int now = m_size; while(m_kvs[now/2].key > key) { m_kvs[now] = m_kvs[now/2]; - (*m_idx)[m_kvs[now/2].key] = now; + (*m_idx)[m_kvs[now/2].value] = now; now /= 2; } m_kvs[now].key = key; m_kvs[now].value = value; - (*m_idx)[key] = now; + (*m_idx)[value] = now; } /** @@ -159,7 +159,7 @@ namespace alg { // if the last key is less than the minimum key among both the children if(lastKey > m_kvs[child].key) { m_kvs[now] = m_kvs[child]; - (*m_idx)[m_kvs[now].key] = now; // record index + (*m_idx)[m_kvs[now].value] = now; // record index } else { // It fits there break; @@ -168,7 +168,7 @@ namespace alg { m_kvs[now].key = lastKey; m_kvs[now].value= lastValue; - (*m_idx)[lastKey] = now; // record index + (*m_idx)[lastValue] = now; // record index } /** @@ -176,8 +176,8 @@ namespace alg { * step 1. find the value * step 2. decrease the key to the newkey */ - void decrease_key(int32_t oldkey, int32_t newkey) { - int32_t index = (*m_idx)[oldkey]; + void decrease_key(T value, int32_t newkey) { + int32_t index = (*m_idx)[value]; if (index > m_size || index == 0) return; // value not found if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning. T oldvalue = m_kvs[index].value; @@ -185,7 +185,7 @@ namespace alg { int now = index; while(m_kvs[now/2].key > newkey) { m_kvs[now] = m_kvs[now/2]; - (*m_idx)[m_kvs[now].key] = now; // record index + (*m_idx)[m_kvs[now].value] = now; // record index now /= 2; } diff --git a/include/prim_mst.h b/include/prim_mst.h index bf9b8bc5..b3bf5069 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -33,75 +33,6 @@ 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. @@ -118,66 +49,54 @@ namespace alg { * * Output: Vnew and Enew describe a minimal spanning tree */ - Graph * run() { + 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()); - // 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; + // a binary heap + Heap Q(g.vertex_count()); - // 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(); - } - } + // all vertices + Graph::Adjacent * a; + list_for_each_entry(a, &g.list(), a_node){ + if (a->v.id != src_id) { + Q.insert(INT_MAX, a->v.id); + keys[a->v.id] = INT_MAX; } + } - 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; - }; + Q.insert(0, src_id); + keys[src_id] = 0; - return mst; - } + while (!Q.is_empty()) { + int32_t id = Q.min_value(); + Q.delete_min(); // remove u from Q - /** - * 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); + 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; + } + } + } + + // 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/undirected_graph.h b/include/undirected_graph.h index 2d2afadb..5570267c 100644 --- a/include/undirected_graph.h +++ b/include/undirected_graph.h @@ -128,22 +128,23 @@ namespace alg { } /** * randomly generate a graph, for test purpose + * start from 1 */ static 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); } } diff --git a/src/dijkstra_demo.cpp b/src/dijkstra_demo.cpp index bb43d956..a0873a8b 100644 --- a/src/dijkstra_demo.cpp +++ b/src/dijkstra_demo.cpp @@ -18,8 +18,8 @@ int main(void) g->printdot(); Graph::Adjacent * a; - printf("finding Dijkstra shortest path starting from 0: \n"); - HashTable * result = Dijkstra::run(*g, 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); @@ -29,9 +29,9 @@ int main(void) } delete result; - printf("finding Dijkstra shortest path starting from 1: \n"); + printf("finding Dijkstra shortest path starting from 2: \n"); - result = Dijkstra::run(*g, 1); + 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/heap_demo.cpp b/src/heap_demo.cpp index aa4d3ea3..bf761a66 100644 --- a/src/heap_demo.cpp +++ b/src/heap_demo.cpp @@ -17,9 +17,8 @@ int main() printf("inserting: %d->%d\n", i, value); } - int index = 9; - printf("decrease a key[%d] to %d\n", index, -1); - heap.decrease_key(index, -1); + printf("decrease a value[%d] to %d\n", 5, -1); + heap.decrease_key(5, -1); while(!heap.is_empty()) { printf("deleting min: %d->%d\n", heap.min_key(), heap.min_value()); heap.delete_min(); diff --git a/src/prim_mst_demo.cpp b/src/prim_mst_demo.cpp index a51da33c..2dc15319 100644 --- a/src/prim_mst_demo.cpp +++ b/src/prim_mst_demo.cpp @@ -5,24 +5,18 @@ #include "undirected_graph.h" #include "prim_mst.h" -using namespace alg; - int main(void) { using namespace alg; srand(time(NULL)); int NVERTEX = 10; - UndirectedGraph * g = UndirectedGraph::randgraph(NVERTEX); + 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->printdot(); - delete mst; + Graph * prim = alg::Prim::run(*g, 1); + prim->printdot(); + delete prim; delete g; return 0; } From e99b5384257f60c1c0b6ecb655462144d3ff2f0f Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 19 Dec 2013 13:25:49 +0800 Subject: [PATCH 146/217] add an 8-queue solution --- Makefile | 3 +- README.md | 1 + include/8queen.h | 87 +++++++++++++++++++++++++++++++++++++++++++++ src/8queue_demo.cpp | 8 +++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 include/8queen.h create mode 100644 src/8queue_demo.cpp diff --git a/Makefile b/Makefile index 6b8fc6b0..7c9d56c7 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,8 @@ PROGRAMS = m_based_demo \ scc_demo \ sort_demo \ bubble_sort_demo \ - selection_sort_demo + selection_sort_demo \ + 8queue_demo all: $(PROGRAMS) diff --git a/README.md b/README.md index 25a6eb8b..2448301a 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ K-Means Knuth–Morris–Pratt algorithm Disjoint-Set + 8-Queue Problem ####贡献者 ( Contributors ) : Samana : for heavy work of MSVC compatability diff --git a/include/8queen.h b/include/8queen.h new file mode 100644 index 00000000..27062e3a --- /dev/null +++ b/include/8queen.h @@ -0,0 +1,87 @@ +/******************************************************************************* + * DANIEL'1'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * 8-Queue + * + * http://en.wikipedia.org/wiki/Eight_queens_puzzle + ******************************************************************************/ + +#ifndef __8QUEEN_H__ +#define __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 //__8QUEEN_H__ 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(); +} + From 2a4d5d3dac300b079907c743493efb8b12741afe Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 30 Dec 2013 10:42:56 +0800 Subject: [PATCH 147/217] add a simple palindrome solution --- Makefile | 3 +- README.md | 1 + include/palindrome.h | 79 +++++++++++++++++++++++++++++++++++++++++ src/palindrome_demo.cpp | 8 +++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 include/palindrome.h create mode 100644 src/palindrome_demo.cpp diff --git a/Makefile b/Makefile index 7c9d56c7..a167bc1d 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,8 @@ PROGRAMS = m_based_demo \ sort_demo \ bubble_sort_demo \ selection_sort_demo \ - 8queue_demo + 8queue_demo \ + palindrome_demo all: $(PROGRAMS) diff --git a/README.md b/README.md index 2448301a..f30ddb72 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ Knuth–Morris–Pratt algorithm Disjoint-Set 8-Queue Problem + Palindrome ####贡献者 ( Contributors ) : Samana : for heavy work of MSVC compatability diff --git a/include/palindrome.h b/include/palindrome.h new file mode 100644 index 00000000..1724a73c --- /dev/null +++ b/include/palindrome.h @@ -0,0 +1,79 @@ +/******************************************************************************* + * DANIEL'S ALGORITHM IMPLEMENTAIONS + * + * /\ | _ _ ._ o _|_ |_ ._ _ _ + * /--\ | (_| (_) | | |_ | | | | | _> + * _| + * + * 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/src/palindrome_demo.cpp b/src/palindrome_demo.cpp new file mode 100644 index 00000000..d98c63eb --- /dev/null +++ b/src/palindrome_demo.cpp @@ -0,0 +1,8 @@ +#include "palindrome.h" +#include + +int main() { + alg::palindrome("banana"); + alg::palindrome("abba"); + alg::palindrome("aaaaa"); +} From d5490398ab810141da155755ec5b5ae442b4241a Mon Sep 17 00:00:00 2001 From: Ivan Lyon Date: Thu, 6 Feb 2014 16:19:46 +0800 Subject: [PATCH 148/217] =?UTF-8?q?=E5=BF=AB=E9=80=9F=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=EF=BC=9A=E6=9E=A2=E7=BA=BD=E5=80=BC=E3=80=8Cpivot=E3=80=8D?= =?UTF-8?q?=E9=80=89=E5=8F=96=E8=BF=9B=E8=A1=8C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/xtaci/algorithms/issues/14 --- include/quick_sort.h | 51 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/include/quick_sort.h b/include/quick_sort.h index b8962216..35caf1dd 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -19,31 +19,49 @@ #define __QUICKSORT_H__ #include +#include namespace alg { + + /** + * Return median of begin, middle, and end. + * Order these and hide the pivot. + */ + template + static const T & __median3(T list[], int begin, int end) { + assert(begin + 2 <= end); + int middle = end - (end - begin) / 2; + if (list[middle] < list[begin]) + swap(list[middle], list[begin]); + if (list[end] < list[begin]) + swap(list[end], list[begin]); + if (list[end] < list[middle]) + swap(list[end], list[middle]); + + //Place pivot at position [end - 1] + swap(list[middle], list[end - 1]); + return list[end - 1]; + } + /** * 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]); - - int i = begin + 1; - int j = end; - - while(i <= j) { - while((i <= end) && (list[i] <= pivot)) - i++; - while((j >= begin) && (list[j] > pivot)) - j--; + T pivot = __median3(list, begin, end); + + int i = begin; + int j = end - 1; + + while(i < j) { + while(list[++i] < pivot) {} + while(pivot < list[--j]) {} if(i < j) swap(list[i],list[j]); } - swap(list[begin],list[j]); - return j; // final pivot position + swap(list[i],list[end - 1]); + return i; // final pivot position } /** @@ -51,10 +69,13 @@ namespace alg { */ template static void quicksort(T list[],int begin,int end) { - if( begin < end) { + if( begin + 1 < end) { int pivot_idx = __partition(list, begin, end); quicksort(list, begin, pivot_idx-1); quicksort(list, pivot_idx+1, end); + } else if ( begin + 1 == end) { + if (list[begin + 1] > list[end]) + swap(list[begin + 1], list[end]); } } } From 958f3f3c2364f05826b4f8eb27a9745f3faff22f Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 18 Feb 2014 11:03:11 +0800 Subject: [PATCH 149/217] indent --- include/scc.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/scc.h b/include/scc.h index 381cc81f..23e34e0e 100644 --- a/include/scc.h +++ b/include/scc.h @@ -38,15 +38,15 @@ namespace alg { // 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) { + list_for_each_entry(a, &g.list(), a_node) { Q.insert(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; - } + // 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) From 6602d8cf0ce175a7fbababbf8da815b4832fec5c Mon Sep 17 00:00:00 2001 From: Lin Lyu Date: Thu, 6 Mar 2014 21:26:57 +0800 Subject: [PATCH 150/217] Update sort_demo.cpp added the head file for built-in function rand() --- src/sort_demo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sort_demo.cpp b/src/sort_demo.cpp index 758faee4..3f50f7bd 100644 --- a/src/sort_demo.cpp +++ b/src/sort_demo.cpp @@ -1,5 +1,5 @@ - +#include #include #include "sort.h" @@ -114,4 +114,4 @@ int main (int argc, char const *argv[]) return 0; -} \ No newline at end of file +} From 1b92df78ec1e2438a8baa480b0db0b4f47045080 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 17 May 2014 13:57:17 +0800 Subject: [PATCH 151/217] fix bugs in astar algorithm --- include/astar.h | 56 +++++++++++++++++++++++++++++----------------- src/astar_demo.cpp | 2 +- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/include/astar.h b/include/astar.h index 2c6be4f6..6723702d 100644 --- a/include/astar.h +++ b/include/astar.h @@ -52,6 +52,10 @@ namespace alg { 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. @@ -61,9 +65,14 @@ namespace alg { 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()) { } + f_score(grid.row(),grid.col()) { + m_openset_grid.clear(false); + m_closedset.clear(false); + } /** * the A* algorithm @@ -74,27 +83,32 @@ namespace alg { static float SQRT2 = 1.414213562373095; uint32_t nrow = m_grid.row(); uint32_t ncol = m_grid.col(); - m_closedset.clear(false); + + // test wheather the (x1, y1) is the wall, we don't do stupid searching. + //if (m_grid(x1, y1) == WALL) { + // return NULL; + //} // 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); + m_openset.insert(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(y1,x1) = 0.0f; - f_score(y1,x1) = g_score(y1,x1) + estimate(x1,y1,x2,y2); + 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(); + while(!m_openset.is_empty()) { + uint32_t value = m_openset.min_value(); int cx = value/ncol; int cy = value%ncol; @@ -121,8 +135,9 @@ namespace alg { return as; } - openset.delete_min(); - m_closedset(cy, cx) = true; + m_openset.delete_min(); + m_closedset(cx, cy) = true; + m_openset_grid(cx, cy) = false; // for each neighbor int nx, ny; @@ -132,26 +147,27 @@ namespace alg { if (ny<0 || ny>=(int)nrow) continue; // except the wall; - if(m_grid(ny,nx) == WALL) continue; + 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(ny,nx)) continue; + if(m_closedset(nx,ny)) continue; - float tentative = g_score(cy,cx); + float tentative = g_score(cx,cy); if (nx == cx || ny == cy) { - tentative += 1 + m_grid(ny,nx); + tentative += 1 + m_grid(nx,ny); } else { - tentative += (1 + m_grid(ny,nx)) * SQRT2; + tentative += (1 + m_grid(nx,ny)) * SQRT2; } // if neighbour not in the openset or dist < g_score[neighbour] - if (!openset.contains(nx*ncol+ny) || tentative < g_score(ny,nx)) { + if (!m_openset_grid(nx,ny) || tentative < g_score(nx,ny)) { came_from[nx*ncol+ny] = cx*ncol+cy; // record path - g_score(ny,nx) = tentative; - f_score(ny,nx) = tentative + estimate(nx,ny,x2,y2); - if (!openset.contains(nx*ncol+ny)) { - openset.insert(f_score(ny,nx), nx*ncol+ny); + g_score(nx,ny) = tentative; + f_score(nx,ny) = tentative + estimate(nx,ny,x2,y2); + if (!m_openset_grid(nx,ny)) { + m_openset.insert(f_score(nx,ny), nx*ncol+ny); + m_openset_grid(nx,ny) = true; } } } 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 From 7d9106ea9cbb1996175badddadc50f5ef8c626ff Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 17 May 2014 13:58:33 +0800 Subject: [PATCH 152/217] optimize astar algorithm with an extra array for fast testing openset --- include/astar.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/astar.h b/include/astar.h index 6723702d..d443441c 100644 --- a/include/astar.h +++ b/include/astar.h @@ -85,9 +85,9 @@ namespace alg { 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; - //} + if (m_grid(x1, y1) == WALL) { + return NULL; + } // the set of tentavie nodes to be evaluated, // initialy containing the start node From 91282a9910424c5a24575e5aabdbb9d5749b1e53 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 17 May 2014 14:21:39 +0800 Subject: [PATCH 153/217] optimize astar alg, added verbose comments --- include/astar.h | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/include/astar.h b/include/astar.h index d443441c..78fa276f 100644 --- a/include/astar.h +++ b/include/astar.h @@ -107,13 +107,14 @@ namespace alg { as->path = NULL; as->num_nodes = 0; + // the main A*algorithm while(!m_openset.is_empty()) { uint32_t value = m_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 + 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) { @@ -135,37 +136,38 @@ namespace alg { return as; } + // delete current positon from openset and move it into closed set. m_openset.delete_min(); m_closedset(cx, cy) = true; m_openset_grid(cx, cy) = false; - // for each neighbor + // for each valid neighbor of current position 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; + // 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; - // if neighbour in the closed set + // 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) { - tentative += 1 + m_grid(nx,ny); - } else { - tentative += (1 + m_grid(nx,ny)) * SQRT2; + 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 path - g_score(nx,ny) = tentative; - f_score(nx,ny) = tentative + estimate(nx,ny,x2,y2); - if (!m_openset_grid(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.insert(f_score(nx,ny), nx*ncol+ny); m_openset_grid(nx,ny) = true; } @@ -173,9 +175,16 @@ namespace alg { } } } + + // 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)); } From ccd723e3b7a6a4754c1a22576f53723032a364a6 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Mon, 19 May 2014 00:47:28 +0800 Subject: [PATCH 154/217] suffix_tree --- include/suffix_tree.h | 310 ++++++++++++++++++++++++++++++++++++ src/suffix_tree_demo.cpp | 336 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 646 insertions(+) create mode 100644 include/suffix_tree.h create mode 100644 src/suffix_tree_demo.cpp diff --git a/include/suffix_tree.h b/include/suffix_tree.h new file mode 100644 index 00000000..1b9e14a6 --- /dev/null +++ b/include/suffix_tree.h @@ -0,0 +1,310 @@ +#include +#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), pos(0), root(test_str), active_point(&root, 0, 0), remainder(0), ls() {} + int construct(void); + + // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist + int search(string sub); + + // return the length of the longest prefix of sub which can be matched in suffix tree + template + Iterator inc_search(Iterator sub) + { + typedef typename Iterator::value_type T; // extract real type + + Iterator result = sub; + Node* node = &root; + Edge* edge = NULL; + 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; + } + + int print_tree(void); +private: + string test_str; + + struct Node; + typedef struct Node Node; + + struct Edge{ + // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) + int begin, end; + // Is there a better way to find test_str? + string& test_node_str; + + Node * endpoint; + + Edge(int b, int e, string& str): + test_node_str(str) + { + begin = b; + end = e; + endpoint = NULL; + //std::cout << "Edge initialized" << std::endl; + } + + void change_edge(int b, 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[](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) + { + int end = edge.test_node_str.size()-1; + if (end >= edge.end) + end = edge.end; + + char c; + for (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; } + }; + typedef struct Edge Edge; + + 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"; + map::iterator iter = findedges.find(c); + //cout << "founded?" << endl; + if (iter != findedges.end()) + return iter->second; + else + 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; + } + }; + //typedef struct Node Node; + + 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 active_point.active_edge; } + void set_active_edge(char edge) { active_point.active_edge = edge; } + 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? + int pos; + 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* seperate_edge(Node * node, Edge* edge, int rule); + + // check if we can change active node + void check_an(void) + { + Node* node = get_active_node(); + Edge* edge = node->find_edge(get_active_edge()); + + if (edge == NULL) + return; + + int edge_size = edge->end - edge->begin + 1; + + // update + if (edge_size == get_active_length()) { + set_active_node(edge->endpoint); + set_active_edge(0); + set_active_length(0); + } + } + + // 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) { + 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/src/suffix_tree_demo.cpp b/src/suffix_tree_demo.cpp new file mode 100644 index 00000000..e3ce387c --- /dev/null +++ b/src/suffix_tree_demo.cpp @@ -0,0 +1,336 @@ +#include "suffix_tree.h" +#include + +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 + "#"; + + while (pos < test_str.size()) { + ls.clear(); + remainder++; + //cout << "Char: " << test_str[pos] << endl; + + bool flag = true; + while (flag) + flag = insert(); + pos++; + } + return 0; +} + +int SuffixTree::insert(void) +{ + int result = 0; + + Node* node = active_point.active_node; + if (node == (&root)) { + //cout << "ActiveNode is root." << endl; + result = insert_rule1(); + } + else { + //cout << "ActiveNode isn't root." << endl; + result = insert_rule3(); + } + + return result; +} + +// rule1 applies when the active node is root +int SuffixTree::insert_rule1(void) +{ + using std::numeric_limits; + + //cout << "Rule 1" << endl; + Node* node = &root; + + Edge* a_edge = node->find_edge(get_active_edge()); + + // next active edge + char active_char = 0; + + // can we find a match at active node? + Edge* possible = NULL; + bool will_insert = false; + if (get_active_length() != 0 && a_edge != NULL) { + // shouldn't throw out_of_range here, e.g. abcabc* + char match_char = (*a_edge)[get_active_length()]; + if (match_char == get_ele(pos)) + possible = a_edge; + else + will_insert = true; // will insert while active length is not 0 and activechar don't match + //cout << "Active char is " << active_char << endl; + + // node for insertion + } + else if (get_active_length() == 0) { + //cout << "Active char is NULL." << endl; + possible = node->find_edge(get_ele(pos)); + + // new active edge here and only here! + if (possible) + active_char = get_ele(pos); + else + active_char = 0; + } + else { + cout << "Error!!!!!!!!!!!!!!!!!!!1" << endl; + //throw; + } + + + if (possible) { + remainder++; + + // if not 0, then it's not a new edge, should not set + if (get_active_length() == 0) + set_active_edge(active_char); + + inc_active_len(); + check_an(); + } + else { + // seperate the old edge, set new active edge + if (a_edge != NULL) { + node = seperate_edge(node, a_edge, 1); + } + else + set_active_edge(0); + + //cout << "append a new edge at endpoint" << endl; + Edge* new_edge2 = new Edge(pos, numeric_limits::max(), test_str); + //cout << node << endl; + node->add_edge(new_edge2); + } + + remainder--; + + return will_insert; +} + +SuffixTree::Node* SuffixTree::seperate_edge(Node * node, Edge* a_edge, int rule) +{ + //cout << "seperate the old edge here: " << (*a_edge) << endl; + + char active_char; + + if (remainder > 2) + active_char = (*a_edge)[1]; + else + active_char = get_ele(pos); + + 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->find_edge(active_char) << "|||||||||||||||||||||||||| char " << active_char << endl; + //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); + //cout << node->find_edge(active_char) << "||||||||||||||||||||||||||2 char " << active_char << endl; + + old_edge1->endpoint->add_edge(a_edge); + //cout << (*node); +// old_edge1->endpoint->suffix_link = a_edge->endpoint->suffix_link; +// a_edge->endpoint->suffix_link = NULL; +/*----------------------------------------------------------------------- + Edge* new_edge1 = new Edge(new_begin, new_end, test_str); + a_edge->endpoint->add_edge(new_edge1); +------------------------------------------------------------------*/ + + //cout << "change edge" << endl; + + //cout << "What's wrong?" << endl; + cout << "The old edge split as -- " << (*a_edge) << " and -- " << (*old_edge1) << endl; + //cout << "What's wrong?" << endl; + + if (rule == 1) { + set_active_edge(active_char); + dec_active_len(); + } + else if (rule == 3) { + Node* n = &root; // new active node + //cout << node; + if (node->suffix_link) { + n = node->suffix_link; + cout << " Moved to suffix link!--------------" << endl; + } + else + cout << " Moved to root!------------------" << endl; + set_active_node(n); + } + + cout << "root " << (&root) << endl; + //cout << node << endl; + Node* new_node = old_edge1->endpoint; + ls.ins_link(new_node); + //cout << node << endl; + + return new_node; +} + +// applies when the active is not root +int SuffixTree::insert_rule3() +{ + //cout << "Rule3" << endl; + Node * node = get_active_node(); + cout << "Active node " << node << endl; + Edge * edge = node->find_edge(get_active_edge()); + + // input match a suffix? + bool match = false; + if (get_active_length() == 0) { + if (node->find_edge(get_ele(pos))) { + match = true; + + set_active_edge(get_ele(pos)); + inc_active_len(); + check_an(); + } + } + else { + // assert edge is not NULL + char match_char = (*edge)[get_active_length()]; + if (match_char == get_ele(pos)) { + match = true; + + inc_active_len(); + check_an(); + } + } + + if (match) + return 0; + + if (edge != NULL) { + node = seperate_edge(node, edge, 3); + } + + using std::numeric_limits; + + //cout << "append a new edge at endpoint" << endl; + Edge* new_edge2 = new Edge(pos, numeric_limits::max(), test_str); + cout << node << endl; + node->add_edge(new_edge2); + + remainder--; + + return 1; // should insert again at a different 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 << "Begining" << endl; + SuffixTree st("BANANAS"); + + 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; +} From 5a802d21aeaeccfdef5e5503c766f085dfef3b78 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Mon, 19 May 2014 22:30:56 +0800 Subject: [PATCH 155/217] makefile --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a167bc1d..eff8a30c 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,8 @@ PROGRAMS = m_based_demo \ bubble_sort_demo \ selection_sort_demo \ 8queue_demo \ - palindrome_demo + palindrome_demo \ + suffix_tree_demo all: $(PROGRAMS) From 27902fad3894a16bd7363f798dd6494e878c0e2f Mon Sep 17 00:00:00 2001 From: nower Date: Mon, 19 May 2014 23:53:18 +0800 Subject: [PATCH 156/217] support c++0x standard --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a167bc1d..00978fa0 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CPP=g++ AR=ar RANLIB=ranlib -CFLAGS= -g -Wall -Wno-unused-function +CFLAGS= -g -Wall -Wno-unused-function -std=gnu++0x SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = @@ -68,7 +68,8 @@ PROGRAMS = m_based_demo \ bubble_sort_demo \ selection_sort_demo \ 8queue_demo \ - palindrome_demo + palindrome_demo \ + suffix_array_demo all: $(PROGRAMS) From 71478e7f672b8e2bcc6150d53058b6a60a6e8b13 Mon Sep 17 00:00:00 2001 From: nower Date: Tue, 20 May 2014 00:12:33 +0800 Subject: [PATCH 157/217] add suffix array --- include/suffix_array.h | 92 +++++++++++++++++++++++++++++++++++++++ src/suffix_array_demo.cpp | 37 ++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 include/suffix_array.h create mode 100644 src/suffix_array_demo.cpp diff --git a/include/suffix_array.h b/include/suffix_array.h new file mode 100644 index 00000000..87e305db --- /dev/null +++ b/include/suffix_array.h @@ -0,0 +1,92 @@ +/* + * suffix array algorithm + * + * 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 _SUFFIX_ARRAY_H +#define _SUFFIX_ARRAY_H + +#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 "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< Date: Tue, 20 May 2014 09:35:26 +0800 Subject: [PATCH 158/217] update readme.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f30ddb72..ae49b167 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Red-black tree Interval tree Prefix Tree(Trie) - *Suffix Tree(未实现)* + Suffix Tree B-Tree Hash by multiplication @@ -96,4 +96,4 @@ wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST wyh267: for base64, LRU, bubble sort, selection sort - ZhangYou0122 : Push-Relabel algorithm + ZhangYou0122 : Push-Relabel algorithm, SuffixTree From 27c82aee26bf2d8a1ec9aa4bfcad3e17cea87b45 Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 20 May 2014 12:31:50 +0800 Subject: [PATCH 159/217] update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ae49b167..fb50434f 100644 --- a/README.md +++ b/README.md @@ -96,4 +96,5 @@ wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST wyh267: for base64, LRU, bubble sort, selection sort - ZhangYou0122 : Push-Relabel algorithm, SuffixTree + ZhangYou0122: Push-Relabel algorithm + UsingtcNower: Suffix Tree From 09db9c7a4444fc971d62021992875e838254d602 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 21 May 2014 10:10:33 +0800 Subject: [PATCH 160/217] update contributor --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb50434f..55988453 100644 --- a/README.md +++ b/README.md @@ -97,4 +97,4 @@ xmuliang: for HeapSort, Kruskal MST wyh267: for base64, LRU, bubble sort, selection sort ZhangYou0122: Push-Relabel algorithm - UsingtcNower: Suffix Tree + UsingtcNower: Suffix Array From 5ce8ce996c8649a9ae2671a8e260ed7a6907c441 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Wed, 21 May 2014 13:20:31 +0800 Subject: [PATCH 161/217] remove unordered map --- include/suffix_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/suffix_tree.h b/include/suffix_tree.h index 1b9e14a6..05bffa33 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -1,5 +1,5 @@ #include -#include +//#include #include #include #include From 106757f8feb1cc82d09eac2dfc0546bdd5a18cc1 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 21 May 2014 14:08:21 +0800 Subject: [PATCH 162/217] update README, and some indent,comment problem --- README.md | 5 +- include/suffix_array.h | 80 ++++--- include/suffix_tree.h | 528 +++++++++++++++++++++-------------------- 3 files changed, 314 insertions(+), 299 deletions(-) diff --git a/README.md b/README.md index 55988453..e907418f 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Prefix Tree(Trie) Suffix Tree B-Tree + Suffix Array Hash by multiplication Hash table @@ -96,5 +97,5 @@ wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST wyh267: for base64, LRU, bubble sort, selection sort - ZhangYou0122: Push-Relabel algorithm - UsingtcNower: Suffix Array + ZhangYou0122: Push-Relabel algorithm, Suffix Tree + UsingtcNower: Suffix Array diff --git a/include/suffix_array.h b/include/suffix_array.h index 87e305db..92fd67e9 100644 --- a/include/suffix_array.h +++ b/include/suffix_array.h @@ -1,16 +1,27 @@ -/* - * suffix array algorithm +/******************************************************************************* + * 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. * - * 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 + * Want to get more detailed information about suffix array? * - * author: nowerzt@gmail.com - */ + * Please google SUFF_AR_ENG.pdf + * + * AUTHOR: nowerzt@gmail.com + ******************************************************************************/ -#ifndef _SUFFIX_ARRAY_H -#define _SUFFIX_ARRAY_H +#ifndef __SUFFIX_ARRAY_H__ +#define __SUFFIX_ARRAY_H__ #include #include @@ -21,32 +32,32 @@ 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] > 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) + * _| + * + * SUFFIX TREE + * + * In computer science, a suffix tree (also called PAT tree or, in an earlier + * form, position tree) is a compressed trie containing all the suffixes of the + * given text as their keys and positions in the text as their values. Suffix + * trees allow particularly fast implementations of many important string + * operations. + * + * http://en.wikipedia.org/wiki/Suffix_tree + ******************************************************************************/ + #include -//#include #include #include #include @@ -14,297 +31,284 @@ 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), pos(0), root(test_str), active_point(&root, 0, 0), remainder(0), ls() {} - int construct(void); - - // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist - int search(string sub); - - // return the length of the longest prefix of sub which can be matched in suffix tree - template - Iterator inc_search(Iterator sub) - { - typedef typename Iterator::value_type T; // extract real type - - Iterator result = sub; - Node* node = &root; - Edge* edge = NULL; - 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(); +class SuffixTree { + public: + // active point is initialized as (root, None, 0), remainder initialized as 1 + SuffixTree(string str):test_str(str), pos(0), root(test_str), active_point(&root, 0, 0), remainder(0), ls() {} + int construct(void); + + // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist + int search(string sub); + + // return the length of the longest prefix of sub which can be matched in suffix tree + template + Iterator inc_search(Iterator sub) { + typedef typename Iterator::value_type T; // extract real type + + Iterator result = sub; + Node* node = &root; + Edge* edge = NULL; + 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; } - else { - if (pos >= edge_len) { - node = edge->endpoint; - edge = NULL; - edge_len = 0; - } - else { - if (*result == (*edge)[pos]) { - result++; - pos++; - } - else - flag = false; + + int print_tree(void); + private: + string test_str; + + struct Node; + typedef struct Node Node; + + struct Edge{ + // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) + int begin, end; + // Is there a better way to find test_str? + string& test_node_str; + + Node * endpoint; + + Edge(int b, int e, string& str): + test_node_str(str) { + begin = b; + end = e; + endpoint = NULL; + //std::cout << "Edge initialized" << std::endl; + } + + void change_edge(int b, 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[](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) { + int end = edge.test_node_str.size()-1; + if (end >= edge.end) + end = edge.end; + + char c; + for (int i=edge.begin; i<=end; i++) { + c = edge.test_node_str[i]; + os << c; } + if (end != edge.end) + os << '#'; + + return os; } - } - - return result; - } - - int print_tree(void); -private: - string test_str; - - struct Node; - typedef struct Node Node; - - struct Edge{ - // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) - int begin, end; - // Is there a better way to find test_str? - string& test_node_str; - - Node * endpoint; - - Edge(int b, int e, string& str): - test_node_str(str) - { - begin = b; - end = e; - endpoint = NULL; - //std::cout << "Edge initialized" << std::endl; - } - void change_edge(int b, int e) - { - begin = b; - end = e; - } + bool is_none(void) { return begin == 0 && end == 0; } + }; - int length(void) - { + typedef struct Edge Edge; - 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; - } + 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; - char operator[](int i) - { - i += begin; - if (i > end) - throw out_of_range("Edge [] out of range."); + friend class LinkState; - return test_node_str[i]; - } + Node(string& str) : + test_node_str(str), suffix_link(NULL) { edges.clear(); findedges.clear(); } - friend ostream& operator<<(ostream& os, Edge& edge) - { - int end = edge.test_node_str.size()-1; - if (end >= edge.end) - end = edge.end; + 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; + } - char c; - for (int i=edge.begin; i<=end; i++) { - c = edge.test_node_str[i]; - os << c; } - if (end != edge.end) - os << '#'; - return os; - } + // find edge by the first char + Edge* find_edge(char c) + { + //cout << "finding edge"; + map::iterator iter = findedges.find(c); + //cout << "founded?" << endl; + if (iter != findedges.end()) + return iter->second; + else + return NULL; + } - bool is_none(void) { return begin == 0 && end == 0; } - }; - typedef struct Edge Edge; - - 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; - } + bool isleaf() { return edges.empty(); } - 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; + bool operator==(Node& other) { + return (this) == (&other); } - } + friend ostream& operator<<(ostream& os, Node& node) { + map::iterator iter; + map::iterator iter_f; - // find edge by the first char - Edge* find_edge(char c) - { - //cout << "finding edge"; - map::iterator iter = findedges.find(c); - //cout << "founded?" << endl; - if (iter != findedges.end()) - return iter->second; - else - return NULL; - } + for (iter=node.edges.begin(); iter!=node.edges.end(); ++iter) + os << iter->first << '\t'; + os << endl; - bool isleaf() { return edges.empty(); } + for (iter_f=node.findedges.begin(); iter_f!=node.findedges.end(); ++iter_f) + os << iter_f->first << "-->" << iter_f->second << endl; - bool operator==(Node& other) - { - return (this) == (&other); + return os; + } + }; + //typedef struct Node Node; + + 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 active_point.active_edge; } + void set_active_edge(char edge) { active_point.active_edge = edge; } + 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? + int pos; + 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* seperate_edge(Node * node, Edge* edge, int rule); + + // check if we can change active node + void check_an(void) { + Node* node = get_active_node(); + Edge* edge = node->find_edge(get_active_edge()); + + if (edge == NULL) + return; + + int edge_size = edge->end - edge->begin + 1; + + // update + if (edge_size == get_active_length()) { + set_active_node(edge->endpoint); + set_active_edge(0); + set_active_length(0); + } } - friend ostream& operator<<(ostream& os, Node& node) - { - map::iterator iter; - map::iterator iter_f; + // this class indicate when shall we insert a suffix link + // ls should be a singleton + class LinkState { + bool first; - 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; + Node* prev, *curr; - return os; - } - }; - //typedef struct Node Node; + public: + LinkState() : first(true), prev(NULL), curr(NULL) {} - 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 active_point.active_edge; } - void set_active_edge(char edge) { active_point.active_edge = edge; } - 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? - int pos; - 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* seperate_edge(Node * node, Edge* edge, int rule); - - // check if we can change active node - void check_an(void) - { - Node* node = get_active_node(); - Edge* edge = node->find_edge(get_active_edge()); - - if (edge == NULL) - return; - - int edge_size = edge->end - edge->begin + 1; - - // update - if (edge_size == get_active_length()) { - set_active_node(edge->endpoint); - set_active_edge(0); - set_active_length(0); - } - } + void ins_link(Node* node) { + prev = curr; + curr = node; - // this class indicate when shall we insert a suffix link - // ls should be a singleton - class LinkState - { - bool first; - - Node* prev, *curr; + if (!first) { + prev->suffix_link = curr; + cout << "Suffix link added from prev " << prev << " to curr " << curr << endl; + } - public: - LinkState() : first(true), prev(NULL), curr(NULL) {} - - void ins_link(Node* node) - { - prev = curr; - curr = node; - - if (!first) { - prev->suffix_link = curr; - cout << "Suffix link added from prev " << prev << " to curr " << curr << endl; + first = false; } - first = false; - } + void clear(void) { + first = true; + prev = curr = NULL; + } + }; - void clear(void) - { - first = true; - prev = curr = NULL; - } - }; - LinkState ls; + LinkState ls; }; From fb2a1a00e88f6a6409cd83cb78d7fd2cbfe4c6c2 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Wed, 21 May 2014 14:41:26 +0800 Subject: [PATCH 163/217] 0 warning --- include/suffix_tree.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/suffix_tree.h b/include/suffix_tree.h index 05bffa33..00c9ac6a 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -21,7 +21,7 @@ class SuffixTree { public: // active point is initialized as (root, None, 0), remainder initialized as 1 - SuffixTree(string str):test_str(str), pos(0), root(test_str), active_point(&root, 0, 0), remainder(0), ls() {} + SuffixTree(string str):test_str(str), root(test_str), active_point(&root, 0, 0), remainder(0), pos(0), ls() {} int construct(void); // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist @@ -82,13 +82,13 @@ class SuffixTree struct Edge{ // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) - int begin, end; + unsigned int begin, end; // Is there a better way to find test_str? string& test_node_str; Node * endpoint; - Edge(int b, int e, string& str): + Edge(unsigned int b, unsigned int e, string& str): test_node_str(str) { begin = b; @@ -97,7 +97,7 @@ class SuffixTree //std::cout << "Edge initialized" << std::endl; } - void change_edge(int b, int e) + void change_edge(unsigned int b, unsigned int e) { begin = b; end = e; @@ -118,7 +118,7 @@ class SuffixTree return me.begin < other.begin; } - char operator[](int i) + char operator[](unsigned int i) { i += begin; if (i > end) @@ -129,12 +129,12 @@ class SuffixTree friend ostream& operator<<(ostream& os, Edge& edge) { - int end = edge.test_node_str.size()-1; + unsigned int end = edge.test_node_str.size()-1; if (end >= edge.end) end = edge.end; char c; - for (int i=edge.begin; i<=end; i++) { + for (unsigned int i=edge.begin; i<=end; i++) { c = edge.test_node_str[i]; os << c; } @@ -246,7 +246,7 @@ class SuffixTree // how many suffixes is to be inserted? int remainder; // how many characters inserted? - int pos; + unsigned int pos; char get_ele(int i) { return test_str[i]; } // insert a char from pos to suffix tree int insert(); From 075e05bace8d43cb80e029a350e82996a9140c6a Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 21 May 2014 16:43:14 +0800 Subject: [PATCH 164/217] update suffix_tree --- include/suffix_tree.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/suffix_tree.h b/include/suffix_tree.h index 87df7289..bc6eb8a8 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -17,6 +17,7 @@ ******************************************************************************/ #include +//#include #include #include #include @@ -31,12 +32,13 @@ 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), pos(0), root(test_str), active_point(&root, 0, 0), remainder(0), ls() {} + SuffixTree(string str):test_str(str), root(test_str), active_point(&root, 0, 0), remainder(0), pos(0), ls() {} int construct(void); // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist @@ -54,7 +56,6 @@ class SuffixTree { int edge_len = -1; bool flag = true; - while (flag) { if (edge == NULL) { edge = node->find_edge(*result); @@ -96,27 +97,25 @@ class SuffixTree { struct Edge{ // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) - int begin, end; + unsigned int begin, end; // Is there a better way to find test_str? string& test_node_str; Node * endpoint; - Edge(int b, int e, string& str): - test_node_str(str) { + 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(int b, int e) { + 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 @@ -128,7 +127,7 @@ class SuffixTree { return me.begin < other.begin; } - char operator[](int i) { + char operator[](unsigned int i) { i += begin; if (i > end) throw out_of_range("Edge [] out of range."); @@ -137,12 +136,12 @@ class SuffixTree { } friend ostream& operator<<(ostream& os, Edge& edge) { - int end = edge.test_node_str.size()-1; + unsigned int end = edge.test_node_str.size()-1; if (end >= edge.end) end = edge.end; char c; - for (int i=edge.begin; i<=end; i++) { + for (unsigned int i=edge.begin; i<=end; i++) { c = edge.test_node_str[i]; os << c; } @@ -167,8 +166,10 @@ class SuffixTree { friend class LinkState; - Node(string& str) : - test_node_str(str), suffix_link(NULL) { edges.clear(); findedges.clear(); } + Node(string& str) : test_node_str(str), suffix_link(NULL) { + edges.clear(); + findedges.clear(); + } void add_edge(Edge* edge) { if (edge->endpoint == NULL) @@ -195,8 +196,7 @@ class SuffixTree { } // find edge by the first char - Edge* find_edge(char c) - { + Edge* find_edge(char c) { //cout << "finding edge"; map::iterator iter = findedges.find(c); //cout << "founded?" << endl; @@ -228,14 +228,14 @@ class SuffixTree { }; //typedef struct Node Node; - class ActivePoint{ + 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; } + ActivePoint(Node* node, char edge, int length): active_node(node), + active_edge(edge), active_length(length) { std::cout << "ActivePoint initialized" << std::endl; } }; Node root; @@ -253,7 +253,7 @@ class SuffixTree { // how many suffixes is to be inserted? int remainder; // how many characters inserted? - int pos; + unsigned int pos; char get_ele(int i) { return test_str[i]; } // insert a char from pos to suffix tree int insert(); From b7dcd001887274d1b96f72465c625d2dbbc153a0 Mon Sep 17 00:00:00 2001 From: ZhangYou0122 Date: Sat, 31 May 2014 13:35:51 +0800 Subject: [PATCH 165/217] debugging --- include/suffix_tree.h | 53 +++++--- src/suffix_tree_demo.cpp | 271 +++++++++++++++------------------------ 2 files changed, 135 insertions(+), 189 deletions(-) diff --git a/include/suffix_tree.h b/include/suffix_tree.h index 00c9ac6a..3b429581 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -21,7 +21,7 @@ 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), ls() {} + SuffixTree(string str):test_str(str), root(test_str), active_point(&root, NULL, 0), remainder(0), pos(0), base_pos(0), ls() {} int construct(void); // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist @@ -94,7 +94,7 @@ class SuffixTree begin = b; end = e; endpoint = NULL; - //std::cout << "Edge initialized" << std::endl; + std::cout << "Edge initialized" << std::endl; } void change_edge(unsigned int b, unsigned int e) @@ -167,7 +167,7 @@ class SuffixTree 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; + cout << "edge added. Now we have " << edges.size() << "edges." << endl; } void del_edge(Edge* edge) { @@ -178,9 +178,9 @@ class SuffixTree else { // note we should erase the findedges too edges.erase(edge); - //cout << "delete" << (*edge)[0] << endl; + cout << "delete" << (*edge)[0] << endl; findedges.erase((*edge)[0]); - //cout << "edge deleted. Now we have " << edges.size() << "edges." << endl; + cout << "edge deleted. Now we have " << edges.size() << "edges." << endl; } } @@ -188,13 +188,18 @@ class SuffixTree // find edge by the first char Edge* find_edge(char c) { - //cout << "finding edge"; + cout << "finding edge char " << c; map::iterator iter = findedges.find(c); - //cout << "founded?" << endl; - if (iter != findedges.end()) + cout << " founded? "; + + if (iter != findedges.end()) { + cout << "yes." << endl; return iter->second; - else + } + else { + cout << "no." << endl; return NULL; + } } bool isleaf() { return edges.empty(); } @@ -224,10 +229,10 @@ class SuffixTree class ActivePoint{ public: Node* active_node; - char active_edge; + Edge* active_edge; int active_length; - ActivePoint(Node* node, char edge, int length): + ActivePoint(Node* node, Edge* edge, int length): active_node(node), active_edge(edge), active_length(length) { std::cout << "ActivePoint initialized" << std::endl; } }; @@ -236,8 +241,8 @@ class SuffixTree 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 active_point.active_edge; } - void set_active_edge(char edge) { active_point.active_edge = edge; } + Edge* get_active_edge(void) { return active_point.active_edge; } + void set_active_edge(Edge* edge) { active_point.active_edge = edge; } 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++; } @@ -247,6 +252,7 @@ class SuffixTree int remainder; // how many characters inserted? unsigned int pos; + unsigned int base_pos; // the beginnig 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(); @@ -258,21 +264,32 @@ class SuffixTree Node* seperate_edge(Node * node, Edge* edge, int rule); // check if we can change active node - void check_an(void) + void check_active_node(void) { Node* node = get_active_node(); - Edge* edge = node->find_edge(get_active_edge()); + Edge* edge = get_active_edge(); if (edge == NULL) return; - int edge_size = edge->end - edge->begin + 1; + unsigned int edge_size = edge->end - edge->begin + 1; + unsigned int length = get_active_length(); // update - if (edge_size == get_active_length()) { + if (edge_size == length) { set_active_node(edge->endpoint); set_active_edge(0); set_active_length(0); + base_pos += edge_size; + } + else if (length > edge_size) { + set_active_length(length-edge_size); + set_active_node(edge->endpoint); + int new_length = get_active_length(); + base_pos += edge_size; + Edge *new_active_edge = edge->endpoint->find_edge(get_ele(base_pos)); + set_active_edge(new_active_edge); + check_active_node(); } } @@ -292,7 +309,7 @@ class SuffixTree prev = curr; curr = node; - if (!first) { + if (first == false) { prev->suffix_link = curr; cout << "Suffix link added from prev " << prev << " to curr " << curr << endl; } diff --git a/src/suffix_tree_demo.cpp b/src/suffix_tree_demo.cpp index e3ce387c..e22fd57f 100644 --- a/src/suffix_tree_demo.cpp +++ b/src/suffix_tree_demo.cpp @@ -54,219 +54,148 @@ int SuffixTree::construct(void) while (pos < test_str.size()) { ls.clear(); remainder++; - //cout << "Char: " << test_str[pos] << endl; + cout << "Char: " << test_str[pos] << endl; + cout << "Suffix yet inserted begin at " << base_pos << " " << test_str[base_pos] << endl; - bool flag = true; - while (flag) - flag = insert(); + int move = 0; + while (move == 0) + move = insert(); pos++; } return 0; } int SuffixTree::insert(void) -{ - int result = 0; - - Node* node = active_point.active_node; - if (node == (&root)) { - //cout << "ActiveNode is root." << endl; - result = insert_rule1(); - } - else { - //cout << "ActiveNode isn't root." << endl; - result = insert_rule3(); - } - - return result; -} - -// rule1 applies when the active node is root -int SuffixTree::insert_rule1(void) { using std::numeric_limits; - - //cout << "Rule 1" << endl; - Node* node = &root; - Edge* a_edge = node->find_edge(get_active_edge()); + int move = 1; - // next active edge - char active_char = 0; + Node* node = active_point.active_node; + int length = get_active_length(); - // can we find a match at active node? - Edge* possible = NULL; - bool will_insert = false; - if (get_active_length() != 0 && a_edge != NULL) { - // shouldn't throw out_of_range here, e.g. abcabc* - char match_char = (*a_edge)[get_active_length()]; - if (match_char == get_ele(pos)) - possible = a_edge; - else - will_insert = true; // will insert while active length is not 0 and activechar don't match - //cout << "Active char is " << active_char << endl; + Edge* a_edge = get_active_edge(); - // node for insertion - } - else if (get_active_length() == 0) { - //cout << "Active char is NULL." << endl; - possible = node->find_edge(get_ele(pos)); - - // new active edge here and only here! - if (possible) - active_char = get_ele(pos); - else - active_char = 0; + if (a_edge == NULL) { + Edge *search_edge = node->find_edge(get_ele(pos)); + + if (search_edge == NULL) { + // insert new suffix + Edge *new_edge = new Edge(pos, numeric_limits::max(), test_str); + node->add_edge(new_edge); + remainder--; + if (node->suffix_link) { + // move to suffix link + set_active_node(node->suffix_link); + Edge *new_active_edge = node->suffix_link->find_edge(base_pos); + set_active_edge(new_active_edge); + move = 0; + } + else { + // move to root + set_active_node(&root); + + if (base_pos != pos) { + Edge *new_active_edge = root.find_edge(get_ele(base_pos)); + set_active_edge(new_active_edge); + dec_active_len(); + } + base_pos++; + + if (remainder > 0) { + move = 0; + } + else + move = 1; + } + } + else { + // set new active edge + set_active_edge(search_edge); + inc_active_len(); + move = 1; + } } else { - cout << "Error!!!!!!!!!!!!!!!!!!!1" << endl; - //throw; - } - - - if (possible) { - remainder++; + char expected_ele = (*a_edge)[get_active_length()]; - // if not 0, then it's not a new edge, should not set - if (get_active_length() == 0) - set_active_edge(active_char); - - inc_active_len(); - check_an(); - } - else { - // seperate the old edge, set new active edge - if (a_edge != NULL) { - node = seperate_edge(node, a_edge, 1); + cout << (*a_edge) << endl; + cout << get_active_length() << endl; + cout << expected_ele << " vs " << get_ele(pos) << endl; + if (expected_ele == get_ele(pos)) { + // expand active length + inc_active_len(); + check_active_node(); + move = 1; } - else - set_active_edge(0); - - //cout << "append a new edge at endpoint" << endl; - Edge* new_edge2 = new Edge(pos, numeric_limits::max(), test_str); - //cout << node << endl; - node->add_edge(new_edge2); - } + else { + // seperate edge and insert new suffix + Node * new_node = seperate_edge(node, a_edge, length); + Edge *new_edge = new Edge(pos, numeric_limits::max(), test_str); + new_node->add_edge(new_edge); + remainder--; + ls.ins_link(new_node); + + if (new_node->suffix_link) { + // move to suffix link + set_active_node(node->suffix_link); + Edge *new_active_edge = node->suffix_link->find_edge(get_ele(base_pos)); + set_active_edge(new_active_edge); + move = 0; + } + else { + // fall back to root + set_active_node(&root); + dec_active_len(); + base_pos++; + if (base_pos != pos) { + Edge *new_active_edge = root.find_edge(get_ele(pos-remainder+1)); + set_active_edge(new_active_edge); + base_pos = pos - remainder + 1; + + set_active_length(pos-base_pos); + check_active_node(); + + move = 0; + } + else { + set_active_edge(NULL); + move = 0; + } + } - remainder--; + } - return will_insert; + } + return move; } SuffixTree::Node* SuffixTree::seperate_edge(Node * node, Edge* a_edge, int rule) { - //cout << "seperate the old edge here: " << (*a_edge) << endl; - - char active_char; - - if (remainder > 2) - active_char = (*a_edge)[1]; - else - active_char = get_ele(pos); - + cout << "seperate 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->find_edge(active_char) << "|||||||||||||||||||||||||| char " << active_char << endl; - //cout << (*node); + 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); - //cout << node->find_edge(active_char) << "||||||||||||||||||||||||||2 char " << active_char << endl; old_edge1->endpoint->add_edge(a_edge); - //cout << (*node); -// old_edge1->endpoint->suffix_link = a_edge->endpoint->suffix_link; -// a_edge->endpoint->suffix_link = NULL; -/*----------------------------------------------------------------------- - Edge* new_edge1 = new Edge(new_begin, new_end, test_str); - a_edge->endpoint->add_edge(new_edge1); -------------------------------------------------------------------*/ - - //cout << "change edge" << endl; - //cout << "What's wrong?" << endl; cout << "The old edge split as -- " << (*a_edge) << " and -- " << (*old_edge1) << endl; - //cout << "What's wrong?" << endl; - - if (rule == 1) { - set_active_edge(active_char); - dec_active_len(); - } - else if (rule == 3) { - Node* n = &root; // new active node - //cout << node; - if (node->suffix_link) { - n = node->suffix_link; - cout << " Moved to suffix link!--------------" << endl; - } - else - cout << " Moved to root!------------------" << endl; - set_active_node(n); - } cout << "root " << (&root) << endl; - //cout << node << endl; + cout << node << endl; Node* new_node = old_edge1->endpoint; - ls.ins_link(new_node); - //cout << node << endl; - - return new_node; -} - -// applies when the active is not root -int SuffixTree::insert_rule3() -{ - //cout << "Rule3" << endl; - Node * node = get_active_node(); - cout << "Active node " << node << endl; - Edge * edge = node->find_edge(get_active_edge()); - - // input match a suffix? - bool match = false; - if (get_active_length() == 0) { - if (node->find_edge(get_ele(pos))) { - match = true; - - set_active_edge(get_ele(pos)); - inc_active_len(); - check_an(); - } - } - else { - // assert edge is not NULL - char match_char = (*edge)[get_active_length()]; - if (match_char == get_ele(pos)) { - match = true; - - inc_active_len(); - check_an(); - } - } - - if (match) - return 0; - - if (edge != NULL) { - node = seperate_edge(node, edge, 3); - } - - using std::numeric_limits; - - //cout << "append a new edge at endpoint" << endl; - Edge* new_edge2 = new Edge(pos, numeric_limits::max(), test_str); cout << node << endl; - node->add_edge(new_edge2); - remainder--; - - return 1; // should insert again at a different node - + return new_node; } int SuffixTree::print_tree() @@ -313,7 +242,7 @@ using namespace std; int main() { cout << "Begining" << endl; - SuffixTree st("BANANAS"); + SuffixTree st("mississippi"); cout << "Constructing..." << endl; st.construct(); From a021ec6ea3633a6604c535ca76d704477d075e16 Mon Sep 17 00:00:00 2001 From: cdkr <775481991@qq.com> Date: Sat, 21 Jun 2014 03:10:26 +0800 Subject: [PATCH 166/217] Optimized test_prime --- include/prime.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/prime.h b/include/prime.h index 8780dfd3..fd7b73ef 100644 --- a/include/prime.h +++ b/include/prime.h @@ -35,7 +35,7 @@ namespace alg { if (n%2 == 0) return false; unsigned sqrtn = sqrt(n); - for (unsigned int i = 2; i <= sqrtn; ++i) { + for (unsigned int i = 3; i <= sqrtn; i+=2) { if (n % i == 0) { return false; } From 1400e7c5207fd2a36d981badeb082860e124244d Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 25 Jul 2014 17:09:44 +0800 Subject: [PATCH 167/217] fix a bug in quicksort --- include/quick_sort.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/quick_sort.h b/include/quick_sort.h index 35caf1dd..a446f7af 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -74,8 +74,8 @@ namespace alg { quicksort(list, begin, pivot_idx-1); quicksort(list, pivot_idx+1, end); } else if ( begin + 1 == end) { - if (list[begin + 1] > list[end]) - swap(list[begin + 1], list[end]); + if (list[begin] > list[end]) + swap(list[begin], list[end]); } } } From f1473fa85ee067efa35244c230aaac8bd291ddd5 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 25 Jul 2014 17:16:30 +0800 Subject: [PATCH 168/217] rollback quicksort to random pivot version --- include/quick_sort.h | 51 +++++++++++++------------------------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/include/quick_sort.h b/include/quick_sort.h index a446f7af..b8962216 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -19,49 +19,31 @@ #define __QUICKSORT_H__ #include -#include namespace alg { - - /** - * Return median of begin, middle, and end. - * Order these and hide the pivot. - */ - template - static const T & __median3(T list[], int begin, int end) { - assert(begin + 2 <= end); - int middle = end - (end - begin) / 2; - if (list[middle] < list[begin]) - swap(list[middle], list[begin]); - if (list[end] < list[begin]) - swap(list[end], list[begin]); - if (list[end] < list[middle]) - swap(list[end], list[middle]); - - //Place pivot at position [end - 1] - swap(list[middle], list[end - 1]); - return list[end - 1]; - } - /** * the quick-sort partition routine */ template static int __partition(T list[],int begin, int end) { - T pivot = __median3(list, begin, end); - - int i = begin; - int j = end - 1; - - while(i < j) { - while(list[++i] < pivot) {} - while(pivot < list[--j]) {} + 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]); } - swap(list[i],list[end - 1]); - return i; // final pivot position + swap(list[begin],list[j]); + return j; // final pivot position } /** @@ -69,13 +51,10 @@ namespace alg { */ template static void quicksort(T list[],int begin,int end) { - if( begin + 1 < end) { + if( begin < end) { int pivot_idx = __partition(list, begin, end); quicksort(list, begin, pivot_idx-1); quicksort(list, pivot_idx+1, end); - } else if ( begin + 1 == end) { - if (list[begin] > list[end]) - swap(list[begin], list[end]); } } } From 62761362a454e8cd48c148059f32c6fddda92da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Su=C3=A1rez?= Date: Tue, 9 Sep 2014 20:00:50 +0200 Subject: [PATCH 169/217] AVL tree added, but there's still a bug in the erasure method --- Makefile | 6 +- README.md | 20 +-- include/avl.h | 230 +++++++++++++++++++++++++++++++++++ include/binary_search_tree.h | 2 +- src/avl_demo.cpp | 59 +++++++++ 5 files changed, 305 insertions(+), 12 deletions(-) create mode 100644 include/avl.h create mode 100644 src/avl_demo.cpp diff --git a/Makefile b/Makefile index ed8cccc0..73ca5f8a 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CPP=g++ AR=ar RANLIB=ranlib -CFLAGS= -g -Wall -Wno-unused-function -std=gnu++0x +CFLAGS= -g -Wall -Wno-unused-function -std=c++11 SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = @@ -70,7 +70,8 @@ PROGRAMS = m_based_demo \ 8queue_demo \ palindrome_demo \ suffix_array_demo \ - suffix_tree_demo + suffix_tree_demo \ + avl_demo all: $(PROGRAMS) @@ -79,3 +80,4 @@ all: $(PROGRAMS) clean: rm -rf $(PROGRAMS) *.dSYM + diff --git a/README.md b/README.md index e907418f..9f2ddb6f 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,11 @@ Queue Stack Binary Heap - Fibonacci Heap + Fibonacci Heap Priority Queue (list based) - Bubble sort - Selection sort + Bubble sort + Selection sort Insertion sort Radix sort Quick sort @@ -51,13 +51,14 @@ Largest common sequence Binary search tree + AVL tree Dynamic order statistics Red-black tree Interval tree Prefix Tree(Trie) Suffix Tree B-Tree - Suffix Array + Suffix Array Hash by multiplication Hash table @@ -72,7 +73,7 @@ Base64 Graph data structure - Strongly Connected Components(SCC) + Strongly Connected Components(SCC) Prim's minimum spanning tree Kruskal MST Directed/Undirected graph ops @@ -89,13 +90,14 @@ K-Means Knuth–Morris–Pratt algorithm Disjoint-Set - 8-Queue Problem - Palindrome + 8-Queue Problem + Palindrome ####贡献者 ( Contributors ) : - Samana : for heavy work of MSVC compatability + 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 + UsingtcNower: Suffix Array + afernandez90: AVL trees diff --git a/include/avl.h b/include/avl.h new file mode 100644 index 00000000..9dc6d621 --- /dev/null +++ b/include/avl.h @@ -0,0 +1,230 @@ +/******************************************************************************* + * 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 + * + ******************************************************************************/ + +#ifndef __AVL_H__ +#define __AVL_H__ + +#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()) { + tree = tree->erase(x); + numNodes--; + } + } + + void toGraphViz(std::ostream &stream, std::string name) const { + if (!isEmpty()) { + stream << "digraph " << name << " {" << std::endl; + tree->toGraphViz(stream); + stream << "}" << std::endl; + } + } + + private: + + 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) { + if (value == x) { + if (left == 0 && right == 0) { + delete this; + return 0; + } else if (left == 0) { + *this = *right; + delete right; + } else if (right == 0) { + *this = *left; + delete left; + } else { + // Tracing path to rightmost leaf of the left subtree + std::stack trace; + + Node *current = left; + while (current->right != 0) { + trace.push(current); + current = current->right; + } + + value = current->value; + Node *lsubtree = current->left; + delete current; + + if (trace.empty()) trace.push(left); + + trace.top()->right = lsubtree; + + do { + trace.top()->update(); + trace.pop(); + } while (!trace.empty()); + } + return update(); + } + else if (x < value) { + if (left != 0) { + left = left->erase(x); + return update(); + } else return this; + } + else { + if (right != 0) { + right = right->erase(x); + 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/binary_search_tree.h b/include/binary_search_tree.h index 21ff297a..5066c771 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -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: diff --git a/src/avl_demo.cpp b/src/avl_demo.cpp new file mode 100644 index 00000000..9eb66173 --- /dev/null +++ b/src/avl_demo.cpp @@ -0,0 +1,59 @@ +#include +#include "avl.h" + +using namespace std; +using namespace alg; + +const unsigned N = 4096*32; +const unsigned N_ELEMS_TO_REMOVE = 4096*8; + +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 " << N_ELEMS_TO_REMOVE << " random elements for the tree... "; + for (unsigned i = 0; i < N_ELEMS_TO_REMOVE; ++i) { + unsigned idx = rand() % N; + avl.erase(values[idx]); + } + cout << "Done" << endl; + + printTreeStatus(avl); + + cout << "Do you want to see the GraphViz representation of the Tree (Y/n)? "; + char usrInput; + cin >> usrInput; + if (usrInput == 'Y' || usrInput == 'y') avl.toGraphViz(cout, "AVL"); + + return 0; +} + From 3171767d370f75b099550c7d10590987d6e5b074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Su=C3=A1rez?= Date: Wed, 10 Sep 2014 18:39:42 +0200 Subject: [PATCH 170/217] bug fixed, AVL trees now working properly --- include/avl.h | 40 ++++++++++++++++++++++++---------------- src/avl_demo.cpp | 21 ++++++++++++++------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/include/avl.h b/include/avl.h index 9dc6d621..e9ffe90c 100644 --- a/include/avl.h +++ b/include/avl.h @@ -51,8 +51,9 @@ class AVL { void erase(const T &x) { if (!isEmpty()) { - tree = tree->erase(x); - numNodes--; + bool found = false; + tree = tree->erase(x, found); + if (found) numNodes--; } } @@ -64,7 +65,7 @@ class AVL { } } - private: + public: struct Node { Node *left, *right; @@ -93,51 +94,58 @@ class AVL { return update(); } - Node *erase(const T &x) { + 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 right; + delete aux; } else if (right == 0) { + Node *aux = left; *this = *left; - delete left; + delete aux; } else { // Tracing path to rightmost leaf of the left subtree std::stack trace; Node *current = left; - while (current->right != 0) { + 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()) trace.push(left); - - trace.top()->right = lsubtree; - - do { - trace.top()->update(); + if (trace.empty()) { left = lsubtree; } + else { + trace.top()->right = lsubtree; trace.pop(); - } while (!trace.empty()); + 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); + left = left->erase(x, found); return update(); } else return this; } else { if (right != 0) { - right = right->erase(x); + right = right->erase(x, found); return update(); } else return this; } diff --git a/src/avl_demo.cpp b/src/avl_demo.cpp index 9eb66173..444185f0 100644 --- a/src/avl_demo.cpp +++ b/src/avl_demo.cpp @@ -5,7 +5,7 @@ using namespace std; using namespace alg; const unsigned N = 4096*32; -const unsigned N_ELEMS_TO_REMOVE = 4096*8; +const unsigned N_ELEMS_TO_REMOVE = N-128; // Must be between 0 and N-1 template void printTreeStatus(const AVL &t) { @@ -40,20 +40,27 @@ int main() cout << "ERROR: Value " << values[idx] << " was inserted and not found!" << endl; } - cout << "Now removing " << N_ELEMS_TO_REMOVE << " random elements for the tree... "; + 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) { - unsigned idx = rand() % N; - avl.erase(values[idx]); + avl.erase(avl.root()); } cout << "Done" << endl; printTreeStatus(avl); - cout << "Do you want to see the GraphViz representation of the Tree (Y/n)? "; + // 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(cout, "AVL"); - + if (usrInput == 'Y' || usrInput == 'y') avl.toGraphViz(cerr, "AVL"); + return 0; } From 3ae4d87ca5d626174a3154896d44d57621c73291 Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 11 Sep 2014 14:09:41 +0800 Subject: [PATCH 171/217] update Makefile --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 73ca5f8a..9f25fa8c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CPP=g++ AR=ar RANLIB=ranlib -CFLAGS= -g -Wall -Wno-unused-function -std=c++11 +CFLAGS= -g -Wall -Wno-unused-function SRCDIR = ./src INCLUDEDIR = -I./include -I. DEPS = @@ -69,7 +69,6 @@ PROGRAMS = m_based_demo \ selection_sort_demo \ 8queue_demo \ palindrome_demo \ - suffix_array_demo \ suffix_tree_demo \ avl_demo From 1312092d77a93f0571b4910fad06b21d33d1362d Mon Sep 17 00:00:00 2001 From: fuli Date: Thu, 11 Sep 2014 14:59:17 +0800 Subject: [PATCH 172/217] fix Makefile for compatibility of cxx11 --- Makefile | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 202 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 9f25fa8c..04870219 100644 --- a/Makefile +++ b/Makefile @@ -4,25 +4,25 @@ CPP=g++ AR=ar RANLIB=ranlib 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_demo \ + +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_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 \ universal_hash_demo \ perfect_hash_demo \ binary_search_tree_demo \ @@ -74,8 +74,194 @@ PROGRAMS = m_based_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) + +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) + +heap_sort_demo: $(SRCDIR)/heap_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +kruskal_mst_demo: $(SRCDIR)/kruskal_mst_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + +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 From 2179038643760950a1c75b3dfbb33f51845f765b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Su=C3=A1rez?= Date: Thu, 11 Sep 2014 14:36:42 +0200 Subject: [PATCH 173/217] Author information added to AVL headerfile --- include/avl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/avl.h b/include/avl.h index e9ffe90c..b339739c 100644 --- a/include/avl.h +++ b/include/avl.h @@ -13,6 +13,9 @@ * 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 * ******************************************************************************/ From d81d1a693c6fa1d5fb1ce903b05faf9d7267158d Mon Sep 17 00:00:00 2001 From: Samana Date: Wed, 26 Nov 2014 22:33:21 -0500 Subject: [PATCH 174/217] + Added .Net style Dictionary ( cache friendly hash table ) + Minor VC2013 compliance fixes --- include/avl.h | 2 + include/dictionary.h | 562 ++++++++++++++++++++++++++++++++++++++++ include/hash_multi.h | 4 +- include/prime.h | 2 +- include/suffix_array.h | 3 +- include/suffix_tree.h | 2 + msvc/alg_vs.h | 4 +- src/dictionary_demo.cpp | 49 ++++ 8 files changed, 622 insertions(+), 6 deletions(-) create mode 100644 include/dictionary.h create mode 100644 src/dictionary_demo.cpp diff --git a/include/avl.h b/include/avl.h index b339739c..4b8f00cd 100644 --- a/include/avl.h +++ b/include/avl.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include namespace alg { 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/hash_multi.h b/include/hash_multi.h index bc75cb37..4639e229 100644 --- a/include/hash_multi.h +++ b/include/hash_multi.h @@ -42,7 +42,7 @@ namespace alg { } #ifdef _MSC_VER -#define log2(x) (log(x) / log(2)) +#define log2(x) (log(x) / log(2.0)) #endif /** @@ -50,7 +50,7 @@ namespace alg { */ 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/prime.h b/include/prime.h index fd7b73ef..81f772e4 100644 --- a/include/prime.h +++ b/include/prime.h @@ -34,7 +34,7 @@ namespace alg { if (n%2 == 0) return false; - unsigned sqrtn = sqrt(n); + unsigned sqrtn = sqrt((double)n); for (unsigned int i = 3; i <= sqrtn; i+=2) { if (n % i == 0) { return false; diff --git a/include/suffix_array.h b/include/suffix_array.h index 92fd67e9..c078bd0a 100644 --- a/include/suffix_array.h +++ b/include/suffix_array.h @@ -27,6 +27,7 @@ #include #include #include +#include using namespace std; @@ -69,7 +70,7 @@ namespace alg { for(size_t k=0;k>1) + +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); +} From bc16e44e9453e41f2bc67443f1b918ba8b3d688b Mon Sep 17 00:00:00 2001 From: fuli Date: Wed, 21 Jan 2015 10:27:36 +0800 Subject: [PATCH 175/217] fix a bug in RANDOM macro --- include/generic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/generic.h b/include/generic.h index c55487c6..8671f740 100644 --- a/include/generic.h +++ b/include/generic.h @@ -24,7 +24,7 @@ #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 { /** From b6e62b4e3567fa50814cf37a854307263e23c0da Mon Sep 17 00:00:00 2001 From: orthographic-pedant Date: Wed, 30 Sep 2015 18:51:52 -0400 Subject: [PATCH 176/217] Fixed typographical error, changed arbitary to arbitrary in README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f2ddb6f..f347d414 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Prime test(trial division) Prime test(Miller-Rabin's method) 2D Array - Arbitary Integer + Arbitrary Integer Linear congruential generator Maximum subarray problem From a5c52404a3f716b9582faa5c4265b804f1a3b40b Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 22 Oct 2015 15:52:26 +0800 Subject: [PATCH 177/217] fix a bug in dijkstra --- include/dijkstra.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index c7b9c9c3..f1831c18 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -76,7 +76,7 @@ namespace alg { list_for_each_entry(v, &u->v_head, v_node){ uint32_t alt = dist_u + v->weight; uint32_t dist_v = dist[v->id]; - if (alt < dist_v && !visited[v->id]) { + if (alt < dist_v) { /* uint32_t tmp = dist[v->id]; if (tmp != INT_MAX) { From 8caabf1bcb10cb89ad7a1df80af29f4abf2edd2a Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 23 Oct 2015 14:55:03 +0800 Subject: [PATCH 178/217] a better implementation of heap inspired by golang/heap --- Makefile | 5 -- README.md | 1 - include/astar.h | 10 +-- include/dijkstra.h | 31 +++---- include/heap.h | 190 +++++++++++++++++++---------------------- include/heap_sort.h | 54 ------------ include/kruskal_mst.h | 2 +- include/prim_mst.h | 20 ++--- include/scc.h | 8 +- src/heap_demo.cpp | 21 +++-- src/heap_sort_demo.cpp | 34 -------- 11 files changed, 133 insertions(+), 243 deletions(-) delete mode 100644 include/heap_sort.h delete mode 100644 src/heap_sort_demo.cpp diff --git a/Makefile b/Makefile index 04870219..e9ba280c 100644 --- a/Makefile +++ b/Makefile @@ -53,8 +53,6 @@ PROGRAMS = m_based_demo \ random_demo \ k-means_demo \ kmp_demo \ - heap_sort_demo \ - kruskal_mst_demo \ LRU_cache_demo \ base64_demo \ max_subarray_demo \ @@ -209,9 +207,6 @@ k-means_demo: $(SRCDIR)/k-means_demo.cpp kmp_demo : $(SRCDIR)/kmp_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) -heap_sort_demo: $(SRCDIR)/heap_sort_demo.cpp - $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) - kruskal_mst_demo: $(SRCDIR)/kruskal_mst_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) diff --git a/README.md b/README.md index 9f2ddb6f..1a431a9f 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,6 @@ Radix sort Quick sort Merge sort - Heap sort Double linked list Skip list Self-organized linked-list ops (move-to-front, move-ahead-one) diff --git a/include/astar.h b/include/astar.h index 78fa276f..03474b34 100644 --- a/include/astar.h +++ b/include/astar.h @@ -93,7 +93,7 @@ namespace alg { // initialy containing the start node // encoding [x,y] to [x*ncol + y] // using binary heap ... - m_openset.insert(0, x1*ncol+y1); + m_openset.push(0, x1*ncol+y1); // record the starting point in openset_grid m_openset_grid(x1,y1) = true; @@ -109,7 +109,8 @@ namespace alg { // the main A*algorithm while(!m_openset.is_empty()) { - uint32_t value = m_openset.min_value(); + Heap::elem e = m_openset.pop(); + uint32_t value = e.data; int cx = value/ncol; int cy = value%ncol; @@ -136,8 +137,7 @@ namespace alg { return as; } - // delete current positon from openset and move it into closed set. - m_openset.delete_min(); + // move it into closed set. m_closedset(cx, cy) = true; m_openset_grid(cx, cy) = false; @@ -168,7 +168,7 @@ namespace alg { g_score(nx,ny) = tentative; // update path cost for current position f_score(nx,ny) = tentative + estimate(nx,ny,x2,y2); // record path cost to this neighbour if (!m_openset_grid(nx,ny)) { // only insert the neighbour if it hasn't been add to the openset. - m_openset.insert(f_score(nx,ny), nx*ncol+ny); + m_openset.push(f_score(nx,ny), nx*ncol+ny); m_openset_grid(nx,ny) = true; } } diff --git a/include/dijkstra.h b/include/dijkstra.h index f1831c18..d0bebe7d 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -37,6 +37,7 @@ namespace alg { class Dijkstra { public: static const int UNDEFINED = -1; + static const int LARGE_NUMBER = 999999; // run dijkstra algorithm, and return the previous table static HashTable * run(const Graph & g, uint32_t src_id) { // a binary heap @@ -51,43 +52,35 @@ namespace alg { // all vertices Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node){ - dist[a->v.id] = INT_MAX; // set inital distance to each vertex as INT_MAX + dist[a->v.id] = LARGE_NUMBER; // set inital distance to each vertex to a large number (*previous)[a->v.id] = UNDEFINED; // clear path to UNDEFINED visited[a->v.id] = false; // all vertices are not visited + Q.push(LARGE_NUMBER, a->v.id); // push all vertices to heap } // source vertex, the first vertex in Heap-Q - Q.insert(0, src_id); dist[src_id] = 0; + // decrease-key the source vertex to 0 + Q.decrease_key(src_id,0); while(!Q.is_empty()) { // for every un-visited vertex, try relaxing the path - int32_t id = Q.min_value(); - Q.delete_min(); // remove u from Q - if (visited[id]) { // jump visited vertex, it means a closer vertex has found - // printf("visted:%d %d\n", id, dist[id]); + Heap::elem e = Q.pop(); + uint32_t id = e.data; + if (visited[id]) { // ignore visited vertex continue; } Graph::Adjacent * u = g[id]; // the vertex to process int dist_u = dist[id]; // current known shortest distance to u - visited[id] = true; // mark the vertex as visited. + visited[id] = true; // mark the vertex as visited. Graph::Vertex * v; list_for_each_entry(v, &u->v_head, v_node){ uint32_t alt = dist_u + v->weight; - uint32_t dist_v = dist[v->id]; - if (alt < dist_v) { - /* - uint32_t tmp = dist[v->id]; - if (tmp != INT_MAX) { - printf("old %d %d\n", v->id, tmp); - printf("new %d %d\n", v->id, dist[v->id]); - } - */ - + if (alt < dist[v->id]) { dist[v->id] = alt; - (*previous)[v->id] = u->v.id; - Q.insert(alt, v->id); + (*previous)[v->id] = id; + Q.decrease_key(v->id, alt); // decrease-key } } } diff --git a/include/heap.h b/include/heap.h index 3462660a..959d6a3e 100644 --- a/include/heap.h +++ b/include/heap.h @@ -8,8 +8,8 @@ * 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. + * left child is at ( 2i ), right child is at ( 2i+1 ) and parent is + * at (int) (i / 2). Heap size is stored at index 0. * * Basic operations of a heap are: * @@ -27,8 +27,7 @@ #include #include #include -#include "hash_code.h" -#include "hash_table.h" +#include "generic.h" namespace alg { /** @@ -36,33 +35,29 @@ namespace alg { */ template class Heap { - private: + public: /** * define key-value pair of heap struct. */ - struct KV { + struct elem { public: - int32_t key; - T value; + int key; + T data; }; - int32_t m_size; // current heap size. - int32_t m_max; // max heap size. - KV * m_kvs; // key value pairs. - - HashTable * m_idx; // key -> idx + private: + int m_size; // current heap size. + int m_max; // max heap size. + elem * m_heap; // key value pairs. public: Heap(int max) { m_size = 0; m_max = max+1; - m_kvs = new KV[m_max]; - m_kvs[0].key = INT_MIN; - m_idx = new HashTable(m_max); + m_heap = new elem[m_max]; }; ~Heap() { - delete [] m_kvs; - delete m_idx; + delete [] m_heap; }; private: @@ -70,37 +65,20 @@ namespace alg { Heap& operator=(const Heap&); public: - - inline int min_key() const { return m_kvs[1].key; }; - inline const T & min_value() const { return m_kvs[1].value; }; - // for loop through the kvs - inline uint32_t count() const { return m_size; }; - inline const T & operator[] (uint32_t idx) const { return m_kvs[idx+1].value; }; + inline int count() const { return m_size; }; /** * insert a 'key'->'value' pair into the heap. */ - void insert(int key, const T & value) { + void push(int key, const T & data) { // heap full, just return; if(m_size == m_max) return; - + // put in the back, and try move upward the heap + m_heap[m_size].key = key; + m_heap[m_size].data= data; + up(m_size); m_size++; - m_kvs[m_size].key = key; - m_kvs[m_size].value = value; - (*m_idx)[value] = m_size; - - // Adjust its position - int now = m_size; - while(m_kvs[now/2].key > key) { - m_kvs[now] = m_kvs[now/2]; - (*m_idx)[m_kvs[now/2].value] = now; - now /= 2; - } - - m_kvs[now].key = key; - m_kvs[now].value = value; - (*m_idx)[value] = now; } /** @@ -113,84 +91,94 @@ namespace alg { */ inline void clear() { m_size = 0; } + bool contains(const T & data) { + for(int i=1;i<=m_size;i++) { + if(m_heap[i].data== data) return true; + } + return false; + } + /** - * contains test + * pop the min element */ - bool contains(const T & value) { - for(int32_t i=1;i<=m_size;i++) { - if(m_kvs[i].value == value) return true; - } + elem pop() { + int n = m_size-1; + swap(m_heap[0],m_heap[n]); + down(0, n); + m_size--; + return m_heap[m_size]; + } + /** + * remove the given data + */ + bool remove(T data) { + for (int i=0;i heap top. + * decrease key + * simpliy implemented as remove then push */ - void delete_min() { - // heap[1] is the minimum key. So we remove heap[1]. - // Size of the heap is decreased. Now heap[1] has to be filled. - // We put the last key in its place and see if it fits. If it - // does not fit, take minimum key among both its children and - // replaces parent with it. Again See if the last key fits - //in that place. - int32_t lastKey; - T lastValue; - int32_t child,now; - - // empty heap, just return - if (m_size == 0) return; - - lastKey = m_kvs[m_size].key; - lastValue = m_kvs[m_size].value; - m_size--; + void decrease_key(T data, int newkey) { + if (remove(data)) { + push(newkey, data); + } + } - // now refers to the index at which we are now - for(now = 1; now*2 <= m_size ;now = child) { - // child is the index of the key which is minimum among - // both the children, Indexes of children are i*2 and i*2 + 1 - child = now*2; - // child!=heapSize beacuse heap[heapSize+1] does not exist, - // which means it has only one child - if(child != m_size && m_kvs[child+1].key < m_kvs[child].key) { - child++; // choose the minium one. + void up(int j) { + for (;;) { + int i = (j-1)/2; // parent + if (i==j || !less(j,i)) { // j not smaller than i + break; } - // To check if the last key fits or not it suffices to check - // if the last key is less than the minimum key among both the children - if(lastKey > m_kvs[child].key) { - m_kvs[now] = m_kvs[child]; - (*m_idx)[m_kvs[now].value] = now; // record index + swap(m_heap[i], m_heap[j]); + j=i; + } + } + + void down(int i, int n) { + for(;;) { + int j1 = 2*i+1; // left child + if (j1 >=n || j1 < 0) { // j1 < 0 after int overflow + break; + } + + int j = j1; + int j2 = j1+1; // left child + if (j2 < n && !less(j1,j2)) { + j = j2; // choose the minium one. } - else { // It fits there + + if (!less(j,i)) { break; } + swap(m_heap[i], m_heap[j]); + i=j; } - - m_kvs[now].key = lastKey; - m_kvs[now].value= lastValue; - (*m_idx)[lastValue] = now; // record index } - /** - * so called DECREASE KEY operation. - * step 1. find the value - * step 2. decrease the key to the newkey - */ - void decrease_key(T value, int32_t newkey) { - int32_t index = (*m_idx)[value]; - if (index > m_size || index == 0) return; // value not found - if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning. - T oldvalue = m_kvs[index].value; - - int now = index; - while(m_kvs[now/2].key > newkey) { - m_kvs[now] = m_kvs[now/2]; - (*m_idx)[m_kvs[now].value] = now; // record index - now /= 2; + void print_heap() { + for (int i=0;i - * _| - * - * HEAPSORT - * - * Features: - * 1. Although somewhat slower in practice on most machines than a well-implemented quicksort, - it has the advantage of a more favorable worst-case O(n log n) runtime - * - * http://en.wikipedia.org/wiki/Heapsort - * - ******************************************************************************/ - -#ifndef __HEAPSORT_H__ -#define __HEAPSORT_H__ - -#include - -namespace alg { - /** - * heap sort an array - */ - template - static void heapsort(T *array,int number_of_elements) { - Heap heap(number_of_elements); - int i; - - // In order to build a heap structure from input array - for(i=0;iheap.insert(v->weight, v); // weight->vertex + pa->heap.push(v->weight, v); // weight->vertex } } diff --git a/include/prim_mst.h b/include/prim_mst.h index b3bf5069..8c4892fa 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -30,10 +30,12 @@ #include "undirected_graph.h" #include "double_linked_list.h" #include "heap.h" +#include "hash_table.h" namespace alg { class Prim { public: + static const int LARGE_NUMBER = 999999; /** * Prim's Algorithm. * @@ -62,24 +64,20 @@ namespace alg { // all vertices Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node){ - if (a->v.id != src_id) { - Q.insert(INT_MAX, a->v.id); - keys[a->v.id] = INT_MAX; - } + Q.push(LARGE_NUMBER, a->v.id); + keys[a->v.id] = LARGE_NUMBER; } - - Q.insert(0, src_id); + + Q.decrease_key(src_id, 0); keys[src_id] = 0; while (!Q.is_empty()) { - int32_t id = Q.min_value(); - Q.delete_min(); // remove u from Q - - Graph::Adjacent * u = g[id]; // the vertex to process + Heap::elem e = Q.pop(); + Graph::Adjacent * u = g[e.data]; // 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; + pi[v->id] = e.data; Q.decrease_key(v->id, v->weight); keys[v->id] = v->weight; } diff --git a/include/scc.h b/include/scc.h index 23e34e0e..1d641a1b 100644 --- a/include/scc.h +++ b/include/scc.h @@ -39,7 +39,7 @@ namespace alg { Heap Q(g.vertex_count()) ; Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node) { - Q.insert(INT_MAX - a->f, a->v.id); // descending order of a->f + Q.push(INT_MAX - a->f, a->v.id); // descending order of a->f } // step 2. discover @@ -51,9 +51,9 @@ namespace alg { // step 3. call DFS(GT), but in the main loop of DFS, consider the vertices // in order of decreasing u.f (as computed in line 1) while(!Q.is_empty()) { - int32_t key = Q.min_key(); - int32_t id = Q.min_value(); - Q.delete_min(); + Heap::elem e = Q.pop(); + int32_t key = e.key; + int32_t id = e.data; if ((*GT)[id]->color == Graph::WHITE) { printf("component:%d %d\n",id, INT_MAX - key); _DFS_VISIT(*GT, (*GT)[id]); diff --git a/src/heap_demo.cpp b/src/heap_demo.cpp index bf761a66..ccae4aea 100644 --- a/src/heap_demo.cpp +++ b/src/heap_demo.cpp @@ -9,20 +9,25 @@ int main() int MAXELEMENTS=10; Heap heap(MAXELEMENTS); - int32_t i; + int i; srand(time(NULL)); for (i=0;i < MAXELEMENTS; i++) { - int32_t value = i; - heap.insert(i, value); - printf("inserting: %d->%d\n", i, value); + heap.push(100-i, i); + printf("push: key:%d->value:%d\n", 100-i, i); } + heap.print_heap(); + + for (i=0;i%d\n", heap.min_key(), heap.min_value()); - heap.delete_min(); + Heap::elem e = heap.pop(); + printf("pop: key:%d->value:%d\n", e.key, e.data); } + heap.print_heap(); return 0; } diff --git a/src/heap_sort_demo.cpp b/src/heap_sort_demo.cpp deleted file mode 100644 index 7a8423c4..00000000 --- a/src/heap_sort_demo.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -#include "generic.h" -#include "heap_sort.h" - -using namespace alg; - -int main() -{ - const int MAX_ELEMENTS = 10; - int list[MAX_ELEMENTS]; - - int i = 0; - - srand(time(NULL)); - // generate random numbers and fill them to the list - for(i = 0; i < MAX_ELEMENTS; i++ ){ - list[i] = rand()%100; - } - printf("The list before sorting is:\n"); - printlist(list,MAX_ELEMENTS); - - // sort the list using heap sort - heapsort(&list[0],MAX_ELEMENTS); - - // print the result - printf("The list after sorting using heapsort algorithm:\n"); - printlist(list,MAX_ELEMENTS); - return 0; -} - - From 2fb4c5ab2755c6814e180a23e8b6378f1bab12e8 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 23 Oct 2015 15:13:08 +0800 Subject: [PATCH 179/217] clean --- include/prim_mst.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/prim_mst.h b/include/prim_mst.h index 8c4892fa..3949e895 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -73,11 +73,12 @@ namespace alg { while (!Q.is_empty()) { Heap::elem e = Q.pop(); - Graph::Adjacent * u = g[e.data]; // the vertex to process + 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] = e.data; + pi[v->id] = id; Q.decrease_key(v->id, v->weight); keys[v->id] = v->weight; } From b5756134050f5aeab5b430674cc27ad1984ae88c Mon Sep 17 00:00:00 2001 From: Daniel Fu Date: Fri, 23 Oct 2015 17:05:22 +0800 Subject: [PATCH 180/217] Update heap.h --- include/heap.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/include/heap.h b/include/heap.h index 959d6a3e..c82f4d06 100644 --- a/include/heap.h +++ b/include/heap.h @@ -7,14 +7,23 @@ * * Heap Data structure * - * Heaps can be used as an array. For any key at array position I, - * left child is at ( 2i ), right child is at ( 2i+1 ) and parent is - * 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 ******************************************************************************/ From e95583a3d8adccfddc6b5737dc6389014a796105 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 23 Oct 2015 17:06:53 +0800 Subject: [PATCH 181/217] fix ident --- include/heap.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/heap.h b/include/heap.h index c82f4d06..d6343ef7 100644 --- a/include/heap.h +++ b/include/heap.h @@ -57,7 +57,7 @@ namespace alg { private: int m_size; // current heap size. int m_max; // max heap size. - elem * m_heap; // key value pairs. + elem * m_heap; // key value pairs. public: Heap(int max) { m_size = 0; @@ -122,8 +122,8 @@ namespace alg { * remove the given data */ bool remove(T data) { - for (int i=0;i Date: Fri, 23 Oct 2015 17:09:48 +0800 Subject: [PATCH 182/217] add qualifier --- include/heap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/heap.h b/include/heap.h index d6343ef7..8712109b 100644 --- a/include/heap.h +++ b/include/heap.h @@ -121,7 +121,7 @@ namespace alg { /** * remove the given data */ - bool remove(T data) { + bool remove(const T &data) { for (int i=0;i Date: Sun, 8 Nov 2015 23:19:15 -0200 Subject: [PATCH 183/217] Add Fenwick Tree algorithm - Gabriel123Duarte --- include/fenwick_tree.h | 44 +++++++++++++++++++++++++++++++++++++++ src/fenwick_tree_demo.cpp | 16 ++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 include/fenwick_tree.h create mode 100644 src/fenwick_tree_demo.cpp diff --git a/include/fenwick_tree.h b/include/fenwick_tree.h new file mode 100644 index 00000000..ba3f581c --- /dev/null +++ b/include/fenwick_tree.h @@ -0,0 +1,44 @@ +#ifndef __FENWICK_H__ +#define __FENWICK_H__ + +#include + +#define LSONE(x) (x & (-x)) + +class Fenwick +{ + private: + std::vector fen; + public: + Fenwick() {} + + // We don't use the index 0 + Fenwick(int n) + { + fen.assign(n + 1, 0); + } + + // RSQ 1..a + 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 \ No newline at end of file diff --git a/src/fenwick_tree_demo.cpp b/src/fenwick_tree_demo.cpp new file mode 100644 index 00000000..d5e294de --- /dev/null +++ b/src/fenwick_tree_demo.cpp @@ -0,0 +1,16 @@ +#include +#include "fenwick_tree.h" + +int main() +{ + Fenwick ft(5); + + ft.update(2, 1); + ft.update(4, 10); + + printf("%d\n", ft.rsq(1)); + + ft.update(1, 5); + printf("%d\n", ft.rsq(1)); + return 0; +} \ No newline at end of file From 99defa0c2139648cc551509bf583457137598da5 Mon Sep 17 00:00:00 2001 From: Gabriel Duarte Date: Mon, 9 Nov 2015 08:53:33 -0200 Subject: [PATCH 184/217] Added some comments in the header file --- include/.goutputstream-UUQE8X | 61 +++++++++++++++++++++++++++++++++++ include/fenwick_tree.h | 23 +++++++++++-- 2 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 include/.goutputstream-UUQE8X diff --git a/include/.goutputstream-UUQE8X b/include/.goutputstream-UUQE8X new file mode 100644 index 00000000..e92d1ab5 --- /dev/null +++ b/include/.goutputstream-UUQE8X @@ -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 __FENWICK_H__ +#define __FENWICK_H__ + +#include + +#define LSONE(x) (x & (-x)) + +class Fenwick +{ + private: + // Vector representing the table + std::vector fen; + public: + Fenwick() {} + + // We don't use the index 0, because it is the base case + Fenwick(int n) + { + fen.assign(n + 1, 0); + } + + // Calculate the + int rsq(int a) + { + int ans = 0; + for(; a; a -= LSONE(a)) + ans += fen[a]; + return ans; + } + + // RSQ a..b + inline int rsq(int a, int b) + { + return rsq(b) - (a == 1 ? 0 : rsq(a - 1)); + } + + // Update the value of the k-th element by x + void update(int k, int x) + { + for(; k < (int)fen.size(); k += LSONE(k)) + fen[k] += x; + } +}; + +#endif diff --git a/include/fenwick_tree.h b/include/fenwick_tree.h index ba3f581c..e92d1ab5 100644 --- a/include/fenwick_tree.h +++ b/include/fenwick_tree.h @@ -1,3 +1,19 @@ +/******************************************************************************* + * Fenwick Tree + * + * Data structure providing prefix sums and modify the table in O(log n) - n is the size o the table. + * + * In this algorithm we use two functions: + * - RSQ - This function calculates the range sum query in O(log n) + * - Update - This function adjusts the values in the given range in O(log n) + * + * https://en.wikipedia.org/wiki/Fenwick_tree + * + * @author Gabriel Duarte (gabriellagoa10@yahoo.com.br) + * @github Gabriel123Duarte + * + ******************************************************************************/ + #ifndef __FENWICK_H__ #define __FENWICK_H__ @@ -8,17 +24,18 @@ class Fenwick { private: + // Vector representing the table std::vector fen; public: Fenwick() {} - // We don't use the index 0 + // We don't use the index 0, because it is the base case Fenwick(int n) { fen.assign(n + 1, 0); } - // RSQ 1..a + // Calculate the int rsq(int a) { int ans = 0; @@ -41,4 +58,4 @@ class Fenwick } }; -#endif \ No newline at end of file +#endif From 943b52a8eb2d42b3fb1f92dd00a05f963fbd361f Mon Sep 17 00:00:00 2001 From: Yanzhe Chen Date: Wed, 30 Mar 2016 20:16:12 +0800 Subject: [PATCH 185/217] Add shell sort --- Makefile | 4 ++++ README.md | 1 + include/shell_sort.h | 44 +++++++++++++++++++++++++++++++++++++++++ src/shell_sort_demo.cpp | 32 ++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 include/shell_sort.h create mode 100644 src/shell_sort_demo.cpp diff --git a/Makefile b/Makefile index e9ba280c..c0c50190 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ LIBS = -lm PROGRAMS = m_based_demo \ integer_demo \ insertion_sort_demo \ + shell_sort_demo \ radix_sort_demo \ shuffle_demo \ quick_sort_demo \ @@ -81,6 +82,9 @@ integer_demo: $(SRCDIR)/integer_demo.cpp insertion_sort_demo: $(SRCDIR)/insertion_sort_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) +shell_sort_demo: $(SRCDIR)/shell_sort_demo.cpp + $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) + radix_sort_demo: $(SRCDIR)/radix_sort_demo.cpp $(CPP) $(CFLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) diff --git a/README.md b/README.md index 04958eaf..5bb32f29 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Bubble sort Selection sort Insertion sort + Shell sort Radix sort Quick sort Merge sort diff --git a/include/shell_sort.h b/include/shell_sort.h new file mode 100644 index 00000000..d3d2db2e --- /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 __SHELL_SORT_H__ +#define __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/src/shell_sort_demo.cpp b/src/shell_sort_demo.cpp new file mode 100644 index 00000000..e284bd8d --- /dev/null +++ b/src/shell_sort_demo.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +#include "generic.h" +#include "shell_sort.h" + +using namespace alg; + +int main() +{ + const int MAX_ELEMENTS = 10; + int list[MAX_ELEMENTS]; + + int i = 0; + + srand(time(NULL)); + // generate random numbers and fill them to the list + for(i = 0; i < MAX_ELEMENTS; i++ ){ + list[i] = rand()%100; + } + printf("The list before sorting is:\n"); + printlist(list,MAX_ELEMENTS); + + // sort the list using shell sort + shell_sort(&list[0],MAX_ELEMENTS); + + // print the result + printf("The list after sorting using shell sort algorithm:\n"); + printlist(list,MAX_ELEMENTS); + return 0; +} From cc7793cf77d550bd47d18dd55de8c97390f7af01 Mon Sep 17 00:00:00 2001 From: Yanzhe Chen Date: Wed, 30 Mar 2016 22:04:42 +0800 Subject: [PATCH 186/217] Fix bugs in heap --- include/heap.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/heap.h b/include/heap.h index 8712109b..351ba0db 100644 --- a/include/heap.h +++ b/include/heap.h @@ -61,7 +61,7 @@ namespace alg { public: Heap(int max) { m_size = 0; - m_max = max+1; + m_max = max; m_heap = new elem[m_max]; }; @@ -101,7 +101,7 @@ namespace alg { inline void clear() { m_size = 0; } bool contains(const T & data) { - for(int i=1;i<=m_size;i++) { + for(int i=0;i Date: Thu, 31 Mar 2016 09:47:50 +0800 Subject: [PATCH 187/217] indent --- include/shell_sort.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/shell_sort.h b/include/shell_sort.h index d3d2db2e..22b04de9 100644 --- a/include/shell_sort.h +++ b/include/shell_sort.h @@ -22,22 +22,22 @@ namespace alg { */ 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; - } + 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; + } } } From c3c99c40033d0e3a6030f1a699a1b233504f85e2 Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 26 Apr 2016 17:40:14 +0800 Subject: [PATCH 188/217] update --- README.md | 4 ++++ donate_alg.png | Bin 0 -> 4349 bytes 2 files changed, 4 insertions(+) create mode 100644 donate_alg.png diff --git a/README.md b/README.md index 5bb32f29..b2203990 100644 --- a/README.md +++ b/README.md @@ -101,3 +101,7 @@ ZhangYou0122: Push-Relabel algorithm, Suffix Tree UsingtcNower: Suffix Array afernandez90: AVL trees + +####支持此项目 ( Donations ) : +![donate](donate_alg.png) +欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化补全及完善。 diff --git a/donate_alg.png b/donate_alg.png new file mode 100644 index 0000000000000000000000000000000000000000..04e73bb091a433492a5a564e25cec76445518861 GIT binary patch literal 4349 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 H@xA?Dd2w2* literal 0 HcmV?d00001 From 50035c9941f8fca3d7e810ad8455536f3d5d7bc5 Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 26 Apr 2016 18:28:38 +0800 Subject: [PATCH 189/217] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2203990..33744dd0 100644 --- a/README.md +++ b/README.md @@ -104,4 +104,4 @@ ####支持此项目 ( Donations ) : ![donate](donate_alg.png) -欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化补全及完善。 +欢迎使用支付宝扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化补全及完善。 From b8c632b6352e06fdd990fa2c012ebe7eb188cf0c Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 10:39:55 +0900 Subject: [PATCH 190/217] definiton -> definition --- include/binary_search_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 5066c771..2fc544c0 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -31,7 +31,7 @@ namespace alg { class BST { private: /** - * binary search tree definiton. + * binary search tree definition. */ struct treeNode { KeyT key; // key From 841a1bdbba7cd5a52f33fa3fc3e017937e4d2f28 Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 10:44:45 +0900 Subject: [PATCH 191/217] h:55 inital -> initial --- include/dijkstra.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dijkstra.h b/include/dijkstra.h index d0bebe7d..5013f14f 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -52,7 +52,7 @@ namespace alg { // all vertices Graph::Adjacent * a; list_for_each_entry(a, &g.list(), a_node){ - dist[a->v.id] = LARGE_NUMBER; // set inital distance to each vertex to a large number + 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 From 70a90bdde9638c1f5c21b172272409608591e27c Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 10:47:51 +0900 Subject: [PATCH 192/217] h:39 definiton -> definition --- include/hash_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hash_table.h b/include/hash_table.h index 0fcdb713..1c5abd6e 100644 --- a/include/hash_table.h +++ b/include/hash_table.h @@ -36,7 +36,7 @@ namespace alg { typedef _HashCode hash_code_fn; private: /** - * definiton of Key-Value pair. + * definition of Key-Value pair. */ struct HashKV { key_type key; // 32-bit key From a2554338602c9e3c49f0a1e147eb20cd7c5185cc Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 10:51:02 +0900 Subject: [PATCH 193/217] h:16 seperately -> separately h:17 fucntion -> function --- include/merge_sort.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/merge_sort.h b/include/merge_sort.h index 8a45aece..5eab291d 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. * * ------------ From 0556913a27d355357b45172a35a26b5c88dd0848 Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 10:54:31 +0900 Subject: [PATCH 194/217] h:78 apropriate -> appropriate --- include/priority_queue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/priority_queue.h b/include/priority_queue.h index 4a8dbe28..e81edf35 100644 --- a/include/priority_queue.h +++ b/include/priority_queue.h @@ -75,7 +75,7 @@ namespace alg { list_add(&n->node, &m_head); m_count++; } else { - // sequentially find the apropriate position + // sequentially find the appropriate position PQNode * pos; bool found = false; list_for_each_entry(pos, &m_head, node) { From a0ce506be525bb55aad2cf1779adcfd07cd594ed Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 10:57:31 +0900 Subject: [PATCH 195/217] h:100 higer -> higher --- include/skiplist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/skiplist.h b/include/skiplist.h index 1c330ba7..f45d4f33 100644 --- a/include/skiplist.h +++ b/include/skiplist.h @@ -97,7 +97,7 @@ namespace alg { if(x == NULL || x->key != key) { int lvl = random_level(); // random promotion - // for nodes higer than current max level + // for nodes higher than current max level // make 'header node' as it's prev if(lvl > m_level) { for(int i = m_level + 1; i <= lvl; i++) { From 4cf920ed7d76cbdb2e02a3389fea8609c97499cf Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 11:01:26 +0900 Subject: [PATCH 196/217] h:27: postion -> position h:260: beginnig -> beginning h:269: seperate -> separate --- include/suffix_tree.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/suffix_tree.h b/include/suffix_tree.h index 23bd04d6..d738d9c3 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -24,7 +24,7 @@ class SuffixTree SuffixTree(string str):test_str(str), root(test_str), active_point(&root, 0, 0), remainder(0), pos(0), active_e(0), ls() {} int construct(void); - // return -1 if no such sub exist, return the beginning postion of this substring in thr original string if it exist + // return -1 if no such sub exist, return the beginning position of this substring in thr original string if it exist int search(string sub); // return the length of the longest prefix of sub which can be matched in suffix tree @@ -257,7 +257,7 @@ class SuffixTree int remainder; // how many characters inserted? unsigned int pos; - unsigned int active_e; // the beginnig position of suffixes need to be inserted + unsigned int active_e; // the beginning position of suffixes need to be inserted char get_ele(int i) { return test_str[i]; } // insert a char from pos to suffix tree int insert(); @@ -266,7 +266,7 @@ class SuffixTree int print_node(Node* node, int level); - Node* seperate_edge(Node * node, Edge* edge); + Node* separate_edge(Node * node, Edge* edge); // check if we can change active node bool check_active_node(void) From 56e957685304afbff7d110821288ffd893e367f9 Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 11:03:08 +0900 Subject: [PATCH 197/217] h:66: arbitary -> arbitrary --- include/universal_hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/universal_hash.h b/include/universal_hash.h index 29afcf7d..1b162857 100644 --- a/include/universal_hash.h +++ b/include/universal_hash.h @@ -63,7 +63,7 @@ namespace alg { } /** - * hash an arbitary length integer. + * hash an arbitrary length integer. * len, number of 32-bit integer, max len is 32 */ static uint32_t uhash_bigint(const struct UHash * params, uint32_t * key, uint32_t len) { From 20ecf38f3b78fe96e65b538abf26d0e2e7014096 Mon Sep 17 00:00:00 2001 From: tmdrnjs54 Date: Thu, 19 May 2016 11:06:34 +0900 Subject: [PATCH 198/217] 85: seperate -> separate --- src/suffix_tree_demo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/suffix_tree_demo.cpp b/src/suffix_tree_demo.cpp index 8862e9b2..d4425c68 100644 --- a/src/suffix_tree_demo.cpp +++ b/src/suffix_tree_demo.cpp @@ -82,7 +82,7 @@ int SuffixTree::construct(void) ls.ins_link(node); break; } - Node *newnode = seperate_edge(node, a_edge); + Node *newnode = separate_edge(node, a_edge); Edge* newedge = new Edge(pos, numeric_limits::max(), test_str); newnode->add_edge(newedge); ls.ins_link(newnode); @@ -106,7 +106,7 @@ int SuffixTree::construct(void) SuffixTree::Node* SuffixTree::seperate_edge(Node * node, Edge* a_edge) { - cout << "seperate the old edge here: " << (*a_edge) << endl; + cout << "separate the old edge here: " << (*a_edge) << endl; int new_begin = a_edge->begin + get_active_length(); int new_end = a_edge->end; @@ -175,7 +175,7 @@ using namespace std; int main() { - cout << "Begining" << endl; + cout << "Beginning" << endl; SuffixTree st("mississippi"); cout << "Constructing..." << endl; From e9a800739c10c2bbc4c2617cd07b74a62a72f9da Mon Sep 17 00:00:00 2001 From: "Hesham.Safi" Date: Sat, 21 May 2016 15:06:47 +0200 Subject: [PATCH 199/217] issue #46 : include/suffix_tree.h : - fixed build errors ( access modifiers issue) - removed typedef struct ... as it is unnecessary in C++ src/suffic_tree_demo.cpp : - fixed typo in function declaration name (seperate -> separate) --- include/suffix_tree.h | 16 +++------------- src/suffix_tree_demo.cpp | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/suffix_tree.h b/include/suffix_tree.h index d738d9c3..7fd684e6 100644 --- a/include/suffix_tree.h +++ b/include/suffix_tree.h @@ -31,8 +31,6 @@ class SuffixTree template Iterator inc_search(Iterator sub) { - typedef typename Iterator::value_type T; // extract real type - Iterator result = sub; Node* node = &root; Edge* edge = NULL; @@ -73,13 +71,7 @@ class SuffixTree return result; } - int print_tree(void); -private: - string test_str; - struct Node; - typedef struct Node Node; - struct Edge{ // the begin and end pos of this edge, note that INT_MAX stands for #(the changing end pos of this entire string) unsigned int begin, end; @@ -146,7 +138,6 @@ class SuffixTree bool is_none(void) { return begin == 0 && end == 0; } }; - typedef struct Edge Edge; struct Node{ string& test_node_str; @@ -224,10 +215,9 @@ class SuffixTree return os; } }; - //typedef struct Node Node; - - friend struct Node; - + int print_tree(void); +private: + string test_str; class ActivePoint{ public: Node* active_node; diff --git a/src/suffix_tree_demo.cpp b/src/suffix_tree_demo.cpp index d4425c68..4a5170b5 100644 --- a/src/suffix_tree_demo.cpp +++ b/src/suffix_tree_demo.cpp @@ -104,7 +104,7 @@ int SuffixTree::construct(void) return 0; } -SuffixTree::Node* SuffixTree::seperate_edge(Node * node, Edge* a_edge) +SuffixTree::Node* SuffixTree::separate_edge(Node * node, Edge* a_edge) { cout << "separate the old edge here: " << (*a_edge) << endl; int new_begin = a_edge->begin + get_active_length(); From 7f8d1ab173f3f1d1e9016c39745fb53d7b67134f Mon Sep 17 00:00:00 2001 From: ahmetince Date: Sat, 6 Aug 2016 12:55:28 +0300 Subject: [PATCH 200/217] rearranged I tried to rearrange the code with cpp codes. --- src/random_demo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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< Date: Sun, 7 Aug 2016 21:47:05 +0800 Subject: [PATCH 201/217] add .travis.yml --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..e4d9ce7f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: cpp + +compiler: + - gcc + - clang + +script: + - make From 788277858072c74ed13c9c6ee14abdb7d8b98bfe Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 7 Aug 2016 21:47:59 +0800 Subject: [PATCH 202/217] upd readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 33744dd0..d9b7eb9f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ ###Algorithms & Data Structures in C++ +[![Build Status][1]][2] +[1]: https://travis-ci.org/xtaci/algorithms.svg?branch=master +[2]: https://travis-ci.org/xtaci/algorithms ####目标 ( goal ) : From e30dd73ee55ca26558288b37cf79198a97c3b938 Mon Sep 17 00:00:00 2001 From: Vic Luo Date: Thu, 1 Sep 2016 14:05:37 +0800 Subject: [PATCH 203/217] Correct import guard macro name --- include/2darray.h | 4 ++-- include/8queen.h | 6 +++--- include/astar.h | 4 ++-- include/avl.h | 4 ++-- include/bellman_ford.h | 4 ++-- include/binary_search_tree.h | 4 ++-- include/bitset.h | 4 ++-- include/bloom_filter.h | 4 ++-- include/btree.h | 4 ++-- include/dijkstra.h | 4 ++-- include/directed_graph.h | 4 ++-- include/disjoint-set.h | 4 ++-- include/dos_tree.h | 4 ++-- include/double_linked_list.h | 4 ++-- include/edmonds_karp.h | 4 ++-- include/fenwick_tree.h | 4 ++-- include/fib-heap.h | 4 ++-- include/generic.h | 4 ++-- include/graph_defs.h | 4 ++-- include/graph_search.h | 4 ++-- include/hash_code.h | 4 ++-- include/hash_multi.h | 4 ++-- include/hash_string.h | 4 ++-- include/hash_table.h | 4 ++-- include/heap.h | 4 ++-- include/huffman.h | 4 ++-- include/imath.h | 4 ++-- include/insertion_sort.h | 4 ++-- include/integer.h | 4 ++-- include/interval_tree.h | 4 ++-- include/k-means.h | 4 ++-- include/kmp.h | 4 ++-- include/kruskal_mst.h | 4 ++-- include/lcs.h | 4 ++-- include/md5.h | 4 ++-- include/merge_sort.h | 4 ++-- include/perfect_hash.h | 4 ++-- include/prim_mst.h | 4 ++-- include/prime.h | 4 ++-- include/priority_queue.h | 4 ++-- include/queue.h | 4 ++-- include/quick_sort.h | 4 ++-- include/radix_sort.h | 4 ++-- include/random.h | 4 ++-- include/random_select.h | 4 ++-- include/rbtree.h | 4 ++-- include/rbtree_defs.h | 4 ++-- include/relabel_to_front.h | 4 ++-- include/scc.h | 4 ++-- include/selection_sort.h | 6 +++--- include/sha1.h | 4 ++-- include/shell_sort.h | 4 ++-- include/shuffle.h | 4 ++-- include/simhash.h | 4 ++-- include/skiplist.h | 4 ++-- include/sol.h | 4 ++-- include/stack.h | 4 ++-- include/suffix_array.h | 6 +++--- include/trie.h | 4 ++-- include/undirected_graph.h | 4 ++-- include/universal_hash.h | 4 ++-- include/word_seg.h | 4 ++-- msvc/alg_vs.h | 6 +++--- utils/byteorder.h | 4 ++-- utils/gb18030.h | 4 ++-- 65 files changed, 134 insertions(+), 134 deletions(-) diff --git a/include/2darray.h b/include/2darray.h index 1383e242..929a286a 100644 --- a/include/2darray.h +++ b/include/2darray.h @@ -10,8 +10,8 @@ * Simulated by 1-dimension array. ******************************************************************************/ -#ifndef __2D_ARRAY_H__ -#define __2D_ARRAY_H__ +#ifndef 2D_ARRAY_H__ +#define 2D_ARRAY_H__ #include #include diff --git a/include/8queen.h b/include/8queen.h index 27062e3a..17eaefef 100644 --- a/include/8queen.h +++ b/include/8queen.h @@ -9,8 +9,8 @@ * http://en.wikipedia.org/wiki/Eight_queens_puzzle ******************************************************************************/ -#ifndef __8QUEEN_H__ -#define __8QUEEN_H__ +#ifndef 8QUEEN_H__ +#define 8QUEEN_H__ #include #include @@ -84,4 +84,4 @@ namespace alg { }; } -#endif //__8QUEEN_H__ +#endif //8QUEEN_H__ diff --git a/include/astar.h b/include/astar.h index 03474b34..6dc68f02 100644 --- a/include/astar.h +++ b/include/astar.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef __ASTAR_H__ -#define __ASTAR_H__ +#ifndef ASTAR_H__ +#define ASTAR_H__ #include #include diff --git a/include/avl.h b/include/avl.h index 4b8f00cd..aa1ef6ca 100644 --- a/include/avl.h +++ b/include/avl.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef __AVL_H__ -#define __AVL_H__ +#ifndef AVL_H__ +#define AVL_H__ #include #include diff --git a/include/bellman_ford.h b/include/bellman_ford.h index 2d6df417..d859d72a 100644 --- a/include/bellman_ford.h +++ b/include/bellman_ford.h @@ -44,8 +44,8 @@ * ******************************************************************************/ -#ifndef __BELLMAN_FORD_H__ -#define __BELLMAN_FORD_H__ +#ifndef BELLMAN_FORD_H__ +#define BELLMAN_FORD_H__ #include #include diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 2fc544c0..254cb0f2 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -18,8 +18,8 @@ * ******************************************************************************/ -#ifndef __BINARY_SEARCH_TREE_H__ -#define __BINARY_SEARCH_TREE_H__ +#ifndef BINARY_SEARCH_TREE_H__ +#define BINARY_SEARCH_TREE_H__ #include #include diff --git a/include/bitset.h b/include/bitset.h index 83171c12..fd6ae57b 100644 --- a/include/bitset.h +++ b/include/bitset.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __BIT_SET_H__ -#define __BIT_SET_H__ +#ifndef BIT_SET_H__ +#define BIT_SET_H__ #include #include diff --git a/include/bloom_filter.h b/include/bloom_filter.h index 810badd5..952d44ab 100644 --- a/include/bloom_filter.h +++ b/include/bloom_filter.h @@ -18,8 +18,8 @@ * ******************************************************************************/ -#ifndef __BLOOM_FILTER_H__ -#define __BLOOM_FILTER_H__ +#ifndef BLOOM_FILTER_H__ +#define BLOOM_FILTER_H__ #include #include diff --git a/include/btree.h b/include/btree.h index bec96048..5f50b6e2 100644 --- a/include/btree.h +++ b/include/btree.h @@ -24,8 +24,8 @@ * http://en.wikipedia.org/wiki/B-tree ******************************************************************************/ -#ifndef __BTREE_H__ -#define __BTREE_H__ +#ifndef BTREE_H__ +#define BTREE_H__ #include #include diff --git a/include/dijkstra.h b/include/dijkstra.h index 5013f14f..73b6c2ee 100644 --- a/include/dijkstra.h +++ b/include/dijkstra.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef __DIJKSTRA_H__ -#define __DIJKSTRA_H__ +#ifndef DIJKSTRA_H__ +#define DIJKSTRA_H__ #include #include diff --git a/include/directed_graph.h b/include/directed_graph.h index 0eb8e56e..7694e5a3 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __DIRECTED_GRAPH_H__ -#define __DIRECTED_GRAPH_H__ +#ifndef DIRECTED_GRAPH_H__ +#define DIRECTED_GRAPH_H__ #include #include diff --git a/include/disjoint-set.h b/include/disjoint-set.h index c13a002e..1d1568c4 100644 --- a/include/disjoint-set.h +++ b/include/disjoint-set.h @@ -18,8 +18,8 @@ * http://en.wikipedia.org/wiki/Disjoint-set_data_structure ******************************************************************************/ -#ifndef __DISJOINTSET_H__ -#define __DISJOINTSET_H__ +#ifndef DISJOINTSET_H__ +#define DISJOINTSET_H__ namespace alg { template diff --git a/include/dos_tree.h b/include/dos_tree.h index 7440990f..f754f180 100644 --- a/include/dos_tree.h +++ b/include/dos_tree.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef __DOS_TREE_H__ -#define __DOS_TREE_H__ +#ifndef DOS_TREE_H__ +#define DOS_TREE_H__ #include #include diff --git a/include/double_linked_list.h b/include/double_linked_list.h index 7b8a8637..be595e7e 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 DOUBLE_LINKED_LIST_H__ +#define DOUBLE_LINKED_LIST_H__ struct list_head { struct list_head *next, *prev; diff --git a/include/edmonds_karp.h b/include/edmonds_karp.h index 396c9fbc..f9ca4b56 100644 --- a/include/edmonds_karp.h +++ b/include/edmonds_karp.h @@ -21,8 +21,8 @@ * ******************************************************************************/ -#ifndef __EDMONDS_KARP_H__ -#define __EDMONDS_KARP_H__ +#ifndef EDMONDS_KARP_H__ +#define EDMONDS_KARP_H__ #include #include diff --git a/include/fenwick_tree.h b/include/fenwick_tree.h index e92d1ab5..cc12d602 100644 --- a/include/fenwick_tree.h +++ b/include/fenwick_tree.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __FENWICK_H__ -#define __FENWICK_H__ +#ifndef FENWICK_H__ +#define FENWICK_H__ #include diff --git a/include/fib-heap.h b/include/fib-heap.h index 68100b8b..b5303bf6 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Fibonacci_heap ******************************************************************************/ -#ifndef __FIB_HEAP_H__ -#define __FIB_HEAP_H__ +#ifndef FIB_HEAP_H__ +#define FIB_HEAP_H__ #include #include #include diff --git a/include/generic.h b/include/generic.h index 8671f740..16d50e84 100644 --- a/include/generic.h +++ b/include/generic.h @@ -9,8 +9,8 @@ * ******************************************************************************/ -#ifndef __ALG_INC_H__ -#define __ALG_INC_H__ +#ifndef ALG_INC_H__ +#define ALG_INC_H__ #include #include #include diff --git a/include/graph_defs.h b/include/graph_defs.h index 8860c9b1..f2b61ada 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -1,5 +1,5 @@ -#ifndef __GRAPH_DEFS_H__ -#define __GRAPH_DEFS_H__ +#ifndef GRAPH_DEFS_H__ +#define GRAPH_DEFS_H__ #include "double_linked_list.h" diff --git a/include/graph_search.h b/include/graph_search.h index 438ea660..7605aed6 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 BREADTH_FIRST_SEARCH_H__ +#define BREADTH_FIRST_SEARCH_H__ #include #include diff --git a/include/hash_code.h b/include/hash_code.h index 89f22b2b..7773a108 100644 --- a/include/hash_code.h +++ b/include/hash_code.h @@ -1,5 +1,5 @@ -#ifndef __HASH_CODE_H__ -#define __HASH_CODE_H__ +#ifndef HASH_CODE_H__ +#define HASH_CODE_H__ #include #include "hash_string.h" namespace alg { diff --git a/include/hash_multi.h b/include/hash_multi.h index 4639e229..73040cef 100644 --- a/include/hash_multi.h +++ b/include/hash_multi.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __HASH_MULTIPLICATION_H__ -#define __HASH_MULTIPLICATION_H__ +#ifndef HASH_MULTIPLICATION_H__ +#define HASH_MULTIPLICATION_H__ #include #include diff --git a/include/hash_string.h b/include/hash_string.h index 52d1b7cf..9a95d4fa 100644 --- a/include/hash_string.h +++ b/include/hash_string.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef __STRING_HASH_H__ -#define __STRING_HASH_H__ +#ifndef STRING_HASH_H__ +#define STRING_HASH_H__ #include diff --git a/include/hash_table.h b/include/hash_table.h index 1c5abd6e..9ed41eb3 100644 --- a/include/hash_table.h +++ b/include/hash_table.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __HASH_TABLE_H__ -#define __HASH_TABLE_H__ +#ifndef HASH_TABLE_H__ +#define HASH_TABLE_H__ #include #include diff --git a/include/heap.h b/include/heap.h index 351ba0db..dec4f9bc 100644 --- a/include/heap.h +++ b/include/heap.h @@ -28,8 +28,8 @@ * http://en.wikipedia.org/wiki/Binary_heap ******************************************************************************/ -#ifndef __HEAP_H__ -#define __HEAP_H__ +#ifndef HEAP_H__ +#define HEAP_H__ #include #include diff --git a/include/huffman.h b/include/huffman.h index b47a4d12..c95fc9b5 100644 --- a/include/huffman.h +++ b/include/huffman.h @@ -21,8 +21,8 @@ * ******************************************************************************/ -#ifndef __HUFFMAN_CODING_H__ -#define __HUFFMAN_CODING_H__ +#ifndef HUFFMAN_CODING_H__ +#define HUFFMAN_CODING_H__ #include #include diff --git a/include/imath.h b/include/imath.h index 6a23ab52..00e1e472 100644 --- a/include/imath.h +++ b/include/imath.h @@ -9,8 +9,8 @@ * ******************************************************************************/ -#ifndef __IMATH_H__ -#define __IMATH_H__ +#ifndef IMATH_H__ +#define IMATH_H__ #include #include diff --git a/include/insertion_sort.h b/include/insertion_sort.h index 42427e4b..8fcf6f42 100644 --- a/include/insertion_sort.h +++ b/include/insertion_sort.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef __INSERTION_SORT_H__ -#define __INSERTION_SORT_H__ +#ifndef INSERTION_SORT_H__ +#define INSERTION_SORT_H__ namespace alg { /** diff --git a/include/integer.h b/include/integer.h index f177d5ad..3c8e7d1b 100644 --- a/include/integer.h +++ b/include/integer.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef __INTEGER_H__ -#define __INTEGER_H__ +#ifndef INTEGER_H__ +#define INTEGER_H__ #include #include diff --git a/include/interval_tree.h b/include/interval_tree.h index c4edca19..5b6848e2 100644 --- a/include/interval_tree.h +++ b/include/interval_tree.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef __INTERVAL_TREE_H__ -#define __INTERVAL_TREE_H__ +#ifndef INTERVAL_TREE_H__ +#define INTERVAL_TREE_H__ #include #include diff --git a/include/k-means.h b/include/k-means.h index 953430de..966c085e 100644 --- a/include/k-means.h +++ b/include/k-means.h @@ -12,8 +12,8 @@ * https://github.com/wycg1984 ******************************************************************************/ -#ifndef __KMEANS_H__ -#define __KMEANS_H__ +#ifndef KMEANS_H__ +#define KMEANS_H__ #include #include #include diff --git a/include/kmp.h b/include/kmp.h index ada982a1..acb38297 100644 --- a/include/kmp.h +++ b/include/kmp.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __KMP_H__ -#define __KMP_H__ +#ifndef KMP_H__ +#define KMP_H__ #include namespace alg { diff --git a/include/kruskal_mst.h b/include/kruskal_mst.h index d6ed961e..b4f8078e 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 KRUSKAL_MST_H__ +#define KRUSKAL_MST_H__ #include #include diff --git a/include/lcs.h b/include/lcs.h index a3c3e9d9..93d6fa5f 100644 --- a/include/lcs.h +++ b/include/lcs.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __LCS_H__ -#define __LCS_H__ +#ifndef LCS_H__ +#define LCS_H__ #include "generic.h" #include "2darray.h" diff --git a/include/md5.h b/include/md5.h index 5ff52525..3d8c1410 100644 --- a/include/md5.h +++ b/include/md5.h @@ -23,8 +23,8 @@ */ -#ifndef __MD5_H__ -#define __MD5_H__ +#ifndef MD5_H__ +#define MD5_H__ #include /* Data structure for MD5 (Message Digest) computation */ diff --git a/include/merge_sort.h b/include/merge_sort.h index 5eab291d..519c19a2 100644 --- a/include/merge_sort.h +++ b/include/merge_sort.h @@ -32,8 +32,8 @@ * ******************************************************************************/ -#ifndef __MERGE_SORT_H__ -#define __MERGE_SORT_H__ +#ifndef MERGE_SORT_H__ +#define MERGE_SORT_H__ namespace alg { /** diff --git a/include/perfect_hash.h b/include/perfect_hash.h index 52dd9801..28b23191 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 PERFECT_HASH_H__ +#define PERFECT_HASH_H__ #include #include #include diff --git a/include/prim_mst.h b/include/prim_mst.h index 3949e895..97d8e0a7 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -22,8 +22,8 @@ * ******************************************************************************/ -#ifndef __PRIM_MST_H__ -#define __PRIM_MST_H__ +#ifndef PRIM_MST_H__ +#define PRIM_MST_H__ #include #include diff --git a/include/prime.h b/include/prime.h index 81f772e4..593fb81a 100644 --- a/include/prime.h +++ b/include/prime.h @@ -11,8 +11,8 @@ * http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test * ******************************************************************************/ -#ifndef __PRIME_H__ -#define __PRIME_H__ +#ifndef PRIME_H__ +#define PRIME_H__ #include #include diff --git a/include/priority_queue.h b/include/priority_queue.h index e81edf35..10214a83 100644 --- a/include/priority_queue.h +++ b/include/priority_queue.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __PRIORITY_QUEUE_H__ -#define __PRIORITY_QUEUE_H__ +#ifndef PRIORITY_QUEUE_H__ +#define PRIORITY_QUEUE_H__ #include #include diff --git a/include/queue.h b/include/queue.h index 1de7b292..7e322aec 100644 --- a/include/queue.h +++ b/include/queue.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef __QUEUE_H__ -#define __QUEUE_H__ +#ifndef QUEUE_H__ +#define QUEUE_H__ #include #include diff --git a/include/quick_sort.h b/include/quick_sort.h index b8962216..936d0860 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __QUICKSORT_H__ -#define __QUICKSORT_H__ +#ifndef QUICKSORT_H__ +#define QUICKSORT_H__ #include diff --git a/include/radix_sort.h b/include/radix_sort.h index 4272ce48..16298355 100644 --- a/include/radix_sort.h +++ b/include/radix_sort.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef __RADIX_SORT_H__ -#define __RADIX_SORT_H__ +#ifndef RADIX_SORT_H__ +#define RADIX_SORT_H__ #include #include diff --git a/include/random.h b/include/random.h index 456ab698..2ae56aa3 100644 --- a/include/random.h +++ b/include/random.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __RANDOM_H__ -#define __RANDOM_H__ +#ifndef RANDOM_H__ +#define RANDOM_H__ #include #include diff --git a/include/random_select.h b/include/random_select.h index 3577bdd9..500d0c9a 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -17,8 +17,8 @@ * ******************************************************************************/ -#ifndef __RANDOM_SELECT_H__ -#define __RANDOM_SELECT_H__ +#ifndef RANDOM_SELECT_H__ +#define RANDOM_SELECT_H__ #include diff --git a/include/rbtree.h b/include/rbtree.h index c9b8a318..bace1061 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -15,8 +15,8 @@ * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ -#ifndef __RBTREE_H__ -#define __RBTREE_H__ +#ifndef RBTREE_H__ +#define RBTREE_H__ #include #include #include diff --git a/include/rbtree_defs.h b/include/rbtree_defs.h index ab5ef4ea..00395bb4 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -15,8 +15,8 @@ * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ -#ifndef __RBTREE_DEFS_H__ -#define __RBTREE_DEFS_H__ +#ifndef RBTREE_DEFS_H__ +#define RBTREE_DEFS_H__ #include #include diff --git a/include/relabel_to_front.h b/include/relabel_to_front.h index c8a4d950..8e1ecf37 100644 --- a/include/relabel_to_front.h +++ b/include/relabel_to_front.h @@ -9,8 +9,8 @@ * * */ -#ifndef __RELABEL_TO_FRONT_H__ -#define __RELABEL_TO_FRONT_H__ +#ifndef RELABEL_TO_FRONT_H__ +#define RELABEL_TO_FRONT_H__ #include #include diff --git a/include/scc.h b/include/scc.h index 1d641a1b..5e4b9f44 100644 --- a/include/scc.h +++ b/include/scc.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Strongly_connected_component ******************************************************************************/ -#ifndef __SCC_H__ -#define __SCC_H__ +#ifndef SCC_H__ +#define SCC_H__ #include #include #include diff --git a/include/selection_sort.h b/include/selection_sort.h index a956ad9a..b08f9d96 100644 --- a/include/selection_sort.h +++ b/include/selection_sort.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Selection_sort ******************************************************************************/ -#ifndef __SELECTION_SORT_H__ -#define __SELECTION_SORT_H__ +#ifndef SELECTION_SORT_H__ +#define SELECTION_SORT_H__ #include #include @@ -49,4 +49,4 @@ namespace alg { } } -#endif //__SELECTION_SORT_H__ +#endif //SELECTION_SORT_H__ diff --git a/include/sha1.h b/include/sha1.h index 3079e20c..d68c0a4a 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 SHA1_H__ +#define SHA1_H__ #include diff --git a/include/shell_sort.h b/include/shell_sort.h index 22b04de9..c6a8c717 100644 --- a/include/shell_sort.h +++ b/include/shell_sort.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef __SHELL_SORT_H__ -#define __SHELL_SORT_H__ +#ifndef SHELL_SORT_H__ +#define SHELL_SORT_H__ namespace alg { /** diff --git a/include/shuffle.h b/include/shuffle.h index fe8b97ab..16f5deab 100644 --- a/include/shuffle.h +++ b/include/shuffle.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __SHUFFLE_H__ -#define __SHUFFLE_H__ +#ifndef SHUFFLE_H__ +#define SHUFFLE_H__ #include #include diff --git a/include/simhash.h b/include/simhash.h index f68e9e58..d98b87c0 100644 --- a/include/simhash.h +++ b/include/simhash.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef __SIMHASH_H__ -#define __SIMHASH_H__ +#ifndef SIMHASH_H__ +#define SIMHASH_H__ #include #include diff --git a/include/skiplist.h b/include/skiplist.h index f45d4f33..e34d8f04 100644 --- a/include/skiplist.h +++ b/include/skiplist.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __SKIP_LIST_H__ -#define __SKIP_LIST_H__ +#ifndef SKIP_LIST_H__ +#define SKIP_LIST_H__ #include #include #include diff --git a/include/sol.h b/include/sol.h index 070ee4c5..a2e148b5 100644 --- a/include/sol.h +++ b/include/sol.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef __SOL_H__ -#define __SOL_H__ +#ifndef SOL_H__ +#define SOL_H__ #include "double_linked_list.h" namespace alg { diff --git a/include/stack.h b/include/stack.h index acc75414..8b664f5e 100644 --- a/include/stack.h +++ b/include/stack.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __STACK_H__ -#define __STACK_H__ +#ifndef STACK_H__ +#define STACK_H__ #include #include diff --git a/include/suffix_array.h b/include/suffix_array.h index c078bd0a..a47fe2fc 100644 --- a/include/suffix_array.h +++ b/include/suffix_array.h @@ -20,8 +20,8 @@ * AUTHOR: nowerzt@gmail.com ******************************************************************************/ -#ifndef __SUFFIX_ARRAY_H__ -#define __SUFFIX_ARRAY_H__ +#ifndef SUFFIX_ARRAY_H__ +#define SUFFIX_ARRAY_H__ #include #include @@ -100,4 +100,4 @@ namespace alg { } } -#endif // __SUFFIX_ARRAY_H__ +#endif // SUFFIX_ARRAY_H__ diff --git a/include/trie.h b/include/trie.h index c9990f28..ac253704 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 TRIE_H__ +#define TRIE_H__ #include #include #include diff --git a/include/undirected_graph.h b/include/undirected_graph.h index 5570267c..c1e4cd08 100644 --- a/include/undirected_graph.h +++ b/include/undirected_graph.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef __UNDIRECTED_GRAPH_H__ -#define __UNDIRECTED_GRAPH_H__ +#ifndef UNDIRECTED_GRAPH_H__ +#define UNDIRECTED_GRAPH_H__ #include #include diff --git a/include/universal_hash.h b/include/universal_hash.h index 1b162857..1a8abe20 100644 --- a/include/universal_hash.h +++ b/include/universal_hash.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef __UNIVERSAL_HASH_H__ -#define __UNIVERSAL_HASH_H__ +#ifndef UNIVERSAL_HASH_H__ +#define UNIVERSAL_HASH_H__ #include #include diff --git a/include/word_seg.h b/include/word_seg.h index eb0f65c7..00528827 100644 --- a/include/word_seg.h +++ b/include/word_seg.h @@ -17,8 +17,8 @@ * ******************************************************************************/ -#ifndef __WORD_SEG_H__ -#define __WORD_SEG_H__ +#ifndef WORD_SEG_H__ +#define WORD_SEG_H__ #include #include diff --git a/msvc/alg_vs.h b/msvc/alg_vs.h index 13b5aa67..78e56b88 100644 --- a/msvc/alg_vs.h +++ b/msvc/alg_vs.h @@ -1,5 +1,5 @@ -#ifndef __ALGVS_H__ -#define __ALGVS_H__ +#ifndef ALGVS_H__ +#define ALGVS_H__ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS @@ -15,4 +15,4 @@ #define typeof decltype #endif//_MSC_VER -#endif//__ALGVS_H__ \ No newline at end of file +#endif//ALGVS_H__ \ No newline at end of file diff --git a/utils/byteorder.h b/utils/byteorder.h index ca2fada9..1cfcaca9 100644 --- a/utils/byteorder.h +++ b/utils/byteorder.h @@ -1,5 +1,5 @@ -#ifndef __BYTEORDER_H__ -#define __BYTEORDER_H__ +#ifndef BYTEORDER_H__ +#define BYTEORDER_H__ #include #include diff --git a/utils/gb18030.h b/utils/gb18030.h index 88d28e85..fdc2803d 100644 --- a/utils/gb18030.h +++ b/utils/gb18030.h @@ -1,5 +1,5 @@ -#ifndef __GB18030_H__ -#define __GB18030_H__ +#ifndef GB18030_H__ +#define GB18030_H__ /** * Read from the string encoded in GB18030 into WORD From b8b2ed5b72c9e8ab81d99c0e57999d7900f2a92e Mon Sep 17 00:00:00 2001 From: Vic Luo Date: Thu, 1 Sep 2016 14:14:36 +0800 Subject: [PATCH 204/217] Rename all identifiers with 2 underscores at the beginning --- include/2darray.h | 4 ++-- include/8queen.h | 6 +++--- include/astar.h | 4 ++-- include/avl.h | 4 ++-- include/bellman_ford.h | 4 ++-- include/binary_search_tree.h | 12 ++++++------ include/bitset.h | 4 ++-- include/bloom_filter.h | 4 ++-- include/btree.h | 4 ++-- include/dijkstra.h | 4 ++-- include/directed_graph.h | 4 ++-- include/disjoint-set.h | 4 ++-- include/dos_tree.h | 4 ++-- include/double_linked_list.h | 26 +++++++++++++------------- include/edmonds_karp.h | 4 ++-- include/fenwick_tree.h | 4 ++-- include/fib-heap.h | 4 ++-- include/generic.h | 4 ++-- include/graph_defs.h | 4 ++-- include/graph_search.h | 4 ++-- include/hash_code.h | 4 ++-- include/hash_multi.h | 4 ++-- include/hash_string.h | 4 ++-- include/hash_table.h | 4 ++-- include/heap.h | 4 ++-- include/huffman.h | 4 ++-- include/imath.h | 4 ++-- include/insertion_sort.h | 4 ++-- include/integer.h | 4 ++-- include/interval_tree.h | 4 ++-- include/k-means.h | 4 ++-- include/kmp.h | 4 ++-- include/kruskal_mst.h | 4 ++-- include/lcs.h | 4 ++-- include/max_subarray.h | 4 ++-- include/md5.h | 4 ++-- include/merge_sort.h | 8 ++++---- include/perfect_hash.h | 4 ++-- include/prim_mst.h | 4 ++-- include/prime.h | 4 ++-- include/priority_queue.h | 6 +++--- include/queue.h | 4 ++-- include/quick_sort.h | 8 ++++---- include/radix_sort.h | 14 +++++++------- include/random.h | 4 ++-- include/random_select.h | 8 ++++---- include/rbtree.h | 4 ++-- include/rbtree_defs.h | 4 ++-- include/relabel_to_front.h | 4 ++-- include/scc.h | 4 ++-- include/selection_sort.h | 6 +++--- include/sha1.h | 4 ++-- include/shell_sort.h | 4 ++-- include/shuffle.h | 4 ++-- include/simhash.h | 4 ++-- include/skiplist.h | 4 ++-- include/sol.h | 12 ++++++------ include/stack.h | 4 ++-- include/suffix_array.h | 6 +++--- include/trie.h | 4 ++-- include/undirected_graph.h | 4 ++-- include/universal_hash.h | 4 ++-- include/word_seg.h | 4 ++-- msvc/alg_vs.h | 6 +++--- src/lcs_demo.cpp | 6 +++--- utils/byteorder.h | 4 ++-- utils/gb18030.h | 4 ++-- 67 files changed, 170 insertions(+), 170 deletions(-) diff --git a/include/2darray.h b/include/2darray.h index 929a286a..2a565810 100644 --- a/include/2darray.h +++ b/include/2darray.h @@ -10,8 +10,8 @@ * Simulated by 1-dimension array. ******************************************************************************/ -#ifndef 2D_ARRAY_H__ -#define 2D_ARRAY_H__ +#ifndef ALGO_2D_ARRAY_H__ +#define ALGO_2D_ARRAY_H__ #include #include diff --git a/include/8queen.h b/include/8queen.h index 17eaefef..511ebe21 100644 --- a/include/8queen.h +++ b/include/8queen.h @@ -9,8 +9,8 @@ * http://en.wikipedia.org/wiki/Eight_queens_puzzle ******************************************************************************/ -#ifndef 8QUEEN_H__ -#define 8QUEEN_H__ +#ifndef ALGO_8QUEEN_H__ +#define ALGO_8QUEEN_H__ #include #include @@ -84,4 +84,4 @@ namespace alg { }; } -#endif //8QUEEN_H__ +#endif //ALGO_8QUEEN_H__ diff --git a/include/astar.h b/include/astar.h index 6dc68f02..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 diff --git a/include/avl.h b/include/avl.h index aa1ef6ca..697317ab 100644 --- a/include/avl.h +++ b/include/avl.h @@ -19,8 +19,8 @@ * ******************************************************************************/ -#ifndef AVL_H__ -#define AVL_H__ +#ifndef ALGO_AVL_H__ +#define ALGO_AVL_H__ #include #include diff --git a/include/bellman_ford.h b/include/bellman_ford.h index d859d72a..40771ae4 100644 --- a/include/bellman_ford.h +++ b/include/bellman_ford.h @@ -44,8 +44,8 @@ * ******************************************************************************/ -#ifndef BELLMAN_FORD_H__ -#define BELLMAN_FORD_H__ +#ifndef ALGO_BELLMAN_FORD_H__ +#define ALGO_BELLMAN_FORD_H__ #include #include diff --git a/include/binary_search_tree.h b/include/binary_search_tree.h index 254cb0f2..574914af 100644 --- a/include/binary_search_tree.h +++ b/include/binary_search_tree.h @@ -18,8 +18,8 @@ * ******************************************************************************/ -#ifndef BINARY_SEARCH_TREE_H__ -#define BINARY_SEARCH_TREE_H__ +#ifndef ALGO_BINARY_SEARCH_TREE_H__ +#define ALGO_BINARY_SEARCH_TREE_H__ #include #include @@ -57,7 +57,7 @@ namespace alg { BST():m_root(NULL){}; ~BST() { - __destruct(m_root); + destruct_(m_root); } /** @@ -159,10 +159,10 @@ namespace alg { } private: - void __destruct(treeNode *n) { + void destruct_(treeNode *n) { if (n==NULL) return; - __destruct(n->left); - __destruct(n->right); + destruct_(n->left); + destruct_(n->right); delete n; } diff --git a/include/bitset.h b/include/bitset.h index fd6ae57b..9e7b9bbc 100644 --- a/include/bitset.h +++ b/include/bitset.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef BIT_SET_H__ -#define BIT_SET_H__ +#ifndef ALGO_BIT_SET_H__ +#define ALGO_BIT_SET_H__ #include #include diff --git a/include/bloom_filter.h b/include/bloom_filter.h index 952d44ab..08253593 100644 --- a/include/bloom_filter.h +++ b/include/bloom_filter.h @@ -18,8 +18,8 @@ * ******************************************************************************/ -#ifndef BLOOM_FILTER_H__ -#define BLOOM_FILTER_H__ +#ifndef ALGO_BLOOM_FILTER_H__ +#define ALGO_BLOOM_FILTER_H__ #include #include diff --git a/include/btree.h b/include/btree.h index 5f50b6e2..6e17050f 100644 --- a/include/btree.h +++ b/include/btree.h @@ -24,8 +24,8 @@ * http://en.wikipedia.org/wiki/B-tree ******************************************************************************/ -#ifndef BTREE_H__ -#define BTREE_H__ +#ifndef ALGO_BTREE_H__ +#define ALGO_BTREE_H__ #include #include diff --git a/include/dijkstra.h b/include/dijkstra.h index 73b6c2ee..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 diff --git a/include/directed_graph.h b/include/directed_graph.h index 7694e5a3..9e46cfe0 100644 --- a/include/directed_graph.h +++ b/include/directed_graph.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef DIRECTED_GRAPH_H__ -#define DIRECTED_GRAPH_H__ +#ifndef ALGO_DIRECTED_GRAPH_H__ +#define ALGO_DIRECTED_GRAPH_H__ #include #include diff --git a/include/disjoint-set.h b/include/disjoint-set.h index 1d1568c4..be6bff7d 100644 --- a/include/disjoint-set.h +++ b/include/disjoint-set.h @@ -18,8 +18,8 @@ * http://en.wikipedia.org/wiki/Disjoint-set_data_structure ******************************************************************************/ -#ifndef DISJOINTSET_H__ -#define DISJOINTSET_H__ +#ifndef ALGO_DISJOINTSET_H__ +#define ALGO_DISJOINTSET_H__ namespace alg { template diff --git a/include/dos_tree.h b/include/dos_tree.h index f754f180..42689457 100644 --- a/include/dos_tree.h +++ b/include/dos_tree.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef DOS_TREE_H__ -#define DOS_TREE_H__ +#ifndef ALGO_DOS_TREE_H__ +#define ALGO_DOS_TREE_H__ #include #include diff --git a/include/double_linked_list.h b/include/double_linked_list.h index be595e7e..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 f9ca4b56..295de725 100644 --- a/include/edmonds_karp.h +++ b/include/edmonds_karp.h @@ -21,8 +21,8 @@ * ******************************************************************************/ -#ifndef EDMONDS_KARP_H__ -#define EDMONDS_KARP_H__ +#ifndef ALGO_EDMONDS_KARP_H__ +#define ALGO_EDMONDS_KARP_H__ #include #include diff --git a/include/fenwick_tree.h b/include/fenwick_tree.h index cc12d602..4806536e 100644 --- a/include/fenwick_tree.h +++ b/include/fenwick_tree.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef FENWICK_H__ -#define FENWICK_H__ +#ifndef ALGO_FENWICK_H__ +#define ALGO_FENWICK_H__ #include diff --git a/include/fib-heap.h b/include/fib-heap.h index b5303bf6..44af130a 100644 --- a/include/fib-heap.h +++ b/include/fib-heap.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Fibonacci_heap ******************************************************************************/ -#ifndef FIB_HEAP_H__ -#define FIB_HEAP_H__ +#ifndef ALGO_FIB_HEAP_H__ +#define ALGO_FIB_HEAP_H__ #include #include #include diff --git a/include/generic.h b/include/generic.h index 16d50e84..785e5078 100644 --- a/include/generic.h +++ b/include/generic.h @@ -9,8 +9,8 @@ * ******************************************************************************/ -#ifndef ALG_INC_H__ -#define ALG_INC_H__ +#ifndef ALGO_ALG_INC_H__ +#define ALGO_ALG_INC_H__ #include #include #include diff --git a/include/graph_defs.h b/include/graph_defs.h index f2b61ada..06e77be2 100644 --- a/include/graph_defs.h +++ b/include/graph_defs.h @@ -1,5 +1,5 @@ -#ifndef GRAPH_DEFS_H__ -#define GRAPH_DEFS_H__ +#ifndef ALGO_GRAPH_DEFS_H__ +#define ALGO_GRAPH_DEFS_H__ #include "double_linked_list.h" diff --git a/include/graph_search.h b/include/graph_search.h index 7605aed6..e0d18f4d 100644 --- a/include/graph_search.h +++ b/include/graph_search.h @@ -20,8 +20,8 @@ * ******************************************************************************/ -#ifndef BREADTH_FIRST_SEARCH_H__ -#define BREADTH_FIRST_SEARCH_H__ +#ifndef ALGO_BREADTH_FIRST_SEARCH_H__ +#define ALGO_BREADTH_FIRST_SEARCH_H__ #include #include diff --git a/include/hash_code.h b/include/hash_code.h index 7773a108..a310580c 100644 --- a/include/hash_code.h +++ b/include/hash_code.h @@ -1,5 +1,5 @@ -#ifndef HASH_CODE_H__ -#define HASH_CODE_H__ +#ifndef ALGO_HASH_CODE_H__ +#define ALGO_HASH_CODE_H__ #include #include "hash_string.h" namespace alg { diff --git a/include/hash_multi.h b/include/hash_multi.h index 73040cef..ec22f65f 100644 --- a/include/hash_multi.h +++ b/include/hash_multi.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef HASH_MULTIPLICATION_H__ -#define HASH_MULTIPLICATION_H__ +#ifndef ALGO_HASH_MULTIPLICATION_H__ +#define ALGO_HASH_MULTIPLICATION_H__ #include #include diff --git a/include/hash_string.h b/include/hash_string.h index 9a95d4fa..6eee926c 100644 --- a/include/hash_string.h +++ b/include/hash_string.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef STRING_HASH_H__ -#define STRING_HASH_H__ +#ifndef ALGO_STRING_HASH_H__ +#define ALGO_STRING_HASH_H__ #include diff --git a/include/hash_table.h b/include/hash_table.h index 9ed41eb3..72018610 100644 --- a/include/hash_table.h +++ b/include/hash_table.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef HASH_TABLE_H__ -#define HASH_TABLE_H__ +#ifndef ALGO_HASH_TABLE_H__ +#define ALGO_HASH_TABLE_H__ #include #include diff --git a/include/heap.h b/include/heap.h index dec4f9bc..d793cdab 100644 --- a/include/heap.h +++ b/include/heap.h @@ -28,8 +28,8 @@ * http://en.wikipedia.org/wiki/Binary_heap ******************************************************************************/ -#ifndef HEAP_H__ -#define HEAP_H__ +#ifndef ALGO_HEAP_H__ +#define ALGO_HEAP_H__ #include #include diff --git a/include/huffman.h b/include/huffman.h index c95fc9b5..50088b53 100644 --- a/include/huffman.h +++ b/include/huffman.h @@ -21,8 +21,8 @@ * ******************************************************************************/ -#ifndef HUFFMAN_CODING_H__ -#define HUFFMAN_CODING_H__ +#ifndef ALGO_HUFFMAN_CODING_H__ +#define ALGO_HUFFMAN_CODING_H__ #include #include diff --git a/include/imath.h b/include/imath.h index 00e1e472..b3fa2430 100644 --- a/include/imath.h +++ b/include/imath.h @@ -9,8 +9,8 @@ * ******************************************************************************/ -#ifndef IMATH_H__ -#define IMATH_H__ +#ifndef ALGO_IMATH_H__ +#define ALGO_IMATH_H__ #include #include diff --git a/include/insertion_sort.h b/include/insertion_sort.h index 8fcf6f42..eb9f58ef 100644 --- a/include/insertion_sort.h +++ b/include/insertion_sort.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef INSERTION_SORT_H__ -#define INSERTION_SORT_H__ +#ifndef ALGO_INSERTION_SORT_H__ +#define ALGO_INSERTION_SORT_H__ namespace alg { /** diff --git a/include/integer.h b/include/integer.h index 3c8e7d1b..1d5ff609 100644 --- a/include/integer.h +++ b/include/integer.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef INTEGER_H__ -#define INTEGER_H__ +#ifndef ALGO_INTEGER_H__ +#define ALGO_INTEGER_H__ #include #include diff --git a/include/interval_tree.h b/include/interval_tree.h index 5b6848e2..ec107364 100644 --- a/include/interval_tree.h +++ b/include/interval_tree.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef INTERVAL_TREE_H__ -#define INTERVAL_TREE_H__ +#ifndef ALGO_INTERVAL_TREE_H__ +#define ALGO_INTERVAL_TREE_H__ #include #include diff --git a/include/k-means.h b/include/k-means.h index 966c085e..86fdef3c 100644 --- a/include/k-means.h +++ b/include/k-means.h @@ -12,8 +12,8 @@ * https://github.com/wycg1984 ******************************************************************************/ -#ifndef KMEANS_H__ -#define KMEANS_H__ +#ifndef ALGO_KMEANS_H__ +#define ALGO_KMEANS_H__ #include #include #include diff --git a/include/kmp.h b/include/kmp.h index acb38297..d75d207b 100644 --- a/include/kmp.h +++ b/include/kmp.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef KMP_H__ -#define KMP_H__ +#ifndef ALGO_KMP_H__ +#define ALGO_KMP_H__ #include namespace alg { diff --git a/include/kruskal_mst.h b/include/kruskal_mst.h index b4f8078e..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 diff --git a/include/lcs.h b/include/lcs.h index 93d6fa5f..ce218022 100644 --- a/include/lcs.h +++ b/include/lcs.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef LCS_H__ -#define LCS_H__ +#ifndef ALGO_LCS_H__ +#define ALGO_LCS_H__ #include "generic.h" #include "2darray.h" diff --git a/include/max_subarray.h b/include/max_subarray.h index c791df3b..96b0d943 100644 --- a/include/max_subarray.h +++ b/include/max_subarray.h @@ -21,8 +21,8 @@ * http://en.wikipedia.org/wiki/Maximum_subarray_problem ******************************************************************************/ -#ifndef __MAX_SUBARRAY__ -#define __MAX_SUBARRAY__ +#ifndef MAX_SUBARRAY__ +#define MAX_SUBARRAY__ namespace alg { /** diff --git a/include/md5.h b/include/md5.h index 3d8c1410..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 519c19a2..b50d1976 100644 --- a/include/merge_sort.h +++ b/include/merge_sort.h @@ -32,15 +32,15 @@ * ******************************************************************************/ -#ifndef MERGE_SORT_H__ -#define MERGE_SORT_H__ +#ifndef ALGO_MERGE_SORT_H__ +#define ALGO_MERGE_SORT_H__ namespace alg { /** * Merge functions merges the two sorted parts. Sorted parts will be from [left, mid] and [mid+1, right]. */ template - static void __merge(T *array, int left, int mid, int right) { + static void merge_(T *array, int left, int mid, int right) { /*We need a Temporary array to store the new sorted part*/ T tempArray[right-left+1]; int pos=0,lpos = left,rpos = mid + 1; @@ -75,7 +75,7 @@ namespace alg { /* Sort the right part */ merge_sort(array,mid+1,right); /* Merge the two sorted parts */ - __merge(array,left,mid,right); + merge_(array,left,mid,right); } } diff --git a/include/perfect_hash.h b/include/perfect_hash.h index 28b23191..55af66c1 100644 --- a/include/perfect_hash.h +++ b/include/perfect_hash.h @@ -10,8 +10,8 @@ * http://en.wikipedia.org/wiki/Perfect_hash * ******************************************************************************/ -#ifndef PERFECT_HASH_H__ -#define PERFECT_HASH_H__ +#ifndef ALGO_PERFECT_HASH_H__ +#define ALGO_PERFECT_HASH_H__ #include #include #include diff --git a/include/prim_mst.h b/include/prim_mst.h index 97d8e0a7..be48ab58 100644 --- a/include/prim_mst.h +++ b/include/prim_mst.h @@ -22,8 +22,8 @@ * ******************************************************************************/ -#ifndef PRIM_MST_H__ -#define PRIM_MST_H__ +#ifndef ALGO_PRIM_MST_H__ +#define ALGO_PRIM_MST_H__ #include #include diff --git a/include/prime.h b/include/prime.h index 593fb81a..357f8b96 100644 --- a/include/prime.h +++ b/include/prime.h @@ -11,8 +11,8 @@ * http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test * ******************************************************************************/ -#ifndef PRIME_H__ -#define PRIME_H__ +#ifndef ALGO_PRIME_H__ +#define ALGO_PRIME_H__ #include #include diff --git a/include/priority_queue.h b/include/priority_queue.h index 10214a83..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 @@ -80,7 +80,7 @@ namespace alg { bool found = false; list_for_each_entry(pos, &m_head, node) { if (n->priority <= pos->priority) { - __list_add(&n->node, pos->node.prev, &pos->node); + list_add_(&n->node, pos->node.prev, &pos->node); m_count++; found = true; break; diff --git a/include/queue.h b/include/queue.h index 7e322aec..55051228 100644 --- a/include/queue.h +++ b/include/queue.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef QUEUE_H__ -#define QUEUE_H__ +#ifndef ALGO_QUEUE_H__ +#define ALGO_QUEUE_H__ #include #include diff --git a/include/quick_sort.h b/include/quick_sort.h index 936d0860..b3a74489 100644 --- a/include/quick_sort.h +++ b/include/quick_sort.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef QUICKSORT_H__ -#define QUICKSORT_H__ +#ifndef ALGO_QUICKSORT_H__ +#define ALGO_QUICKSORT_H__ #include @@ -25,7 +25,7 @@ namespace alg { * the quick-sort partition routine */ template - static int __partition(T list[],int begin, int end) { + static int partition_(T list[],int begin, int end) { int pivot_idx = RANDOM(begin,end); T pivot = list[pivot_idx]; swap(list[begin], list[pivot_idx]); @@ -52,7 +52,7 @@ namespace alg { template static void quicksort(T list[],int begin,int end) { if( begin < end) { - int pivot_idx = __partition(list, begin, end); + int pivot_idx = partition_(list, begin, end); quicksort(list, begin, pivot_idx-1); quicksort(list, pivot_idx+1, end); } diff --git a/include/radix_sort.h b/include/radix_sort.h index 16298355..ec5e0733 100644 --- a/include/radix_sort.h +++ b/include/radix_sort.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef RADIX_SORT_H__ -#define RADIX_SORT_H__ +#ifndef ALGO_RADIX_SORT_H__ +#define ALGO_RADIX_SORT_H__ #include #include @@ -29,7 +29,7 @@ namespace alg { /** * couting sort */ - static void __radix(int byte, const unsigned N, const uint32_t *source, uint32_t *dest) { + static void radix_(int byte, const unsigned N, const uint32_t *source, uint32_t *dest) { unsigned count[256]; unsigned index[256]; memset(count, 0, sizeof (count)); @@ -51,10 +51,10 @@ namespace alg { */ static void radix_sort(uint32_t *source, const unsigned N) { uint32_t * temp = new uint32_t[N]; - __radix(0, N, source, temp); - __radix(1, N, temp, source); - __radix(2, N, source, temp); - __radix(3, N, temp, source); + radix_(0, N, source, temp); + radix_(1, N, temp, source); + radix_(2, N, source, temp); + radix_(3, N, temp, source); delete [] temp; } diff --git a/include/random.h b/include/random.h index 2ae56aa3..1b2fd82e 100644 --- a/include/random.h +++ b/include/random.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef RANDOM_H__ -#define RANDOM_H__ +#ifndef ALGO_RANDOM_H__ +#define ALGO_RANDOM_H__ #include #include diff --git a/include/random_select.h b/include/random_select.h index 500d0c9a..8893008d 100644 --- a/include/random_select.h +++ b/include/random_select.h @@ -17,8 +17,8 @@ * ******************************************************************************/ -#ifndef RANDOM_SELECT_H__ -#define RANDOM_SELECT_H__ +#ifndef ALGO_RANDOM_SELECT_H__ +#define ALGO_RANDOM_SELECT_H__ #include @@ -27,7 +27,7 @@ namespace alg { * the random_select partition routine */ template - static int __partition(T list[],int begin, int end) { + static int partition_(T list[],int begin, int end) { int pivot_idx = RANDOM(begin,end); T pivot = list[pivot_idx]; swap(list[begin],list[pivot_idx]); @@ -56,7 +56,7 @@ namespace alg { if(begin == end) return begin; - int pivot_idx = __partition(list, begin, end); + int pivot_idx = partition_(list, begin, end); int human_idx = pivot_idx - begin + 1; if(k < human_idx) diff --git a/include/rbtree.h b/include/rbtree.h index bace1061..61c129bd 100644 --- a/include/rbtree.h +++ b/include/rbtree.h @@ -15,8 +15,8 @@ * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ -#ifndef RBTREE_H__ -#define RBTREE_H__ +#ifndef ALGO_RBTREE_H__ +#define ALGO_RBTREE_H__ #include #include #include diff --git a/include/rbtree_defs.h b/include/rbtree_defs.h index 00395bb4..a99a26b0 100644 --- a/include/rbtree_defs.h +++ b/include/rbtree_defs.h @@ -15,8 +15,8 @@ * http://en.literateprograms.org/Red-black_tree_(C) ******************************************************************************/ -#ifndef RBTREE_DEFS_H__ -#define RBTREE_DEFS_H__ +#ifndef ALGO_RBTREE_DEFS_H__ +#define ALGO_RBTREE_DEFS_H__ #include #include diff --git a/include/relabel_to_front.h b/include/relabel_to_front.h index 8e1ecf37..ef933e02 100644 --- a/include/relabel_to_front.h +++ b/include/relabel_to_front.h @@ -9,8 +9,8 @@ * * */ -#ifndef RELABEL_TO_FRONT_H__ -#define RELABEL_TO_FRONT_H__ +#ifndef ALGO_RELABEL_TO_FRONT_H__ +#define ALGO_RELABEL_TO_FRONT_H__ #include #include diff --git a/include/scc.h b/include/scc.h index 5e4b9f44..ef41af12 100644 --- a/include/scc.h +++ b/include/scc.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Strongly_connected_component ******************************************************************************/ -#ifndef SCC_H__ -#define SCC_H__ +#ifndef ALGO_SCC_H__ +#define ALGO_SCC_H__ #include #include #include diff --git a/include/selection_sort.h b/include/selection_sort.h index b08f9d96..7b0f53e3 100644 --- a/include/selection_sort.h +++ b/include/selection_sort.h @@ -17,8 +17,8 @@ * http://en.wikipedia.org/wiki/Selection_sort ******************************************************************************/ -#ifndef SELECTION_SORT_H__ -#define SELECTION_SORT_H__ +#ifndef ALGO_SELECTION_SORT_H__ +#define ALGO_SELECTION_SORT_H__ #include #include @@ -49,4 +49,4 @@ namespace alg { } } -#endif //SELECTION_SORT_H__ +#endif //ALGO_SELECTION_SORT_H__ diff --git a/include/sha1.h b/include/sha1.h index d68c0a4a..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 index c6a8c717..7d9285c2 100644 --- a/include/shell_sort.h +++ b/include/shell_sort.h @@ -13,8 +13,8 @@ * ******************************************************************************/ -#ifndef SHELL_SORT_H__ -#define SHELL_SORT_H__ +#ifndef ALGO_SHELL_SORT_H__ +#define ALGO_SHELL_SORT_H__ namespace alg { /** diff --git a/include/shuffle.h b/include/shuffle.h index 16f5deab..0bdd69cd 100644 --- a/include/shuffle.h +++ b/include/shuffle.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef SHUFFLE_H__ -#define SHUFFLE_H__ +#ifndef ALGO_SHUFFLE_H__ +#define ALGO_SHUFFLE_H__ #include #include diff --git a/include/simhash.h b/include/simhash.h index d98b87c0..650af6c2 100644 --- a/include/simhash.h +++ b/include/simhash.h @@ -12,8 +12,8 @@ * ******************************************************************************/ -#ifndef SIMHASH_H__ -#define SIMHASH_H__ +#ifndef ALGO_SIMHASH_H__ +#define ALGO_SIMHASH_H__ #include #include diff --git a/include/skiplist.h b/include/skiplist.h index e34d8f04..7469511d 100644 --- a/include/skiplist.h +++ b/include/skiplist.h @@ -11,8 +11,8 @@ * ******************************************************************************/ -#ifndef SKIP_LIST_H__ -#define SKIP_LIST_H__ +#ifndef ALGO_SKIP_LIST_H__ +#define ALGO_SKIP_LIST_H__ #include #include #include diff --git a/include/sol.h b/include/sol.h index a2e148b5..c8064fc8 100644 --- a/include/sol.h +++ b/include/sol.h @@ -16,8 +16,8 @@ * ******************************************************************************/ -#ifndef SOL_H__ -#define SOL_H__ +#ifndef ALGO_SOL_H__ +#define ALGO_SOL_H__ #include "double_linked_list.h" namespace alg { @@ -26,8 +26,8 @@ namespace alg { */ static inline void list_mtf(struct list_head *entry, struct list_head *head) { if (entry->prev == head) return; - __list_del(entry->prev, entry->next); - __list_add(entry, head, head->next); + list_del_(entry->prev, entry->next); + list_add_(entry, head, head->next); } @@ -38,8 +38,8 @@ namespace alg { // if the entry in the 1st position if (entry->prev == head) return; struct list_head * prev = entry->prev; - __list_del(entry->prev, entry->next); - __list_add(entry, prev->prev, prev); + list_del_(entry->prev, entry->next); + list_add_(entry, prev->prev, prev); } } #endif // diff --git a/include/stack.h b/include/stack.h index 8b664f5e..21ab1159 100644 --- a/include/stack.h +++ b/include/stack.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef STACK_H__ -#define STACK_H__ +#ifndef ALGO_STACK_H__ +#define ALGO_STACK_H__ #include #include diff --git a/include/suffix_array.h b/include/suffix_array.h index a47fe2fc..8c7e11fb 100644 --- a/include/suffix_array.h +++ b/include/suffix_array.h @@ -20,8 +20,8 @@ * AUTHOR: nowerzt@gmail.com ******************************************************************************/ -#ifndef SUFFIX_ARRAY_H__ -#define SUFFIX_ARRAY_H__ +#ifndef ALGO_SUFFIX_ARRAY_H__ +#define ALGO_SUFFIX_ARRAY_H__ #include #include @@ -100,4 +100,4 @@ namespace alg { } } -#endif // SUFFIX_ARRAY_H__ +#endif // ALGO_SUFFIX_ARRAY_H__ diff --git a/include/trie.h b/include/trie.h index ac253704..0cdba5ef 100644 --- a/include/trie.h +++ b/include/trie.h @@ -10,8 +10,8 @@ * http://en.wikipedia.org/wiki/Trie ******************************************************************************/ -#ifndef TRIE_H__ -#define TRIE_H__ +#ifndef ALGO_TRIE_H__ +#define ALGO_TRIE_H__ #include #include #include diff --git a/include/undirected_graph.h b/include/undirected_graph.h index c1e4cd08..51804de4 100644 --- a/include/undirected_graph.h +++ b/include/undirected_graph.h @@ -14,8 +14,8 @@ * ******************************************************************************/ -#ifndef UNDIRECTED_GRAPH_H__ -#define UNDIRECTED_GRAPH_H__ +#ifndef ALGO_UNDIRECTED_GRAPH_H__ +#define ALGO_UNDIRECTED_GRAPH_H__ #include #include diff --git a/include/universal_hash.h b/include/universal_hash.h index 1a8abe20..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 diff --git a/include/word_seg.h b/include/word_seg.h index 00528827..ed99b763 100644 --- a/include/word_seg.h +++ b/include/word_seg.h @@ -17,8 +17,8 @@ * ******************************************************************************/ -#ifndef WORD_SEG_H__ -#define WORD_SEG_H__ +#ifndef ALGO_WORD_SEG_H__ +#define ALGO_WORD_SEG_H__ #include #include diff --git a/msvc/alg_vs.h b/msvc/alg_vs.h index 78e56b88..ca1d0163 100644 --- a/msvc/alg_vs.h +++ b/msvc/alg_vs.h @@ -1,5 +1,5 @@ -#ifndef ALGVS_H__ -#define ALGVS_H__ +#ifndef ALGO_ALGVS_H__ +#define ALGO_ALGVS_H__ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS @@ -15,4 +15,4 @@ #define typeof decltype #endif//_MSC_VER -#endif//ALGVS_H__ \ No newline at end of file +#endif//ALGO_ALGVS_H__ \ No newline at end of file diff --git a/src/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 diff --git a/utils/gb18030.h b/utils/gb18030.h index fdc2803d..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 From 68ad0f22303aec9db74eb6b8dfccc4de2bcc697e Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 22 Oct 2016 17:23:02 +0800 Subject: [PATCH 205/217] Update README.md --- README.md | 131 ++++++++++++++++++++++++++---------------------------- 1 file changed, 62 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index d9b7eb9f..dac3795d 100644 --- a/README.md +++ b/README.md @@ -26,75 +26,68 @@ ####已实现 ( Implemented ): - Array shuffle - Prime test(trial division) - Prime test(Miller-Rabin's method) - 2D Array - Arbitrary Integer - Linear congruential generator - Maximum subarray problem - - Bit-Set - Queue - Stack - Binary Heap - Fibonacci Heap - Priority Queue (list based) - - Bubble sort - Selection sort - Insertion sort - Shell sort - Radix sort - Quick sort - Merge sort - Double linked list - Skip list - Self-organized linked-list ops (move-to-front, move-ahead-one) - Largest common sequence - - Binary search tree - AVL tree - Dynamic order statistics - Red-black tree - Interval tree - Prefix Tree(Trie) - Suffix Tree - B-Tree - Suffix Array - - Hash by multiplication - Hash table - Universal hash function - Perfect hash - Java's string hash - FNV-1a string hash - SimHash - Bloom Filter - SHA-1 Message Digest Algorithm - MD5 - Base64 - - Graph data structure - Strongly Connected Components(SCC) - Prim's minimum spanning tree - Kruskal MST - Directed/Undirected graph ops - Breadth First Search - Depth First Search - Dijkstra's algorithm - Bellman-Ford algorithm - Edmonds-Karp Maximal Flow - Push–Relabel algorithm - - Huffman Coding - Word segementation(CHN/GB18030) using HMM and viterbi algorithm. - A* algorithm - K-Means - Knuth–Morris–Pratt algorithm - Disjoint-Set - 8-Queue Problem - Palindrome +| Name | File | +|------|------| +|Array shuffle|https://github.com/xtaci/algorithms/blob/master/include/shuffle.h | +|Prime test(trial division)|https://github.com/xtaci/algorithms/blob/master/include/prime.h| +|Prime test(Miller-Rabin's method)|https://github.com/xtaci/algorithms/blob/master/include/prime.h| +|2D Array|https://github.com/xtaci/algorithms/blob/master/include/2darray.h| +|Arbitrary Integer|https://github.com/xtaci/algorithms/blob/master/include/integer.h| +|Linear congruential generator|https://github.com/xtaci/algorithms/blob/master/include/random.h| +|Maximum subarray problem|https://github.com/xtaci/algorithms/blob/master/include/max_subarray.h| +|Bit-Set|https://github.com/xtaci/algorithms/blob/master/include/bitset.h| +|Queue|https://github.com/xtaci/algorithms/blob/master/include/queue.h| +|Stack|https://github.com/xtaci/algorithms/blob/master/include/stack.h| +|Binary Heap|https://github.com/xtaci/algorithms/blob/master/include/heap.h| +|Fibonacci Heap|https://github.com/xtaci/algorithms/blob/master/include/fib-heap.h| +|Priority Queue (list based)|https://github.com/xtaci/algorithms/blob/master/include/priority_queue.h| +|Bubble sort|https://github.com/xtaci/algorithms/blob/master/include/bubble_sort.h| +|Selection sort|https://github.com/xtaci/algorithms/blob/master/include/selection_sort.h| +|Insertion sort|https://github.com/xtaci/algorithms/blob/master/include/insertion_sort.h| +|Shell sort|https://github.com/xtaci/algorithms/blob/master/include/shell_sort.h| +|Radix sort|https://github.com/xtaci/algorithms/blob/master/include/radix_sort.h| +|Quicksort|https://github.com/xtaci/algorithms/blob/master/include/quick_sort.h| +|Merge sort|https://github.com/xtaci/algorithms/blob/master/include/merge_sort.h| +|Double linked list|https://github.com/xtaci/algorithms/blob/master/include/double_linked_list.h| +|Skip list|https://github.com/xtaci/algorithms/blob/master/include/skiplist.h| +|Largest common sequence|https://github.com/xtaci/algorithms/blob/master/include/lcs.h| +|Binary search tree|https://github.com/xtaci/algorithms/blob/master/include/binary_search_tree.h| +|AVL tree|https://github.com/xtaci/algorithms/blob/master/include/avl.h| +|Dynamic order statistics|https://github.com/xtaci/algorithms/blob/master/include/dos_tree.h| +|Red-black tree|https://github.com/xtaci/algorithms/blob/master/include/rbtree.h| +|Interval tree|https://github.com/xtaci/algorithms/blob/master/include/interval_tree.h| +|Prefix Tree(Trie)|https://github.com/xtaci/algorithms/blob/master/include/trie.h| +|Suffix Tree|https://github.com/xtaci/algorithms/blob/master/include/suffix_tree.h| +|B-Tree|https://github.com/xtaci/algorithms/blob/master/include/btree.h| +|Suffix Array|https://github.com/xtaci/algorithms/blob/master/include/suffix_array.h| +|Hash by multiplication|https://github.com/xtaci/algorithms/blob/master/include/hash_multi.h| +|Hash table|https://github.com/xtaci/algorithms/blob/master/include/hash_table.h| +|Universal hash function|https://github.com/xtaci/algorithms/blob/master/include/universal_hash.h| +|Perfect hash|https://github.com/xtaci/algorithms/blob/master/include/perfect_hash.h| +|Java's string hash|https://github.com/xtaci/algorithms/blob/master/include/hash_string.h| +|FNV-1a string hash|https://github.com/xtaci/algorithms/blob/master/include/hash_string.h| +|SimHash|https://github.com/xtaci/algorithms/blob/master/include/simhash.h| +|Bloom Filter|https://github.com/xtaci/algorithms/blob/master/include/bloom_filter.h| +|SHA-1 Message Digest Algorithm|https://github.com/xtaci/algorithms/blob/master/include/sha1.h| +|MD5|https://github.com/xtaci/algorithms/blob/master/include/md5.h| +|Base64|https://github.com/xtaci/algorithms/blob/master/include/base64.h| +|Strongly Connected Components(SCC)|https://github.com/xtaci/algorithms/blob/master/include/scc.h| +|Prim's minimum spanning tree|https://github.com/xtaci/algorithms/blob/master/include/prim_mst.h| +|Kruskal MST|https://github.com/xtaci/algorithms/blob/master/include/kruskal_mst.h| +|Breadth First Search|https://github.com/xtaci/algorithms/blob/master/include/graph_search.h| +|Depth First Search|https://github.com/xtaci/algorithms/blob/master/include/graph_search.h| +|Dijkstra's algorithm|https://github.com/xtaci/algorithms/blob/master/include/dijkstra.h| +|Bellman-Ford algorithm|https://github.com/xtaci/algorithms/blob/master/include/bellman_ford.h| +|Edmonds-Karp Maximal Flow|https://github.com/xtaci/algorithms/blob/master/include/edmonds_karp.h| +|Push–Relabel algorithm|https://github.com/xtaci/algorithms/blob/master/include/relabel_to_front.h| +|Huffman Coding|https://github.com/xtaci/algorithms/blob/master/include/huffman.h| +|Word segementation|https://github.com/xtaci/algorithms/blob/master/include/word_seg.h| +|A\* algorithm|https://github.com/xtaci/algorithms/blob/master/include/astar.h| +|K-Means|https://github.com/xtaci/algorithms/blob/master/include/k-means.h| +|Knuth–Morris–Pratt algorithm|https://github.com/xtaci/algorithms/blob/master/include/kmp.h| +|Disjoint-Set|https://github.com/xtaci/algorithms/blob/master/include/disjoint-set.h| +|8-Queue Problem|https://github.com/xtaci/algorithms/blob/master/include/8queen.h| +|Palindrome|https://github.com/xtaci/algorithms/blob/master/include/palindrome.h| ####贡献者 ( Contributors ) : Samana: for heavy work of MSVC compatability From c9fae93ad4eadff6b8b2006db5cbf8c560893e60 Mon Sep 17 00:00:00 2001 From: Mohamed Ayman Date: Mon, 26 Dec 2016 00:51:56 +0200 Subject: [PATCH 206/217] Add Lowest commen ancestor algorithm --- src/lca_demo.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/lca_demo.cpp diff --git a/src/lca_demo.cpp b/src/lca_demo.cpp new file mode 100644 index 00000000..7bbf548d --- /dev/null +++ b/src/lca_demo.cpp @@ -0,0 +1,99 @@ +#include + +int numberOfNodes, MAXLOG; +std::vector< std::vector > adjList; +int parent[50005], nodeHeight[50005]; +bool visited[50005]; +int binaryLiftDp[50005][27]; + +void 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); + } + } +} + +int getMaxLog(){ + int curValue = 1; + int curLog = 1; + while(curValue < numberOfNodes) curValue *= 2, curLog++; + return curLog; +} + +void initializeDP() +{ + nodeHeight[-1] = -1; + MAXLOG = getMaxLog(); + 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++) + { + if(binaryLiftDp[j][i - 1] + 1) + binaryLiftDp[j][i] = binaryLiftDp[binaryLiftDp[j][i - 1]][i - 1]; + else binaryLiftDp[j][i] = -1; + } + } +} + +int LCA(int a, int b) +{ + 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(!(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]; +} + +void buildTree() +{ + printf("Enter number of nodes of the tree: "); + scanf("%d", &numberOfNodes); + adjList.resize(numberOfNodes, std::vector ()); + for(int i = 0; i < numberOfNodes - 1; i++) + { + int firstNode, secondNode; + printf("Enter the two nodes to be connected: "); + scanf("%d %d", &firstNode, &secondNode); + adjList[firstNode].push_back(secondNode); + adjList[secondNode].push_back(firstNode); + } +} + +void answerQueries() +{ + int queryCount; + printf("Enter the number of queries: "); + scanf("%d", &queryCount); + for(int i = 0; i < queryCount; i++) + { + int firstNode, secondNode; + printf("Enter the two nodes : "); + scanf("%d %d", &firstNode, &secondNode); + printf("%d\n", LCA(firstNode, secondNode)); + } +} + +int main() +{ + buildTree(); + initializeDP(); + answerQueries(); +} From ffe13e93ee0e0408cd54bdcc1982f247e075d241 Mon Sep 17 00:00:00 2001 From: Mohamed Ayman Date: Mon, 26 Dec 2016 00:56:30 +0200 Subject: [PATCH 207/217] Add const size for array --- src/lca_demo.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/lca_demo.cpp b/src/lca_demo.cpp index 7bbf548d..19002d3e 100644 --- a/src/lca_demo.cpp +++ b/src/lca_demo.cpp @@ -1,10 +1,14 @@ -#include +#include +#include -int numberOfNodes, MAXLOG; +const int MAX_NODE = 5000; +const int MAX_LOG = 20; + +int numberOfNodes, maxLog; std::vector< std::vector > adjList; -int parent[50005], nodeHeight[50005]; -bool visited[50005]; -int binaryLiftDp[50005][27]; +int parent[MAX_NODE], nodeHeight[MAX_NODE]; +bool visited[MAX_NODE]; +int binaryLiftDp[MAX_NODE][MAX_LOG]; void dfs(int currentNode, int currentParent) { @@ -31,10 +35,10 @@ int getMaxLog(){ void initializeDP() { nodeHeight[-1] = -1; - MAXLOG = getMaxLog(); + maxLog = getMaxLog(); dfs(0, -1); for(int i = 0; i < numberOfNodes; i++) binaryLiftDp[i][0] = parent[i]; - for(int i = 1; i <= MAXLOG; i++) + for(int i = 1; i <= maxLog; i++) { for(int j = 0; j < numberOfNodes; j++) { @@ -48,13 +52,13 @@ void initializeDP() int LCA(int a, int b) { if(nodeHeight[a] < nodeHeight[b]) std::swap(a,b); - for(int i = MAXLOG; i >= 0; i--) + for(int i = maxLog; i >= 0; i--) { if(binaryLiftDp[a][i] + 1 && nodeHeight[binaryLiftDp[a][i]] >= nodeHeight[b]) a = binaryLiftDp[a][i]; } if(!(a - b)) return a; - for(int i = MAXLOG; i >= 0; i--) + 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]; From e65421342902b29efdd39fd4e7d32086f4c7c261 Mon Sep 17 00:00:00 2001 From: xtaci Date: Fri, 20 Jan 2017 11:08:17 +0800 Subject: [PATCH 208/217] update makefile --- .travis.yml | 3 --- Makefile | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4d9ce7f..8226360b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,5 @@ language: cpp - compiler: - - gcc - clang - script: - make diff --git a/Makefile b/Makefile index c0c50190..ee02999c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all clean -CC=gcc -CPP=g++ +CC=clang +CPP=clang++ AR=ar RANLIB=ranlib CFLAGS= -g -Wall -Wno-unused-function From 5c50c332114874e8e175a83fef12d0b24547d45b Mon Sep 17 00:00:00 2001 From: Mohamed Ayman Date: Tue, 21 Feb 2017 00:19:27 +0200 Subject: [PATCH 209/217] apply OOP principles to LCA --- include/LCA.h | 38 ++++++++++++++ src/lca_demo.cpp | 126 ++++++++++++++++++++++++++--------------------- 2 files changed, 108 insertions(+), 56 deletions(-) create mode 100644 include/LCA.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/src/lca_demo.cpp b/src/lca_demo.cpp index 19002d3e..899cc1ba 100644 --- a/src/lca_demo.cpp +++ b/src/lca_demo.cpp @@ -1,16 +1,36 @@ +#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. +*/ -const int MAX_NODE = 5000; -const int MAX_LOG = 20; - -int numberOfNodes, maxLog; -std::vector< std::vector > adjList; -int parent[MAX_NODE], nodeHeight[MAX_NODE]; -bool visited[MAX_NODE]; -int binaryLiftDp[MAX_NODE][MAX_LOG]; +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(); +} -void dfs(int currentNode, int currentParent) +/** +*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; @@ -25,40 +45,58 @@ void dfs(int currentNode, int currentParent) } } -int getMaxLog(){ +/** +*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++; + while(curValue < _numberOfNodes) curValue *= 2, curLog++; return curLog; } -void initializeDP() +void LCA::initDP() { - nodeHeight[-1] = -1; - maxLog = getMaxLog(); dfs(0, -1); - for(int i = 0; i < numberOfNodes; i++) binaryLiftDp[i][0] = parent[i]; - for(int i = 1; i <= maxLog; i++) + 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++) + for(int j = 0; j < _numberOfNodes; j++) { - if(binaryLiftDp[j][i - 1] + 1) + /** + * 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(int a, int b) +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--) + for(int i = _maxLog; i >= 0; i--) { if(binaryLiftDp[a][i] + 1 && nodeHeight[binaryLiftDp[a][i]] >= nodeHeight[b]) a = binaryLiftDp[a][i]; } - if(!(a - b)) return a; - for(int i = maxLog; i >= 0; 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]; @@ -66,38 +104,14 @@ int LCA(int a, int b) return parent[a]; } -void buildTree() -{ - printf("Enter number of nodes of the tree: "); - scanf("%d", &numberOfNodes); - adjList.resize(numberOfNodes, std::vector ()); - for(int i = 0; i < numberOfNodes - 1; i++) - { - int firstNode, secondNode; - printf("Enter the two nodes to be connected: "); - scanf("%d %d", &firstNode, &secondNode); - adjList[firstNode].push_back(secondNode); - adjList[secondNode].push_back(firstNode); - } -} - -void answerQueries() -{ - int queryCount; - printf("Enter the number of queries: "); - scanf("%d", &queryCount); - for(int i = 0; i < queryCount; i++) - { - int firstNode, secondNode; - printf("Enter the two nodes : "); - scanf("%d %d", &firstNode, &secondNode); - printf("%d\n", LCA(firstNode, secondNode)); - } -} - -int main() -{ - buildTree(); - initializeDP(); - answerQueries(); +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; } From 82dd1bb637986c3ed6394e8da09b7ddd5592600a Mon Sep 17 00:00:00 2001 From: xtaci Date: Tue, 21 Feb 2017 10:00:11 +0800 Subject: [PATCH 210/217] Delete .goutputstream-UUQE8X --- include/.goutputstream-UUQE8X | 61 ----------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 include/.goutputstream-UUQE8X diff --git a/include/.goutputstream-UUQE8X b/include/.goutputstream-UUQE8X deleted file mode 100644 index e92d1ab5..00000000 --- a/include/.goutputstream-UUQE8X +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Fenwick Tree - * - * Data structure providing prefix sums and modify the table in O(log n) - n is the size o the table. - * - * In this algorithm we use two functions: - * - RSQ - This function calculates the range sum query in O(log n) - * - Update - This function adjusts the values in the given range in O(log n) - * - * https://en.wikipedia.org/wiki/Fenwick_tree - * - * @author Gabriel Duarte (gabriellagoa10@yahoo.com.br) - * @github Gabriel123Duarte - * - ******************************************************************************/ - -#ifndef __FENWICK_H__ -#define __FENWICK_H__ - -#include - -#define LSONE(x) (x & (-x)) - -class Fenwick -{ - private: - // Vector representing the table - std::vector fen; - public: - Fenwick() {} - - // We don't use the index 0, because it is the base case - Fenwick(int n) - { - fen.assign(n + 1, 0); - } - - // Calculate the - int rsq(int a) - { - int ans = 0; - for(; a; a -= LSONE(a)) - ans += fen[a]; - return ans; - } - - // RSQ a..b - inline int rsq(int a, int b) - { - return rsq(b) - (a == 1 ? 0 : rsq(a - 1)); - } - - // Update the value of the k-th element by x - void update(int k, int x) - { - for(; k < (int)fen.size(); k += LSONE(k)) - fen[k] += x; - } -}; - -#endif From 1a94def5c1dc01b051df1aa72315cd85757d3ca7 Mon Sep 17 00:00:00 2001 From: Mohamed Ayman Date: Wed, 22 Feb 2017 00:20:42 +0200 Subject: [PATCH 211/217] add LCA entry to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dac3795d..4bd9675a 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ |Disjoint-Set|https://github.com/xtaci/algorithms/blob/master/include/disjoint-set.h| |8-Queue Problem|https://github.com/xtaci/algorithms/blob/master/include/8queen.h| |Palindrome|https://github.com/xtaci/algorithms/blob/master/include/palindrome.h| +|LCA using Binary Lifting|https://github.com/xtaci/algorithms/blob/master/include/LCA.h| ####贡献者 ( Contributors ) : Samana: for heavy work of MSVC compatability From fb003ae73232d5ff619e80fed430a3384fcffca2 Mon Sep 17 00:00:00 2001 From: yrong Date: Sun, 16 Apr 2017 11:33:07 +0800 Subject: [PATCH 212/217] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4bd9675a..58cd686e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [1]: https://travis-ci.org/xtaci/algorithms.svg?branch=master [2]: https://travis-ci.org/xtaci/algorithms -####目标 ( goal ) : +#### 目标 ( goal ) : 1. 经典的算法实现 (classical algorithms implementations) @@ -12,7 +12,7 @@ 3. 正确,易于使用和改造, 一个头文件一个算法,并附带一个demo. (correct! and ease of use, one .header file per algorithm) -####约定 ( Convention ): +#### 约定 ( Convention ): 1. 一个算法用一个.h文件表示放到include下. ( one .header file per algorithm. ) 2. 算法演示的demo程序放到src下. ( one demo per algorithm. ) @@ -24,7 +24,7 @@ eg: ![demograph](demo_graph.png) -####已实现 ( Implemented ): +#### 已实现 ( Implemented ): | Name | File | |------|------| @@ -90,7 +90,7 @@ |Palindrome|https://github.com/xtaci/algorithms/blob/master/include/palindrome.h| |LCA using Binary Lifting|https://github.com/xtaci/algorithms/blob/master/include/LCA.h| -####贡献者 ( Contributors ) : +#### 贡献者 ( Contributors ) : Samana: for heavy work of MSVC compatability wycg1984: for K-Means xmuliang: for HeapSort, Kruskal MST @@ -99,6 +99,6 @@ UsingtcNower: Suffix Array afernandez90: AVL trees -####支持此项目 ( Donations ) : +#### 支持此项目 ( Donations ) : ![donate](donate_alg.png) 欢迎使用支付宝扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化补全及完善。 From a4333de509ae5f04ddf83b7abc5dfc285021dc24 Mon Sep 17 00:00:00 2001 From: xtaci Date: Sat, 3 Jun 2017 21:00:38 +0800 Subject: [PATCH 213/217] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 58cd686e..b7fcffcb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -###Algorithms & Data Structures in C++ +### Algorithms & Data Structures in C++ + [![Build Status][1]][2] + [1]: https://travis-ci.org/xtaci/algorithms.svg?branch=master [2]: https://travis-ci.org/xtaci/algorithms From 21aed1508df1460182d5be231e771a9f99d5428c Mon Sep 17 00:00:00 2001 From: godbod Date: Sun, 18 Feb 2018 22:41:11 +0100 Subject: [PATCH 214/217] This pull request solve the cleaning of *.o file issue --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ee02999c..82f536a5 100644 --- a/Makefile +++ b/Makefile @@ -263,5 +263,5 @@ suffix_array_demo: $(SRCDIR)/suffix_array_demo.cpp $(CPP) $(C11FLAGS) -o $@ $^ $(INCLUDEDIR) $(LIBS) clean: - rm -rf $(PROGRAMS) *.dSYM + rm -rf $(PROGRAMS) *.dSYM *.o From ed2726e1a8174807f40b26ee717a6795ae050737 Mon Sep 17 00:00:00 2001 From: Saurabh Deepak Shukla <47148573+SaurabhShukla2024@users.noreply.github.com> Date: Fri, 20 Nov 2020 22:25:10 +0530 Subject: [PATCH 215/217] I have fixed the typo in README.md 8-Queen Problem was *-Queue Problem. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b7fcffcb..cf2aa0bf 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ |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-Queue Problem|https://github.com/xtaci/algorithms/blob/master/include/8queen.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| From cd540cfef27a25ed0f39acfaa45a2d92e5222450 Mon Sep 17 00:00:00 2001 From: xtaci Date: Wed, 12 May 2021 18:10:26 +0800 Subject: [PATCH 216/217] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index cf2aa0bf..907e484d 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,3 @@ ZhangYou0122: Push-Relabel algorithm, Suffix Tree UsingtcNower: Suffix Array afernandez90: AVL trees - -#### 支持此项目 ( Donations ) : -![donate](donate_alg.png) -欢迎使用支付宝扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化补全及完善。 From 9449b5d50b940508780f980e6686692ab97e8792 Mon Sep 17 00:00:00 2001 From: xtaci Date: Thu, 1 Aug 2024 17:49:54 +0800 Subject: [PATCH 217/217] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 907e484d..91d25f57 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![Build Status][1]][2] -[1]: https://travis-ci.org/xtaci/algorithms.svg?branch=master -[2]: https://travis-ci.org/xtaci/algorithms +[1]: https://img.shields.io/github/created-at/xtaci/algorithms +[2]: https://img.shields.io/github/created-at/xtaci/algorithms #### 目标 ( goal ) :