├── .gitignore ├── chapter2 ├── Selection.hpp ├── test.cpp ├── test2.cpp ├── Insertion.hpp ├── Shell.hpp ├── HeapSort.hpp ├── Merge2.hpp ├── Merge.hpp ├── Quick.hpp ├── OrderArrayMaxPQ.cpp ├── UnOrderArrayMaxPQ.cpp ├── MaxPQ.cpp └── IndexMinPQ.hpp ├── common ├── Common.cpp └── Common.hpp ├── chapter1 ├── BinarySearch2.cpp └── BinarySearch.cpp ├── chapter3 ├── test4.cpp ├── test5.cpp ├── SeparateChainingHashST.hpp ├── SequentialSearchST.hpp ├── test3.cpp ├── BinarySearchST.hpp ├── test.cpp ├── LinearProbingHashST.hpp ├── test2.cpp ├── test1.cpp ├── AvlTree.hpp ├── BST.hpp └── RedBlackBST.hpp ├── chapter5 ├── BLsearch.hpp ├── LSD.hpp ├── Kmp.hpp ├── BoyerMoore.hpp ├── Quick3string.hpp ├── MSD.hpp ├── test1.cpp └── TrieST.hpp ├── chapter4 ├── DirectedEdge.hpp ├── DepthFirstSearch.hpp ├── DirectedDFS.hpp ├── CC.hpp ├── SymbolGraph.hpp ├── Graph.hpp ├── Edge.hpp ├── Kruskal.hpp ├── DepthFirstOrder.hpp ├── Digraph.hpp ├── Kosaraju.hpp ├── DepthFirstPaths.hpp ├── DirectedCycle.hpp ├── BreadthFirstPaths.hpp ├── EdgeWeightDigraph.hpp ├── DijkstraSP.hpp ├── EdgeWeightedGraph.hpp ├── LazyPrimMST.hpp ├── BellmanFord.hpp ├── PrimMST.hpp └── test1.cpp └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/ 3 | Testing/ 4 | CMakeFiles/ 5 | cmake_install* 6 | CMakeCache.txt 7 | CPack* 8 | CTest* 9 | *.tcl 10 | Makefile 11 | test2 12 | CMakeList* 13 | main.cpp 14 | *.a 15 | .gitignore 16 | tale.txt 17 | tiny*.txt 18 | routes.txt -------------------------------------------------------------------------------- /chapter2/Selection.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | using namespace std; 7 | /** 8 | * 选择排序 9 | **/ 10 | template 11 | void Selection(vector& a) 12 | { 13 | for(size_t i = 0; i < a.size(); ++i) { 14 | auto max_one = min_element(a.begin() + i, a.end()); 15 | swap(*(a.begin() + i), *max_one); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /chapter2/test.cpp: -------------------------------------------------------------------------------- 1 | #include "Merge.hpp" 2 | #include "Merge2.hpp" 3 | #include "Quick.hpp" 4 | #include "HeapSort.hpp" 5 | int *Merge::aux = nullptr; 6 | int *Merge2::aux = nullptr; 7 | 8 | /** 9 | * 测试各种排序算法 10 | **/ 11 | int main(int argc, char** argv) { 12 | Common* c = Common::getInstance(); 13 | vector vec1 = c->getRandomVector(6); 14 | vec1.insert(vec1.begin(), 0); 15 | HeapSort::sort(vec1); 16 | c->show(vec1.begin(), vec1.end()); 17 | return 1; 18 | } -------------------------------------------------------------------------------- /chapter2/test2.cpp: -------------------------------------------------------------------------------- 1 | #include "IndexMinPQ.hpp" 2 | 3 | /** 4 | * 测试IndexMinPQ 5 | **/ 6 | 7 | int main() 8 | { 9 | IndexMinPQ pq(7); 10 | vector v = Common::getInstance()->getRandomVector(7); 11 | for(size_t i = 0; i < v.size(); ++i) { 12 | cout << v[i] << " "; 13 | pq.insert(i + 1, v[i]); 14 | } 15 | cout << endl; 16 | pq.show(); 17 | for(size_t i = 0; i < v.size(); ++i) { 18 | cout << pq.delMin() << " "; 19 | // pq.show(); 20 | } 21 | cout << endl; 22 | } -------------------------------------------------------------------------------- /chapter2/Insertion.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __INSERT__H 2 | #define __INSERT__H 3 | 4 | #include 5 | #include "Common.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | /** 11 | * 插入排序 12 | **/ 13 | template 14 | void Insertion(iterator b, iterator e) { 15 | int len = distance(b , e); 16 | for(int i = 1; i < len; ++i) { 17 | for(int j = i; j > 0 && *(b + j) < *(b + j - 1); --j) 18 | swap(*(b + j - 1), *(b + j)); 19 | } 20 | } 21 | 22 | #endif -------------------------------------------------------------------------------- /chapter2/Shell.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | using namespace std; 7 | /** 8 | * 希尔排序 9 | **/ 10 | 11 | template 12 | void Shell(vector& v) { 13 | int len = v.size(), h = 1; 14 | while(h < len / 3) h = 3*h + 1; 15 | while(h) { 16 | //插入排序 17 | for (int i = 1; i < len; i+= h) { 18 | for(int j = i; j > 0 && v[j] < v[j - h]; j -= h) 19 | swap(v[j], v[j -h]); 20 | } 21 | h = h / 3; 22 | } 23 | } -------------------------------------------------------------------------------- /common/Common.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.hpp" 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | Common* Common::getInstance() { 8 | static Common single; 9 | return &single; 10 | } 11 | 12 | std::vector 13 | Common::getRandomVector(int length, uint_fast32_t seed ,bool isSort) const{ 14 | static default_random_engine e; 15 | static uniform_int_distribution<> u(1, 100); 16 | e.seed(seed); 17 | vector res; 18 | for(int i = 0; i < length; ++i) { 19 | res.push_back(u(e)); 20 | } 21 | if(isSort) 22 | sort(res.begin(), res.end()); 23 | return res; 24 | } -------------------------------------------------------------------------------- /chapter1/BinarySearch2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 非递归实现的二分查找 3 | **/ 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int BinarySearch(vector& a, int key) { 9 | int lo = 0, 10 | ho = a.size(), 11 | mid; 12 | while(lo < ho) { 13 | mid = (lo + ho) / 2; 14 | if(a[mid] > key) ho = mid; 15 | else if(a[mid] < key) lo = mid + 1; 16 | else return mid; 17 | } 18 | return -1; 19 | } 20 | 21 | 22 | int main() { 23 | vector vs{1,2,3,4,12,34,555,1234,5321}; 24 | cout << BinarySearch(vs, 2) << endl; 25 | cout << BinarySearch(vs, 34) << endl; 26 | cout << BinarySearch(vs, 324) << endl; 27 | cout << BinarySearch(vs, 555) << endl; 28 | return 0; 29 | } -------------------------------------------------------------------------------- /chapter3/test4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-22 18:10:15 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-22 19:11:47 6 | */ 7 | #define CATCH_CONFIG_MAIN 8 | #include "catch.hpp" 9 | #include "Common.hpp" 10 | #include "SeparateChainingHashST.hpp" 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * 拉链法的散列表的单元测试 17 | **/ 18 | 19 | TEST_CASE("put", "[schST]") { 20 | SeparateChainingHashST st(10); 21 | st.put(1, "1"); 22 | st.put(11, "11"); 23 | REQUIRE(st.size() == 2); 24 | REQUIRE(st.get(11) == "11"); 25 | REQUIRE(st.get(1) == "1"); 26 | st.put(123, "123"); 27 | REQUIRE(st.size() == 3); 28 | REQUIRE(st.get(123) == "123"); 29 | } -------------------------------------------------------------------------------- /common/Common.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_HPP 2 | #define __COMMON_HPP 3 | #include 4 | #include 5 | #include 6 | 7 | class Common { 8 | public: 9 | template 10 | void show(iterator,iterator) const; 11 | 12 | std::vector getRandomVector(int length, uint_fast32_t seed = time(NULL),bool isSort = false) const; 13 | static Common* getInstance(); 14 | private: 15 | Common() = default; 16 | }; 17 | 18 | template 19 | void Common::show(iterator begin,iterator end)const { 20 | auto begin_cp = begin; 21 | while(begin_cp != end) { 22 | std::cout << *begin_cp++; 23 | if(begin_cp != end) 24 | std::cout << " "; 25 | } 26 | std::cout << std::endl; 27 | } 28 | #endif -------------------------------------------------------------------------------- /chapter3/test5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-22 19:11:45 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-22 20:16:51 6 | */ 7 | #define CATCH_CONFIG_MAIN 8 | #include "catch.hpp" 9 | #include "Common.hpp" 10 | #include "LinearProbingHashST.hpp" 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * 线性探测法的散列表的单元测试 17 | **/ 18 | 19 | TEST_CASE("put", "[ST]") { 20 | LinearProbingHashST st(2); 21 | st.put(1, 1); 22 | st.put(2, 2); 23 | REQUIRE(st.size() == 2); 24 | st.put(3, 3); 25 | st.put(7, 7); 26 | st.put(19, 19); 27 | st.put(22, 22); 28 | st.put(43, 43); 29 | st.put(48, 48); 30 | st.put(56, 56); 31 | st.put(70, 70); 32 | REQUIRE(st.size() == 10); 33 | st.delet(7); 34 | REQUIRE(st.size() == 9); 35 | } -------------------------------------------------------------------------------- /chapter5/BLsearch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-13 23:39:13 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-14 18:49:01 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | /** 18 | * 暴力子字符串查找 19 | **/ 20 | class BLsearch 21 | { 22 | private: 23 | /* data */ 24 | public: 25 | static int search(string s, string txt) { 26 | for(unsigned i = 0; i <= txt.size() - s.size(); ++ i) 27 | { 28 | unsigned j = 0; 29 | for( ; j < s.size(); ++j) 30 | if(txt[i + j] != s[j]) break; 31 | if(j == s.size()) return i; 32 | } 33 | return txt.size(); 34 | } 35 | }; 36 | 37 | 38 | -------------------------------------------------------------------------------- /chapter2/HeapSort.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | using namespace std; 7 | /** 8 | * 堆排序 9 | **/ 10 | template 11 | class HeapSort { 12 | public: 13 | static void sort(vector&); 14 | private: 15 | static void sink(vector& a, int k, int N); 16 | }; 17 | 18 | template 19 | void HeapSort::sort(vector& a) { 20 | int N = a.size() - 1; 21 | for(int i = N / 2; i >= 1; --i) 22 | sink(a, i, N); 23 | while(N > 1) { 24 | swap(a[1], a[N--]); 25 | sink(a, 1, N); 26 | } 27 | } 28 | 29 | template 30 | void HeapSort::sink(vector& a, int k, int N) { 31 | int j; 32 | while(k <= N / 2) { 33 | j = 2 * k; 34 | if(j < N && a[j] < a[j + 1]) ++j; 35 | if(a[k] >= a[j]) break; 36 | swap(a[k], a[j]); 37 | k = j; 38 | } 39 | } -------------------------------------------------------------------------------- /chapter4/DirectedEdge.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-12 10:11:54 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 19:35:17 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "Digraph.hpp" 14 | #include 15 | using namespace std; 16 | /** 17 | * 加权有向边 18 | **/ 19 | class DirectedEdge 20 | { 21 | public: 22 | DirectedEdge(int v = 0, int w = 0, double weight = 0) 23 | : v(v), w(w), _weight(weight) {} 24 | bool operator==(const DirectedEdge& rhs) const { 25 | return rhs.v == v && rhs.w == w && rhs._weight == _weight; 26 | } 27 | double weight() {return _weight;} 28 | int from() const{return v;} 29 | int to() const {return w;} 30 | private: 31 | int v; 32 | int w; 33 | double _weight; 34 | }; -------------------------------------------------------------------------------- /chapter1/BinarySearch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 递归实现的二分查找 3 | **/ 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | //左闭右开还是左右都是闭区间 9 | int BinarySearch(vector& a,int lo,int ho, int key) { 10 | // if(lo > ho) return -1; 11 | // int mid = (lo + ho) / 2; 12 | // if(a[mid] > key) return BinarySearch(a, lo, mid - 1, key); 13 | // else if(a[mid] < key) BinarySearch(a, mid + 1, ho, key); 14 | // else return mid; 15 | if(lo >= ho) return -1; 16 | int mid = (lo + ho) / 2; 17 | if(a[mid] > key) return BinarySearch(a, lo, mid, key); 18 | else if(a[mid] < key) BinarySearch(a, mid + 1, ho, key); 19 | else return mid; 20 | } 21 | 22 | 23 | int main() { 24 | vector vs{1,2,3,4,12,34,555,1234,5321}; 25 | cout << BinarySearch(vs, 0, vs.size() ,2) << endl; 26 | cout << BinarySearch(vs, 0, vs.size() ,34) << endl; 27 | cout << BinarySearch(vs, 0, vs.size() ,324) << endl; 28 | cout << BinarySearch(vs, 0, vs.size() ,555) << endl; 29 | return 0; 30 | } -------------------------------------------------------------------------------- /chapter2/Merge2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | using namespace std; 5 | /** 6 | * 自底向上归并排序 7 | **/ 8 | class Merge2 { 9 | public: 10 | static void sort(vector &); 11 | private: 12 | static int* aux; 13 | static void merge(vector& , int,int,int); 14 | }; 15 | 16 | void Merge2::sort(vector &a) { 17 | aux = new int[a.size()](); 18 | for(size_t sz = 1; sz < a.size(); sz += sz) 19 | for(size_t i = 0; i < a.size() - sz ; i += 2 * sz) { 20 | merge(a, i, i + sz - 1, min(i + 2 *sz - 1, a.size() - 1)); 21 | } 22 | } 23 | 24 | void Merge2::merge(vector& a, int lo,int mid,int ho) { 25 | int i = lo 26 | , j = mid + 1 27 | , ao = lo; 28 | for(int k = lo; k <= ho ; ++k) 29 | aux[k] = a[k]; 30 | while(ao <= ho) { 31 | if(i > mid) a[ao++] = aux[j++]; 32 | else if (j > ho) a[ao++] = aux[i++]; 33 | else if (aux[i] > aux[j]) a[ao++] = aux[j++]; 34 | else a[ao++] = aux[i++]; 35 | } 36 | } -------------------------------------------------------------------------------- /chapter4/DepthFirstSearch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-25 18:23:46 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-11 11:16:31 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | /** 16 | * 深度优先搜索 17 | **/ 18 | 19 | class DepthFirstSearch{ 20 | public: 21 | int getCount() const {return count;} 22 | bool getMarked(int i) const {return marked[i];} 23 | 24 | DepthFirstSearch(Graph& g, int i); 25 | ~DepthFirstSearch() {delete [] marked;} 26 | private: 27 | void dfs(Graph& g, int v); 28 | bool *marked; 29 | int count; 30 | }; 31 | 32 | 33 | DepthFirstSearch::DepthFirstSearch(Graph& g, int i) 34 | : count(0) 35 | { 36 | marked = new bool [g.V()]; 37 | for(int i = 0; i < g.V(); ++i) 38 | marked[i] = false; 39 | dfs(g, i); 40 | } 41 | 42 | void DepthFirstSearch::dfs(Graph& g, int v) 43 | { 44 | marked[v] = true; 45 | ++count; 46 | for(auto x: g.adj(v)) { 47 | if(!marked[x]) dfs(g, x); 48 | } 49 | } -------------------------------------------------------------------------------- /chapter5/LSD.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-13 11:27:12 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-13 13:22:41 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | /** 19 | * 低位优先的字符串排序 20 | **/ 21 | class LSD 22 | { 23 | private: 24 | /* data */ 25 | public: 26 | LSD(vector& a, int w); 27 | ~LSD(); 28 | }; 29 | 30 | LSD::LSD(vector& a, int w) 31 | { 32 | vector aux(a.size()); 33 | unsigned int R = 128; 34 | for(int v = w - 1; v >= 0; --v) 35 | { 36 | int count[R + 1] = {0}; 37 | for(unsigned i = 0; i < a.size(); ++i) 38 | count[static_cast(a[i][v]) + 1]++; 39 | for(unsigned i = 0; i < R; ++i) 40 | count[i + 1] += count[i]; 41 | for(unsigned i = 0; i < a.size(); ++i) 42 | aux[count[static_cast(a[i][v])]++] = a[i]; 43 | for(unsigned i = 0; i < a.size(); ++i) 44 | a[i] = aux[i]; 45 | } 46 | } 47 | 48 | LSD::~LSD() 49 | { 50 | } 51 | -------------------------------------------------------------------------------- /chapter4/DirectedDFS.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-28 19:38:34 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 10:12:23 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "Digraph.hpp" 14 | #include 15 | using namespace std; 16 | /** 17 | * 有向图DFS 18 | **/ 19 | class DirectedDFS 20 | { 21 | public: 22 | DirectedDFS(Digraph& g, int s); 23 | DirectedDFS(Digraph& g, vector ss); 24 | ~DirectedDFS() {delete [] marked;} 25 | bool getMarked(int i) {return marked[i];} 26 | private: 27 | void dfs(Digraph& g, int v); 28 | bool *marked; 29 | }; 30 | 31 | DirectedDFS::DirectedDFS(Digraph& g, int s) : 32 | marked(new bool [g.V()]) 33 | { 34 | for(int i = 0; i < g.V(); ++i) 35 | marked[i] = false; 36 | dfs(g, s); 37 | } 38 | 39 | DirectedDFS::DirectedDFS(Digraph& g, vector ss) : 40 | marked(new bool [g.V()]) 41 | { 42 | for(int i = 0; i < g.V(); ++i) 43 | marked[i] = false; 44 | for(auto s : ss) 45 | dfs(g, s); 46 | } 47 | 48 | void DirectedDFS::dfs(Digraph& g, int v) 49 | { 50 | marked[v] = true; 51 | for(auto x : g.adj(v)) 52 | { 53 | if(!marked[x]) 54 | dfs(g ,x); 55 | } 56 | } -------------------------------------------------------------------------------- /chapter4/CC.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-27 15:10:58 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-27 15:39:11 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | using namespace std; 18 | /** 19 | * 连通分量 20 | **/ 21 | class CC{ 22 | public: 23 | CC(Graph& g); 24 | int getCount() const {return count;} 25 | int getId(int i) const {return id[i];} 26 | bool connected(int v, int w) {return id[v] == id[w];} 27 | private: 28 | void dfs(Graph&g, int v); 29 | bool* marked; 30 | int *id; 31 | int count; 32 | }; 33 | 34 | CC::CC(Graph& g) 35 | :marked(nullptr), id(nullptr), count(0) 36 | { 37 | 38 | marked = new bool[g.V()] (); 39 | id = new int [g.V()] (); 40 | for(int i = 0; i < g.V(); ++i) { 41 | marked[i] = false; 42 | } 43 | for(int i = 0; i < g.V(); ++i) { 44 | if(!marked[i]) { 45 | dfs(g, i); 46 | count++; 47 | } 48 | } 49 | } 50 | 51 | void CC::dfs(Graph&g, int v) 52 | { 53 | marked[v] = true; 54 | id[v] = count; 55 | for(auto x : g.adj(v)) { 56 | if(!marked[x]) 57 | dfs(g, x); 58 | } 59 | } -------------------------------------------------------------------------------- /chapter2/Merge.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MERGE_H_ 2 | #define MERGE_H_ 3 | #include 4 | #include 5 | #include "Common.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | /** 10 | * 自顶向下归并排序 11 | **/ 12 | 13 | class Merge{ 14 | public: 15 | static void sort(vector& ); 16 | private: 17 | static int* aux; 18 | static void sort(vector&, int lo,int ho); 19 | static void merge(vector&, int lo,int mid, int ho); 20 | }; 21 | 22 | void Merge::sort(vector& a){ 23 | aux = new int[a.size()](); 24 | sort(a, 0, a.size() - 1); 25 | } 26 | 27 | void Merge::sort(vector& a, int lo, int ho) 28 | { 29 | if(lo >= ho) return ; 30 | int mid = lo + (ho - lo) / 2; 31 | sort(a, lo, mid); 32 | sort(a, mid + 1, ho); 33 | merge(a, lo, mid, ho); 34 | } 35 | 36 | void Merge::merge(vector& a, int lo,int mid, int ho) { 37 | int i = lo, j = mid + 1, 38 | ao = lo; 39 | for(int n = lo; n <= ho; ++n) { 40 | aux[n] = a[n]; 41 | } 42 | while(ao <= ho) { 43 | if(i > mid) a[ao++] = aux[j++]; 44 | else if (j > ho) a[ao++] = aux[i++]; 45 | else if (aux[i] > aux[j]) a[ao++] = aux[j++]; 46 | else a[ao++] = aux[i++]; 47 | } 48 | //调试代码 49 | // for(int i = 0; i < 10; i ++) { 50 | // cout << a[i] << " "; 51 | // } 52 | // cout << endl; 53 | } 54 | 55 | #endif //asd -------------------------------------------------------------------------------- /chapter4/SymbolGraph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-27 16:47:30 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-27 17:08:22 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | using namespace std; 19 | /** 20 | * 符号图 21 | **/ 22 | class SymbolGraph 23 | { 24 | public: 25 | SymbolGraph(string stream); 26 | bool contain(string s) const {return st.count(s) > 0;} 27 | int index(string s) {return st[s];} 28 | string name(int v) {return keys[v];} 29 | private: 30 | map st; 31 | string *keys; 32 | Graph* g; 33 | }; 34 | 35 | SymbolGraph::SymbolGraph(string filename) 36 | { 37 | ifstream in(filename); 38 | vector vec; 39 | string a, b; 40 | while(in >> a >> b) { 41 | if(!st.count(a)) 42 | st.insert({a,st.size()}); 43 | if(!st.count(b)) 44 | st.insert({b,st.size()}); 45 | } 46 | keys = new string [st.size()]; 47 | for(auto n : st) { 48 | keys[n.second] = n.first; 49 | } 50 | g = new Graph(st.size()); 51 | in.seekg(0); 52 | while(in >> a >> b) { 53 | g->addEdge(st[a], st[b]); 54 | } 55 | in.close(); 56 | } -------------------------------------------------------------------------------- /chapter5/Kmp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-14 18:48:56 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-14 19:36:56 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | /** 18 | * Kmp 19 | **/ 20 | 21 | class Kmp 22 | { 23 | private: 24 | /* data */ 25 | static constexpr int R = 256; 26 | string pat; 27 | vector> dfa; 28 | 29 | public: 30 | Kmp(string pat); 31 | ~Kmp(); 32 | 33 | int search(const string& s) const; 34 | }; 35 | 36 | Kmp::Kmp(string pat) 37 | : pat(pat), dfa(R, vector(pat.size())) 38 | { 39 | int M = pat.size(); 40 | for(int i = 0; i < R; ++i) 41 | dfa[i][0] = 0; 42 | dfa[pat.at(0)][0] = 1; 43 | for(int X = 0, j = 1; j < M ; ++j) 44 | { 45 | for(int i = 0; i < R; ++i) 46 | dfa[i][j] = dfa[i][X]; 47 | dfa[pat.at(j)][j] = 1 + j; 48 | 49 | X = dfa[pat.at(j)][X]; 50 | } 51 | } 52 | 53 | Kmp::~Kmp() 54 | { 55 | } 56 | 57 | int Kmp::search(const string& s) const 58 | { 59 | unsigned i = 0, j = 0; 60 | for(; j < s.size() && i < pat.size(); ++j) 61 | i = dfa[s.at(j)][i]; 62 | if(j == s.size()) return j; 63 | return j - pat.size(); 64 | } 65 | -------------------------------------------------------------------------------- /chapter4/Graph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-25 13:54:42 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-27 14:19:01 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | /** 15 | * 图 16 | **/ 17 | 18 | class Graph{ 19 | public: 20 | Graph(int v); 21 | Graph(string s); 22 | int V() const {return v;} 23 | int E() const {return e;} 24 | list adj(int i) const; 25 | void addEdge(int v, int w); 26 | 27 | ~Graph() {delete [] adjs;} 28 | private: 29 | int v; //vertex 30 | int e; //edge 31 | list *adjs; 32 | }; 33 | 34 | Graph::Graph(int v) 35 | :v(v), e(0) 36 | { 37 | adjs =new list [v]; 38 | } 39 | 40 | list 41 | Graph::adj(int i) const 42 | { 43 | return adjs[i]; 44 | } 45 | 46 | void Graph::addEdge(int v, int w) 47 | { 48 | adjs[v].push_back(w); 49 | adjs[w].push_back(v); 50 | e++; 51 | } 52 | 53 | Graph::Graph(string s) 54 | { 55 | ifstream istrm(s, ios::binary); 56 | if(!istrm.is_open()) { 57 | abort(); 58 | } 59 | // istream_iterator inter(istrm), enditer; 60 | int a, b; 61 | istrm >> a; 62 | v = a; 63 | istrm >> a; 64 | // e = a; 65 | e = 0; 66 | adjs =new list [v]; 67 | while(istrm >> a >> b) { 68 | addEdge(a, b); 69 | } 70 | } -------------------------------------------------------------------------------- /chapter5/BoyerMoore.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-14 21:08:02 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-14 21:17:53 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | /** 18 | * BoyerMoore 19 | **/ 20 | class BoyerMoore 21 | { 22 | private: 23 | /* data */ 24 | static constexpr int R = 256; 25 | string pat; 26 | int right[R]; 27 | 28 | public: 29 | BoyerMoore(const string& s); 30 | int search(const string& s) const; 31 | ~BoyerMoore(); 32 | }; 33 | 34 | int BoyerMoore::search(const string& s) const { 35 | int i = 0, j, skip = 0; 36 | for( ;i <= s.size() - pat.size(); i += skip) { 37 | skip = 0; 38 | for(j = pat.size() - 1; j >= 0; --j) { 39 | if(s.at(i + j) != pat.at(j)) { 40 | skip = j - right[s.at(i + j)]; 41 | if(skip < 1) skip = 1; 42 | break; 43 | } 44 | } 45 | if(!skip) return i; 46 | } 47 | return s.size(); 48 | } 49 | 50 | BoyerMoore::BoyerMoore(const string& s) 51 | :pat(s), right({0}) 52 | { 53 | fill(begin(right), end(right), -1); 54 | for(unsigned i = 0; i < s.size(); ++i) 55 | right[s.at(i)] = i; 56 | } 57 | 58 | BoyerMoore::~BoyerMoore() 59 | { 60 | } 61 | -------------------------------------------------------------------------------- /chapter4/Edge.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-01 20:29:57 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-04 22:30:43 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | /** 15 | * 加权边 16 | **/ 17 | template 18 | class Edge 19 | { 20 | public: 21 | Edge(T v, T w, double weight); 22 | double weight() const {return _weight;} 23 | const T& either() const {return v;} 24 | const T& other(const T& vertex); 25 | int compareTo(const Edge& e) const; 26 | string toString() const; 27 | private: 28 | T v, w; 29 | double _weight; 30 | }; 31 | 32 | template 33 | Edge::Edge(T v, T w, double weight) 34 | : v(v), w(w), _weight(weight) 35 | { 36 | } 37 | 38 | template 39 | const T& Edge::other(const T& vertex) 40 | { 41 | if(vertex == w) return v; 42 | else if(vertex == v) return w; 43 | else throw exception(); 44 | } 45 | 46 | template 47 | int Edge::compareTo(const Edge& e) const 48 | { 49 | if(_weight > e.weight()) return 1; 50 | else if(_weight < e.weight()) return -1; 51 | else return 0; 52 | } 53 | 54 | template 55 | string Edge::toString() const 56 | { 57 | ostringstream ins; 58 | ins << v << "-" << w << " " << weight << "\n"; 59 | return ins.str(); 60 | } -------------------------------------------------------------------------------- /chapter4/Kruskal.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-11 10:52:16 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-11 11:10:29 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "EdgeWeightedGraph.hpp" 18 | #include "IndexMinPQ.hpp" 19 | #include "Graph.hpp" 20 | #include "LazyPrimMST.hpp" 21 | #include "DepthFirstSearch.hpp" 22 | using namespace std; 23 | /** 24 | * Kruskal算法 25 | **/ 26 | class Kruskal 27 | { 28 | public: 29 | Kruskal(EdgeWeightedGraph& g); 30 | double weight() const ; 31 | private: 32 | vector > egs; 33 | }; 34 | 35 | Kruskal:: 36 | Kruskal(EdgeWeightedGraph& g) 37 | :egs() 38 | { 39 | priority_queue, vector>, greater_> mq; 40 | for(auto e: g.edges()) mq.push(e); 41 | Graph ng(g.V()); 42 | while(mq.size()) 43 | { 44 | Edge e = mq.top(); 45 | mq.pop(); 46 | int v = e.either(), w = e.other(v); 47 | DepthFirstSearch df(ng, v); 48 | if(df.getMarked(w)) 49 | continue; 50 | ng.addEdge(v, w); 51 | egs.push_back(e); 52 | } 53 | } 54 | 55 | double Kruskal::weight() const 56 | { 57 | double tl = 0; 58 | for(auto e: egs) { 59 | tl += e.weight(); 60 | } 61 | return tl; 62 | } -------------------------------------------------------------------------------- /chapter4/DepthFirstOrder.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-28 22:34:55 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-28 22:58:26 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "Digraph.hpp" 16 | #include 17 | using namespace std; 18 | /** 19 | * 基于深度优先搜索的顶点排序 20 | **/ 21 | class DepthFirstOrder{ 22 | public: 23 | DepthFirstOrder(Digraph& g); 24 | ~DepthFirstOrder() {delete [] marked;} 25 | const queue& getPre() const {return pre;} 26 | const queue& getPost() const {return post;} 27 | const stack& getReversePost() const {return reversePost;} 28 | private: 29 | void dfs(Digraph& g, int v); 30 | bool *marked; 31 | queue pre; 32 | queue post; 33 | stack reversePost; 34 | }; 35 | 36 | DepthFirstOrder:: 37 | DepthFirstOrder(Digraph& g) 38 | : marked(nullptr) ,pre(), post(), reversePost() 39 | { 40 | marked = new bool [g.V()]; 41 | for(int i = 0; i < g.V(); ++i) 42 | marked[i] = false; 43 | for(int i = 0; i < g.V(); ++i) 44 | if(!marked[i]) dfs(g, i); 45 | } 46 | 47 | void 48 | DepthFirstOrder::dfs(Digraph& g, int v) 49 | { 50 | pre.push(v); 51 | marked[v] = true; 52 | for(auto w : g.adj(v)) 53 | if(!marked[w]) dfs(g, w); 54 | 55 | post.push(v); 56 | reversePost.push(v); 57 | } -------------------------------------------------------------------------------- /chapter3/SeparateChainingHashST.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | #include 7 | #include "BinarySearchST.hpp" 8 | using namespace std; 9 | 10 | /** 11 | * 拉链法散列表 12 | * 因为没有Java的hasCode方法, 13 | * 所以这里的代码直接使用int类型 14 | **/ 15 | 16 | template 17 | class SeparateChainingHashST 18 | { 19 | public: 20 | SeparateChainingHashST(int M); 21 | ~SeparateChainingHashST(); 22 | Value get(int key); 23 | void put(int key, Value val); 24 | int size() const {return this->N;} 25 | private: 26 | int N; //键值对总数 27 | int M; //散列表的大小 28 | BinarySearchST *st; 29 | 30 | int hash(int key) const; 31 | }; 32 | 33 | template 34 | SeparateChainingHashST::SeparateChainingHashST(int M) 35 | : N(0), M(M) 36 | { 37 | st = new BinarySearchST[M](); 38 | } 39 | 40 | template 41 | SeparateChainingHashST::~SeparateChainingHashST() 42 | { 43 | delete [] st; 44 | } 45 | 46 | template 47 | int SeparateChainingHashST::hash(int key) const 48 | { 49 | return (key & 0x7fffffff) % M; 50 | } 51 | 52 | template 53 | Value SeparateChainingHashST::get(int key) 54 | { 55 | return st[hash(key)].get(key); 56 | } 57 | 58 | template 59 | void SeparateChainingHashST::put(int key, Value val) 60 | { 61 | st[hash(key)].put(key, val); 62 | N++; 63 | } -------------------------------------------------------------------------------- /chapter5/Quick3string.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-13 14:55:29 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-13 15:23:13 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | /** 18 | * 三向字符串快速排序 19 | **/ 20 | class Quick3string 21 | { 22 | private: 23 | /* data */ 24 | int charAt(string& s,unsigned int i) const; 25 | void sort(vector& a, int lo, int hi, int p); 26 | public: 27 | Quick3string(vector& a); 28 | ~Quick3string(); 29 | }; 30 | 31 | int Quick3string::charAt(string& s, unsigned int i) const 32 | { 33 | if(i >= s.size()) 34 | return -1; 35 | else return static_cast(s[i]); 36 | } 37 | 38 | Quick3string::Quick3string(vector& a) 39 | { 40 | sort(a, 0, a.size() - 1, 0); 41 | } 42 | 43 | Quick3string::~Quick3string() 44 | { 45 | } 46 | 47 | void Quick3string::sort(vector& a, int lo, int hi, int p) 48 | { 49 | if(lo >= hi) 50 | return ; 51 | int lr = lo, 52 | ml = hi, 53 | i = lo + 1, 54 | v = charAt(a.at(lo), p); 55 | while(i <= ml) { 56 | int t = charAt(a.at(i), p); 57 | if(v < t) swap(a.at(i), a.at(ml--)); 58 | else if (v == t) ++i; 59 | else swap(a.at(i++), a.at(lr++)); 60 | } 61 | sort(a, lo, lr - 1, p); 62 | sort(a, ml + 1, hi, p); 63 | if(v >= 0) sort(a, lr, ml, p + 1); 64 | } -------------------------------------------------------------------------------- /chapter4/Digraph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-28 18:29:27 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-31 21:13:00 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | /** 16 | * 有向图 17 | **/ 18 | class Digraph 19 | { 20 | public: 21 | Digraph(int n); 22 | Digraph(string s); 23 | ~Digraph() { delete [] adjs;} 24 | void addEdge(int v, int w); 25 | int V() const {return v;} 26 | int E() const {return e;} 27 | Digraph reverse(); 28 | const list& adj(int v) {return adjs[v];} 29 | private: 30 | int v; 31 | int e; 32 | list* adjs; 33 | }; 34 | 35 | Digraph::Digraph(string s) 36 | : v(0), e(0), adjs(nullptr) 37 | { 38 | ifstream istrm(s, ios::binary); 39 | if(!istrm.is_open()) { 40 | abort(); 41 | } 42 | int a, b; 43 | istrm >> a; 44 | v = a; 45 | istrm >> b; 46 | adjs = new list [v](); 47 | while(istrm >> a >> b) { 48 | addEdge(a, b); 49 | } 50 | istrm.close(); 51 | } 52 | 53 | Digraph::Digraph(int n) 54 | :v(n), e(0), adjs(new list [n]) 55 | { 56 | } 57 | 58 | void Digraph::addEdge(int v, int w) 59 | { 60 | adjs[v].push_back(w); 61 | ++e; 62 | } 63 | 64 | Digraph Digraph::reverse() 65 | { 66 | Digraph d(v); 67 | for(int i = 0; i < v; ++i) 68 | for(auto w : adj(i)) 69 | { 70 | d.addEdge(w, i); 71 | } 72 | return d; 73 | } -------------------------------------------------------------------------------- /chapter4/Kosaraju.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-31 21:07:20 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-13 11:27:15 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "Digraph.hpp" 17 | #include "DepthFirstOrder.hpp" 18 | using namespace std; 19 | /** 20 | * Kosaraju算法 21 | **/ 22 | class Kosaraju 23 | { 24 | public: 25 | Kosaraju(Digraph& g); 26 | ~Kosaraju() {delete [] id; delete [] marked;} 27 | bool stronglyConnected(int v, int w) const {return id[v] == id[w];} 28 | private: 29 | void dfs(Digraph& g, int v); 30 | int count; 31 | bool *marked; 32 | int *id; 33 | }; 34 | 35 | Kosaraju:: 36 | Kosaraju(Digraph& g) : 37 | count(0), marked(new bool [g.V()]), id(new int [g.V()]) 38 | { 39 | for(int i = 0; i < g.V(); ++i) 40 | { 41 | marked[i] = false; 42 | id[i] = -1; 43 | } 44 | Digraph rg = g.reverse(); 45 | DepthFirstOrder roder(rg); 46 | stack stk = roder.getReversePost(); 47 | while(!stk.empty()) { 48 | int k = stk.top(); 49 | stk.pop(); 50 | if(!marked[k]) { 51 | dfs(g, k); 52 | count++; 53 | } 54 | } 55 | } 56 | 57 | void Kosaraju::dfs(Digraph& g, int v) 58 | { 59 | id[v] = count; 60 | marked[v] = true; 61 | for(auto w : g.adj(v)) { 62 | if(!marked[w]) { 63 | dfs(g, w); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /chapter4/DepthFirstPaths.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-25 19:14:34 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-25 20:27:27 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | /** 17 | * 深度优先搜索 18 | * 寻找路径 19 | **/ 20 | class DepthFirstPaths 21 | { 22 | public: 23 | DepthFirstPaths(Graph& g, int s); 24 | ~DepthFirstPaths() {delete [] edgeTo; delete [] marked;} 25 | bool hasPathTo(int v) const {return marked[v];}; 26 | vector pathTo(int v); 27 | private: 28 | void dfs(Graph& g, int v); 29 | int *edgeTo; 30 | bool *marked; 31 | int s; //起点 32 | }; 33 | 34 | DepthFirstPaths::DepthFirstPaths(Graph& g, int s) 35 | : edgeTo(nullptr), marked(nullptr), s(s) 36 | { 37 | edgeTo = new int [g.V()]; 38 | marked = new bool [g.V()] ; 39 | for(int i = 0;i < g.V(); ++i) { 40 | marked[i] = false; 41 | } 42 | dfs(g, s); 43 | } 44 | 45 | void DepthFirstPaths::dfs(Graph& g, int v) 46 | { 47 | marked[v] = true; 48 | for(auto x : g.adj(v)) { 49 | if(!marked[x]) { 50 | edgeTo[x] = v; 51 | dfs(g, x); 52 | } 53 | } 54 | } 55 | 56 | vector 57 | DepthFirstPaths::pathTo(int v) 58 | { 59 | vector vec; 60 | if(!marked[v]) return vec; 61 | vec.push_back(v); 62 | while(v != s) 63 | { 64 | v = edgeTo[v]; 65 | vec.push_back(v); 66 | 67 | } 68 | reverse(vec.begin(), vec.end()); 69 | return vec; 70 | } -------------------------------------------------------------------------------- /chapter5/MSD.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-13 13:22:27 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-13 14:55:33 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | /** 19 | * 高位优先的字符串排序 20 | **/ 21 | class MSD 22 | { 23 | private: 24 | int R; //标准ascii=128 25 | vector aux; 26 | 27 | int charAt(string& s,unsigned int i) const; 28 | void sort(vector& s, int lo, int hi, int pos); 29 | public: 30 | MSD(vector& s); 31 | ~MSD(); 32 | }; 33 | 34 | MSD::MSD(vector& s) 35 | :R(128), aux(s.size()) 36 | { 37 | sort(s, 0, s.size(), 0); 38 | } 39 | 40 | MSD::~MSD() 41 | { 42 | } 43 | 44 | int MSD::charAt(string& s, unsigned int i) const 45 | { 46 | if(i >= s.size()) 47 | return -1; 48 | else return static_cast(s[i]); 49 | } 50 | 51 | void MSD::sort(vector& s, int lo, int hi, int pos) 52 | { 53 | if(hi - lo <= 1) { 54 | // std::sort(s.begin() + lo, s.begin() + hi); 55 | return; 56 | } 57 | vector count(R + 2, 0); 58 | for(int i = lo; i < hi; ++i) 59 | count.at(charAt(s.at(i), pos) + 2)++; 60 | for(int i = 0; i < R + 1; ++i) 61 | count.at(i + 1) += count.at(i); 62 | for(int i = lo; i < hi; ++i) 63 | aux[count[charAt(s[i], pos) + 1]++] = s[i]; 64 | for(int i = lo; i < hi; ++i) 65 | s[i] = aux[i - lo]; 66 | 67 | for(int i = 1; i <= R; ++i) 68 | sort(s, lo + count[i], lo + count[i + 1], pos + 1); 69 | } -------------------------------------------------------------------------------- /chapter4/DirectedCycle.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-28 20:28:49 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-28 22:28:31 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "Digraph.hpp" 14 | #include 15 | #include 16 | using namespace std; 17 | /** 18 | * 寻找有向环 19 | **/ 20 | class DirectedCycle 21 | { 22 | public: 23 | DirectedCycle(Digraph& g); 24 | ~DirectedCycle(); 25 | vector > cycles; 26 | private: 27 | void dfs(Digraph& g, int v); 28 | bool *marked; 29 | int *edgeTo; 30 | bool *stackOn; 31 | }; 32 | 33 | DirectedCycle:: 34 | DirectedCycle(Digraph& g) 35 | : cycles(), marked(new bool [g.V()]), edgeTo(new int [g.V()]), stackOn(new bool [g.V()]) 36 | 37 | { 38 | for(int i = 0; i < g.V(); ++i) { 39 | marked[i] = false; 40 | stackOn[i] = false; 41 | } 42 | for(int i = 0; i < g.V(); ++i) 43 | if(!marked[i]) dfs(g, i); 44 | } 45 | 46 | void 47 | DirectedCycle::dfs(Digraph& g, int v) 48 | { 49 | stackOn[v] = true; 50 | marked[v] = true; 51 | for(auto x : g.adj(v)) { 52 | if(!marked[x]) { 53 | edgeTo[x] = v; 54 | dfs(g, x); 55 | } else if (stackOn[x]){ 56 | stack tk; 57 | for(int w = v ; w != x; w = edgeTo[w]) 58 | { 59 | tk.push(w); 60 | } 61 | tk.push(x); 62 | cycles.push_back(tk); 63 | } 64 | } 65 | stackOn[v] = false; 66 | } 67 | 68 | DirectedCycle:: 69 | ~DirectedCycle() 70 | { 71 | delete [] marked; 72 | delete [] edgeTo; 73 | delete [] stackOn; 74 | } -------------------------------------------------------------------------------- /chapter4/BreadthFirstPaths.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-27 13:46:34 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-27 16:47:33 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | using namespace std; 18 | /** 19 | * 广度优先搜索 20 | **/ 21 | class BreadthFirstPaths 22 | { 23 | public: 24 | BreadthFirstPaths(Graph& g, int s); 25 | bool hasPathTo(int v) const {return marked[v];} 26 | stack pathTo(int v); 27 | private: 28 | void bfs(Graph& g, int s); 29 | bool *marked; 30 | int *edgeTo; 31 | int s; 32 | }; 33 | 34 | BreadthFirstPaths:: 35 | BreadthFirstPaths(Graph& g, int s) 36 | :marked(nullptr), edgeTo(nullptr), s(s) 37 | { 38 | marked = new bool [g.V()](); 39 | edgeTo = new int [g.V()](); 40 | for(int i = 0; i < g.V(); ++i) { 41 | marked[i] = false; 42 | } 43 | bfs(g, s); 44 | } 45 | 46 | void 47 | BreadthFirstPaths::bfs(Graph& g, int s) 48 | { 49 | marked[s] = true; 50 | queue qu; 51 | qu.push(s); 52 | int i; 53 | while(!qu.empty()) 54 | { 55 | i = qu.front(); 56 | qu.pop(); 57 | for(auto x : g.adj(i)) 58 | { 59 | if(!marked[x]) { 60 | marked[x] = true; 61 | edgeTo[x] = i; 62 | qu.push(x); 63 | } 64 | } 65 | } 66 | } 67 | 68 | stack BreadthFirstPaths::pathTo(int v) 69 | { 70 | stack stk; 71 | if(!hasPathTo(v)) 72 | return stk; 73 | for( ; v != s ; v = edgeTo[v]) 74 | { 75 | stk.push(v); 76 | } 77 | stk.push(v); 78 | return stk; 79 | } -------------------------------------------------------------------------------- /chapter4/EdgeWeightDigraph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-12 10:15:02 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 11:02:29 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "Digraph.hpp" 14 | #include 15 | #include 16 | #include "DirectedEdge.hpp" 17 | using namespace std; 18 | /** 19 | * 加权有向图 20 | **/ 21 | class EdgeWeightDigraph 22 | { 23 | public: 24 | EdgeWeightDigraph(string name); 25 | ~EdgeWeightDigraph() {delete [] adjs;} 26 | void addEdge(DirectedEdge ); 27 | int E() const {return e;} 28 | int V() const {return v;} 29 | const vector & adj(int v) const{return adjs[v];} 30 | vector edges()const; 31 | private: 32 | int e; 33 | int v; 34 | vector* adjs; 35 | }; 36 | 37 | EdgeWeightDigraph:: 38 | EdgeWeightDigraph(string s) 39 | : e(0), v(0), adjs(nullptr) 40 | { 41 | ifstream in(s); 42 | if(!in.is_open()) { 43 | cout << "打开文件失败" << endl; 44 | abort(); 45 | } 46 | int a, b; 47 | double c; 48 | in >> a >> b; 49 | v = a; 50 | adjs = new vector [v](); 51 | // while (in >> a >> b >> c) 52 | // { 53 | // Edge e(a, b, c); 54 | // addEdge(e); 55 | // } 56 | do { 57 | in >> a >> b >> c; 58 | DirectedEdge e(a, b, c); 59 | addEdge(e); 60 | } while(!in.eof()); 61 | in.close(); 62 | } 63 | 64 | void EdgeWeightDigraph::addEdge(DirectedEdge e) 65 | { 66 | adjs[e.from()].push_back(e); 67 | this->e++; 68 | } 69 | 70 | vector EdgeWeightDigraph::edges() const 71 | { 72 | vector bags; 73 | for(int i = 0; i < V(); ++i) 74 | { 75 | for(auto e: adjs[i]) 76 | bags.push_back(e); 77 | } 78 | return bags; 79 | } -------------------------------------------------------------------------------- /chapter2/Quick.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "Insertion.hpp" 6 | using namespace std; 7 | /** 8 | * 快速排序 9 | **/ 10 | class Quick { 11 | public: 12 | static void sort(vector& a); 13 | private: 14 | static void sort(vector& a, int i, int j); 15 | static int partition(vector& a, int i, int j); 16 | }; 17 | 18 | void Quick::sort(vector& a) { 19 | sort(a, 0, a.size() - 1); 20 | } 21 | 22 | // void Quick::sort(vector& a, int i, int j) { 23 | // /** 24 | // * 原版 25 | // **/ 26 | // // if(i >= j) return ; 27 | // /** 28 | // * 改进1:小尺度选插入排序 29 | // **/ 30 | // if(i + 10 >= j) { 31 | // Insertion(a.begin() + i, a.begin() + j + 1); 32 | // return; 33 | // } 34 | // int mid = partition(a, i ,j); 35 | // sort(a, i, mid - 1); 36 | // sort(a, mid+1, j); 37 | // } 38 | 39 | void Quick::sort(vector& a, int i, int j) { 40 | if(i >= j) return ; 41 | int lt = i, gt = j, mid = lt + 1; 42 | while(gt >= mid) { 43 | if(a[mid] > a[lt]) swap(a[mid], a[gt--]); 44 | else if (a[mid] < a[lt]) swap(a[mid++], a[lt++]); 45 | else mid++; 46 | } 47 | sort(a, i, lt - 1); 48 | sort(a, gt + 1, j); 49 | } 50 | 51 | int Quick::partition(vector& a, int i, int j){ 52 | int lo = i, ho = j + 1; 53 | /** 54 | * 改进2:取中位数 55 | **/ 56 | int total = 0 57 | , n = 0; 58 | for(int k = i; k <= j; k += 3) { 59 | total += a[k]; 60 | ++n; 61 | } 62 | int tarl = total / n, 63 | tar = a[tarl]; 64 | /** 65 | * 原版 66 | **/ 67 | // int tarl = i, 68 | // tar = a[tarl]; 69 | while(lo <= ho) { 70 | while(a[--ho] >= tar) if(ho == i) break; 71 | while(a[++lo] <= tar) if(lo == j) break; 72 | if(lo >= ho) break; 73 | swap(a[lo], a[ho]); 74 | } 75 | swap(a[tarl], a[ho]); 76 | return ho; 77 | } -------------------------------------------------------------------------------- /chapter4/DijkstraSP.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-12 17:49:18 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 22:14:02 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "Edge.hpp" 15 | #include 16 | #include "EdgeWeightDigraph.hpp" 17 | #include "IndexMinPQ.hpp" 18 | using namespace std; 19 | /** 20 | * Dijkstra 21 | **/ 22 | 23 | class DijkstraSP 24 | { 25 | private: 26 | /* data */ 27 | vector edgeTo; 28 | vector distTo; 29 | IndexMinPQ pq; 30 | 31 | 32 | public: 33 | DijkstraSP(EdgeWeightDigraph& g, int v); 34 | ~DijkstraSP() {}; 35 | 36 | bool hasPathTo(int v) const {return distTo[v] < numeric_limits::max();} 37 | double DistTo(int v) const {return distTo[v];} 38 | vector pathTo(int v) const ; 39 | }; 40 | 41 | DijkstraSP::DijkstraSP(EdgeWeightDigraph& g, int v) 42 | :edgeTo(g.V()), distTo(g.V()), pq(g.V()) 43 | { 44 | for(auto& x: distTo) 45 | x = numeric_limits::max(); 46 | pq.insert(v, 0); 47 | distTo[v] = 0; 48 | while(pq.size()) 49 | { 50 | int from = pq.delMin(); 51 | for(auto e: g.adj(from)) { 52 | int to = e.to(); 53 | if(distTo[to] > distTo[from] + e.weight()) { 54 | distTo[to] = distTo[from] + e.weight(); 55 | edgeTo[to] = e; 56 | 57 | if(!pq.contain(to)) 58 | pq.insert(to, e.weight()); 59 | else 60 | pq.change(to, e.weight()); 61 | } 62 | } 63 | } 64 | } 65 | 66 | 67 | vector 68 | DijkstraSP::pathTo(int v) const 69 | { 70 | vector res; 71 | if(!hasPathTo(v)) 72 | return res; 73 | while(distTo[v]){ 74 | res.push_back(edgeTo[v]); 75 | v = edgeTo[v].from(); 76 | } 77 | reverse(res.begin(), res.end()); 78 | return res; 79 | } -------------------------------------------------------------------------------- /chapter4/EdgeWeightedGraph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-01 20:51:28 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 17:51:11 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "Edge.hpp" 15 | using namespace std; 16 | /** 17 | * 加权无向图 18 | **/ 19 | class EdgeWeightedGraph 20 | { 21 | public: 22 | EdgeWeightedGraph(int V); 23 | EdgeWeightedGraph(string s); 24 | int V() const {return _V;} 25 | int E() const {return _E;} 26 | const list >& adj(int v) const {return adjs[v];}; 27 | void addEdge(Edge e); 28 | list > edges() const; 29 | 30 | private: 31 | int _V; 32 | int _E; 33 | list>* adjs; 34 | }; 35 | 36 | EdgeWeightedGraph::EdgeWeightedGraph(int V) 37 | : _V(V), _E(0), adjs(nullptr) 38 | { 39 | adjs = new list >[_V] (); 40 | } 41 | 42 | EdgeWeightedGraph::EdgeWeightedGraph(string s) 43 | : _V(0), _E(0), adjs(nullptr) 44 | { 45 | ifstream in(s); 46 | if(!in.is_open()) { 47 | cout << "打开文件失败" << endl; 48 | abort(); 49 | } 50 | int a, b; 51 | double c; 52 | in >> a >> b; 53 | _V = a; 54 | adjs = new list >[_V] (); 55 | // while (in >> a >> b >> c) 56 | // { 57 | // Edge e(a, b, c); 58 | // addEdge(e); 59 | // } 60 | do { 61 | in >> a >> b >> c; 62 | Edge e(a, b, c); 63 | addEdge(e); 64 | } while(!in.eof()); 65 | in.close(); 66 | } 67 | 68 | void EdgeWeightedGraph::addEdge(Edge e) 69 | { 70 | int v = e.either(), w = e.other(v); 71 | adjs[v].push_back(e); 72 | adjs[w].push_back(e); 73 | ++_E; 74 | } 75 | 76 | list > EdgeWeightedGraph::edges() const 77 | { 78 | list> le; 79 | for(int j = 0; j < _V; ++j) 80 | for(auto ej : adjs[j]) 81 | if(ej.other(j) > j) le.push_back(ej); 82 | return le; 83 | } -------------------------------------------------------------------------------- /chapter4/LazyPrimMST.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-04 21:51:40 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-10 22:00:26 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "EdgeWeightedGraph.hpp" 17 | using namespace std; 18 | /** 19 | * 最小生成树的Prim算法的延时实现 20 | **/ 21 | struct greater_ { 22 | bool operator() (const Edge& a, const Edge& b){ 23 | int cmp = a.compareTo(b); 24 | if(cmp > 0) 25 | return true; 26 | return false; 27 | } 28 | }; 29 | 30 | class LazyPrimMST 31 | { 32 | public: 33 | using Eg = Edge; 34 | LazyPrimMST(EdgeWeightedGraph& g); 35 | queue edges() const {return mst;}; 36 | double weight() const; 37 | private: 38 | void visit(EdgeWeightedGraph& g, int v); 39 | priority_queue,greater_> pq; 40 | queue mst; 41 | bool *marked; 42 | }; 43 | 44 | double LazyPrimMST::weight() const 45 | { 46 | double tl = 0; 47 | queue mst_copy = mst; 48 | while(mst_copy.size()) 49 | { 50 | Eg e = mst_copy.front(); 51 | mst_copy.pop(); 52 | tl += e.weight(); 53 | } 54 | return tl; 55 | } 56 | 57 | LazyPrimMST:: 58 | LazyPrimMST(EdgeWeightedGraph& g) 59 | : pq(), mst(), marked(new bool [g.V()]) 60 | { 61 | for(int i = 0; i < g.V(); ++i) 62 | marked[i] = false; 63 | visit(g, 0); 64 | while(!pq.empty()) 65 | { 66 | Eg e = pq.top(); 67 | pq.pop(); 68 | 69 | int v = e.either(), w = e.other(v); 70 | if(marked[v] && marked[w]) { 71 | continue; 72 | } 73 | mst.push(e); 74 | if(marked[v]) { 75 | visit(g, w); 76 | } else { 77 | visit(g ,v); 78 | } 79 | } 80 | } 81 | 82 | void LazyPrimMST::visit(EdgeWeightedGraph& g, int v) 83 | { 84 | marked[v] = true; 85 | for(auto x : g.adj(v)) 86 | { 87 | if(!marked[x.other(v)]){ 88 | pq.push(x); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /chapter4/BellmanFord.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-12 22:14:00 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 22:29:00 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "Edge.hpp" 15 | #include 16 | #include 17 | #include "EdgeWeightDigraph.hpp" 18 | #include "IndexMinPQ.hpp" 19 | using namespace std; 20 | /** 21 | * BellmanFord 22 | **/ 23 | 24 | class BellmanFord 25 | { 26 | private: 27 | /* data */ 28 | vector distTo; 29 | vector edgeTo; 30 | queue q; 31 | vector onQ; 32 | public: 33 | BellmanFord(EdgeWeightDigraph& g, int v); 34 | ~BellmanFord(); 35 | bool hasPathTo(int v) const {return distTo[v] < numeric_limits::max();} 36 | double DistTo(int v) const {return distTo[v];} 37 | vector pathTo(int v) const ; 38 | }; 39 | 40 | BellmanFord::BellmanFord(EdgeWeightDigraph& g, int v) : 41 | distTo(g.V()), edgeTo(g.V()), q(), onQ(g.V()) 42 | { 43 | for(int i = 0; i < g.V(); ++i) { 44 | onQ[i] = false; 45 | distTo[i] = numeric_limits::max(); 46 | } 47 | distTo[v] = 0; 48 | q.push(v); 49 | onQ[v] = true; 50 | while(q.size()) 51 | { 52 | int w = q.front(); 53 | q.pop(); 54 | onQ[w] = false; 55 | for(auto e: g.adj(w)){ 56 | int ww = e.to(); 57 | if(distTo[ww] > distTo[w] + e.weight()) 58 | { 59 | distTo[ww] = distTo[w] + e.weight(); 60 | edgeTo[ww] = e; 61 | if(!onQ[ww]) { 62 | q.push(ww); 63 | onQ[ww] =true; 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | BellmanFord::~BellmanFord() 71 | { 72 | } 73 | 74 | vector 75 | BellmanFord::pathTo(int v) const 76 | { 77 | vector res; 78 | if(!hasPathTo(v)) 79 | return res; 80 | while(distTo[v]){ 81 | res.push_back(edgeTo[v]); 82 | v = edgeTo[v].from(); 83 | } 84 | reverse(res.begin(), res.end()); 85 | return res; 86 | } -------------------------------------------------------------------------------- /chapter2/OrderArrayMaxPQ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Common.hpp" 6 | using namespace std; 7 | 8 | /** 9 | * 优先队列 10 | * 2.4.3 有序数组实现 11 | * 这里pair的int值代表的是T这个值的权重 12 | **/ 13 | template 14 | class OrderArrayMaxPQ { 15 | private: 16 | pair* arr; 17 | int N; 18 | int _capacity; 19 | public: 20 | void show() const ; 21 | explicit OrderArrayMaxPQ(int max); 22 | ~OrderArrayMaxPQ() {delete [] arr;} 23 | // explicit OrderArrayMaxPQ(std::initializer_list>); 24 | void insert(pair); 25 | pair delMax(); 26 | bool isEmpty() const { return N == 0;} 27 | int size() const {return N;} 28 | int capacity() const {return _capacity;} 29 | }; 30 | 31 | template 32 | OrderArrayMaxPQ::OrderArrayMaxPQ(int max) : 33 | arr(new pair[max]()), N(0), _capacity(max) 34 | { 35 | } 36 | 37 | // template 38 | // OrderArrayMaxPQ::OrderArrayMaxPQ(std::initializer_list> l) 39 | // : arr(new pair[l.size()]()), N(l.size()), _capacity(l.size()) 40 | // { 41 | // copy(l.begin(), l.end(), arr); 42 | // } 43 | 44 | template 45 | void OrderArrayMaxPQ::insert(pair x) { 46 | if(capacity() == size()) 47 | return ; 48 | arr[N++] = x; 49 | for(int i = N - 1; i > 0 && arr[i] < arr[i - 1]; --i) 50 | swap(arr[i], arr[i - 1]); 51 | } 52 | 53 | template 54 | pair OrderArrayMaxPQ::delMax() { 55 | pair res; 56 | if(isEmpty()) 57 | return res; 58 | res = arr[N - 1]; 59 | arr[--N] = pair(); 60 | return res; 61 | } 62 | 63 | template 64 | void OrderArrayMaxPQ::show() const { 65 | cout << "N: " << size() << " arr: "; 66 | for(int i = 0; i < N; ++i) 67 | cout << arr[i].first << " "; 68 | cout << endl; 69 | } 70 | 71 | int main(int argc, char** argv) { 72 | OrderArrayMaxPQ pq(20); 73 | vector v = Common::getInstance()->getRandomVector(12); 74 | for(auto x: v) { 75 | pq.insert({x, x}); 76 | } 77 | while(pq.size()) { 78 | pq.show(); 79 | pq.delMax(); 80 | } 81 | } -------------------------------------------------------------------------------- /chapter3/SequentialSearchST.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | /** 10 | * 链表实现 11 | **/ 12 | 13 | template 14 | class SequentialSearchST { 15 | public: 16 | struct Node { 17 | Node(const S& key, const T& val, shared_ptr next = nullptr) 18 | :key(key), val(val), next(next) {} 19 | 20 | const S key; 21 | T val; 22 | shared_ptr next; 23 | }; 24 | 25 | void show() const; 26 | void put(S key, T val); 27 | const T get(const S& key) const; 28 | bool contain(const S& key) const; 29 | const vector keys() const; 30 | private: 31 | shared_ptr head; 32 | }; 33 | 34 | template 35 | const T SequentialSearchST::get(const S& key) const { 36 | shared_ptr sk(head); 37 | while(sk && sk->key != key) { 38 | sk = sk->next; 39 | } 40 | if(!sk) 41 | return T(); 42 | return sk->val; 43 | } 44 | 45 | template 46 | void SequentialSearchST::put(S key, T val) { 47 | shared_ptr sk(head); 48 | while(sk && sk->key != key) { 49 | sk = sk->next; 50 | } 51 | if(sk) 52 | sk->val = val; 53 | else { 54 | shared_ptr newOne(make_shared(key, val, head)); 55 | head = newOne; 56 | } 57 | } 58 | 59 | template 60 | void SequentialSearchST::show() const { 61 | shared_ptr sk(head); 62 | while(sk) { 63 | cout << sk->key << " " << sk->val << endl; 64 | sk = sk->next; 65 | } 66 | } 67 | 68 | template 69 | bool SequentialSearchST::contain(const S& key) const { 70 | shared_ptr sk(head); 71 | while(sk && sk->key != key) { 72 | sk = sk->next; 73 | } 74 | if(!sk) 75 | return false; 76 | return true; 77 | } 78 | 79 | template 80 | const vector SequentialSearchST::keys() const { 81 | vector res; 82 | shared_ptr sk(head); 83 | while(sk) { 84 | res.push_back(sk->key); 85 | sk = sk->next; 86 | } 87 | return res; 88 | } -------------------------------------------------------------------------------- /chapter2/UnOrderArrayMaxPQ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Common.hpp" 6 | using namespace std; 7 | 8 | /** 9 | * 优先队列 10 | * 2.4.3 无序数组实现 11 | **/ 12 | template 13 | class UnOrderArrayMaxPQ { 14 | private: 15 | pair* arr; 16 | int N; 17 | int _capacity; 18 | public: 19 | void show() const ; 20 | explicit UnOrderArrayMaxPQ(int max); 21 | ~UnOrderArrayMaxPQ() {delete [] arr;} 22 | explicit UnOrderArrayMaxPQ(std::initializer_list>); 23 | void insert(pair); 24 | pair delMax(); 25 | bool isEmpty() const { return N == 0;} 26 | int size() const {return N;} 27 | int capacity() const {return _capacity;} 28 | }; 29 | 30 | template 31 | UnOrderArrayMaxPQ::UnOrderArrayMaxPQ(int max) : 32 | arr(new pair[max]()), N(0), _capacity(max) 33 | { 34 | } 35 | 36 | template 37 | UnOrderArrayMaxPQ::UnOrderArrayMaxPQ(std::initializer_list> l) 38 | : arr(new pair[l.size()]()), N(l.size()), _capacity(l.size()) 39 | { 40 | copy(l.begin(), l.end(), arr); 41 | } 42 | 43 | template 44 | void UnOrderArrayMaxPQ::insert(pair x) { 45 | if(capacity() == size()) 46 | return ; 47 | arr[N++] = x; 48 | } 49 | 50 | template 51 | pair UnOrderArrayMaxPQ::delMax() { 52 | if(isEmpty()) 53 | return pair(); 54 | int max_one = 0; 55 | for(int i = 0; i < N; ++i) 56 | if(arr[max_one].first < arr[i].first) { 57 | max_one = i; 58 | } 59 | swap(arr[max_one], arr[--N]); 60 | pair res = arr[N]; 61 | arr[N] = pair(); 62 | return res; 63 | } 64 | 65 | template 66 | void UnOrderArrayMaxPQ::show() const { 67 | cout << "N: " << size() << " arr: "; 68 | for(int i = 0; i < N; ++i) 69 | cout << arr[i].first << " "; 70 | cout << endl; 71 | } 72 | 73 | int main(int argc, char** argv) { 74 | UnOrderArrayMaxPQ pq(20); 75 | vector v = Common::getInstance()->getRandomVector(12); 76 | for(auto x: v) { 77 | pq.insert({x, x}); 78 | } 79 | while(pq.size()) { 80 | pq.show(); 81 | pq.delMax(); 82 | } 83 | } -------------------------------------------------------------------------------- /chapter4/PrimMST.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-10 17:09:57 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-10 23:44:40 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "EdgeWeightedGraph.hpp" 18 | #include "IndexMinPQ.hpp" 19 | using namespace std; 20 | /** 21 | * Prim算法即时实现 22 | **/ 23 | 24 | class PrimMST 25 | { 26 | public: 27 | PrimMST(EdgeWeightedGraph &g); 28 | ~PrimMST() {delete [] marked; delete [] distTo;} 29 | double weight() const; 30 | const vector >& edges() const {return egs;} 31 | void visit(EdgeWeightedGraph& g, int v); 32 | private: 33 | IndexMinPQ pq; 34 | double *distTo; 35 | bool *marked; 36 | vector >egs; 37 | }; 38 | 39 | PrimMST:: 40 | PrimMST(EdgeWeightedGraph &g) : 41 | pq(g.V()), distTo(new double[g.V()]), marked(new bool [g.V()]), egs(g.V(), Edge(0,0,0)) 42 | { 43 | for(int i = 0; i < g.V(); ++i) 44 | { 45 | distTo[i] = std::numeric_limits::max(); 46 | marked[i] = false; 47 | } 48 | distTo[0] = 0; 49 | pq.insert(0, 0); 50 | while(pq.size()){ 51 | // pq.show(); 52 | visit(g, pq.delMin()); 53 | } 54 | } 55 | 56 | void PrimMST::visit(EdgeWeightedGraph& g, int v) 57 | { 58 | // cout << v << ": " << endl; 59 | 60 | marked[v] = true; 61 | for(auto edg : g.adj(v)) 62 | { 63 | int w = edg.other(v); 64 | 65 | if(marked[w]) continue; 66 | if(edg.weight() < distTo[w]){ 67 | distTo[w] = edg.weight(); 68 | egs[w] = edg; 69 | // cout << v << "-" << w << " "<< edg.weight() << endl; 70 | if(pq.contain(w)) 71 | pq.change(w, distTo[w]); 72 | else 73 | pq.insert(w, distTo[w]); 74 | } 75 | } 76 | // for(int i = 0; i < g.V(); ++i) 77 | // cout << egs[i].either() << "-" << egs[i].other(egs[i].either()) << " "< 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * avl树单元测试 17 | **/ 18 | 19 | TEST_CASE("put", "[avl]") { 20 | AvlTree tri; 21 | tri.put('M','M'); 22 | REQUIRE(tri.get('M')->height == 1); 23 | tri.put('N','N'); 24 | REQUIRE(tri.get('M')->height == 2); 25 | tri.put('O','O'); 26 | auto N = tri.get('N'); 27 | REQUIRE(N->height == 2); 28 | REQUIRE(N->left->height == 1); 29 | REQUIRE(N->right->height == 1); 30 | tri.put('L','L'); 31 | tri.put('K','K'); 32 | REQUIRE(N->height == 3); 33 | REQUIRE(N->left->height == 2); 34 | REQUIRE(N->right->height == 1); 35 | tri.put('Q','Q'); 36 | REQUIRE(N->height == 3); 37 | REQUIRE(N->left->height == 2); 38 | REQUIRE(N->right->height == 2); 39 | tri.put('P','P'); 40 | REQUIRE(N->height == 3); 41 | REQUIRE(N->left->height == 2); 42 | REQUIRE(N->right->height == 2); 43 | tri.put('H','H'); 44 | REQUIRE(N->height == 4); 45 | REQUIRE(N->left->height == 3); 46 | REQUIRE(N->right->height == 2); 47 | tri.put('I','I'); 48 | REQUIRE(N->height == 4); 49 | REQUIRE(N->left->height == 3); 50 | REQUIRE(N->right->height == 2); 51 | tri.put('A','A'); 52 | REQUIRE(N->height == 4); 53 | REQUIRE(N->left->height == 3); 54 | REQUIRE(N->right->height == 2); 55 | REQUIRE(tri.isBalanced() == true); 56 | 57 | SECTION("deleteMin") { 58 | tri.deleteMin(); 59 | REQUIRE(tri.isBalanced() == true); 60 | tri.deleteMin(); 61 | REQUIRE(tri.isBalanced() == true); 62 | tri.deleteMin(); 63 | REQUIRE(tri.isBalanced() == true); 64 | tri.deleteMin(); 65 | REQUIRE(tri.isBalanced() == true); 66 | tri.deleteMin(); 67 | REQUIRE(tri.isBalanced() == true); 68 | tri.deleteMin(); 69 | REQUIRE(tri.isBalanced() == true); 70 | } 71 | 72 | SECTION("delet") { 73 | tri.delet('A'); 74 | REQUIRE(tri.isBalanced() == true); 75 | } 76 | 77 | SECTION("delet1") { 78 | tri.delet('I'); 79 | REQUIRE(tri.isBalanced() == true); 80 | } 81 | } -------------------------------------------------------------------------------- /chapter2/MaxPQ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Common.hpp" 6 | #include 7 | using namespace std; 8 | 9 | /** 10 | * 优先队列 11 | * 二叉堆实现 12 | **/ 13 | template 14 | class MaxPQ { 15 | private: 16 | pair* arr; 17 | int N; 18 | int _capacity; 19 | void swim(int i); 20 | void sink(int i); 21 | public: 22 | void show() const ; 23 | explicit MaxPQ(int max); 24 | ~MaxPQ() {delete [] arr;} 25 | void insert(pair); 26 | pair delMax(); 27 | bool isEmpty() const { return N == 0;} 28 | int size() const {return N;} 29 | int capacity() const {return _capacity;} 30 | }; 31 | 32 | template 33 | MaxPQ::MaxPQ(int max) : 34 | arr(new pair[max + 1]()), N(0), _capacity(max + 1) 35 | { 36 | arr[0] = pair(INT8_MIN, T()); 37 | } 38 | 39 | template 40 | void MaxPQ::insert(pair x) { 41 | if(capacity() == size()) 42 | return ; 43 | arr[++N] = x; 44 | swim(N); 45 | } 46 | 47 | template 48 | pair MaxPQ::delMax() { 49 | pair res; 50 | if(isEmpty()) 51 | return res; 52 | swap(arr[N--], arr[1]); 53 | res = arr[N + 1]; 54 | arr[N + 1] = pair(); 55 | sink(1); 56 | return res; 57 | } 58 | 59 | template 60 | void MaxPQ::show() const { 61 | cout << "N: " << size() << " arr: "; 62 | for(int i = 1; i <= N; ++i) 63 | cout << arr[i].first << " "; 64 | cout << endl; 65 | } 66 | 67 | template 68 | void MaxPQ::swim(int i) { 69 | while(i > 1) { 70 | if(arr[i].first > arr[i / 2].first) swap(arr[i], arr[i / 2]); 71 | i /= 2; 72 | } 73 | } 74 | 75 | template 76 | void MaxPQ::sink(int i) { 77 | int k; 78 | while(i < N) { 79 | k = 2 * i; 80 | if(arr[k].first < arr[k + 1].first) ++k; 81 | if(arr[k].first <= arr[i].first) break; 82 | swap(arr[k], arr[i]); 83 | i = k; 84 | } 85 | } 86 | 87 | int main(int argc, char** argv) { 88 | MaxPQ pq(20); 89 | vector v = Common::getInstance()->getRandomVector(12); 90 | for(auto x: v) { 91 | pq.insert({x, x}); 92 | // pq.show(); 93 | } 94 | while(pq.size()) { 95 | pq.show(); 96 | pq.delMax(); 97 | } 98 | } -------------------------------------------------------------------------------- /chapter5/test1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-13 10:30:43 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-14 21:17:39 6 | */ 7 | #define CATCH_CONFIG_MAIN 8 | #include "catch.hpp" 9 | #include "Common.hpp" 10 | #include "LSD.hpp" 11 | #include "MSD.hpp" 12 | #include "Quick3string.hpp" 13 | #include "TrieST.hpp" 14 | #include "Kmp.hpp" 15 | #include "BLsearch.hpp" 16 | #include "BoyerMoore.hpp" 17 | using namespace std; 18 | 19 | /** 20 | * 测试 21 | **/ 22 | 23 | TEST_CASE("5.1") 24 | { 25 | vector strs = { 26 | "4PGC938", "2IYE230", "3CI0720", "1ICK750", "1OHV845", "4JZY524", "1ICK750", 27 | "3CIO720", "1OHV845", "1OHV845", "2RLA629", "2RLA629", "3ATW723" 28 | }; 29 | LSD lsd(strs, 7); 30 | REQUIRE(strs[0] == "1ICK750"); 31 | REQUIRE(strs[1] == "1ICK750"); 32 | REQUIRE(strs[2] == "1OHV845"); 33 | REQUIRE(strs[3] == "1OHV845"); 34 | REQUIRE(strs[4] == "1OHV845"); 35 | REQUIRE(strs[5] == "2IYE230"); 36 | REQUIRE(strs[strs.size() - 1] == "4PGC938"); 37 | vector strs2 = { 38 | "she", "sells", "seashells", "by", "the", "seashore", "the", "shells", 39 | "she", "sells", "are", "surely", "seashells" 40 | }; 41 | SECTION("msd") { 42 | MSD msd(strs2); 43 | REQUIRE(strs2[0] == "are"); 44 | REQUIRE(strs2[1] == "by"); 45 | REQUIRE(strs2[2] == "seashells"); 46 | } 47 | SECTION("q3s") { 48 | Quick3string msd(strs2); 49 | REQUIRE(strs2[0] == "are"); 50 | REQUIRE(strs2[1] == "by"); 51 | REQUIRE(strs2[2] == "seashells"); 52 | } 53 | } 54 | 55 | TEST_CASE("5.2"){ 56 | vector strs2 = { 57 | "she", "sells", "seashells", "by", "the", "seashore", "sea" 58 | }; 59 | TrieST trie; 60 | for(unsigned x = 0; x < strs2.size(); ++x) 61 | trie.put(strs2.at(x), x + 1); 62 | REQUIRE(trie.get("she") == 1); 63 | REQUIRE(trie.get("the") == 5); 64 | REQUIRE(trie.keys().size() == 7); 65 | REQUIRE(trie.keysThatMatch("the").size() == 1); 66 | REQUIRE(trie.keysThatMatch("seash...").size() == 1); 67 | REQUIRE(trie.longestPrefixOf("seashels") == "sea"); 68 | trie.delet("sea"); 69 | REQUIRE(trie.keys().size() == 6); 70 | REQUIRE(trie.get("sea") == 0); 71 | } 72 | 73 | TEST_CASE("5.3"){ 74 | REQUIRE(BLsearch::search("AAAAE","AAAAAAAAAE") == 5); 75 | Kmp kmp("ABABAC"); 76 | REQUIRE(kmp.search("BCBAABACAABABACAA") == 9); 77 | BoyerMoore bym("ABABAC"); 78 | REQUIRE(bym.search("BCBAABACAABABACAA") == 9); 79 | } -------------------------------------------------------------------------------- /chapter3/BinarySearchST.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | /** 11 | * 数组实现 12 | **/ 13 | template 14 | class BinarySearchST { 15 | public: 16 | BinarySearchST(int size = 10000); 17 | ~BinarySearchST(); 18 | void put(const S&, const T&); 19 | const T get(const S&); 20 | bool contain(const S& key) const; 21 | const vector keys() const; 22 | void show() const; 23 | private: 24 | const int rank(const S&) const; 25 | S* _keys; 26 | T* vals; 27 | int _capacity; 28 | int n; 29 | }; 30 | 31 | template 32 | BinarySearchST::BinarySearchST(int size) 33 | : _keys(new S[size]), 34 | vals(new T[size]), 35 | _capacity(size), 36 | n(0) 37 | { 38 | } 39 | 40 | template 41 | BinarySearchST::~BinarySearchST(){ 42 | delete []_keys; 43 | delete []vals; 44 | } 45 | 46 | template 47 | const int BinarySearchST::rank(const S& key) const{ 48 | if(n == 0) 49 | return 0; 50 | int lo = 0, 51 | hi = n - 1, 52 | mid; 53 | while(lo < hi) { 54 | mid = lo + (hi - lo) / 2; 55 | if(_keys[mid] < key) 56 | lo = mid + 1; 57 | else 58 | hi = mid; 59 | } 60 | if(_keys[lo] < key) 61 | return lo + 1; 62 | else 63 | return lo; 64 | } 65 | 66 | template 67 | void BinarySearchST::put(const S& key, const T& val) 68 | { 69 | int pos = rank(key); 70 | if(pos < n && _keys[pos] == key) { 71 | vals[pos] = val; 72 | return ; 73 | } 74 | //暂时不考虑超出容量的情况 75 | for(int i = n; i > pos; --i) { 76 | _keys[i] = _keys[i - 1]; 77 | vals[i] = vals[i - 1]; 78 | } 79 | _keys[pos] = key; 80 | vals[pos] = val; 81 | ++n; 82 | } 83 | 84 | template 85 | const T BinarySearchST::get(const S& key) { 86 | int pos = rank(key); 87 | if(pos < n && _keys[pos] == key) { 88 | return vals[pos]; 89 | } 90 | return T(); 91 | } 92 | 93 | template 94 | bool BinarySearchST::contain(const S& key) const { 95 | if(!n) 96 | return false; 97 | int pos = rank(key); 98 | return _keys[pos] == key; 99 | } 100 | 101 | template 102 | const vector BinarySearchST::keys() const { 103 | return vector(_keys, _keys + n); 104 | } 105 | 106 | template 107 | void BinarySearchST::show() const { 108 | for(int i = 0; i < n; ++i) { 109 | cout << _keys[i] << " " << vals[i] << endl; 110 | } 111 | } -------------------------------------------------------------------------------- /chapter3/test.cpp: -------------------------------------------------------------------------------- 1 | #include "BinarySearchST.hpp" 2 | #include "SequentialSearchST.hpp" 3 | #include "BST.hpp" 4 | #include "RedBlackBST.hpp" 5 | #include 6 | #include 7 | 8 | 9 | int main(int argc, char** argv) { 10 | /** 11 | * 通用测试 12 | * 输入一个数字统计长度 13 | * 大于等于这个数字的字符串 14 | **/ 15 | // if(argc != 2) { 16 | // cout << "输入统计字符串的最小长度" << endl; 17 | // return 0; 18 | // } 19 | // size_t minLen = atoi(argv[1]); 20 | // if(minLen <= 0) { 21 | // cout << "长度必须为正数" << endl; 22 | // return 0; 23 | // } 24 | // ifstream in("tale.txt"); 25 | // if(!in.is_open()) { 26 | // cout << "打开文件失败" << endl; 27 | // return 0; 28 | // } 29 | // istream_iterator inIter(in), end; 30 | // string str; 31 | 32 | // BST st; 33 | // while(inIter != end) { 34 | // str.assign(*inIter); 35 | // if(str.size() >= minLen) { 36 | // if(!st.contain(str)) st.put(str, 1); 37 | // else st.put(str, st.get(str) + 1); 38 | // } 39 | // ++inIter; 40 | // } 41 | // in.close(); 42 | // st.show(); 43 | 44 | // /** 45 | // * 统计出现次数最多的 46 | // **/ 47 | // int max = 0, time; 48 | // string theKey = ""; 49 | // for(auto x : st.keys()) { 50 | // time = st.get(x); 51 | // if(time > max) { 52 | // theKey = x; 53 | // max = time; 54 | // } 55 | // } 56 | // cout << "max: " << theKey << " " << max << endl; 57 | 58 | /** 59 | * 二叉查找树测试 60 | **/ 61 | // BST st; 62 | // vector vec({12,343,123,123,444,21,142,64,223,676}); //= Common::getInstance()->getRandomVector(10); 63 | // for(auto x : vec) 64 | // st.put(x,x); 65 | // st.show(); 66 | // cout << "max, min: " << st.max() << " " << st.min() << endl; 67 | // cout << "floor, ceiling: " << st.floor(60) << " " << st.ceiling(60) << endl; 68 | // cout << "select: " << st.select(0) << " " << st.select(3) << " " << st.select(5) << " " << st.select(9) << endl; 69 | // cout << "rank: " << st.rank(56) << " " << st.rank(57) << " " << st.rank(58) << endl; 70 | // // for(int i = 10; i > 1; --i) { 71 | // // cout << endl; 72 | // // st.deleteMin(); 73 | // // st.show(); 74 | // // cout << endl; 75 | // // } 76 | // st.delet(343); 77 | // st.show(); 78 | 79 | /** 80 | * 测试红黑树 81 | **/ 82 | vector test1{'S','E','A','R','C','H','X','M','P','L'}; 83 | vector test2{'A','C','E','H','L','M','P','R','S','X'}; 84 | RedBlackBST st1,st2; 85 | for(size_t i = 0; i < test1.size(); ++i) { 86 | st1.put(test1[i], test1[i]); 87 | st2.put(test2[i], test2[i]); 88 | } 89 | st1.show(); 90 | // cout << endl; 91 | // st2.show(); 92 | for(size_t i = 0; i < test2.size(); ++i){ 93 | cout << endl; 94 | // st1.deleteMin(); 95 | st1.deleteMax(); 96 | st1.show(); 97 | } 98 | return 1; 99 | } -------------------------------------------------------------------------------- /chapter3/LinearProbingHashST.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Common.hpp" 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | /** 10 | * 线性探测法的散列表 11 | **/ 12 | 13 | template 14 | class LinearProbingHashST{ 15 | public: 16 | LinearProbingHashST(int M); 17 | int size() const {return N;} 18 | void put(int key, Value val); 19 | Value get(int key); 20 | void delet(int key); 21 | bool contain(int key) const; 22 | private: 23 | int M; //长度 24 | int N; //键值对数量 25 | int* keys; 26 | Value* vals; 27 | 28 | void resize(int sz); 29 | int hash(int key) const; 30 | }; 31 | 32 | template 33 | int LinearProbingHashST::hash(int key) const 34 | { 35 | return (key & 0x7fffffff) % M; 36 | } 37 | 38 | template 39 | LinearProbingHashST::LinearProbingHashST(int M) 40 | :M(M), N(0) 41 | { 42 | keys = new int [M](); 43 | vals = new Value [M](); 44 | for(int i = 0; i < M; ++i) 45 | keys[i] = -1; 46 | } 47 | 48 | template 49 | void 50 | LinearProbingHashST::put(int key, Value val) 51 | { 52 | if(N > M / 2) { 53 | resize(2 * M); 54 | } 55 | int i; 56 | for(i = hash(key); keys[i] != -1; i = (i + 1) % M) { 57 | if(keys[i] == key) 58 | { 59 | vals[i] = val; 60 | return ; 61 | } 62 | } 63 | keys[i] = key; 64 | vals[i] = val; 65 | N++; 66 | } 67 | 68 | template 69 | void 70 | LinearProbingHashST::resize(int sz) 71 | { 72 | int * keys1 = keys; 73 | Value* vals1 = vals; 74 | int M1 = M; 75 | keys = new int [sz](); 76 | vals = new Value [sz] (); 77 | for(int i = 0; i < sz; ++i) { 78 | keys[i] = -1; 79 | } 80 | N = 0; 81 | M = sz; 82 | for(int i = 0; i < M1; ++i) { 83 | if(keys1[i] != -1) { 84 | put(keys1[i], vals1[i]); 85 | } 86 | } 87 | delete [] keys1; 88 | delete [] vals1; 89 | } 90 | 91 | template 92 | Value 93 | LinearProbingHashST::get(int key) 94 | { 95 | int i = hash(key); 96 | for(; keys[i] != -1; i = (i + 1) % M) { 97 | if(keys[i] == key) { 98 | return vals[i]; 99 | } 100 | } 101 | return Value(); 102 | } 103 | 104 | template 105 | void 106 | LinearProbingHashST::delet(int key) 107 | { 108 | if(!contain(key)) 109 | return ; 110 | int i = hash(key); 111 | for(; keys[i] != -1; i = (i + 1) % M) 112 | if(keys[i] == key) 113 | break; 114 | keys[i] = -1; 115 | vals[i] = Value(); 116 | i = (i + 1) % M; 117 | int k; 118 | Value v; 119 | while(keys[i] != -1) { 120 | k = keys[i]; 121 | v = vals[i]; 122 | N--; 123 | keys[i] = -1; 124 | vals[i] = Value(); 125 | put(k, v); 126 | i = (i + 1) % M; 127 | } 128 | N--; 129 | if(N > 0 && N == M/8) 130 | resize(M / 2); 131 | } 132 | 133 | template 134 | bool 135 | LinearProbingHashST::contain(int key) const 136 | { 137 | int i = hash(key); 138 | for(; keys[i] != -1; i = (i + 1) % M) { 139 | if(keys[i] == key) 140 | return true; 141 | } 142 | return false; 143 | } -------------------------------------------------------------------------------- /chapter2/IndexMinPQ.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Common.hpp" 7 | #include 8 | using namespace std; 9 | 10 | /** 11 | * 索引最小优先队列 12 | **/ 13 | template 14 | class IndexMinPQ { 15 | public: 16 | IndexMinPQ(int max); 17 | void show() const; 18 | int size() const {return N;} 19 | int capacity() const {return _capacity;} 20 | void insert(int k, T item); 21 | void change(int k, T item); 22 | bool contain(int k) const {return qp[k] != -1;}; 23 | int delMin(); 24 | private: 25 | void sink(int i); 26 | void swim(int i); 27 | T* element; //元素 28 | int* pq; //二叉堆 29 | int *qp; //index 30 | int N; 31 | int _capacity; 32 | }; 33 | 34 | template 35 | IndexMinPQ::IndexMinPQ(int max) : 36 | element(new T[max + 1]), pq(new int[max + 1]) 37 | , qp(new int[max + 1]), N(0), _capacity(max) 38 | { 39 | for(int i = 0; i < max + 1; ++i) 40 | qp[i] = -1; 41 | } 42 | 43 | template 44 | void IndexMinPQ::sink(int n){ 45 | while(2 * n <= N) { 46 | int m = n * 2; 47 | if(m + 1 <= N && element[pq[m]] > element[pq[m + 1]]) ++m; 48 | if(element[pq[m]] >= element[pq[n]]) break; 49 | swap(pq[m], pq[n]); 50 | swap(qp[pq[m]], qp[pq[n]]); 51 | n = m; 52 | } 53 | } 54 | 55 | template 56 | void IndexMinPQ::swim(int n) { 57 | while(n > 1) { 58 | int m = n / 2; 59 | if(element[pq[m]] <= element[pq[n]]) break; 60 | swap(pq[m], pq[n]); 61 | swap(qp[pq[m]], qp[pq[n]]); 62 | n = m; 63 | } 64 | } 65 | 66 | 67 | template 68 | void IndexMinPQ::insert(int k, T item) { 69 | // cout << "insert " << k << " " << item << endl; 70 | if(capacity() == size()){ 71 | cout << "out of size" << endl; 72 | return ; 73 | } 74 | pq[++N] = k; 75 | element[k] = item; 76 | qp[k] = N; 77 | swim(N); 78 | // show(); 79 | } 80 | 81 | template 82 | void IndexMinPQ::show() const 83 | { 84 | cout << "pq: "; 85 | for(int i = 1; i <= capacity(); ++i) 86 | cout << pq[i] << " "; 87 | cout << endl; 88 | cout << "qp: "; 89 | for(int i = 1; i <= capacity(); ++i) 90 | cout << qp[i] << " "; 91 | cout << endl; 92 | cout << "element: "; 93 | for(int i = 1; i <= capacity(); ++i) 94 | cout << element[i] << " "; 95 | cout << endl; 96 | } 97 | 98 | template 99 | void IndexMinPQ::change(int k, T item) { 100 | if(!contain(k)) { 101 | cout << "change not contain" << endl; 102 | return ; 103 | } 104 | T old_one = element[k]; 105 | element[k] = item; 106 | if(item > old_one) 107 | sink(qp[k]); 108 | else if(item < old_one) 109 | swim(qp[k]); 110 | } 111 | 112 | template 113 | int IndexMinPQ::delMin() { 114 | int min = pq[1]; 115 | swap(pq[1], pq[N]); 116 | swap(qp[pq[1]], qp[pq[N]]); 117 | --N; 118 | // show(); 119 | sink(1); 120 | // show(); 121 | qp[min] = -1; 122 | element[min] = -1; 123 | pq[N + 1] = -1; 124 | return min; 125 | } 126 | 127 | // int main(int argc, char** argv) { 128 | // IndexMinPQ pq(6); 129 | // vector v = Common::getInstance()->getRandomVector(6); 130 | // for(size_t i = 0; i < v.size(); ++i) { 131 | // pq.insert(i + 1, v[i]); 132 | // } 133 | // pq.show(); 134 | // pq.delMin(); 135 | // pq.show(); 136 | // return 0; 137 | // } -------------------------------------------------------------------------------- /chapter3/test2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-19 10:21:08 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-19 11:35:48 6 | */ 7 | 8 | #define CATCH_CONFIG_MAIN 9 | #include "catch.hpp" 10 | #include "Common.hpp" 11 | #include "RedBlackBST.hpp" 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | /** 17 | * 红黑树单元测试 18 | **/ 19 | 20 | TEST_CASE("put", "[rdBST]") { 21 | RedBlackBST bst; 22 | SECTION("test size") { 23 | vector iv1{'S','E','A','R','C','H','X','M','P','L'}; 24 | for(size_t k = 0; k < iv1.size(); ++k) { 25 | bst.put(iv1[k], iv1[k]); 26 | REQUIRE(bst.size() == k + 1); 27 | } 28 | 29 | SECTION("deleteMin") { 30 | bst.deleteMin(); 31 | REQUIRE(bst.size() == 9); 32 | REQUIRE(bst.min() == 'C'); 33 | bst.deleteMin(); 34 | REQUIRE(bst.size() == 8); 35 | REQUIRE(bst.min() == 'E'); 36 | bst.deleteMin(); 37 | REQUIRE(bst.size() == 7); 38 | REQUIRE(bst.min() == 'H'); 39 | bst.deleteMin(); 40 | REQUIRE(bst.size() == 6); 41 | REQUIRE(bst.min() == 'L'); 42 | bst.deleteMin(); 43 | REQUIRE(bst.size() == 5); 44 | REQUIRE(bst.min() == 'M'); 45 | bst.deleteMin(); 46 | REQUIRE(bst.size() == 4); 47 | REQUIRE(bst.min() == 'P'); 48 | bst.deleteMin(); 49 | REQUIRE(bst.size() == 3); 50 | REQUIRE(bst.min() == 'R'); 51 | bst.deleteMin(); 52 | REQUIRE(bst.size() == 2); 53 | REQUIRE(bst.min() == 'S'); 54 | bst.deleteMin(); 55 | REQUIRE(bst.size() == 1); 56 | REQUIRE(bst.min() == 'X'); 57 | bst.deleteMin(); 58 | REQUIRE(bst.size() == 0); 59 | } 60 | 61 | SECTION("deleteMax") { 62 | bst.deleteMax(); 63 | REQUIRE(bst.max() == 'S'); 64 | REQUIRE(bst.size() == 9); 65 | bst.deleteMax(); 66 | REQUIRE(bst.size() == 8); 67 | REQUIRE(bst.max() == 'R'); 68 | bst.deleteMax(); 69 | REQUIRE(bst.size() == 7); 70 | REQUIRE(bst.max() == 'P'); 71 | bst.deleteMax(); 72 | REQUIRE(bst.size() == 6); 73 | REQUIRE(bst.max() == 'M'); 74 | bst.deleteMax(); 75 | REQUIRE(bst.size() == 5); 76 | REQUIRE(bst.max() == 'L'); 77 | bst.deleteMax(); 78 | REQUIRE(bst.size() == 4); 79 | REQUIRE(bst.max() == 'H'); 80 | bst.deleteMax(); 81 | REQUIRE(bst.size() == 3); 82 | REQUIRE(bst.max() == 'E'); 83 | bst.deleteMax(); 84 | REQUIRE(bst.size() == 2); 85 | REQUIRE(bst.max() == 'C'); 86 | bst.deleteMax(); 87 | REQUIRE(bst.size() == 1); 88 | REQUIRE(bst.max() == 'A'); 89 | bst.deleteMax(); 90 | REQUIRE(bst.size() == 0); 91 | } 92 | 93 | SECTION("delete") { 94 | bst.delet('X'); 95 | auto v1 = bst.keys(); 96 | REQUIRE(bst.size() == 9); 97 | REQUIRE(bst.max() == 'S'); 98 | REQUIRE(v1.size() == 9); 99 | bst.delet('A'); 100 | REQUIRE(bst.size() == 8); 101 | REQUIRE(bst.min() == 'C'); 102 | } 103 | 104 | SECTION("delete1") { 105 | bst.delet('M'); 106 | REQUIRE(bst.size() == 9); 107 | REQUIRE(bst.get('M') == nullptr); 108 | bst.delet('E'); 109 | REQUIRE(bst.size() == 8); 110 | REQUIRE(bst.get('E') == nullptr); 111 | } 112 | } 113 | SECTION("test every step") { 114 | bst.put('S','S'); 115 | REQUIRE(bst.size() == 1); 116 | bst.put('E','E'); 117 | REQUIRE(bst.size() == 2); 118 | auto ne = bst.get('E'); 119 | REQUIRE(ne->color == Color::Red); 120 | bst.put('A', 'A'); 121 | REQUIRE(bst.size() == 3); 122 | auto na = bst.get('A'); 123 | REQUIRE(na->color == Color::Black); 124 | REQUIRE(ne->color == Color::Black); 125 | bst.put('R','R'); 126 | REQUIRE(bst.size() == 4); 127 | auto nr = bst.get('R'); 128 | REQUIRE(nr->color == Color::Red); 129 | } 130 | } 131 | 132 | TEST_CASE("put2", "[rdBST]") { 133 | RedBlackBST bst; 134 | SECTION("test size") { 135 | vector iv1{'A','C','E','H','L','M','P','R','S','X'}; 136 | for(size_t k = 0; k < iv1.size(); ++k) { 137 | bst.put(iv1[k], iv1[k]); 138 | REQUIRE(bst.size() == k + 1); 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 《算法第4版》的C++代码实现 2 | ========== 3 | 4 | >这个项目包含《算法第4版》书中的部分代码和本人的实现。希望能和大家交流学习,炒鸡感谢哒!🐶 5 | 6 | 7 | | 算法第4版 | 8 | | :----------------------------: | 9 | | ![算法第4版](https://bkimg.cdn.bcebos.com/pic/3b292df5e0fe9925679fe8a53ea85edf8cb171b0?x-bce-process=image/resize,m_lfit,w_268,limit_1/format,f_jpg) | 10 | 11 | 目录 12 | ---- 13 | 14 | ### 第1章 基础 15 |  [二分查找(递归)](https://github.com/LurenAA/Algorithms/blob/master/chapter1/BinarySearch.cpp)
16 |  [二分查找(非递归)](https://github.com/LurenAA/Algorithms/blob/master/chapter1/BinarySearch2.cpp)
17 | 18 | ### 第2章 排序 19 |  [堆排序](https://github.com/LurenAA/Algorithms/blob/master/chapter2/HeapSort.hpp)
20 |  [插入排序](https://github.com/LurenAA/Algorithms/blob/master/chapter2/Insertion.hpp)
21 |  [归并排序(自顶向下)](https://github.com/LurenAA/Algorithms/blob/master/chapter2/Merge.hpp)
22 |  [归并排序(自底向上)](https://github.com/LurenAA/Algorithms/blob/master/chapter2/Merge2.hpp)
23 |  [快速排序](https://github.com/LurenAA/Algorithms/blob/master/chapter2/Quick.hpp)
24 |  [插入排序](https://github.com/LurenAA/Algorithms/blob/master/chapter2/Selection.hpp)
25 |  [希尔排序](https://github.com/LurenAA/Algorithms/blob/master/chapter2/Shell.hpp)
26 |  [优先队列(二叉堆)](https://github.com/LurenAA/Algorithms/blob/master/chapter2/MaxPQ.cpp)
27 |  [优先队列(无序数组)](https://github.com/LurenAA/Algorithms/blob/master/chapter2/UnOrderArrayMaxPQ.cpp)
28 |  [优先队列(有序数组)](https://github.com/LurenAA/Algorithms/blob/master/chapter2/OrderArrayMaxPQ.cpp)
29 |  [索引最小优先队列](https://github.com/LurenAA/Algorithms/blob/master/chapter2/IndexMinPQ.hpp)
30 | 31 | ### 第3章 查找 32 |  [链表](https://github.com/LurenAA/Algorithms/blob/master/chapter3/SequentialSearchST.hpp)
33 |  [数组(二分查找)](https://github.com/LurenAA/Algorithms/blob/master/chapter3/BinarySearchST.hpp)
34 |  [二叉查找树](https://github.com/LurenAA/Algorithms/blob/master/chapter3/BST.hpp)
35 |  [红黑树](https://github.com/LurenAA/Algorithms/blob/master/chapter3/RedBlackBST.hpp)
36 |  [AVL树](https://github.com/LurenAA/Algorithms/blob/master/chapter3/AvlTree.hpp)
37 |  [拉链法的散列表](https://github.com/LurenAA/Algorithms/blob/master/chapter3/SeparateChainingHashST.hpp)
38 |  [线性探测法的散列表](https://github.com/LurenAA/Algorithms/blob/master/chapter3/LinearProbingHashST.hpp)
39 | 40 | ### 第4章 图 41 |  [无向图](https://github.com/LurenAA/Algorithms/blob/master/chapter4/Graph.hpp)
42 |  [DFS](https://github.com/LurenAA/Algorithms/blob/master/chapter4/DepthFirstSearch.hpp)
43 |  [DFS寻找路径](https://github.com/LurenAA/Algorithms/blob/master/chapter4/DepthFirstPaths.hpp)
44 |  [DFS连通分量](https://github.com/LurenAA/Algorithms/blob/master/chapter4/CC.hpp)
45 |  [BFS](https://github.com/LurenAA/Algorithms/blob/master/chapter4/BreadthFirstPaths.hpp)
46 |  [符号图](https://github.com/LurenAA/Algorithms/blob/master/chapter4/SymbolGraph.hpp)
47 |  [有向图](https://github.com/LurenAA/Algorithms/blob/master/chapter4/Digraph.hpp)
48 |  [有向图DFS](https://github.com/LurenAA/Algorithms/blob/master/chapter4/DirectedDFS.hpp)
49 |  [寻找有向环](https://github.com/LurenAA/Algorithms/blob/master/chapter4/DirectedCycle.hpp)
50 |  [Kosaraju](https://github.com/LurenAA/Algorithms/blob/master/chapter4/Kosaraju.hpp)
51 |  [加权边](https://github.com/LurenAA/Algorithms/blob/master/chapter4/Edge.hpp)
52 |  [加权无向图](https://github.com/LurenAA/Algorithms/blob/master/chapter4/EdgeWeightedGraph.hpp)
53 |  [Prim算法](https://github.com/LurenAA/Algorithms/blob/master/chapter4/PrimMST.hpp)
54 |  [Prim算法2](https://github.com/LurenAA/Algorithms/blob/master/chapter4/LazyPrimMST.hpp)
55 |  [Kruskal算法](https://github.com/LurenAA/Algorithms/blob/master/chapter4/Kruskal.hpp)
56 |  [Dijkstra](https://github.com/LurenAA/Algorithms/blob/master/chapter4/DijkstraSP.hpp)
57 |  [BellmanFord](https://github.com/LurenAA/Algorithms/blob/master/chapter4/BellmanFord.hpp)
58 | 59 | ### 第5章 字符串 60 |  [高位优先的字符串排序](https://github.com/LurenAA/Algorithms/blob/master/chapter5/MSD.hpp)
61 |  [低位优先的字符串排序](https://github.com/LurenAA/Algorithms/blob/master/chapter5/LSD.hpp)
62 |  [三向字符串快速排序](https://github.com/LurenAA/Algorithms/blob/master/chapter5/Quick3string.hpp)
63 |  [trie](https://github.com/LurenAA/Algorithms/blob/master/chapter5/TrieST.hpp)
64 |  [暴力子字符串查找](https://github.com/LurenAA/Algorithms/blob/master/chapter5/BLsearch.hpp)
65 |  [kmp](https://github.com/LurenAA/Algorithms/blob/master/chapter5/Kmp.hpp)
66 |  [BoyerMoore](https://github.com/LurenAA/Algorithms/blob/master/chapter5/BoyerMoore.hpp)
-------------------------------------------------------------------------------- /chapter5/TrieST.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-02-13 21:41:50 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-13 23:34:01 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | using namespace std; 18 | /** 19 | * trie 20 | **/ 21 | enum const_value{ 22 | R = 256 23 | }; 24 | 25 | template 26 | class TrieST 27 | { 28 | public: 29 | struct Node { 30 | Value val; 31 | vector> next; 32 | Node(Value val = Value()) : 33 | val(val), next(R) {} 34 | }; 35 | private: 36 | /* data */ 37 | shared_ptr root; 38 | 39 | shared_ptr get(shared_ptr x, string key, int d) const; 40 | shared_ptr put(shared_ptr x, string key, Value val, int d); 41 | void collect(shared_ptr x, string pre, queue& q) const; 42 | void collect(shared_ptr x, string pat, string pre, queue& q) const; 43 | int search(shared_ptr x, string s, int d, int len) const; 44 | shared_ptr delet(shared_ptr x, string s, int d); 45 | public: 46 | TrieST(/* args */); 47 | ~TrieST(); 48 | 49 | string longestPrefixOf(string s) const; 50 | Value get(string key) const; 51 | void put(string key, Value val); 52 | queue keys() const; 53 | queue keysWithPrefix(string pre) const; 54 | queue keysThatMatch(string pat) const; 55 | void delet(string s); 56 | }; 57 | 58 | template 59 | shared_ptr::Node> 60 | TrieST::delet(shared_ptr x, string s, int d){ 61 | if(!x) return nullptr; 62 | if(x->val != Value()) 63 | x->val = Value(); 64 | else { 65 | unsigned next = static_cast(s.at(d)); 66 | x->next[next] = delet(x->next[next], s, d + 1); 67 | } 68 | if(x->val != Value()) 69 | return x; 70 | for(int c = 0; c < R; ++ c) 71 | if(x->next[c]) return x; 72 | return nullptr; 73 | } 74 | 75 | template 76 | void TrieST::delet(string s){ 77 | root = delet(root , s, 0); 78 | } 79 | 80 | template 81 | int TrieST::search(shared_ptr x, string s, int d, int len) const 82 | { 83 | if(!x) return len; 84 | if(x->val != Value()) len = d; 85 | if(s.size() == static_cast(len)) return len; 86 | unsigned next = static_cast(s.at(d)); 87 | return search(x->next[next], s, d + 1, len); 88 | } 89 | 90 | template 91 | string TrieST::longestPrefixOf(string s) const 92 | { 93 | 94 | int pos = search(root, s, 0, 0); 95 | return s.substr(0, pos); 96 | } 97 | 98 | template 99 | queue TrieST::keysThatMatch(string pat) const 100 | { 101 | queue q; 102 | collect(root, pat,"", q); 103 | return q; 104 | } 105 | 106 | template 107 | void TrieST::collect(shared_ptr x, string pat, string pre, queue& q) const 108 | { 109 | if(!x) return ; 110 | if(pre.size() == pat.size() && x->val != Value()) 111 | q.push(pre); 112 | if(pre.size() == pat.size()) 113 | return ; 114 | 115 | for(unsigned c = 0; c < R; ++c) 116 | if(pat.at(pre.size()) == '.' || pat.at(pre.size()) == static_cast(c)) 117 | collect(x->next[c], pat, pre + static_cast(c), q); 118 | } 119 | 120 | template 121 | void TrieST::collect(shared_ptr x, string pre, queue& q) const 122 | { 123 | if(!x) return ; 124 | if(x->val != Value()) 125 | q.push(pre); 126 | for(unsigned c = 0; c < R; ++c) 127 | collect(x->next[c], pre + static_cast(c), q); 128 | } 129 | 130 | template 131 | queue TrieST::keys() const 132 | { 133 | return keysWithPrefix(""); 134 | } 135 | 136 | template 137 | queue 138 | TrieST::keysWithPrefix(string pre) const 139 | { 140 | queue q; 141 | collect(get(root, pre, 0), pre, q); 142 | return q; 143 | } 144 | 145 | template 146 | void TrieST::put(string key, Value val) 147 | { 148 | root = put(root, key, val, 0); 149 | } 150 | 151 | template 152 | shared_ptr::Node> 153 | TrieST::put(shared_ptr x, string key, Value val, int d) 154 | { 155 | if(!x) x = make_shared(); 156 | if(d == static_cast(key.size()) ){ 157 | x->val = val; 158 | return x; 159 | } 160 | int pos = static_cast(key.at(d)); 161 | x->next[pos] = put(x->next[pos], key, val, 1+d); 162 | return x; 163 | } 164 | 165 | template 166 | shared_ptr::Node> 167 | TrieST::get(shared_ptr x, string key, int d) const 168 | { 169 | if(!x) 170 | return nullptr; 171 | if(d == static_cast(key.size())) 172 | return x; 173 | int pos = static_cast(key.at(d)); 174 | return get(x->next[pos], key, 1+d); 175 | } 176 | 177 | template 178 | Value TrieST::get(string key) const 179 | { 180 | auto x = get(root, key, 0); 181 | if(!x) return Value(); 182 | return x->val; 183 | } 184 | 185 | template 186 | TrieST::TrieST(/* args */) 187 | :root(new Node()) 188 | { 189 | } 190 | 191 | template 192 | TrieST::~TrieST() 193 | { 194 | } 195 | -------------------------------------------------------------------------------- /chapter4/test1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-25 14:40:47 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-02-12 22:25:22 6 | */ 7 | #define CATCH_CONFIG_MAIN 8 | #include "catch.hpp" 9 | #include "Common.hpp" 10 | #include "DepthFirstOrder.hpp" 11 | #include "Graph.hpp" 12 | #include "DepthFirstSearch.hpp" 13 | #include "DepthFirstPaths.hpp" 14 | #include "BreadthFirstPaths.hpp" 15 | #include "DirectedCycle.hpp" 16 | #include "Digraph.hpp" 17 | #include "DirectedDFS.hpp" 18 | #include "CC.hpp" 19 | #include 20 | #include 21 | #include "Kosaraju.hpp" 22 | #include "EdgeWeightedGraph.hpp" 23 | #include "SymbolGraph.hpp" 24 | #include "LazyPrimMST.hpp" 25 | #include "PrimMST.hpp" 26 | #include "Kruskal.hpp" 27 | #include "EdgeWeightDigraph.hpp" 28 | #include "DijkstraSP.hpp" 29 | #include "BellmanFord.hpp" 30 | using namespace std; 31 | 32 | /** 33 | * 图测试 34 | **/ 35 | 36 | TEST_CASE("Graph") { 37 | Graph g("tinyG.txt"); 38 | REQUIRE(g.V() == 13); 39 | REQUIRE(g.E() == 13); 40 | REQUIRE(g.adj(0).size() == 4); 41 | REQUIRE(g.adj(1).size() == 1); 42 | 43 | CC c(g); 44 | REQUIRE(c.connected(0, 1)); 45 | REQUIRE(c.connected(1, 2)); 46 | REQUIRE(c.connected(2, 3)); 47 | REQUIRE(c.connected(3, 4)); 48 | REQUIRE(c.connected(4, 5)); 49 | REQUIRE(c.connected(5, 6)); 50 | REQUIRE(c.connected(7, 8)); 51 | REQUIRE(c.connected(9, 10)); 52 | REQUIRE(c.connected(10, 11)); 53 | REQUIRE(c.connected(11, 12)); 54 | } 55 | 56 | /** 57 | * dfs 58 | **/ 59 | TEST_CASE("dfs") { 60 | SymbolGraph g1("routes.txt"); 61 | 62 | Graph g(6); 63 | g.addEdge(0, 2); 64 | g.addEdge(0, 1); 65 | g.addEdge(0, 5); 66 | g.addEdge(1, 2); 67 | g.addEdge(2, 3); 68 | g.addEdge(2, 4); 69 | g.addEdge(3, 5); 70 | g.addEdge(3 ,4); 71 | 72 | SECTION("DepthFirstSearch") { 73 | DepthFirstSearch dfs(g, 0); 74 | REQUIRE(dfs.getMarked(0) == true); 75 | REQUIRE(dfs.getMarked(2) == true); 76 | REQUIRE(dfs.getMarked(3) == true); 77 | REQUIRE(dfs.getMarked(4) == true); 78 | } 79 | 80 | SECTION("DepthFirstPaths") { 81 | DepthFirstPaths dfs(g, 0); 82 | vector vec = dfs.pathTo(4); 83 | REQUIRE(vec == vector{0,2,3,4}); 84 | } 85 | 86 | SECTION("BreadthFirstPaths") { 87 | BreadthFirstPaths bfs(g, 0); 88 | stack stk; 89 | SECTION("1") { 90 | stk.push(1); 91 | stk.push(0); 92 | REQUIRE(bfs.pathTo(1) == stk); 93 | } 94 | SECTION("2") { 95 | stk.push(2); 96 | stk.push(0); 97 | REQUIRE(bfs.pathTo(2) == stk); 98 | } 99 | SECTION("5") { 100 | stk.push(5); 101 | stk.push(0); 102 | REQUIRE(bfs.pathTo(5) == stk); 103 | } 104 | 105 | SECTION("3") { 106 | stk.push(3); 107 | stk.push(2); 108 | stk.push(0); 109 | REQUIRE(bfs.pathTo(3) == stk); 110 | } 111 | SECTION("4") { 112 | stk.push(4); 113 | stk.push(2); 114 | stk.push(0); 115 | REQUIRE(bfs.pathTo(4) == stk); 116 | } 117 | } 118 | } 119 | 120 | 121 | TEST_CASE("有向图") 122 | { 123 | Digraph d("tinyDG.txt"); 124 | REQUIRE(d.adj(0) == list{1, 5}); 125 | REQUIRE(d.adj(2) == list{3,0}); 126 | REQUIRE(d.adj(3) == list{2,5}); 127 | Digraph rd = d.reverse(); 128 | REQUIRE(rd.adj(0).size() == 2); 129 | DirectedDFS dfs(d, 0); 130 | REQUIRE(dfs.getMarked(1) == true); 131 | REQUIRE(dfs.getMarked(5) == true); 132 | REQUIRE(dfs.getMarked(2) == true); 133 | REQUIRE(dfs.getMarked(3) == true); 134 | REQUIRE(dfs.getMarked(4) == true); 135 | REQUIRE(dfs.getMarked(6) == false); 136 | DirectedCycle ddc(d); 137 | REQUIRE(ddc.cycles.size() == 5); 138 | DepthFirstOrder odr(d); 139 | REQUIRE(odr.getPost().size() == 13); 140 | REQUIRE(odr.getPre().size() == 13); 141 | REQUIRE(odr.getReversePost().size() == 13); 142 | Kosaraju koj(d); 143 | REQUIRE(koj.stronglyConnected(2, 3)); 144 | REQUIRE(koj.stronglyConnected(3 ,5)); 145 | REQUIRE(koj.stronglyConnected(7 ,8)); 146 | REQUIRE(koj.stronglyConnected(9 ,11)); 147 | } 148 | 149 | TEST_CASE("EdgeWeightedGraph") 150 | { 151 | EdgeWeightedGraph g("tinyEWG.txt"); 152 | REQUIRE(g.E() == 16); 153 | REQUIRE(g.V() == 8); 154 | REQUIRE(g.edges().size() == 16); 155 | REQUIRE(g.adj(0).size() == 4); 156 | REQUIRE(g.adj(1).size() == 4); 157 | REQUIRE(g.adj(2).size() == 5); 158 | REQUIRE(g.adj(3).size() == 3); 159 | LazyPrimMST lpm(g); 160 | queue > egs = lpm.edges(); 161 | REQUIRE(egs.size() == 7); 162 | REQUIRE(abs(lpm.weight() - 1.81) < 1e-6); 163 | PrimMST lpm2(g); 164 | REQUIRE(abs(lpm2.weight() - 1.81) < 1e-6); 165 | Kruskal kk(g); 166 | REQUIRE(abs(kk.weight() - 1.81) < 1e-6); 167 | } 168 | 169 | TEST_CASE("4.4") 170 | { 171 | EdgeWeightDigraph g("tinyEWD.txt"); 172 | 173 | SECTION("DijkstraSP") { 174 | DijkstraSP dj(g, 0); 175 | vector djv = dj.pathTo(1); 176 | REQUIRE(djv[0] == DirectedEdge(0, 4, 0.38)); 177 | REQUIRE(djv[1] == DirectedEdge(4, 5, 0.35)); 178 | REQUIRE(djv[2] == DirectedEdge(5, 1, 0.32)); 179 | REQUIRE(dj.pathTo(2).size() == 1); 180 | REQUIRE(dj.pathTo(3).size() == 3); 181 | auto djv2 = dj.pathTo(6); 182 | REQUIRE(djv2[0] == DirectedEdge(0, 2, 0.26)); 183 | REQUIRE(djv2[1] == DirectedEdge(2, 7, 0.34)); 184 | REQUIRE(djv2[2] == DirectedEdge(7, 3, 0.39)); 185 | REQUIRE(djv2[3] == DirectedEdge(3, 6, 0.52)); 186 | } 187 | 188 | SECTION("BellmanFord") { 189 | BellmanFord dj(g, 0); 190 | vector djv = dj.pathTo(1); 191 | REQUIRE(djv[0] == DirectedEdge(0, 4, 0.38)); 192 | REQUIRE(djv[1] == DirectedEdge(4, 5, 0.35)); 193 | REQUIRE(djv[2] == DirectedEdge(5, 1, 0.32)); 194 | REQUIRE(dj.pathTo(2).size() == 1); 195 | REQUIRE(dj.pathTo(3).size() == 3); 196 | auto djv2 = dj.pathTo(6); 197 | REQUIRE(djv2[0] == DirectedEdge(0, 2, 0.26)); 198 | REQUIRE(djv2[1] == DirectedEdge(2, 7, 0.34)); 199 | REQUIRE(djv2[2] == DirectedEdge(7, 3, 0.39)); 200 | REQUIRE(djv2[3] == DirectedEdge(3, 6, 0.52)); 201 | } 202 | } -------------------------------------------------------------------------------- /chapter3/test1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: xiao gongbai 3 | * @Date: 2020-01-14 23:20:44 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-16 01:12:19 6 | */ 7 | #define CATCH_CONFIG_MAIN 8 | #include "catch.hpp" 9 | #include "Common.hpp" 10 | #include "BST.hpp" 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * 二叉查找树的单元测试 17 | **/ 18 | TEST_CASE("put", "[BST]") { 19 | BST bst; 20 | SECTION("case 1") { 21 | vector init_keys{'H','C','S','A', 'E','R','X'}; 22 | for(size_t i = 0; i < init_keys.size(); ++i) { 23 | bst.put(init_keys[i], init_keys[i]); 24 | REQUIRE(bst.size() == i + 1); 25 | } 26 | 27 | vector keys = bst.keys(); 28 | REQUIRE(keys.size() == init_keys.size()); 29 | vector keys1 = bst.keys('C', 'S'); 30 | REQUIRE(keys1.size() == 5); 31 | auto keys2 = bst.keys('C', 'H'); 32 | REQUIRE(keys2.size() == 3); 33 | 34 | auto H = bst.get('H', 1); 35 | REQUIRE(H->N == 7); 36 | auto C = bst.get('C', 1); 37 | REQUIRE(C->N == 3); 38 | auto S = bst.get('S', 1); 39 | REQUIRE(S->N == 3); 40 | auto A = bst.get('A', 1); 41 | REQUIRE(A->N == 1); 42 | 43 | auto flg = bst.floor('G'); 44 | REQUIRE(flg == 'E'); 45 | auto flh = bst.floor('H'); 46 | REQUIRE(flh == 'H'); 47 | auto flz = bst.floor('Z'); 48 | REQUIRE(flz == 'X'); 49 | auto flb = bst.floor('B'); 50 | REQUIRE(flb == 'A'); 51 | auto flc = bst.floor('C'); 52 | REQUIRE(flc == 'C'); 53 | auto flt = bst.floor('T'); 54 | REQUIRE(flt == 'S'); 55 | auto flq = bst.floor('Q'); 56 | REQUIRE(flq == 'H'); 57 | 58 | auto clq = bst.ceiling('Q'); 59 | REQUIRE(clq == 'R'); 60 | auto clO = bst.ceiling('O'); 61 | REQUIRE(clO == 'R'); 62 | auto clR = bst.ceiling('R'); 63 | REQUIRE(clR == 'R'); 64 | auto clI = bst.ceiling('I'); 65 | REQUIRE(clI == 'R'); 66 | auto clc = bst.ceiling('C'); 67 | REQUIRE(clc == 'C'); 68 | auto cle = bst.ceiling('E'); 69 | REQUIRE(cle == 'E'); 70 | auto clf = bst.ceiling('F'); 71 | REQUIRE(clf == 'H'); 72 | 73 | REQUIRE((bst.select(0) == 'A')); 74 | REQUIRE((bst.select(1) == 'C')); 75 | REQUIRE((bst.select(2) == 'E')); 76 | REQUIRE((bst.select(3) == 'H')); 77 | REQUIRE((bst.select(4) == 'R')); 78 | REQUIRE((bst.select(5) == 'S')); 79 | REQUIRE((bst.select(6) == 'X')); 80 | 81 | REQUIRE(bst.rank('A') == 0); 82 | REQUIRE(bst.rank('B') == 1); 83 | REQUIRE(bst.rank('D') == 2); 84 | REQUIRE(bst.rank('F') == 3); 85 | REQUIRE(bst.rank('R') == 4); 86 | 87 | SECTION("case 1.1") { 88 | bst.deleteMin(); 89 | REQUIRE(bst.size() == 6); 90 | REQUIRE(bst.select(0) == 'C'); 91 | REQUIRE(bst.get('C', 1)->N == 2); 92 | 93 | bst.deleteMin(); 94 | REQUIRE(bst.size() == 5); 95 | REQUIRE(bst.select(0) == 'E'); 96 | REQUIRE(bst.get('E', 1)->N == 1); 97 | 98 | bst.deleteMin(); 99 | REQUIRE(bst.size() == 4); 100 | REQUIRE(bst.select(0) == 'H'); 101 | REQUIRE(bst.get('H', 1)->N == 4); 102 | 103 | bst.deleteMin(); 104 | REQUIRE(bst.size() == 3); 105 | REQUIRE(bst.select(0) == 'R'); 106 | REQUIRE(bst.get('R', 1)->N == 1); 107 | 108 | bst.deleteMin(); 109 | REQUIRE(bst.size() == 2); 110 | REQUIRE(bst.get('S', 1)->N == 2); 111 | 112 | bst.deleteMin(); 113 | REQUIRE(bst.size() == 1); 114 | REQUIRE(bst.get('X', 1)->N == 1); 115 | 116 | bst.deleteMin(); 117 | REQUIRE(bst.size() == 0); 118 | 119 | } 120 | 121 | SECTION("case 1.2") { 122 | bst.deleteMax(); 123 | REQUIRE(bst.max() == 'S'); 124 | REQUIRE(bst.size() == 6); 125 | 126 | bst.deleteMax(); 127 | REQUIRE(bst.max() == 'R'); 128 | REQUIRE(bst.size() == 5); 129 | 130 | bst.deleteMax(); 131 | REQUIRE(bst.max() == 'H'); 132 | REQUIRE(bst.size() == 4); 133 | 134 | bst.deleteMax(); 135 | REQUIRE(bst.max() == 'E'); 136 | REQUIRE(bst.size() == 3); 137 | 138 | bst.deleteMax(); 139 | REQUIRE(bst.max() == 'C'); 140 | REQUIRE(bst.size() == 2); 141 | 142 | bst.deleteMax(); 143 | REQUIRE(bst.max() == 'A'); 144 | REQUIRE(bst.size() == 1); 145 | 146 | bst.deleteMax(); 147 | REQUIRE(bst.size() == 0); 148 | } 149 | 150 | SECTION("case 1.3") { 151 | REQUIRE(bst.size() == 7); 152 | bst.delet('C'); 153 | REQUIRE(bst.rank('E') == 1); 154 | REQUIRE(bst.rank('A') == 0); 155 | REQUIRE(bst.size() == 6); 156 | 157 | bst.delet('H'); 158 | REQUIRE(bst.size() == 5); 159 | REQUIRE(bst.rank('R') == 2); 160 | 161 | bst.delet('R'); 162 | REQUIRE(bst.size() == 4); 163 | REQUIRE(bst.rank('S') == 2); 164 | REQUIRE(bst.rank('A') == 0); 165 | REQUIRE(bst.rank('E') == 1); 166 | 167 | } 168 | } 169 | 170 | SECTION("case 2") { 171 | vector init_keys{'S','E','A','R', 'C','H','X'}; 172 | for(size_t i = 0; i < init_keys.size(); ++i) { 173 | bst.put(init_keys[i], init_keys[i]); 174 | REQUIRE(bst.size() == i + 1); 175 | } 176 | 177 | auto keys = bst.keys(); 178 | REQUIRE(keys.size() == init_keys.size()); 179 | auto keys1 = bst.keys('E','S'); 180 | REQUIRE(keys1.size() == 4); 181 | 182 | auto S = bst.get('S', 1); 183 | REQUIRE(S->N == 7); 184 | auto C = bst.get('C', 1); 185 | REQUIRE(C->N == 1); 186 | auto E = bst.get('E', 1); 187 | REQUIRE(E->N == 5); 188 | auto A = bst.get('A', 1); 189 | CAPTURE(A); 190 | REQUIRE(A->N == 2); 191 | 192 | bool cta = bst.contain('A'); 193 | REQUIRE(cta == true); 194 | bool cts = bst.contain('S'); 195 | REQUIRE(cts == true); 196 | 197 | auto flg = bst.floor('G'); 198 | REQUIRE(flg == 'E'); 199 | auto flh = bst.floor('H'); 200 | REQUIRE(flh == 'H'); 201 | auto flz = bst.floor('Z'); 202 | REQUIRE(flz == 'X'); 203 | auto flb = bst.floor('B'); 204 | REQUIRE(flb == 'A'); 205 | 206 | auto clf = bst.ceiling('F'); 207 | REQUIRE(clf == 'H'); 208 | auto clb = bst.ceiling('B'); 209 | REQUIRE(clb == 'C'); 210 | 211 | auto s0 = bst.select(0); 212 | REQUIRE(s0 == 'A'); 213 | REQUIRE((bst.select(1) == 'C')); 214 | REQUIRE((bst.select(2) == 'E')); 215 | REQUIRE((bst.select(3) == 'H')); 216 | REQUIRE((bst.select(4) == 'R')); 217 | REQUIRE((bst.select(5) == 'S')); 218 | REQUIRE((bst.select(6) == 'X')); 219 | 220 | REQUIRE(bst.rank('A') == 0); 221 | REQUIRE(bst.rank('B') == 1); 222 | REQUIRE(bst.rank('D') == 2); 223 | REQUIRE(bst.rank('F') == 3); 224 | REQUIRE(bst.rank('R') == 4); 225 | 226 | SECTION("case 2.1") { 227 | bst.deleteMin(); 228 | REQUIRE(bst.rank('C') == 0); 229 | REQUIRE(bst.size() == 6); 230 | 231 | bst.deleteMin(); 232 | REQUIRE(bst.rank('E') == 0); 233 | REQUIRE(bst.size() == 5); 234 | 235 | bst.deleteMin(); 236 | REQUIRE(bst.rank('H') == 0); 237 | REQUIRE(bst.size() == 4); 238 | 239 | bst.deleteMin(); 240 | REQUIRE(bst.rank('R') == 0); 241 | REQUIRE(bst.size() == 3); 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /chapter3/AvlTree.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-21 20:48:35 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-21 22:06:17 6 | */ 7 | #pragma once 8 | #include 9 | #include "Common.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | 17 | /** 18 | * avl树 19 | **/ 20 | 21 | template 22 | class AvlTree { 23 | public: 24 | struct Node { 25 | Val val; 26 | Key key; 27 | int height; 28 | shared_ptr left, right; 29 | Node(Val val, Key key, int height = 1) 30 | :val(val), key(key), height(height) {} 31 | int compareTo(Key key); 32 | static int Height(shared_ptr h); 33 | static int BalanceFactor(shared_ptr h1, shared_ptr h2); 34 | }; 35 | shared_ptr rotateRight(shared_ptr h); 36 | shared_ptr rotateLeft(shared_ptr h); 37 | int getBalanceFactor(shared_ptr h) const; 38 | shared_ptr get(Key key); 39 | void put(Key key, Val val); 40 | bool isBalanced(shared_ptr h) const; 41 | bool isBalanced() const {return isBalanced(root);} 42 | Key min() const; 43 | void deleteMin(); 44 | void delet(Key key); 45 | private: 46 | shared_ptr root; 47 | 48 | shared_ptr delet(shared_ptr h, Key key); 49 | shared_ptr min(shared_ptr h) const; 50 | shared_ptr deleteMin(shared_ptr h); 51 | shared_ptr get(shared_ptr h, Key key); 52 | shared_ptr put(shared_ptr h, Key key, Val val); 53 | shared_ptr balance(shared_ptr h); 54 | }; 55 | 56 | template 57 | shared_ptr::Node> 58 | AvlTree::rotateRight(shared_ptr h) 59 | { 60 | auto lh = h->left; 61 | assert(lh != nullptr); 62 | h->left = lh->right; 63 | lh->right = h; 64 | 65 | h->height = max(Node::Height(h->left), Node::Height(h->right)) + 1; 66 | lh->height = max(Node::Height(lh->left), Node::Height(lh->right)) + 1; 67 | 68 | return lh; 69 | } 70 | 71 | template 72 | shared_ptr::Node> 73 | AvlTree::rotateLeft(shared_ptr h) 74 | { 75 | auto rh = h->right; 76 | assert(rh != nullptr); 77 | h->right = rh->left; 78 | rh->left = h; 79 | //这个顺序不能改变,必须从下到上 80 | h->height = max(Node::Height(h->left), Node::Height(h->right)) + 1; 81 | rh->height = max(Node::Height(rh->left), Node::Height(rh->right)) + 1; 82 | 83 | return rh; 84 | } 85 | 86 | template 87 | int 88 | AvlTree::Node::Height(shared_ptr h) 89 | { 90 | if(!h) 91 | return 0; 92 | return h->height; 93 | } 94 | 95 | template 96 | int 97 | AvlTree::Node::BalanceFactor(shared_ptr h1, shared_ptr h2) 98 | { 99 | return Height(h1) - Height(h2); 100 | } 101 | 102 | template 103 | void 104 | AvlTree::put(Key key, Val val) 105 | { 106 | root = put(root, key, val); 107 | } 108 | 109 | template 110 | int 111 | AvlTree::Node::compareTo(Key key) 112 | { 113 | if(this->key > key) 114 | return 1; 115 | else if (this->key < key) 116 | return -1; 117 | return 0; 118 | } 119 | 120 | template 121 | int 122 | AvlTree::getBalanceFactor(shared_ptr h) const 123 | { 124 | if(!h) 125 | return 0; 126 | return Node::BalanceFactor(h->left, h->right); 127 | } 128 | 129 | template 130 | shared_ptr::Node> 131 | AvlTree::put(shared_ptr h, Key key, Val val) 132 | { 133 | if(!h) 134 | return make_shared(key, val, 1); 135 | int cmp = h->compareTo(key); 136 | if(cmp > 0) { 137 | h->left = put(h->left, key, val); 138 | } else if(cmp < 0) { 139 | h->right = put(h->right, key, val); 140 | } else { 141 | h->val = val; 142 | } 143 | h->height = 1 + max(Node::Height(h->left), Node::Height(h->right)); 144 | 145 | return balance(h); 146 | } 147 | 148 | template 149 | shared_ptr::Node> 150 | AvlTree::balance(shared_ptr h) 151 | { 152 | int fc = getBalanceFactor(h); 153 | if(fc >= 2) { 154 | /**LL 155 | * 左旋转 156 | * x y 157 | * / \ / \ 158 | * y T1 T3 x 159 | * / \ ==> / / \ 160 | * T3 T2 T4 T2 T1 161 | * / 162 | * T4 163 | */ 164 | if(fc > 1 && getBalanceFactor(h->left) >= 0) { 165 | h = rotateRight(h); 166 | } 167 | /**LR 168 | * 左右旋转 169 | * x x T2 170 | * / \ / \ / \ 171 | * y T1 T2 T1 y x 172 | * / \ ==> / ==> / \ \ 173 | * T3 T2 y T3 T4 T1 174 | * / / \ 175 | * T4 T3 T4 176 | */ 177 | else if(fc > 1 && getBalanceFactor(h->left) < 0 ) { 178 | h->left = rotateLeft(h->left); 179 | h = rotateRight(h); 180 | } 181 | } else if (fc <= -2) { 182 | /**RR 183 | * 右旋转 184 | * x y 185 | * / \ / \ 186 | * T1 y x T3 187 | * / \ ==> / \ \ 188 | * T2 T3 T1 T2 T4 189 | * \ 190 | * T4 191 | */ 192 | if(fc < -1 && getBalanceFactor(h->right) <= 0) { 193 | h = rotateLeft(h); 194 | } 195 | /**RL 196 | * 右左旋转 197 | * x x T2 198 | * / \ / \ / \ 199 | * T1 y T1 T2 x y 200 | * / \ ==> \ ==> / / \ 201 | * T2 T3 y T1 T4 T3 202 | * \ / \ 203 | * T4 T4 T3 204 | */ 205 | else if (fc < -1 && getBalanceFactor(h->right) > 0) { 206 | h->right = rotateRight(h->right); 207 | h = rotateLeft(h); 208 | } 209 | } 210 | h->height = max(Node::Height(h->left), Node::Height(h->right)) + 1; 211 | return h; 212 | } 213 | 214 | template 215 | shared_ptr::Node> 216 | AvlTree::get(Key key) 217 | { 218 | return get(root, key); 219 | } 220 | 221 | template 222 | shared_ptr::Node> 223 | AvlTree::get(shared_ptr h, Key key) 224 | { 225 | if(!h) 226 | return nullptr; 227 | int cmp = h->compareTo(key); 228 | if(cmp > 0) { 229 | return get(h->left, key); 230 | } else if (cmp < 0) { 231 | return get(h->right, key); 232 | } else { 233 | return h; 234 | } 235 | } 236 | 237 | template 238 | bool 239 | AvlTree::isBalanced(shared_ptr h ) const 240 | { 241 | if(!h) 242 | return true; 243 | return abs(getBalanceFactor(h)) <= 1 && isBalanced(h->left) && isBalanced(h->right); 244 | } 245 | 246 | template 247 | Key AvlTree::min() const 248 | { 249 | return min(root)->key; 250 | } 251 | 252 | template 253 | shared_ptr::Node> 254 | AvlTree::min(shared_ptr h) const 255 | { 256 | if(!h->left) 257 | return h; 258 | return min(h->left); 259 | } 260 | 261 | template 262 | void AvlTree::deleteMin() 263 | { 264 | if(!root) 265 | return ; 266 | root = deleteMin(root); 267 | } 268 | 269 | template 270 | shared_ptr::Node> 271 | AvlTree::deleteMin(shared_ptr h) 272 | { 273 | if(!h->left) 274 | return h->right; 275 | h->left = deleteMin(h->left); 276 | return balance(h); 277 | } 278 | 279 | template 280 | void AvlTree::delet(Key key) 281 | { 282 | if(!root) 283 | return ; 284 | root = delet(root, key); 285 | } 286 | 287 | template 288 | shared_ptr::Node> 289 | AvlTree::delet(shared_ptr h, Key key) 290 | { 291 | if(!h) 292 | return nullptr; 293 | int cmp = h->compareTo(key); 294 | if(cmp > 0) { 295 | h->left = delet(h->left, key); 296 | } else if(cmp < 0) { 297 | h->right = delet(h->right, key); 298 | } else { 299 | if(!h->left) 300 | return h->right; 301 | else if(!h->right) 302 | return h->left; 303 | auto rm = min(h->right); 304 | rm->right = deleteMin(h->right); 305 | rm->left = h->left; 306 | } 307 | return balance(h); 308 | } -------------------------------------------------------------------------------- /chapter3/BST.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: xiao gongbai 3 | * @Date: 2020-01-14 17:31:12 4 | * @Last Modified by: xiao gongbai 5 | * @Last Modified time: 2020-01-15 03:03:40 6 | */ 7 | #pragma once 8 | #include 9 | #include "Common.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | /** 17 | * 二叉查找树的实现 18 | **/ 19 | template 20 | class BST{ 21 | public: 22 | struct Node { 23 | const S key; 24 | T val; 25 | shared_ptr left, right; 26 | int N; 27 | explicit Node(const S&key, const T& val, int N) : 28 | key(key), val(val), left(), right(), N(N) {} 29 | int compareTo(const S&) const; 30 | static int Nsize(shared_ptr x); 31 | }; 32 | 33 | S min() const; 34 | S max() const; 35 | bool contain(const S&) const; 36 | T get(const S&) const; 37 | #ifdef DEBUG 38 | shared_ptr get(const S&, int) const; //测试用 39 | #endif 40 | void put(const S& key, const T& val); 41 | int size() const {return root ? root->N : 0;} 42 | vector keys(const S& min , const S& max) const; 43 | vector keys() const; 44 | S floor(const S& key) const; 45 | S ceiling(const S&key) const; 46 | const S select(int x) const; 47 | int rank(const T&) const; 48 | void deleteMin(); 49 | void deleteMax(); 50 | void delet(const T& key); 51 | private: 52 | shared_ptr delet(shared_ptr nd, const T& key); 53 | shared_ptr deleteMax(shared_ptr); 54 | shared_ptr deleteMin(shared_ptr); 55 | int rank(shared_ptr h, const T& key) const; 56 | shared_ptr select(shared_ptr h, int x) const; 57 | shared_ptr floor(shared_ptr x, const S& key) const; 58 | shared_ptr ceiling(shared_ptr x, const S&key) const; 59 | shared_ptr min(shared_ptr x) const; 60 | shared_ptr max(shared_ptr x) const; 61 | shared_ptr put(shared_ptr x, const S& key, const T& val); 62 | shared_ptr get(shared_ptr x,const S&) const; 63 | void keys(vector&, shared_ptr x,const S& min, const S& max) const; 64 | shared_ptr root; 65 | }; 66 | 67 | template 68 | void BST::put(const S& key, const T& val) 69 | { 70 | root = put(root, key, val); 71 | } 72 | 73 | template 74 | shared_ptr::Node> 75 | BST::put(shared_ptr h, const S& key, const T& val) 76 | { 77 | if(!h) 78 | return make_shared(key, val, 1); 79 | int cmp = h->compareTo(key); 80 | if(cmp > 0) { 81 | h->left = put(h->left, key, val); 82 | } else if (cmp < 0) { 83 | h->right = put(h->right, key, val); 84 | } else { 85 | h->val = val; 86 | } 87 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 88 | return h; 89 | } 90 | 91 | template 92 | int 93 | /** 94 | * BST::Node::compareTo 95 | * 96 | * @param {S} key : 97 | * @return {int} >key 1, 98 | * ::Node::compareTo(const S& key) const 102 | { 103 | if(this->key > key) 104 | return 1; 105 | else if (this->key < key) 106 | return -1; 107 | return 0; 108 | } 109 | 110 | template 111 | int 112 | BST::Node::Nsize(shared_ptr h) 113 | { 114 | if(!h) 115 | return 0; 116 | return h->N; 117 | } 118 | 119 | template 120 | T BST::get(const S& key) const 121 | { 122 | auto h = get(root, key); 123 | if(!h) 124 | return T(); 125 | return h->val; 126 | } 127 | 128 | template 129 | shared_ptr::Node> 130 | BST::get(shared_ptr h,const S& key) const 131 | { 132 | if(!h) 133 | return nullptr; 134 | int cmp = h->compareTo(key); 135 | if(cmp > 0) { 136 | return get(h->left, key); 137 | } else if (cmp < 0) { 138 | return get(h->right, key); 139 | } else { 140 | return h; 141 | } 142 | } 143 | 144 | template 145 | vector BST::keys(const S& min, const S& max) const 146 | { 147 | vector vec; 148 | keys(vec, root, min, max); 149 | return vec; 150 | } 151 | 152 | template 153 | void 154 | BST::keys(vector& vec, shared_ptr h, const S& min, const S& max) const 155 | { 156 | if(!h) 157 | return ; 158 | int cmp1 = h->compareTo(min), 159 | cmp2 = h->compareTo(max); 160 | if(cmp1 >= 0 && cmp2 <= 0) 161 | vec.push_back(h->key); 162 | if(cmp1 >= 0) 163 | keys(vec, h->left, min, max); 164 | if(cmp2 <= 0) 165 | keys(vec, h->right, min, max); 166 | } 167 | 168 | template 169 | S BST::min() const 170 | { 171 | if(!root) 172 | return S(); 173 | auto h = min(root); 174 | return h->key; 175 | } 176 | 177 | template 178 | S BST::max() const 179 | { 180 | if(!root) 181 | return S(); 182 | auto h = max(root); 183 | return h->key; 184 | } 185 | 186 | template 187 | shared_ptr::Node> 188 | BST::min(shared_ptr h) const 189 | { 190 | if(!h->left) 191 | return h; 192 | return min(h->left); 193 | } 194 | 195 | template 196 | shared_ptr::Node> 197 | BST::max(shared_ptr h) const 198 | { 199 | if(!h->right) 200 | return h; 201 | return max(h->right); 202 | } 203 | 204 | template 205 | vector BST::keys() const 206 | { 207 | return keys(min(), max()); 208 | } 209 | 210 | #ifdef DEBUG 211 | template 212 | shared_ptr::Node> 213 | BST::get(const S& key, int) const 214 | { 215 | auto h = get(root, key); 216 | return h; 217 | } 218 | #endif 219 | 220 | template 221 | bool BST::contain(const S& key) const 222 | { 223 | return get(root, key) != nullptr; 224 | } 225 | 226 | template 227 | S BST::floor(const S& key) const 228 | { 229 | if(!root) 230 | return S(); 231 | auto h = floor(root, key); 232 | if(!h) 233 | return S(); 234 | return h->key; 235 | } 236 | 237 | template 238 | shared_ptr::Node> 239 | BST::floor(shared_ptr h, const S& key) const 240 | { 241 | if(!h) 242 | return nullptr; 243 | int cmp = h->compareTo(key); 244 | shared_ptr n; 245 | if(cmp < 0) { 246 | n = floor(h->right, key); 247 | return n ? n : h; 248 | } else if (cmp > 0) { 249 | return floor(h->left, key); 250 | } else { 251 | return h; 252 | } 253 | } 254 | 255 | template 256 | S BST::ceiling(const S&key) const 257 | { 258 | if(!root) 259 | return S(); 260 | auto h = ceiling(root, key); 261 | if(!h) 262 | return S(); 263 | return h->key; 264 | } 265 | 266 | template 267 | shared_ptr::Node> 268 | BST::ceiling(shared_ptr h, const S&key) const 269 | { 270 | if(!h) 271 | return nullptr; 272 | int cmp = h->compareTo(key); 273 | if(cmp < 0) 274 | return ceiling(h->right, key); 275 | else if (!cmp) 276 | return h; 277 | auto n = ceiling(h->left, key); 278 | if(!n) 279 | return h; 280 | return n; 281 | } 282 | 283 | template 284 | const S BST::select(int x) const 285 | { 286 | if(x < 0 || x >= size()) 287 | return S(); 288 | auto h = select(root, x); 289 | return h->key; 290 | } 291 | 292 | template 293 | shared_ptr::Node> 294 | BST::select(shared_ptr h, int x) const 295 | { 296 | int rank = Node::Nsize(h->left); 297 | if(rank > x) { 298 | return select(h->left, x); 299 | } else if(rank < x) { 300 | return select(h->right, x - rank - 1); 301 | } else { 302 | return h; 303 | } 304 | } 305 | 306 | template 307 | int 308 | BST::rank(shared_ptr h, const T& key) const 309 | { 310 | if(!h) 311 | return 0; 312 | int cmp = h->compareTo(key); 313 | if(cmp > 0) 314 | { 315 | return rank(h->left, key); 316 | } 317 | else if (cmp < 0) 318 | { 319 | return Node::Nsize(h->left) + rank(h->right, key) + 1; 320 | } 321 | else 322 | { 323 | return Node::Nsize(h->left); 324 | } 325 | } 326 | 327 | template 328 | int 329 | BST::rank(const T& key) const 330 | { 331 | return rank(root, key); 332 | } 333 | 334 | template 335 | shared_ptr::Node> 336 | BST::deleteMin(shared_ptr h) 337 | { 338 | if(!h->left) 339 | return h->right; 340 | h->left = deleteMin(h->left); 341 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 342 | return h; 343 | } 344 | 345 | template 346 | void 347 | BST::deleteMin() 348 | { 349 | if(!size()) 350 | return ; 351 | root = deleteMin(root); 352 | } 353 | 354 | template 355 | void BST::deleteMax() 356 | { 357 | if(!size()) 358 | return ; 359 | root = deleteMax(root); 360 | } 361 | 362 | template 363 | shared_ptr::Node> 364 | BST::deleteMax(shared_ptr h) 365 | { 366 | if(!h->right) 367 | return h->left; 368 | h->right = deleteMax(h->right); 369 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 370 | return h; 371 | } 372 | 373 | template 374 | void BST::delet(const T& key) 375 | { 376 | if(!size()) 377 | return ; 378 | root = delet(root, key); 379 | } 380 | 381 | template 382 | shared_ptr::Node> 383 | BST::delet(shared_ptr h, const T& key) 384 | { 385 | if(!h) 386 | return nullptr; 387 | int cmp = h->compareTo(key); 388 | if(cmp < 0) { 389 | h->right = delet(h->right, key); 390 | } else if (cmp > 0) { 391 | h->left = delet(h->left, key); 392 | } else { 393 | if(!h->right) return h->left; 394 | if(!h->left) return h->right; 395 | auto min_r = min(h->right); 396 | h->right = deleteMin(h->right); 397 | min_r->left = h->left; 398 | min_r->right = h->right; 399 | h = min_r; 400 | } 401 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 402 | return h; 403 | } 404 | -------------------------------------------------------------------------------- /chapter3/RedBlackBST.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: XiaoGongBai 3 | * @Date: 2020-01-19 10:21:20 4 | * @Last Modified by: XiaoGongBai 5 | * @Last Modified time: 2020-01-21 20:56:32 6 | */ 7 | #pragma once 8 | #include 9 | #include "Common.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | /** 17 | * 红黑树 18 | **/ 19 | enum class Color{ 20 | Red , 21 | Black 22 | }; 23 | template 24 | class RedBlackBST{ 25 | public: 26 | struct Node{ 27 | Key key; 28 | Val val; 29 | shared_ptr left,right; 30 | int N; 31 | Color color; 32 | Node(const Key& key, const Val& val, int N, Color color) 33 | :key(key), val(val), left(), right(), N(N), color(color) {} 34 | static int Nsize(shared_ptr x); 35 | int compareTo(const Key& key) const; 36 | }; 37 | void put(const Key& key, const Val& val); 38 | shared_ptr get(const Key& key) const; 39 | void deleteMin(); 40 | void deleteMax(); 41 | void delet(const Key&); 42 | Key min() const; 43 | Key max() const; 44 | vector keys(const Key& m, const Key& e) const; 45 | vector keys() const; 46 | 47 | const int size() const {return root ? root->N : 0;} 48 | private: 49 | 50 | shared_ptr root; 51 | 52 | void keys(shared_ptr h, vector& res, const Key& m, const Key& e) const; 53 | shared_ptr max(shared_ptr h) const; 54 | shared_ptr min(shared_ptr) const; 55 | shared_ptr get(shared_ptr h,const Key& key) const; 56 | shared_ptr delet(shared_ptr, const Key&); 57 | shared_ptr balance(shared_ptr); 58 | shared_ptr removeRedLeft(shared_ptr); 59 | shared_ptr removeRedRight(shared_ptr); 60 | shared_ptr deleteMax(shared_ptr); 61 | shared_ptr deleteMin(shared_ptr); 62 | shared_ptr put(shared_ptr h, const Key& key, const Val& val); 63 | void flipColor(shared_ptr h); 64 | shared_ptr rotateLeft(shared_ptr node); 65 | shared_ptr rotateRight(shared_ptr h); 66 | bool isRed(shared_ptr node) const; 67 | }; 68 | 69 | template 70 | int 71 | RedBlackBST::Node::Nsize(shared_ptr x) 72 | { 73 | return x ? x->N : 0; 74 | } 75 | 76 | template 77 | int 78 | RedBlackBST::Node::compareTo(const Key& key) const 79 | { 80 | if(key > this->key) { 81 | return -1; 82 | } else if(key < this->key) { 83 | return 1; 84 | } 85 | return 0; 86 | } 87 | 88 | 89 | template 90 | shared_ptr::Node> 91 | RedBlackBST::rotateLeft(shared_ptr h) 92 | { 93 | if(!h) 94 | return nullptr; 95 | auto rh = h->right; 96 | if(!rh) 97 | return h; 98 | h->right = rh->left; 99 | rh->left = h; 100 | rh->N = h->N; 101 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 102 | swap(h->color, rh->color); 103 | return rh; 104 | } 105 | 106 | template 107 | shared_ptr::Node> 108 | RedBlackBST::rotateRight(shared_ptr h) 109 | { 110 | if(!h) { 111 | return nullptr; 112 | } 113 | auto lh = h->left; 114 | if(!lh) 115 | return h; 116 | h->left = lh->right;; 117 | lh->right = h; 118 | lh->N = h->N; 119 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 120 | swap(h->color, lh->color); 121 | return lh; 122 | } 123 | 124 | template 125 | bool 126 | RedBlackBST::isRed(shared_ptr h) const 127 | { 128 | if(!h || h->color == Color::Black) 129 | return false; 130 | return true; 131 | } 132 | 133 | template 134 | void 135 | RedBlackBST::put(const Key& key, const Val& val) 136 | { 137 | root = put(root, key, val); 138 | root->color = Color::Black; 139 | } 140 | 141 | 142 | template 143 | shared_ptr::Node> 144 | RedBlackBST::put(shared_ptr h, const Key& key, const Val& val) 145 | { 146 | if(!h) 147 | return make_shared(key, val, 1, Color::Red); 148 | int cmp = h->compareTo(key); 149 | if(cmp < 0) { 150 | h->right = put(h->right, key, val); 151 | } else if (cmp > 0) { 152 | h->left = put(h->left, key, val); 153 | } else { 154 | h->val =val; 155 | } 156 | if(!isRed(h->left) && isRed(h->right)) 157 | h = rotateLeft(h); 158 | if(isRed(h->left) && isRed(h->left->left)) 159 | h = rotateRight(h); 160 | if(isRed(h->left) && isRed(h->right)) { 161 | flipColor(h); 162 | } 163 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 164 | return h; 165 | } 166 | 167 | template 168 | void 169 | RedBlackBST::flipColor(shared_ptr h) 170 | { 171 | h->color = h->color == Color::Black ? Color::Red : Color::Black; 172 | h->right->color = h->right->color == Color::Black ? Color::Red : Color::Black; 173 | h->left->color = h->left->color == Color::Black ? Color::Red : Color::Black; 174 | } 175 | 176 | template 177 | shared_ptr::Node> 178 | RedBlackBST::get(const Key& key) const 179 | { 180 | return get(root, key); 181 | } 182 | 183 | template 184 | shared_ptr::Node> 185 | RedBlackBST::get(shared_ptr h,const Key& key) const 186 | { 187 | if(!h) 188 | return nullptr; 189 | int cmp = h->compareTo(key); 190 | if(cmp > 0) { 191 | return get(h->left, key); 192 | } else if (cmp < 0) { 193 | return get(h->right, key); 194 | } else 195 | return h; 196 | } 197 | 198 | template 199 | void RedBlackBST::deleteMin() 200 | { 201 | if(!isRed(root->left) && !isRed(root->right)) 202 | root->color = Color::Red; 203 | root = deleteMin(root); 204 | if(root) 205 | root->color = Color::Black; 206 | } 207 | 208 | template 209 | shared_ptr::Node> 210 | RedBlackBST::deleteMin(shared_ptr h) 211 | { 212 | if(!h->left) 213 | return h->right; 214 | if(!isRed(h->left) && !isRed(h->left->left)) 215 | { 216 | h = removeRedLeft(h); 217 | } 218 | h->left = deleteMin(h->left); 219 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 220 | return balance(h); 221 | } 222 | 223 | template 224 | shared_ptr::Node> 225 | RedBlackBST::removeRedLeft(shared_ptr h) 226 | { 227 | flipColor(h); 228 | if(isRed(h->right) && isRed(h->right->left)) 229 | { 230 | h->right = rotateRight(h->right); 231 | h = rotateLeft(h); 232 | flipColor(h); 233 | } 234 | return h; 235 | } 236 | 237 | template 238 | shared_ptr::Node> 239 | RedBlackBST::balance(shared_ptr h) 240 | { 241 | if(!isRed(h->left) && isRed(h->right)) 242 | h = rotateLeft(h); 243 | if(isRed(h->left) && isRed(h->left->left)) 244 | h = rotateRight(h); 245 | if(isRed(h->left) && isRed(h->right)) { 246 | flipColor(h); 247 | } 248 | return h; 249 | } 250 | 251 | template 252 | Key 253 | RedBlackBST::min() const 254 | { 255 | if(!root) 256 | return Val(); 257 | return min(root)->key; 258 | } 259 | 260 | template 261 | shared_ptr::Node> 262 | RedBlackBST::min(shared_ptr h) const 263 | { 264 | if(!h->left) 265 | return h; 266 | return min(h->left); 267 | } 268 | 269 | template 270 | Key 271 | RedBlackBST::max() const 272 | { 273 | if(!root) 274 | return Val(); 275 | return max(root)->key; 276 | } 277 | 278 | template 279 | shared_ptr::Node> 280 | RedBlackBST::max(shared_ptr h) const 281 | { 282 | if(!h->right) 283 | return h; 284 | return max(h->right); 285 | } 286 | 287 | template 288 | void RedBlackBST::deleteMax() 289 | { 290 | if(!isRed(root->left) && !isRed(root->right)) 291 | root->color = Color::Red; 292 | root = deleteMax(root); 293 | if(root) 294 | root->color = Color::Black; 295 | } 296 | 297 | template 298 | shared_ptr::Node> 299 | RedBlackBST::deleteMax(shared_ptr h) 300 | { 301 | if(isRed(h->left)) 302 | h = rotateRight(h); 303 | if(!h->right) 304 | return h->left; 305 | if(!isRed(h->right) && !isRed(h->right->left)) 306 | h = removeRedRight(h); 307 | h->right = deleteMax(h->right); 308 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 309 | return balance(h); 310 | } 311 | 312 | template 313 | shared_ptr::Node> 314 | RedBlackBST::removeRedRight(shared_ptr h) 315 | { 316 | flipColor(h); 317 | if(isRed(h->left->left)) { 318 | h = rotateRight(h); 319 | flipColor(h); 320 | } 321 | return h; 322 | } 323 | 324 | template 325 | void RedBlackBST::delet(const Key& key) 326 | { 327 | if(!isRed(root->left) && !isRed(root->right)) 328 | root->color = Color::Red; 329 | root = delet(root, key); 330 | if(root) 331 | root->color = Color::Black; 332 | } 333 | 334 | template 335 | shared_ptr::Node> 336 | RedBlackBST::delet(shared_ptr h, const Key& key) 337 | { 338 | int cmp = h->compareTo(key); 339 | if(cmp > 0) { 340 | if(!isRed(h->left) && !isRed(h->left->left)) 341 | h = removeRedLeft(h); 342 | h->left = delet(h->left, key); 343 | } else if(cmp < 0){ 344 | if(isRed(h->left)) 345 | h = rotateRight(h); 346 | if(!isRed(h->right) && !isRed(h->right->left)) { 347 | h = removeRedRight(h); 348 | } 349 | h->right = delet(h->right, key); 350 | } else { 351 | if(!h->right) 352 | return h->left; 353 | h->val = get(h->right, min(h->right)->key)->val; 354 | h->key = min(h->right)->key; 355 | h->right = deleteMin(h->right); 356 | } 357 | h->N = Node::Nsize(h->left) + Node::Nsize(h->right) + 1; 358 | return balance(h); 359 | } 360 | 361 | template 362 | vector 363 | RedBlackBST::keys(const Key& m, const Key& e) const 364 | { 365 | vector res; 366 | keys(root, res, m, e); 367 | return res; 368 | } 369 | 370 | template 371 | void 372 | RedBlackBST::keys(shared_ptr h, vector& res, const Key& m, const Key& e) const 373 | { 374 | if(!h) 375 | return ; 376 | int cmp1 = h->compareTo(m), 377 | cmp2 = h->compareTo(e); 378 | if(cmp1 >= 0 && cmp2 <= 0) { 379 | res.push_back(h->key); 380 | } 381 | if(cmp1 > 0) { 382 | keys(h->left, res, m, e); 383 | } 384 | if(cmp2 < 0) { 385 | keys(h->right, res, m, e); 386 | } 387 | } 388 | 389 | template 390 | vector 391 | RedBlackBST::keys() const 392 | { 393 | return keys(min(), max()); 394 | } --------------------------------------------------------------------------------