├── .gitignore ├── Mathematical Algorithms ├── Euclidean Algorithm.cpp ├── Sieve of Eratosthenes.cpp ├── Exponentiation by Squaring.cpp ├── Matrix Multiplication.cpp ├── Matrix Exponentiation.cpp ├── Pascal's Triangle.cpp ├── Extended Euclidean Algorithm.cpp ├── PageRank.cpp ├── Strassen's Algorithm.cpp └── Simplex Algorithm.cpp ├── README.md ├── Recursion, Backtracking etc. ├── Power Set.cpp ├── K-Combinations.cpp └── Permutations.cpp ├── Searching Algorithms ├── Ternary Search.cpp ├── Binary Search.cpp └── Quickselect.cpp ├── LICENSE ├── Sorting Algorithms ├── Insertion Sort.cpp ├── Selection Sort.cpp ├── Counting Sort.cpp ├── Bubble Sort.cpp ├── Quicksort.cpp ├── Merge Sort.cpp ├── Heapsort.cpp └── Bitonic Sorter.cpp ├── Data Structures ├── Binary Indexed Tree.cpp ├── Disjoint Set Union.cpp ├── Priority Queue.cpp ├── Segment Tree.cpp ├── Suffix Array + LCP Array.cpp ├── Trie.cpp ├── Bit Queue.cpp ├── Suffix Automaton.cpp ├── XOR Linked List.c ├── Pairing Heap.cpp ├── Link-cut Tree.cpp ├── Binomial Heap.cpp ├── Proto-vEB Tree.cpp ├── Circular Doubly-Linked List.cpp ├── Fibonacci Heap.cpp └── van Emde Boas Tree.cpp ├── Dynamic Programming ├── Matrix Chain Multiplication.cpp ├── 0-1 Knapsack.cpp ├── Unbounded Knapsack.cpp ├── Longest Common Subsequence.cpp ├── Needleman-Wunsch.cpp ├── Nussinov Algorithm.cpp └── Segmented Least Squares.cpp ├── String Algorithms ├── Knuth-Morris-Pratt.cpp └── Z Algorithm.cpp ├── Graph Algorithms ├── Depth-First Search.cpp ├── Breadth-First Search.cpp ├── Floyd-Warshall Algorithm.cpp ├── Connected Components.cpp ├── Topological Sorting.cpp ├── Bellman-Ford Algorithm.cpp ├── Cycle Detection.cpp ├── Tarjan's SCC Algorithm.cpp ├── Kruskal's Algorithm.cpp ├── Dijkstra's Algorithm.cpp ├── Ford-Fulkerson Algorithm.cpp ├── Heavy-Light Decomposition.cpp ├── Edmonds-Karp Algorithm.cpp ├── Dinic's Algorithm.cpp ├── Kosaraju's Algorithm.cpp └── Prim's Algorithm.cpp ├── Greedy Algorithms ├── Interval Scheduling.cpp └── First-Fit Bin Packing.cpp ├── Miscellaneous └── Fast Input (Thanks to Ermin Hodzic).cpp ├── Geometric Algorithms ├── Segment Intersection.cpp ├── Point in Convex Polygon.cpp └── Graham Scan.cpp └── Compression Algorithms └── Huffman Coding.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /Mathematical Algorithms/Euclidean Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Euclidean Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | //Euklidov algoritam za racunanje najveceg zajednickog delioca (NZD) dva broja 23 | //Slozenost: O(log^2 N) 24 | 25 | int gcd(int a, int b) 26 | { 27 | if (a%b == 0) return b; 28 | return gcd(b,a%b); 29 | } 30 | 31 | int main() 32 | { 33 | printf("%d\n",gcd(6,15)); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Algorithms 2 | ========== 3 | 4 | This repository contains my implementations of several algorithms and data structures in C++ (credited to others where necessary). It has initially started out as a repository used for programming contests, but has since then grown into a repository involving a wide variety of implementations not typically useful for such events. 5 | Will be updated periodically. You are free to use these codes wherever you want without permission. This comes without any warranties though! 6 | 7 | Pull requests 8 | ---------------- 9 | If you spot any errors in the implementation(s), please let me know by submitting a relevant pull request. Furthermore, if you'd like to see a particular data structure or algorithm implemented here, let me know by raising an issue. 10 | 11 | License 12 | ---------------- 13 | MIT 14 | -------------------------------------------------------------------------------- /Recursion, Backtracking etc./Power Set.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Power Set 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | //Metoda koja generise partitivni skup nekog skupa 23 | //Slozenost: O(2^n) 24 | 25 | int n; 26 | int skup[100]; 27 | bool inSet[100]; 28 | 29 | void powerSet(int pos) 30 | { 31 | if (pos==n) 32 | { 33 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #define EPS 1e-12 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | //Ternarna pretraga maksimuma/minimuma funkcije koja menja monotonost najviše jednom 23 | //Slozenost: O(log n) 24 | 25 | inline double f(double x) 26 | { 27 | return x*x + x - 1; 28 | } 29 | 30 | inline double ter_search(double left, double right) 31 | { 32 | if (right - left < EPS) return (left+right)/2.0; 33 | double leftThird = (2.0*left + right)/3.0; 34 | double rightThird = (left + 2.0*right)/3.0; 35 | if (f(leftThird) > f(rightThird)) return ter_search(leftThird, right); 36 | else return ter_search(left, rightThird); 37 | } 38 | 39 | int main() 40 | { 41 | printf("%.6lf\n",ter_search(-5.0, 1.0)); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /Mathematical Algorithms/Sieve of Eratosthenes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Sieve of Eratosthenes 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | vector primes; 24 | bool mark[MAX_N]; 25 | 26 | //Algoritam koji izdvaja sve proste brojeve do broja B 27 | //Slozenost: O(N log log N) 28 | 29 | inline void sieve(int B) 30 | { 31 | if (B > 1) primes.push_back(2); 32 | for (int i=3;i<=B;i+=2) 33 | { 34 | if (!mark[i]) 35 | { 36 | mark[i]=true; 37 | primes.push_back(i); 38 | if (i<=sqrt(B)+1) for (int j=i*i;j<=B;j+=i) mark[j]=true; 39 | } 40 | } 41 | } 42 | 43 | int main() 44 | { 45 | sieve(30); 46 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | //Algoritam za stepenovanje kvadriranjem po datom modulu i za racunanje modularnog inverza (pod uslovom da je modul prost) 23 | //Slozenost O(log N) 24 | 25 | inline lld mod_pow(lld num, lld pow, lld mod) 26 | { 27 | lld ret = 1; 28 | while (pow) 29 | { 30 | if (pow&1) 31 | { 32 | ret = (ret*num)%mod; 33 | } 34 | pow>>=1; 35 | num = (num*num)%mod; 36 | } 37 | return ret; 38 | } 39 | 40 | inline lld mod_inv(lld num, lld mod) 41 | { 42 | return mod_pow(num, mod-2, mod); 43 | } 44 | 45 | int main() 46 | { 47 | printf("%lld\n",mod_pow(5,2,10)); 48 | printf("%lld\n",mod_inv(1423,13)); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /Sorting Algorithms/Insertion Sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Insertion Sort 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int niz[MAX_N]; 25 | 26 | //Insertion sort algoritam za sortiranje niza 27 | //Slozenost: O(n^2) 28 | 29 | inline void insertionSort() 30 | { 31 | for (int i=1;i= 0 && niz[j] > tmp) 36 | { 37 | niz[j+1] = niz[j]; 38 | j--; 39 | } 40 | niz[j+1] = tmp; 41 | } 42 | } 43 | 44 | int main() 45 | { 46 | n = 5; 47 | niz[0] = 4; 48 | niz[1] = 2; 49 | niz[2] = 5; 50 | niz[3] = 1; 51 | niz[4] = 3; 52 | insertionSort(); 53 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, x; 24 | int niz[MAX_N]; 25 | 26 | //Binarna pretraga elementa u sortiranom nizu 27 | //Slozenost: O(log n) 28 | 29 | inline int b_search(int left, int right, int x) 30 | { 31 | int i = left; 32 | int j = right; 33 | while (i < j) 34 | { 35 | int mid = (i+j)/2; 36 | if (niz[mid] == x) return mid; 37 | if (niz[mid] < x) i = mid+1; 38 | else j = mid-1; 39 | } 40 | if (niz[i] == x) return i; 41 | return -1; 42 | } 43 | 44 | int main() 45 | { 46 | n = 5, x = 4; 47 | niz[0] = 1; 48 | niz[1] = 2; 49 | niz[2] = 3; 50 | niz[3] = 4; 51 | niz[4] = 5; 52 | printf("%d\n",b_search(0, n-1, x)); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Data Structures/Binary Indexed Tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Binary Indexed Tree 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int bit[MAX_N]; 25 | 26 | //Struktura za efikasno cuvanje kumulativnih suma 27 | //Slozenost: O(log N) po operaciji 28 | 29 | inline void update(int x, int val) 30 | { 31 | while (x <= n) 32 | { 33 | bit[x] += val; 34 | x += (x & -x); 35 | } 36 | } 37 | 38 | inline int read(int x) 39 | { 40 | int ret = 0; 41 | while (x > 0) 42 | { 43 | ret += bit[x]; 44 | x -= (x & -x); 45 | } 46 | return ret; 47 | } 48 | 49 | int main() 50 | { 51 | n = 10; 52 | update(1, 1); 53 | update(3, 1); 54 | update(5, 5); 55 | update(2, -2); 56 | update(5, -1); 57 | printf("%d\n",read(6)); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /Sorting Algorithms/Selection Sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Selection Sort 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int niz[MAX_N]; 25 | 26 | //Selection sort algoritam za sortiranje niza 27 | //Slozenost: O(n^2) 28 | 29 | inline void selectionSort() 30 | { 31 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | int n, k; 23 | int skup[100]; 24 | bool inSet[100]; 25 | 26 | //Program koji generise sve kombinacije od po K elemenata datog skupa 27 | //Slozenost: O((n choose k)) 28 | 29 | void kCombinations(int pos, int amt) 30 | { 31 | if (n-pos 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | int n; 23 | int niz[100]; 24 | bool inPerm[100]; 25 | int currPerm[100]; 26 | 27 | //Algoritam koji generise sve permutacije datog niza 28 | //Slozenost: O(n!) 29 | 30 | void generatePermutations(int pos) 31 | { 32 | if (pos == n) 33 | { 34 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | #define MAX_K 1000001 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | int n; 25 | int niz[MAX_N]; 26 | int Count[MAX_K]; 27 | 28 | //Counting sort algoritam za sortiranje niza pozitivnih celih brojeva ne vecih od MAX_K 29 | //Slozenost: O(n + k) 30 | 31 | void countingSort() 32 | { 33 | for (int i=0;i 0) 38 | { 39 | niz[ii++] = i; 40 | Count[i]--; 41 | } 42 | } 43 | } 44 | 45 | int main() 46 | { 47 | n = 5; 48 | niz[0] = 4; 49 | niz[1] = 2; 50 | niz[2] = 5; 51 | niz[3] = 1; 52 | niz[4] = 3; 53 | countingSort(); 54 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int niz[MAX_N]; 25 | 26 | //Bubble sort algoritam za sortiranje niza 27 | //Slozenost: O(n^2) 28 | 29 | inline void bubbleSort() 30 | { 31 | bool swapped; 32 | int it = 0; 33 | do 34 | { 35 | swapped = false; 36 | for (int i=0;i niz[i+1]) 39 | { 40 | swap(niz[i], niz[i+1]); 41 | swapped = true; 42 | } 43 | } 44 | it++; 45 | } while (swapped); 46 | } 47 | 48 | int main() 49 | { 50 | n = 5; 51 | niz[0] = 4; 52 | niz[1] = 2; 53 | niz[2] = 5; 54 | niz[3] = 1; 55 | niz[4] = 3; 56 | bubbleSort(); 57 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 305 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | int n; 25 | int p[MAX_N]; 26 | int m[MAX_N][MAX_N]; 27 | int memo[MAX_N][MAX_N]; 28 | 29 | //Algoritam koji odredjuje optimalan redosled mnozenja N matrica 30 | //Dimenzije i-te matrice su: p[i-1] x p[i] 31 | //Slozenost: O(N^3) 32 | 33 | inline int MatrixChainMultiplication(int i, int j) 34 | { 35 | if (i == j) return 0; 36 | if (memo[i][j] > 0) return memo[i][j]; 37 | int ret = INF; 38 | for (int k=i;k 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int niz[MAX_N]; 25 | 26 | //Quicksort algoritam za sortiranje niza 27 | //Slozenost: O(n log n) 28 | 29 | void qsort(int left, int right) 30 | { 31 | if (left < right) 32 | { 33 | int i = left; 34 | int j = right; 35 | int pivot = niz[(i+j)/2]; 36 | while (i<=j) 37 | { 38 | while (niz[i]pivot) j--; 40 | if (i<=j) 41 | { 42 | swap(niz[i], niz[j]); 43 | i++; 44 | j--; 45 | } 46 | } 47 | qsort(left,j); 48 | qsort(i,right); 49 | } 50 | } 51 | 52 | int main() 53 | { 54 | n = 5; 55 | niz[0] = 4; 56 | niz[1] = 2; 57 | niz[2] = 5; 58 | niz[3] = 1; 59 | niz[4] = 3; 60 | qsort(0, n-1); 61 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | int n, capacity; 23 | int Weight[101], Value[101], Sol[1001]; 24 | 25 | //Algoritam za odredjivanje maksimalne vrednosti koja moze stati u ranac datog kapaciteta 26 | //Mozemo uzeti tacno jedan komad od svake vrste predmeta 27 | //Slozenost O(n*K) 28 | 29 | inline int Knapsack01() 30 | { 31 | for (int i=0;i<=capacity;i++) Sol[i] = 0; 32 | for (int i=0;i=1;j--) 35 | { 36 | if (Weight[i] <= j) 37 | { 38 | int x = Sol[j]; 39 | int y = Sol[j-Weight[i]]+Value[i]; 40 | Sol[j] = max(x,y); 41 | } 42 | } 43 | } 44 | return Sol[capacity]; 45 | } 46 | 47 | int main() 48 | { 49 | n = 4, capacity = 6; 50 | Weight[0] = 1, Value[0] = 4; 51 | Weight[1] = 2, Value[1] = 6; 52 | Weight[2] = 3, Value[2] = 12; 53 | Weight[3] = 2, Value[3] = 7; 54 | printf("%d\n",Knapsack01()); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /String Algorithms/Knuth-Morris-Pratt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Knuth-Morris-Pratt 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, m; 24 | string needle, haystack; 25 | int P[MAX_N]; 26 | vector matches; 27 | 28 | //Knuth-Morris-Pratt algoritam za string matching 29 | //Slozenost: O(N + M) 30 | 31 | inline void KMP() 32 | { 33 | for (int i=0;i -1 && needle[i] != needle[j]) j = P[j]; 37 | i++; 38 | j++; 39 | P[i] = j; 40 | } 41 | for (int i=0, j=0;i -1 && haystack[i] != needle[j]) j = P[j]; 44 | i++; 45 | j++; 46 | if (j == m) 47 | { 48 | matches.push_back(i - m); 49 | j = P[j]; 50 | } 51 | } 52 | } 53 | 54 | int main() 55 | { 56 | n = 6, m = 2; 57 | haystack = "abcabc"; 58 | needle = "bc"; 59 | KMP(); 60 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | struct Node 24 | { 25 | vector adj; 26 | }; 27 | Node graf[MAX_N]; 28 | bool mark[MAX_N]; 29 | 30 | //Algoritam za pretrazivanje grafa u dubinu 31 | //Slozenost: O(V + E) 32 | 33 | inline void DFS(int start) 34 | { 35 | stack dfs_stek; 36 | dfs_stek.push(start); 37 | while (!dfs_stek.empty()) 38 | { 39 | int xt = dfs_stek.top(); 40 | dfs_stek.pop(); 41 | mark[xt] = true; 42 | printf("Traversing Node ID %d\n", xt); 43 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | struct Node 24 | { 25 | vector adj; 26 | }; 27 | Node graf[MAX_N]; 28 | bool mark[MAX_N]; 29 | 30 | //Algoritam za pretrazivanje grafa u sirinu 31 | //Slozenost: O(V + E) 32 | 33 | inline void BFS(int start) 34 | { 35 | queue bfs_queue; 36 | bfs_queue.push(start); 37 | while (!bfs_queue.empty()) 38 | { 39 | int xt = bfs_queue.front(); 40 | bfs_queue.pop(); 41 | mark[xt] = true; 42 | printf("Traversing Node ID %d\n", xt); 43 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 100001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | 25 | struct Interval 26 | { 27 | int L, R; 28 | bool operator <(const Interval &a) const 29 | { 30 | if (R != a.R) return (R < a.R); 31 | return (L < a.L); 32 | } 33 | }; 34 | Interval I[MAX_N]; 35 | 36 | //Algoritam koji odredjuje maksimalan broj disjunktnih intervala iz nekog skupa 37 | //Slozenost: O(n log n) 38 | 39 | inline int ScheduleIntervals() 40 | { 41 | sort(I, I+n); 42 | 43 | int ret = 1; 44 | int currentEnd = I[0].R; 45 | 46 | for (int i=1;i= currentEnd) 49 | { 50 | currentEnd = I[i].R; 51 | ret++; 52 | } 53 | } 54 | 55 | return ret; 56 | } 57 | 58 | int main() 59 | { 60 | n = 4; 61 | 62 | I[0].L = -1, I[0].R = 1; 63 | I[1].L = 0, I[1].R = 5; 64 | I[2].L = 2, I[2].R = 3; 65 | I[3].L = 5, I[3].R = 9; 66 | 67 | printf("%d\n",ScheduleIntervals()); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /Dynamic Programming/Unbounded Knapsack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Unbounded Knapsack 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | int n, capacity; 23 | int Weight[101], Value[101], Sol[1001]; 24 | 25 | //Algoritam za odredjivanje maksimalne vrednosti koja moze stati u ranac datog kapaciteta 26 | //Mozemo uzimati beskonacno od svake vrste predmeta 27 | //Slozenost O(n*K) 28 | 29 | inline int Knapsack() 30 | { 31 | Sol[0] = 0; 32 | for (int i=1;i<=capacity;i++) 33 | { 34 | int maks = 0; 35 | int tek; 36 | for (int j=0;j maks) maks = tek; 42 | } 43 | } 44 | Sol[i] = maks; 45 | } 46 | return Sol[capacity]; 47 | } 48 | 49 | int main() 50 | { 51 | n = 5, capacity = 17; 52 | Weight[0] = 3, Value[0] = 4; 53 | Weight[1] = 4, Value[1] = 5; 54 | Weight[2] = 7, Value[2] = 10; 55 | Weight[3] = 8, Value[3] = 11; 56 | Weight[4] = 9, Value[4] = 13; 57 | printf("%d\n",Knapsack()); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /Searching Algorithms/Quickselect.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Quickselect 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, k; 24 | int niz[MAX_N]; 25 | 26 | //Quickselect algoritam za nalazenje k-tog elementa u nizu 27 | //Slozenost: O(n) 28 | 29 | int qselect(int left, int right, int k) 30 | { 31 | if (left < right) 32 | { 33 | int pivotIndex = left; 34 | int pivot = niz[(left+right)/2]; 35 | swap(niz[(left+right)/2], niz[right]); 36 | for (int i=left;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 300 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | int n; 25 | 26 | int dist[MAX_N][MAX_N]; 27 | int flojd[MAX_N][MAX_N]; 28 | 29 | //Floyd-Warshallov algoritam za trazenje duzina najkracih puteva svih parova cvorova u grafu 30 | //Slozenost: O(V^3) 31 | 32 | inline void FloydWarshall() 33 | { 34 | for (int i=1;i<=n;i++) 35 | { 36 | for (int j=1;j<=n;j++) 37 | { 38 | flojd[i][j] = dist[i][j]; 39 | } 40 | flojd[i][i] = 0; 41 | } 42 | for (int k=1;k<=n;k++) 43 | { 44 | for (int i=1;i<=n;i++) 45 | { 46 | for (int j=1;j<=n;j++) 47 | { 48 | if (flojd[i][k] + flojd[k][j] < flojd[i][j]) 49 | { 50 | flojd[i][j] = flojd[i][k] + flojd[k][j]; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | int main() 58 | { 59 | n = 3; 60 | dist[1][1] = 0, dist[1][2] = 3, dist[1][3] = INF; 61 | dist[2][1] = INF, dist[2][2] = 0, dist[2][3] = 4; 62 | dist[3][1] = INF, dist[3][2] = 1, dist[3][3] = 0; 63 | FloydWarshall(); 64 | printf("%d\n",flojd[1][3]); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /String Algorithms/Z Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Z Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, m; 24 | string needle, haystack; 25 | int Z[MAX_N]; 26 | vector matches; 27 | 28 | //Z Algoritam koji racuna Z-funkciju nad datim stringom; moze se koristiti za efikasan string matching 29 | //Slozenost: O(N + M) 30 | 31 | inline void Z_Algorithm(string s) 32 | { 33 | int len = s.length(); 34 | int L = 0, R = 0; 35 | for (int i=1;i R) 38 | { 39 | L = R = i; 40 | while (R < len && s[R-L] == s[R]) R++; 41 | Z[i] = R-L; 42 | R--; 43 | } 44 | else 45 | { 46 | int k = i - L; 47 | if (Z[k] < R-i+1) Z[i] = Z[k]; 48 | else 49 | { 50 | L = i; 51 | while (R < len && s[R-L] == s[R]) R++; 52 | Z[i] = R - L; 53 | R--; 54 | } 55 | } 56 | if (Z[i] == m) matches.push_back(i - m - 1); 57 | } 58 | } 59 | 60 | int main() 61 | { 62 | n = 6, m = 2; 63 | haystack = "abcabc"; 64 | needle = "bc"; 65 | Z_Algorithm(needle + "#" + haystack); 66 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define LIMIT 1000000 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | char buffer[LIMIT], * pos = buffer + LIMIT; 24 | 25 | //Algoritam za brzo ucitavanje odredjenih tipova podataka 26 | //date metode za char, long long/int, float/double, char[] 27 | 28 | inline char getnext(){ 29 | if (pos == buffer + LIMIT){ 30 | pos = buffer; 31 | fread(buffer, 1, LIMIT, stdin); 32 | } 33 | return *pos++; 34 | } 35 | 36 | inline lld getint() 37 | { 38 | lld num = 0; 39 | bool sign = 0; 40 | char cc; 41 | while ( !isdigit(cc = getnext()) ) if (cc == '-') sign = 1; 42 | do { num = num * 10 + cc - '0'; } while ( isdigit(cc = getnext()) ); 43 | if (sign) return -num; 44 | else return num; 45 | } 46 | 47 | inline double getfloat() 48 | { 49 | double num=0,rest=1; 50 | int sign=1; 51 | while ((cc=getnext())<'0' || cc>'9') 52 | if (cc=='-') sign=-1; 53 | do { 54 | num=num*10+cc-'0'; 55 | } 56 | while ((cc=getnext())>='0' && cc<='9'); 57 | while ((cc=getnext())>='0' && cc<='9'){ 58 | rest/=10; 59 | num+=rest*(cc-'0'); 60 | } 61 | return num*sign; 62 | } 63 | 64 | inline void getstr(char niz[]) 65 | { 66 | int i=0; 67 | char cc; 68 | while (!isalnum(cc=getnext())); 69 | do { 70 | niz[i++]=cc; 71 | } 72 | while (isalnum((cc=getnext()))); 73 | niz[i]='\0'; 74 | } 75 | -------------------------------------------------------------------------------- /Data Structures/Disjoint Set Union.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Disjoint Set Union 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int numComponents, m; 24 | 25 | struct Node 26 | { 27 | int parent; 28 | int rank; 29 | }; 30 | Node DSU[MAX_N]; 31 | 32 | //Struktura za rad sa disjunktnim skupovima 33 | //Slozenost: Amortizovano O(alfa(N)) po operaciji 34 | 35 | inline void MakeSet(int x) 36 | { 37 | DSU[x].parent = x; 38 | DSU[x].rank = 0; 39 | } 40 | 41 | inline int Find(int x) 42 | { 43 | if (DSU[x].parent == x) return x; 44 | DSU[x].parent = Find(DSU[x].parent); 45 | return DSU[x].parent; 46 | } 47 | 48 | inline void Union(int x, int y) 49 | { 50 | int xRoot = Find(x); 51 | int yRoot = Find(y); 52 | if (xRoot == yRoot) return; 53 | numComponents--; 54 | if (DSU[xRoot].rank < DSU[yRoot].rank) 55 | { 56 | DSU[xRoot].parent = yRoot; 57 | } 58 | else if (DSU[xRoot].rank > DSU[yRoot].rank) 59 | { 60 | DSU[yRoot].parent = xRoot; 61 | } 62 | else 63 | { 64 | DSU[yRoot].parent = xRoot; 65 | DSU[xRoot].rank++; 66 | } 67 | } 68 | 69 | int main() 70 | { 71 | numComponents = 4, m = 8; 72 | 73 | MakeSet(1); 74 | MakeSet(2); 75 | MakeSet(3); 76 | MakeSet(4); 77 | 78 | Union(1, 2); 79 | Union(2, 1); 80 | Union(2, 3); 81 | Union(1, 3); 82 | 83 | printf("%d\n",numComponents); 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /Dynamic Programming/Longest Common Subsequence.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Longest Common Subsequence 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, m; 24 | string A, B; 25 | int dp[MAX_N][MAX_N]; 26 | 27 | //Algoritam koji racuna najduzu zajednicku podsekvencu dva stringa 28 | //Slozenost: O(n*m) 29 | 30 | inline int LCS() 31 | { 32 | for (int i=0;i<=n;i++) dp[i][0] = 0; 33 | for (int j=0;j<=m;j++) dp[0][j] = 0; 34 | for (int i=1;i<=n;i++) 35 | { 36 | for (int j=1;j<=m;j++) 37 | { 38 | if (A[i-1] == B[j-1]) 39 | { 40 | dp[i][j] = dp[i-1][j-1] + 1; 41 | } 42 | else 43 | { 44 | dp[i][j] = max(dp[i][j-1], dp[i-1][j]); 45 | } 46 | } 47 | } 48 | return dp[n][m]; 49 | } 50 | 51 | inline string getLCS() 52 | { 53 | string ret; 54 | stack S; 55 | int ii = n, jj = m; 56 | while (ii != 0 && jj != 0) 57 | { 58 | if (A[ii-1] == B[jj-1]) 59 | { 60 | S.push(A[ii-1]); 61 | ii--; jj--; 62 | } 63 | else if (dp[ii-1][jj] > dp[ii][jj-1]) ii--; 64 | else jj--; 65 | } 66 | while (!S.empty()) 67 | { 68 | ret += S.top(); 69 | S.pop(); 70 | } 71 | return ret; 72 | } 73 | 74 | int main() 75 | { 76 | n = 5, m = 6; 77 | A = "aleks"; 78 | B = "abcdef"; 79 | printf("%d\n",LCS()); 80 | printf("%s\n",getLCS().c_str()); 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /Mathematical Algorithms/Matrix Multiplication.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Matrix Multiplication 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | /* 23 | Naive algorithm for matrix multiplication of two matrices, A (of size n*l) and B (of size l*m). 24 | Complexity: O(nlm) 25 | */ 26 | 27 | inline lld** MatrixMultiply(lld** a, lld** b, int n, int l, int m) 28 | { 29 | lld **c = new lld*[n]; 30 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int niz[MAX_N], tmp[MAX_N]; 25 | 26 | //Merge sort algoritam za sortiranje niza 27 | //Slozenost: O(n log n) 28 | 29 | inline void merge(int left, int mid, int right) 30 | { 31 | int h,i,j,k; 32 | h = left; 33 | i = left; 34 | j = mid+1; 35 | while (h <= mid && j <= right) 36 | { 37 | if (niz[h] <= niz[j]) 38 | { 39 | tmp[i] = niz[h]; 40 | h++; 41 | } 42 | else 43 | { 44 | tmp[i] = niz[j]; 45 | j++; 46 | } 47 | i++; 48 | } 49 | if (h > mid) 50 | { 51 | for(k=j;k<=right;k++) 52 | { 53 | tmp[i] = niz[k]; 54 | i++; 55 | } 56 | } 57 | else 58 | { 59 | for(k=h;k<=mid;k++) 60 | { 61 | tmp[i] = niz[k]; 62 | i++; 63 | } 64 | } 65 | for(k=left;k<=right;k++) niz[k] = tmp[k]; 66 | } 67 | 68 | void mergeSort(int left, int right) 69 | { 70 | if (left == right) return; 71 | int MID = (left+right)/2; 72 | mergeSort(left, MID); 73 | mergeSort(MID+1, right); 74 | merge(left, MID, right); 75 | } 76 | 77 | int main() 78 | { 79 | n = 5; 80 | niz[0] = 4; 81 | niz[1] = 2; 82 | niz[2] = 5; 83 | niz[3] = 1; 84 | niz[4] = 3; 85 | mergeSort(0, n-1); 86 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int PQ[MAX_N]; 24 | int heap_size = 0; 25 | 26 | //Prioritetni red implementiran kao min-heap 27 | //Slozenost: O(log N) za Push/Pop, O(1) za Empty/GetMinimum 28 | 29 | inline bool Empty() 30 | { 31 | return (heap_size == 0); 32 | } 33 | 34 | inline int GetMinimum() 35 | { 36 | if (Empty()) return -1; 37 | return PQ[1]; 38 | } 39 | 40 | inline void Push(int x) 41 | { 42 | PQ[++heap_size] = x; 43 | int pos = heap_size; 44 | while (pos > 1 && PQ[pos/2] > PQ[pos]) 45 | { 46 | swap(PQ[pos/2], PQ[pos]); 47 | pos /= 2; 48 | } 49 | } 50 | 51 | inline void Pop() 52 | { 53 | if (Empty()) return; 54 | int pos = 1; 55 | swap(PQ[pos], PQ[heap_size--]); 56 | while (pos <= heap_size) 57 | { 58 | int ret = pos; 59 | int left = pos*2; 60 | int right = pos*2+1; 61 | if (left <= heap_size && PQ[left] < PQ[ret]) ret = left; 62 | if (right <= heap_size && PQ[right] < PQ[ret]) ret = right; 63 | if (ret != pos) 64 | { 65 | swap(PQ[pos], PQ[ret]); 66 | pos = ret; 67 | } 68 | else break; 69 | } 70 | } 71 | 72 | int main() 73 | { 74 | Push(5); 75 | Push(3); 76 | Push(8); 77 | Push(4); 78 | Push(11); 79 | while (!Empty()) 80 | { 81 | printf("%d ",GetMinimum()); 82 | Pop(); 83 | } 84 | printf("\n"); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /Graph Algorithms/Connected Components.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Connected Components 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | 25 | struct Node 26 | { 27 | vector adj; 28 | }; 29 | Node graf[MAX_N]; 30 | bool mark[MAX_N]; 31 | 32 | //Algoritam za odredjivanje broja povezanih komponenti neusmerenog grafa, koristeci DFS 33 | //Slozenost: O(V + E) 34 | 35 | inline void DFS(int start) 36 | { 37 | stack dfs_stek; 38 | dfs_stek.push(start); 39 | while (!dfs_stek.empty()) 40 | { 41 | int xt = dfs_stek.top(); 42 | dfs_stek.pop(); 43 | mark[xt] = true; 44 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 1000001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | int niz[MAX_N]; 25 | 26 | int heap_size; 27 | 28 | //Heapsort algoritam za sortiranje niza 29 | //Slozenost: O(n log n) 30 | 31 | inline void Heapify(int pos) 32 | { 33 | if (pos > heap_size) return; 34 | int ret = pos; 35 | int left = pos*2; 36 | int right = pos*2+1; 37 | if (left <= heap_size && niz[left] > niz[ret]) ret = left; 38 | if (right <= heap_size && niz[right] > niz[ret]) ret = right; 39 | if (ret != pos) 40 | { 41 | swap(niz[pos], niz[ret]); 42 | Heapify(ret); 43 | } 44 | } 45 | 46 | inline void Pop() 47 | { 48 | int pos = 1; 49 | swap(niz[pos], niz[heap_size--]); 50 | while (pos <= heap_size) 51 | { 52 | int ret = pos; 53 | int left = pos*2; 54 | int right = pos*2+1; 55 | if (left <= heap_size && niz[left] > niz[ret]) ret = left; 56 | if (right <= heap_size && niz[right] > niz[ret]) ret = right; 57 | if (ret != pos) 58 | { 59 | swap(niz[pos], niz[ret]); 60 | pos = ret; 61 | } 62 | else break; 63 | } 64 | } 65 | 66 | int main() 67 | { 68 | n = 5; 69 | niz[1] = 4; 70 | niz[2] = 2; 71 | niz[3] = 5; 72 | niz[4] = 1; 73 | niz[5] = 3; 74 | 75 | heap_size = n; 76 | 77 | for (int i=n/2;i>=1;i--) Heapify(i); 78 | while (heap_size > 1) Pop(); 79 | 80 | for (int i=1;i<=n;i++) printf("%d ",niz[i]); 81 | printf("\n"); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /Graph Algorithms/Topological Sorting.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Topological Sorting 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | 25 | struct Node 26 | { 27 | vector adj; 28 | }; 29 | Node graf[MAX_N]; 30 | bool mark[MAX_N]; 31 | 32 | int indegree[MAX_N]; 33 | int toposort[MAX_N]; 34 | 35 | //Algoritam za topolosko sortiranje usmerenog grafa; moze se koristiti i za otkrivanje ciklusa 36 | //Slozenost: O(V + E) 37 | 38 | inline int TopoSort() 39 | { 40 | queue S; 41 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | struct Point 23 | { 24 | double X, Y; 25 | Point(double x, double y) 26 | { 27 | this->X = x; 28 | this->Y = y; 29 | } 30 | }; 31 | 32 | //Algoritam koji odredjuje da li postoji presek izmedju dve 2D duzi (AB i CD) 33 | //Slozenost: O(1) 34 | 35 | inline double crossProduct(Point a, Point b, Point c) 36 | { 37 | return ((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)); 38 | } 39 | 40 | inline bool isLeft(Point a, Point b, Point c) 41 | { 42 | return (crossProduct(a, b, c) > 0); 43 | } 44 | 45 | inline bool isCollinear(Point a, Point b, Point c) 46 | { 47 | return (crossProduct(a, b, c) == 0); 48 | } 49 | 50 | inline bool oppositeSides(Point a, Point b, Point c, Point d) 51 | { 52 | return (isLeft(a, b, c) != isLeft(a, b, d)); 53 | } 54 | 55 | inline bool isBetween(Point a, Point b, Point c) 56 | { 57 | return (min(a.X, b.X) <= c.X && c.X <= max(a.X, b.X) && min(a.Y, b.Y) <= c.Y && c.Y <= max(a.Y,b.Y)); 58 | } 59 | 60 | inline bool intersect(Point a, Point b, Point c, Point d) 61 | { 62 | if (isCollinear(a, b, c) && isBetween(a, b, c)) return true; 63 | if (isCollinear(a, b, d) && isBetween(a, b, d)) return true; 64 | if (isCollinear(c, d, a) && isBetween(c, d, a)) return true; 65 | if (isCollinear(c, d, b) && isBetween(c, d, b)) return true; 66 | return (oppositeSides(a, b, c, d) && oppositeSides(c, d, a, b)); 67 | } 68 | 69 | int main() 70 | { 71 | Point A(0.0, 0.0), B(0.0, 2.0), C(-1.0, 2.0), D(1.0, 2.0); 72 | printf(intersect(A,B,C,D) ? "YES" : "NO"); 73 | printf("\n"); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /Graph Algorithms/Bellman-Ford Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Bellman-Ford Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | #define MAX_E 25000001 21 | #define INF 987654321 22 | using namespace std; 23 | typedef long long lld; 24 | 25 | int v, e; 26 | 27 | int dist[MAX_N]; 28 | struct Edge 29 | { 30 | int x, y, weight; 31 | }; 32 | Edge E[MAX_N]; 33 | 34 | //Bellman-Ford algoritam za trazenje najkracih puteva iz odredjenog cvora u grafu (graf moze imati i negativne ivice) 35 | //Slozenost: O(V*E) 36 | 37 | inline int BellmanFord(int source) 38 | { 39 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MID (left+right)/2 20 | #define MAX_N 1000001 21 | #define MAX_TREE (MAX_N << 2) 22 | #define INF 987654321 23 | using namespace std; 24 | typedef long long lld; 25 | 26 | int n; 27 | int niz[MAX_N]; 28 | int ST[MAX_TREE]; 29 | 30 | //Segmentno stablo nad datim nizom - u datom primeru cuva se minimum nad svakim segmentom 31 | //Slozenost: InitTree O(N), Update O(log N), Query O(log N) 32 | 33 | void InitTree(int idx, int left, int right) 34 | { 35 | if (left == right) 36 | { 37 | ST[idx] = niz[left]; 38 | return; 39 | } 40 | InitTree(2*idx, left, MID); 41 | InitTree(2*idx+1, MID+1, right); 42 | ST[idx] = min(ST[2*idx], ST[2*idx+1]); 43 | } 44 | 45 | void Update(int idx, int x, int val, int left, int right) 46 | { 47 | if (left == right) 48 | { 49 | ST[idx] = val; 50 | return; 51 | } 52 | if (x <= MID) Update(2*idx, x, val, left, MID); 53 | else Update(2*idx+1, x, val, MID+1, right); 54 | ST[idx] = min(ST[2*idx], ST[2*idx+1]); 55 | } 56 | 57 | int Query(int idx, int l, int r, int left, int right) 58 | { 59 | if (l <= left && right <= r) return ST[idx]; 60 | int ret = INF; 61 | if (l <= MID) ret = min(ret, Query(2*idx, l, r, left, MID)); 62 | if (r > MID) ret = min(ret, Query(2*idx+1, l, r, MID+1, right)); 63 | return ret; 64 | } 65 | 66 | int main() 67 | { 68 | n = 6; 69 | niz[1] = 4; 70 | niz[2] = 2; 71 | niz[3] = 5; 72 | niz[4] = 1; 73 | niz[5] = 6; 74 | niz[6] = 3; 75 | 76 | InitTree(1, 1, n); 77 | printf("%d\n",Query(1, 1, 3, 1, n)); 78 | 79 | Update(1, 4, 10, 1, n); 80 | Update(1, 5, 0, 1, n); 81 | printf("%d\n",Query(1, 4, 6, 1, n)); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /Graph Algorithms/Cycle Detection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Cycle Detection 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | 25 | struct Node 26 | { 27 | vector adj; 28 | }; 29 | Node graf[MAX_N]; 30 | bool mark[MAX_N]; 31 | 32 | //Algoritam za trazenje ciklusa u neusmerenom grafu, koristeci DFS 33 | //Slozenost: O(V + E) 34 | 35 | inline bool DFS(int start) 36 | { 37 | stack dfs_stek; 38 | stack previous; 39 | dfs_stek.push(start); 40 | previous.push(-1); 41 | while (!dfs_stek.empty()) 42 | { 43 | int xt = dfs_stek.top(); 44 | int pt = previous.top(); 45 | dfs_stek.pop(); 46 | previous.pop(); 47 | mark[xt] = true; 48 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | /* 23 | Fast algorithm for exponentiation of an n*n matrix that utilizes exponentiation by squaring. 24 | Complexity: O(n^3 log pow) 25 | */ 26 | 27 | inline lld** MatrixMultiply(lld** a, lld** b, int n, int l, int m) 28 | { 29 | lld **c = new lld*[n]; 30 | for (int i=0;i>=1; 63 | a = MatrixMultiply(a, a, n, n, n); 64 | } 65 | 66 | return ret; 67 | } 68 | 69 | int main() 70 | { 71 | lld **matA; 72 | matA = new lld*[2]; 73 | for (int i=0;i<2;i++) matA[i] = new lld[2]; 74 | matA[0][0] = 4; 75 | matA[0][1] = 2; 76 | matA[1][0] = -1; 77 | matA[1][1] = 1; 78 | 79 | lld **matC = MatrixPower(matA, 2, 5); 80 | 81 | for (int i=0;i<2;i++) 82 | { 83 | for (int j=0;j<2;j++) 84 | { 85 | printf("%lld ", matC[i][j]); 86 | } 87 | printf("\n"); 88 | } 89 | 90 | return 0; 91 | } -------------------------------------------------------------------------------- /Data Structures/Suffix Array + LCP Array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Suffix Array + LCP Array 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 90001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, t; 24 | string s; 25 | int SA[MAX_N], LCP[MAX_N]; 26 | int tmp[MAX_N], poz[MAX_N]; 27 | 28 | //Algoritam koji generise sufiksni niz i niz najdužeg zajedničkog prefiksa (LCP) nad datim stringom 29 | //Slozenost: O(n log^2 n) za sufiksni niz, O(n) za LCP niz 30 | 31 | inline bool suff_compare(int i, int j) 32 | { 33 | if (poz[i] != poz[j]) return (poz[i] < poz[j]); 34 | i += t; 35 | j += t; 36 | if (i < n && j < n) return (poz[i] < poz[j]); 37 | else return (i > j); 38 | } 39 | 40 | inline void buildSA() 41 | { 42 | for (int i=0;i 0) k--; 74 | } 75 | } 76 | } 77 | 78 | int main() 79 | { 80 | n = 6; 81 | s = "banana"; 82 | 83 | buildSA(); 84 | buildLCP(); 85 | 86 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | typedef long long lld; 26 | typedef unsigned long long llu; 27 | using namespace std; 28 | 29 | /* 30 | The trie data structure holds a compact representation of all prefixes of 31 | a given dictionary of strings, enabling linear-time lookups. 32 | Complexity: O(n) for adding a string in the dictionary 33 | O(n) for testing whether a string is in the dictionary 34 | */ 35 | 36 | struct TrieNode 37 | { 38 | bool leaf; 39 | unordered_map chd; // can also use an array, or a regular map 40 | 41 | TrieNode() : leaf(false) { } 42 | }; 43 | 44 | TrieNode *root; 45 | 46 | void insert(TrieNode* x, string s, int pos) 47 | { 48 | if (pos == s.length()) x -> leaf = true; 49 | else 50 | { 51 | char cur = s[pos]; 52 | if (x -> chd[cur] == NULL) 53 | { 54 | x -> chd[cur] = new TrieNode(); 55 | } 56 | insert(x -> chd[cur], s, pos + 1); 57 | } 58 | } 59 | 60 | bool find(TrieNode* x, string s, int pos) 61 | { 62 | if (pos == s.length()) return (x -> leaf); 63 | if (x -> chd[s[pos]] == NULL) return false; 64 | return find(x -> chd[s[pos]], s, pos+1); 65 | } 66 | 67 | int main() 68 | { 69 | string s1 = "911"; 70 | string s2 = "97625999"; 71 | string s3 = "91125426"; 72 | 73 | root = new TrieNode(); 74 | 75 | insert(root, s1, 0); 76 | insert(root, s2, 0); 77 | insert(root, s3, 0); 78 | 79 | cout << (find(root, "9", 0) ? "1" : "0") << endl; 80 | cout << (find(root, "91", 0) ? "1" : "0") << endl; 81 | cout << (find(root, "911", 0) ? "1" : "0") << endl; 82 | cout << (find(root, "9112", 0) ? "1" : "0") << endl; 83 | cout << (find(root, "91125426", 0) ? "1" : "0") << endl; 84 | cout << (find(root, "911254267", 0) ? "1" : "0") << endl; 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /Geometric Algorithms/Point in Convex Polygon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Point in Convex Polygon 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 100001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | struct Point 24 | { 25 | double X, Y; 26 | Point() 27 | { 28 | this->X = 0; 29 | this->Y = 0; 30 | } 31 | Point(double x, double y) 32 | { 33 | this->X = x; 34 | this->Y = y; 35 | } 36 | }; 37 | 38 | int n; 39 | Point Polygon[MAX_N]; 40 | 41 | //Algoritam koji odredjuje da li je tacka Q unutar datog konveksnog mnogougla 42 | //Podrazumeva se da su temena mnogougla data u obrnotum smeru kazaljke na satu 43 | //Moze se lako prosiriti u test preseka dva konveksna mnogougla 44 | //Slozenost: O(log N) 45 | 46 | inline int crossProduct(Point a, Point b, Point c) 47 | { 48 | return ((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)); 49 | } 50 | 51 | inline bool isLeft(Point a, Point b, Point c) 52 | { 53 | return (crossProduct(a, b, c) >= 0); 54 | } 55 | 56 | inline bool inTriangle(Point a, Point b, Point c, Point x) 57 | { 58 | return (isLeft(x,a,b) == isLeft(x,b,c) && isLeft(x,b,c) == isLeft(x,c,a)); 59 | } 60 | 61 | inline int b_search(int left, int right, Point Q) 62 | { 63 | int i = left; 64 | int j = right; 65 | while (i < j-1) 66 | { 67 | int mid = (i+j)/2; 68 | if (isLeft(Polygon[0], Polygon[mid], Q)) i = mid; 69 | else j = mid; 70 | } 71 | return i; 72 | } 73 | 74 | bool inPolygon(Point Q) 75 | { 76 | int poz = b_search(1, n-1, Q); 77 | return inTriangle(Polygon[0], Polygon[poz], Polygon[poz+1], Q); 78 | } 79 | 80 | int main() 81 | { 82 | n = 5; 83 | 84 | Polygon[0] = Point(150, 108); 85 | Polygon[1] = Point(250, 103); 86 | Polygon[2] = Point(289, 169); 87 | Polygon[3] = Point(240, 237); 88 | Polygon[4] = Point(120, 195); 89 | 90 | printf(inPolygon(Point(179, 185)) ? "YES\n" : "NO\n"); 91 | printf(inPolygon(Point(216, 90)) ? "YES\n" : "NO\n"); 92 | printf(inPolygon(Point(129, 174)) ? "YES\n" : "NO\n"); 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /Mathematical Algorithms/Pascal's Triangle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Pascal's Triangle 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 5001 20 | #define MAX_K 5001 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | lld binom[MAX_N][MAX_K]; 25 | 26 | int lasti = 0, lastj = 0; 27 | bool init = false; 28 | 29 | //Algoritam za racunanje binomnih koeficijenata preko rekurentne veze (Paskalovog trougla) 30 | //Slozenost: O(n*k) 31 | 32 | inline lld BinomialCoefficient(int n, int k) 33 | { 34 | if (lasti >= n && lastj >= k) return binom[n][k]; 35 | if (!init) 36 | { 37 | for (int i=0;i<=n;i++) binom[i][0] = 1; 38 | for (int j=1;j<=k;j++) binom[0][j] = 0; 39 | for (int i=1;i<=n;i++) 40 | { 41 | for (int j=1;j<=k;j++) 42 | { 43 | binom[i][j] = binom[i-1][j-1] + binom[i-1][j]; 44 | } 45 | } 46 | init = true; 47 | lasti = n; 48 | lastj = k; 49 | return binom[n][k]; 50 | } 51 | else 52 | { 53 | if (lastj < k) 54 | { 55 | for (int i=1;i<=lasti;i++) 56 | { 57 | for (int j=lastj+1;j<=k;j++) 58 | { 59 | binom[i][j] = binom[i-1][j-1] + binom[i-1][j]; 60 | } 61 | } 62 | lastj = k; 63 | } 64 | if (lasti >= n) return binom[n][k]; 65 | else 66 | { 67 | for (int i=lasti+1;i<=n;i++) 68 | { 69 | binom[i][0] = 1; 70 | for (int j=1;j<=lastj;j++) 71 | { 72 | binom[i][j] = binom[i-1][j-1] + binom[i-1][j]; 73 | } 74 | } 75 | lasti = n; 76 | return binom[n][k]; 77 | } 78 | } 79 | } 80 | 81 | int main() 82 | { 83 | printf("%lld\n",BinomialCoefficient(5, 2)); 84 | printf("%lld\n",BinomialCoefficient(7, 1)); 85 | printf("%lld\n",BinomialCoefficient(7, 3)); 86 | printf("%lld\n",BinomialCoefficient(15, 7)); 87 | printf("%lld\n",BinomialCoefficient(10, 4)); 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /Sorting Algorithms/Bitonic Sorter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Bitonic Sorter 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | typedef long long lld; 22 | typedef unsigned long long llu; 23 | using namespace std; 24 | 25 | /* 26 | The Bitonic Sorter is an algorithm for sorting an array of keys. 27 | 28 | While not very efficient in serial form, it can be used to construct 29 | an efficient parallel sorting algorithm (asymptotically slower than 30 | the AKS algorithm, but in practice faster due to constant factors). 31 | 32 | Complexity: O(n log^2 n) serial 33 | O(log^2 n) parallel 34 | */ 35 | 36 | // Comparator between values a and b 37 | void compare(int &a, int &b) 38 | { 39 | if (a > b) swap(a, b); 40 | } 41 | 42 | // Sorts a bitonic sequence A[lo..hi] 43 | void BitonicSorter(int *A, int lo, int hi) 44 | { 45 | if (lo == hi) return; 46 | int len = (hi - lo + 1) >> 1; 47 | int mid = (hi + lo) >> 1; 48 | // first pass: half-cleaner 49 | for (int i=0;i> 1; 59 | // first half of merger: give two bitonic sequences 60 | for (int i=0;i> 1; 71 | Sorter(A, lo, mid); 72 | Sorter(A, mid+1, hi); 73 | Merger(A, lo, mid, hi); 74 | } 75 | 76 | int main() 77 | { 78 | int *x = new int[8]; 79 | x[0] = 10; x[1] = 30; x[2] = 11; x[3] = 20; 80 | x[4] = 4; x[5] = 330; x[6] = 21; x[7] = 110; 81 | 82 | Sorter(x, 0, 7); 83 | 84 | for (int i=0;i<8;i++) printf("%d ", x[i]); 85 | printf("\n"); 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /Geometric Algorithms/Graham Scan.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Graham Scan 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 100001 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | struct Point 25 | { 26 | double X, Y; 27 | Point() 28 | { 29 | this->X = this->Y = 0; 30 | } 31 | Point(double x, double y) 32 | { 33 | this->X = x; 34 | this->Y = y; 35 | } 36 | }; 37 | 38 | int n; 39 | Point P[MAX_N]; 40 | Point R; 41 | 42 | //Grahamov algoritam za nalazenje konveksnog omotaca datog skupa 2D tacaka 43 | //Slozenost: O(N log N) 44 | 45 | inline bool cmp(Point A, Point B) 46 | { 47 | return atan2(A.Y-R.Y,A.X-R.X) < atan2(B.Y-R.Y,B.X-R.X); 48 | } 49 | 50 | inline double CCW(Point a, Point b, Point c) 51 | { 52 | return ((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)); 53 | } 54 | 55 | inline int GrahamScan(vector &cH) 56 | { 57 | int min_id = 1; 58 | for (int i=2;i<=n;i++) 59 | { 60 | if (P[i].Y < P[min_id].Y || (P[i].Y == P[min_id].Y && P[i].X < P[min_id].X)) 61 | { 62 | min_id = i; 63 | } 64 | } 65 | swap(P[1], P[min_id]); 66 | R = P[1]; 67 | sort(P+2, P+n+1, cmp); 68 | 69 | P[0] = P[n]; 70 | int HullSize = 1; 71 | 72 | for (int i=2;i<=n;i++) 73 | { 74 | while (CCW(P[HullSize-1], P[HullSize], P[i]) <= 0) 75 | { 76 | if (HullSize > 1) HullSize--; 77 | else if (i == n) break; 78 | else i++; 79 | } 80 | swap(P[++HullSize], P[i]); 81 | } 82 | 83 | for (int i=1;i<=HullSize;i++) cH.push_back(P[i]); 84 | return HullSize; 85 | } 86 | 87 | int main() 88 | { 89 | n = 4; 90 | 91 | P[1] = Point(4, 8); 92 | P[2] = Point(4, 12); 93 | P[3] = Point(5, 9.3); 94 | P[4] = Point(7, 8); 95 | 96 | vector cH; 97 | int m = GrahamScan(cH); 98 | 99 | printf("Hull size: %d\n",m); 100 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 20001 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | int n, m; 25 | struct Node 26 | { 27 | vector adj; 28 | }; 29 | Node graf[MAX_N]; 30 | stack Stack; 31 | bool onStack[MAX_N]; 32 | int Indices; 33 | int Index[MAX_N]; 34 | int LowLink[MAX_N]; 35 | int component[MAX_N]; 36 | int numComponents; 37 | 38 | //Tarjanov algoritam za racunanje jako povezanih komponenti datog usmerenog grafa 39 | //Slozenost: O(V + E) 40 | 41 | void tarjanDFS(int i) 42 | { 43 | Index[i] = ++Indices; 44 | LowLink[i] = Indices; 45 | Stack.push(i); onStack[i] = true; 46 | for (int j=0;j0;i--) onStack[i] = LowLink[i] = Index[i] = 0; 77 | numComponents = 0; 78 | for (int i=n;i>0;i--) if (Index[i] == 0) tarjanDFS(i); 79 | } 80 | 81 | int main() 82 | { 83 | n = 8, m = 14; 84 | graf[0].adj.push_back(1); 85 | graf[1].adj.push_back(2); 86 | graf[1].adj.push_back(4); 87 | graf[1].adj.push_back(5); 88 | graf[2].adj.push_back(3); 89 | graf[2].adj.push_back(6); 90 | graf[3].adj.push_back(2); 91 | graf[3].adj.push_back(7); 92 | graf[4].adj.push_back(5); 93 | graf[5].adj.push_back(6); 94 | graf[6].adj.push_back(5); 95 | graf[7].adj.push_back(3); 96 | graf[7].adj.push_back(6); 97 | 98 | Tarjan(); 99 | 100 | printf("%d\n",numComponents); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /Mathematical Algorithms/Extended Euclidean Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Extended Euclidean Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | typedef long long lld; 22 | typedef unsigned long long llu; 23 | using namespace std; 24 | 25 | /* 26 | The Extended Euclidean Algorithm, similarly to its basic variant, 27 | calculates the Greatest Common Divisor (GCD) of two integers, a and b. 28 | However, it also computes two integers, x and y, such that a*x + b*y = gcd(a, b). 29 | 30 | This is the preferred method for calculating the modular inverse of a number, 31 | as well as partitioning an integer into subgroups (as per the Chinese Remainder Theorem). 32 | 33 | Complexity: O(log N) 34 | */ 35 | 36 | inline pair > egcd(lld a, lld b) 37 | { 38 | lld aa = 1, ab = 0, ba = 0, bb = 1; 39 | while (true) 40 | { 41 | lld q = a / b; 42 | if (a == b * q) return make_pair(b, make_pair(ba, bb)); 43 | lld tmp_a = a; 44 | lld tmp_aa = aa; 45 | lld tmp_ab = ab; 46 | a = b; 47 | b = tmp_a - b * q; 48 | aa = ba; 49 | ab = bb; 50 | ba = tmp_aa - ba * q; 51 | bb = tmp_ab - bb * q; 52 | } 53 | } 54 | 55 | inline lld modinv(lld a, lld b) 56 | { 57 | lld b0 = b; 58 | lld aa = 1, ba = 0; 59 | while (true) 60 | { 61 | lld q = a / b; 62 | if (a == b * q) 63 | { 64 | if (b != 1) 65 | { 66 | // Modular inverse does not exist! 67 | return -1; 68 | } 69 | while (ba < 0) ba += b0; 70 | return ba; 71 | } 72 | lld tmp_a = a; 73 | lld tmp_aa = aa; 74 | a = b; 75 | b = tmp_a - b * q; 76 | aa = ba; 77 | ba = tmp_aa - ba * q; 78 | } 79 | } 80 | 81 | int main() 82 | { 83 | lld a = 2250, b = 360; 84 | pair > ret = egcd(a, b); 85 | printf("gcd(%lld, %lld) = %lld = %lld * %lld + %lld * %lld\n", a, b, ret.first, a, ret.second.first, b, ret.second.second); 86 | 87 | a = 806515533049393LL, b = 1304969544928657LL; 88 | lld inv = modinv(a, b); 89 | printf("modinv(%lld, %lld) = %lld\n", a, b, inv); 90 | 91 | a = 4505490, b = 7290036; 92 | inv = modinv(a, b); 93 | printf("modinv(%lld, %lld) = %lld\n", a, b, inv); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /Graph Algorithms/Kruskal's Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Kruskal's Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 100001 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n, m; 24 | int numComponents, ret; 25 | 26 | struct Edge 27 | { 28 | int a, b; 29 | int weight; 30 | bool operator <(const Edge &e) const 31 | { 32 | return (weight < e.weight); 33 | } 34 | }; 35 | Edge E[MAX_N]; 36 | 37 | struct Node 38 | { 39 | int parent; 40 | int rank; 41 | }; 42 | Node DSU[MAX_N]; 43 | 44 | //Kruskalov algoritam za racunanje minimalnog stabla razapinjanja datog tezinskog grafa 45 | //Slozenost: O(E log V) 46 | 47 | inline void MakeSet(int x) 48 | { 49 | DSU[x].parent = x; 50 | DSU[x].rank = 0; 51 | } 52 | 53 | inline int Find(int x) 54 | { 55 | if (DSU[x].parent == x) return x; 56 | DSU[x].parent = Find(DSU[x].parent); 57 | return DSU[x].parent; 58 | } 59 | 60 | inline void Union(int x, int y) 61 | { 62 | int xRoot = Find(x); 63 | int yRoot = Find(y); 64 | if (xRoot == yRoot) return; 65 | if (DSU[xRoot].rank < DSU[yRoot].rank) 66 | { 67 | DSU[xRoot].parent = yRoot; 68 | } 69 | else if (DSU[xRoot].rank > DSU[yRoot].rank) 70 | { 71 | DSU[yRoot].parent = xRoot; 72 | } 73 | else 74 | { 75 | DSU[yRoot].parent = xRoot; 76 | DSU[xRoot].rank++; 77 | } 78 | } 79 | 80 | inline int Kruskal() 81 | { 82 | int ret = 0, numComponents = n; 83 | for (int i=0;i 1;i++) 86 | { 87 | if (Find(E[i].a) != Find(E[i].b)) 88 | { 89 | Union(E[i].a, E[i].b); 90 | ret += E[i].weight; 91 | numComponents--; 92 | } 93 | } 94 | if (numComponents > 1) return -1; 95 | return ret; 96 | } 97 | 98 | int main() 99 | { 100 | n = 7, m = 11; 101 | 102 | E[0].a = 0, E[0].b = 1, E[0].weight = 7; 103 | E[1].a = 0, E[1].b = 3, E[1].weight = 5; 104 | E[2].a = 1, E[2].b = 2, E[2].weight = 8; 105 | E[3].a = 1, E[3].b = 3, E[3].weight = 9; 106 | E[4].a = 1, E[4].b = 4, E[4].weight = 7; 107 | E[5].a = 2, E[5].b = 4, E[5].weight = 5; 108 | E[6].a = 3, E[6].b = 4, E[6].weight = 15; 109 | E[7].a = 3, E[7].b = 5, E[7].weight = 6; 110 | E[8].a = 4, E[8].b = 5, E[8].weight = 8; 111 | E[9].a = 4, E[9].b = 6, E[9].weight = 9; 112 | E[10].a = 5, E[10].b = 6, E[10].weight = 11; 113 | 114 | printf("%d\n",Kruskal()); 115 | 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /Graph Algorithms/Dijkstra's Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Dijkstra's Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 100001 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | int n; 25 | 26 | struct Node 27 | { 28 | int dist; 29 | vector adj; 30 | vector weight; 31 | }; 32 | Node graf[MAX_N]; 33 | bool mark[MAX_N]; 34 | 35 | struct pq_entry 36 | { 37 | int node, dist; 38 | bool operator <(const pq_entry &a) const 39 | { 40 | if (dist != a.dist) return (dist > a.dist); 41 | return (node > a.node); 42 | } 43 | }; 44 | 45 | //Dijkstrin algoritam za nalazenje duzina najkracih puteva iz jednog izvora u grafu 46 | //Slozenost: O((V+E)log V) 47 | 48 | inline void Dijkstra(int source) 49 | { 50 | priority_queue pq; 51 | pq_entry P; 52 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define MID (left+right)/2 21 | #define MAX_N 1000001 22 | #define MAX_TREE (MAX_N << 2) 23 | 24 | typedef long long lld; 25 | typedef unsigned long long llu; 26 | using namespace std; 27 | 28 | /* 29 | The bin packing problem attempts to put n items of sizes 0 < s_i < 1 into bins of capacity 1. 30 | The first-fit algorithm utilises a greedy approach to the problem: it works by placing each 31 | item into the first bin it encounters that has enough free space (potentially creating a new 32 | bin if necessary). This implementation takes advantage of a segment tree data structure to 33 | quickly locate the first fit (assuming we know the number of items, n, in advance). 34 | 35 | Complexity: O(n log n) time 36 | O(n) space 37 | 38 | Approximation ratio: 2 39 | */ 40 | 41 | // the number of items to distribute 42 | int n; 43 | // the segment tree; it is an "almost complete" binary tree 44 | // and hence may be represented by an array 45 | double ST[MAX_TREE]; 46 | 47 | // We have inserted an item of size val into the x-th bin 48 | // Toplevel call: Update(1, x, val, 1, n) 49 | void Update(int idx, int x, double val, int left, int right) 50 | { 51 | if (left == right) 52 | { 53 | // leaf node, left == right == x 54 | ST[idx] += val; 55 | return; 56 | } 57 | 58 | // check which subtree the x-th bin belongs to and recurse 59 | if (x <= MID) Update(2*idx, x, val, left, MID); 60 | else Update(2*idx+1, x, val, MID+1, right); 61 | 62 | // store the new minimum fill level of the current (sub)tree 63 | ST[idx] = min(ST[2*idx], ST[2*idx+1]); 64 | } 65 | 66 | // Determine the first fit bin for a given value 67 | // Toplevel call: Query(1, val, 1, n) 68 | int Query(int idx, double val, int left, int right) 69 | { 70 | if (left == right) 71 | { 72 | // leaf node: we have found the first-fit bin! 73 | return left; 74 | } 75 | // check whether the left subtree contains a fitting bin 76 | if (ST[2*idx] <= 1.0 - val) return Query(2*idx, val, left, MID); 77 | else return Query(2*idx+1, val, MID+1, right); 78 | } 79 | 80 | // Fit an item of size val 81 | inline void FirstFit(double val) 82 | { 83 | int first_fit = Query(1, val, 1, n); 84 | Update(1, first_fit, val, 1, n); 85 | printf("Placed item of value %lf in bin ID %d!\n", val, first_fit); 86 | } 87 | 88 | int main() 89 | { 90 | scanf("%d", &n); 91 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 500 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | struct Node 25 | { 26 | vector adj; 27 | }; 28 | Node graf[MAX_N]; 29 | bool mark[MAX_N]; 30 | int cap[MAX_N][MAX_N]; 31 | int parent[MAX_N]; 32 | 33 | int v, e; 34 | int s, t; 35 | 36 | //Ford-Fulkersonov algoritam za nalazenje maksimalnog protoka izmedju dva cvora u grafu 37 | //Moze se koristiti i za nalazenje maksimalnog matchinga 38 | //Slozenost: O(E * maxFlow) 39 | 40 | inline int DFS() 41 | { 42 | int ret = 0; 43 | for (int i=1;i<=v;i++) parent[i] = 0; 44 | stack dfs_stek; 45 | stack minCapacity; 46 | parent[s] = -1; 47 | dfs_stek.push(s); 48 | minCapacity.push(INF); 49 | while (!dfs_stek.empty()) 50 | { 51 | int xt = dfs_stek.top(); 52 | int mt = minCapacity.top(); 53 | dfs_stek.pop(); 54 | minCapacity.pop(); 55 | if (xt == t) 56 | { 57 | ret = mt; 58 | break; 59 | } 60 | for (int i=0;i 0 && parent[xt1] == 0) 64 | { 65 | dfs_stek.push(xt1); 66 | minCapacity.push(min(mt,cap[xt][xt1])); 67 | parent[xt1] = xt; 68 | } 69 | } 70 | } 71 | if (ret > 0) 72 | { 73 | int currNode = t; 74 | while (currNode != s) 75 | { 76 | cap[parent[currNode]][currNode] -= ret; 77 | cap[currNode][parent[currNode]] += ret; 78 | currNode = parent[currNode]; 79 | } 80 | } 81 | return ret; 82 | } 83 | 84 | inline int FordFulkerson() 85 | { 86 | int flow = 0; 87 | while (true) 88 | { 89 | int currFlow = DFS(); 90 | if (currFlow == 0) break; 91 | else flow += currFlow; 92 | } 93 | return flow; 94 | } 95 | 96 | int main() 97 | { 98 | v = 4, e = 5; 99 | s = 1, t = 4; 100 | 101 | graf[1].adj.push_back(2); 102 | graf[2].adj.push_back(1); 103 | cap[1][2] = 40; 104 | 105 | graf[1].adj.push_back(4); 106 | graf[4].adj.push_back(1); 107 | cap[1][4] = 20; 108 | 109 | graf[2].adj.push_back(4); 110 | graf[4].adj.push_back(2); 111 | cap[2][4] = 20; 112 | 113 | graf[2].adj.push_back(3); 114 | graf[3].adj.push_back(2); 115 | cap[2][3] = 30; 116 | 117 | graf[3].adj.push_back(4); 118 | graf[4].adj.push_back(3); 119 | cap[3][4] = 10; 120 | 121 | printf("%d\n",FordFulkerson()); 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /Graph Algorithms/Heavy-Light Decomposition.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Heavy-Light Decomposition 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define MAX_N 1000001 21 | #define INF 987654321 22 | using namespace std; 23 | typedef long long lld; 24 | typedef unsigned long long llu; 25 | 26 | /* 27 | Heavy-Light Decomposition algorithm for partitioning the edges of a tree into two groups - heavy and light. 28 | Can be used for efficient traversal from any node to the root of the tree, since there are at most log n light edges 29 | along that path; hence, we can skip entire chains of heavy edges. 30 | Complexity: O(n) 31 | */ 32 | 33 | struct Node 34 | { 35 | vector adj; 36 | }; 37 | Node graf[MAX_N]; 38 | 39 | struct TreeNode 40 | { 41 | int parent; 42 | int depth; 43 | int chainTop; 44 | int subTreeSize; 45 | }; 46 | TreeNode T[MAX_N]; 47 | 48 | int DFS(int root, int parent, int depth) 49 | { 50 | T[root].parent = parent; 51 | T[root].depth = depth; 52 | T[root].subTreeSize = 1; 53 | for (int i=0;i T[root].subTreeSize*0.5) HLD(xt, root, chainTop); 71 | else HLD(xt, root, xt); 72 | } 73 | } 74 | 75 | inline int LCA(int u, int v) 76 | { 77 | while (T[u].chainTop != T[v].chainTop) 78 | { 79 | if (T[T[u].chainTop].depth < T[T[v].chainTop].depth) v = T[T[v].chainTop].parent; 80 | else u = T[T[u].chainTop].parent; 81 | } 82 | 83 | if (T[u].depth < T[v].depth) return u; 84 | else return v; 85 | } 86 | 87 | int n; 88 | 89 | int main() 90 | { 91 | n = 7; 92 | 93 | graf[1].adj.push_back(2); 94 | graf[2].adj.push_back(1); 95 | 96 | graf[1].adj.push_back(3); 97 | graf[3].adj.push_back(1); 98 | 99 | graf[1].adj.push_back(4); 100 | graf[4].adj.push_back(1); 101 | 102 | graf[3].adj.push_back(5); 103 | graf[5].adj.push_back(3); 104 | 105 | graf[3].adj.push_back(6); 106 | graf[6].adj.push_back(3); 107 | 108 | graf[3].adj.push_back(7); 109 | graf[7].adj.push_back(3); 110 | 111 | DFS(1, 1, 0); 112 | HLD(1, 1, 1); 113 | 114 | printf("%d\n", LCA(5, 7)); 115 | printf("%d\n", LCA(2, 7)); 116 | 117 | return 0; 118 | } -------------------------------------------------------------------------------- /Graph Algorithms/Edmonds-Karp Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Edmonds-Karp Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 500 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | struct Node 25 | { 26 | vector adj; 27 | }; 28 | Node graf[MAX_N]; 29 | bool mark[MAX_N]; 30 | int cap[MAX_N][MAX_N]; 31 | int parent[MAX_N]; 32 | 33 | int v, e; 34 | int s, t; 35 | 36 | //Edmonds-Karpov algoritam za nalazenje maksimalnog protoka izmedju dva cvora u grafu 37 | //Moze se koristiti i za nalazenje maksimalnog matchinga 38 | //Slozenost: O(V * E^2) 39 | 40 | inline int BFS() 41 | { 42 | int ret = 0; 43 | for (int i=1;i<=v;i++) parent[i] = 0; 44 | queue bfs_queue; 45 | queue minCapacity; 46 | parent[s] = -1; 47 | bfs_queue.push(s); 48 | minCapacity.push(INF); 49 | while (!bfs_queue.empty()) 50 | { 51 | int xt = bfs_queue.front(); 52 | int mt = minCapacity.front(); 53 | bfs_queue.pop(); 54 | minCapacity.pop(); 55 | for (int i=0;i 0 && parent[xt1] == 0) 59 | { 60 | bfs_queue.push(xt1); 61 | minCapacity.push(min(mt,cap[xt][xt1])); 62 | parent[xt1] = xt; 63 | if (xt1 == t) 64 | { 65 | ret = min(mt, cap[xt][xt1]); 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | if (ret > 0) 72 | { 73 | int currNode = t; 74 | while (currNode != s) 75 | { 76 | cap[parent[currNode]][currNode] -= ret; 77 | cap[currNode][parent[currNode]] += ret; 78 | currNode = parent[currNode]; 79 | } 80 | } 81 | return ret; 82 | } 83 | 84 | inline int EdmondsKarp() 85 | { 86 | int flow = 0; 87 | while (true) 88 | { 89 | int currFlow = BFS(); 90 | if (currFlow == 0) break; 91 | else flow += currFlow; 92 | } 93 | return flow; 94 | } 95 | 96 | int main() 97 | { 98 | v = 4, e = 5; 99 | s = 1, t = 4; 100 | 101 | graf[1].adj.push_back(2); 102 | graf[2].adj.push_back(1); 103 | cap[1][2] = 40; 104 | 105 | graf[1].adj.push_back(4); 106 | graf[4].adj.push_back(1); 107 | cap[1][4] = 20; 108 | 109 | graf[2].adj.push_back(4); 110 | graf[4].adj.push_back(2); 111 | cap[2][4] = 20; 112 | 113 | graf[2].adj.push_back(3); 114 | graf[3].adj.push_back(2); 115 | cap[2][3] = 30; 116 | 117 | graf[3].adj.push_back(4); 118 | graf[4].adj.push_back(3); 119 | cap[3][4] = 10; 120 | 121 | printf("%d\n",EdmondsKarp()); 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /Data Structures/Bit Queue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Bit Queue 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | class BitQueue 24 | { 25 | int valid_bits; //the number of valid bits held in queue 26 | int queue; //least significant bit is most recent bit added 27 | public: 28 | BitQueue(): valid_bits(0),queue(0) {} 29 | void push(int val, int bsize); 30 | int pop(int bsize); 31 | int size(); 32 | }; 33 | 34 | class QueueOverflowException: public exception 35 | { 36 | virtual const char* what() const throw() 37 | { 38 | return "Error: Queue Overflow"; 39 | } 40 | } qoverex; 41 | 42 | class QueueUnderflowException: public exception 43 | { 44 | virtual const char* what() const throw() 45 | { 46 | return "Error: Queue Underflow"; 47 | } 48 | } qunderex; 49 | 50 | int BitQueue::size() 51 | { 52 | return this -> valid_bits; 53 | } 54 | 55 | void BitQueue::push(int val, int bsize) 56 | { 57 | if (this -> size() + bsize > 32) throw qoverex; 58 | this -> queue <<= bsize; 59 | if (bsize != 32) val &= (1 << bsize) - 1; 60 | this -> queue |= val; 61 | this -> valid_bits += bsize; 62 | } 63 | 64 | int BitQueue::pop(int bsize) 65 | { 66 | if (this -> size() < bsize) throw qunderex; 67 | int shift_amount = this -> size() - bsize; 68 | int ret; 69 | if (bsize != 32) ret = ((this -> queue) >> shift_amount) & ((1 << bsize) - 1); 70 | else ret = this -> queue; 71 | this -> valid_bits -= bsize; 72 | return ret; 73 | } 74 | 75 | void send(char x) 76 | { 77 | printf("sent 0x%x\n", (unsigned char)x); //stub method for testing 78 | } 79 | 80 | void sendmsg(const char* msg) 81 | { 82 | BitQueue *aux = new BitQueue(); 83 | int len = strlen(msg); 84 | for (int i=0;i push(0, 1); 87 | else if (msg[i] == 'b') aux -> push(2, 2); 88 | else if (msg[i] == 'c') aux -> push(12, 4); 89 | else if (msg[i] == 'd') aux -> push(13, 4); 90 | 91 | if (aux -> size() >= 8) 92 | { 93 | char curr = (char)(aux -> pop(8)); 94 | send(curr); 95 | } 96 | } 97 | aux -> push(7, 3); 98 | while (aux -> size() >= 8) 99 | { 100 | char curr = (char)(aux -> pop(8)); 101 | send(curr); 102 | } 103 | if (aux -> size() > 0) 104 | { 105 | int to_shift = 8 - aux -> size(); 106 | char curr = (char)(aux -> pop(aux -> size())) << to_shift; 107 | send(curr); 108 | } 109 | delete aux; 110 | } 111 | 112 | int main() 113 | { 114 | BitQueue *test = new BitQueue(); 115 | test -> push(55, 5); 116 | test -> push(127, 5); 117 | printf("%d\n", test -> size()); 118 | printf("%d\n", test -> pop(5)); 119 | printf("%d\n", test -> pop(5)); 120 | printf("%d\n", test -> size()); 121 | 122 | sendmsg("abcd"); 123 | 124 | return 0; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /Dynamic Programming/Needleman-Wunsch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Needleman-Wunsch 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_N 1001 22 | 23 | #define DPRINTC(C) printf(#C " = %c\n", (C)) 24 | #define DPRINTS(S) printf(#S " = %s\n", (S)) 25 | #define DPRINTD(D) printf(#D " = %d\n", (D)) 26 | #define DPRINTLLD(LLD) printf(#LLD " = %lld\n", (LLD)) 27 | #define DPRINTLF(LF) printf(#LF " = %.5lf\n", (LF)) 28 | 29 | using namespace std; 30 | typedef long long lld; 31 | typedef unsigned long long llu; 32 | 33 | int n, m; 34 | int match_score, mismatch_score, gap_score; 35 | string A, B; 36 | int dp[MAX_N][MAX_N]; 37 | 38 | /* 39 | Needleman-Wunsch algorithm for determining the optimal alignment between two strings 40 | assuming a given score for hits, gaps and mismatches. 41 | Complexity: O(n * m) time, O(n * m) memory 42 | */ 43 | 44 | inline int needleman_wunsch() 45 | { 46 | for (int i=0;i<=n;i++) dp[i][0] = dp[0][i] = -i * gap_score; 47 | for (int i=1;i<=n;i++) 48 | { 49 | for (int j=1;j<=m;j++) 50 | { 51 | int S = (A[i-1] == B[j-1]) ? match_score : -mismatch_score; 52 | dp[i][j] = max(dp[i-1][j-1] + S, max(dp[i-1][j] - gap_score, dp[i][j-1] - gap_score)); 53 | } 54 | } 55 | return dp[n][m]; 56 | } 57 | 58 | inline pair get_optimal_alignment() 59 | { 60 | string retA, retB; 61 | stack SA, SB; 62 | int ii = n, jj = m; 63 | while (ii != 0 || jj != 0) 64 | { 65 | if (ii == 0) 66 | { 67 | SA.push('-'); 68 | SB.push(B[jj-1]); 69 | jj--; 70 | } 71 | else if (jj == 0) 72 | { 73 | SA.push(A[ii-1]); 74 | SB.push('-'); 75 | ii--; 76 | } 77 | else 78 | { 79 | int S = (A[ii-1] == B[jj-1]) ? match_score : -mismatch_score; 80 | if (dp[ii][jj] == dp[ii-1][jj-1] + S) 81 | { 82 | SA.push(A[ii-1]); 83 | SB.push(B[jj-1]); 84 | ii--; jj--; 85 | } 86 | else if (dp[ii-1][jj] > dp[ii][jj-1]) 87 | { 88 | SA.push(A[ii-1]); 89 | SB.push('-'); 90 | ii--; 91 | } 92 | else 93 | { 94 | SA.push('-'); 95 | SB.push(B[jj-1]); 96 | jj--; 97 | } 98 | } 99 | } 100 | while (!SA.empty()) 101 | { 102 | retA += SA.top(); 103 | retB += SB.top(); 104 | SA.pop(); 105 | SB.pop(); 106 | } 107 | return make_pair(retA, retB); 108 | } 109 | 110 | int main() 111 | { 112 | n = 5, m = 6; 113 | match_score = 2, mismatch_score = 1, gap_score = 1; 114 | A = "CATGT"; 115 | B = "ACGCTG"; 116 | printf("%d\n",needleman_wunsch()); 117 | pair alignment = get_optimal_alignment(); 118 | printf("%s\n%s\n", alignment.first.c_str(), alignment.second.c_str()); 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /Dynamic Programming/Nussinov Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Nussinov Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_N 1001 22 | 23 | #define DPRINTC(C) printf(#C " = %c\n", (C)) 24 | #define DPRINTS(S) printf(#S " = %s\n", (S)) 25 | #define DPRINTD(D) printf(#D " = %d\n", (D)) 26 | #define DPRINTLLD(LLD) printf(#LLD " = %lld\n", (LLD)) 27 | #define DPRINTLF(LF) printf(#LF " = %.5lf\n", (LF)) 28 | 29 | using namespace std; 30 | typedef long long lld; 31 | typedef unsigned long long llu; 32 | 33 | int n; 34 | string A; 35 | int dp[MAX_N][MAX_N]; 36 | 37 | /* 38 | The Nussinov algorithm attepts to predict RNA secondary structure, 39 | under the assumption that RNA will form as many loops as possible. 40 | 41 | Complexity: O(n^3) time, O(n^2) memory 42 | */ 43 | 44 | bool complementary(char X, char Y) 45 | { 46 | return ((X == 'A' && Y == 'U') || (X == 'U' && Y == 'A') || (X == 'C' && Y == 'G') || (X == 'G' && Y == 'C')); 47 | } 48 | 49 | int nussinov(int i, int j) 50 | { 51 | if (dp[i][j] != -1) return dp[i][j]; 52 | 53 | if (i >= j - 1) 54 | { 55 | dp[i][j] = 0; 56 | return 0; 57 | } 58 | 59 | int ret = 0; 60 | ret = max(ret, nussinov(i + 1, j)); 61 | ret = max(ret, nussinov(i, j - 1)); 62 | if (complementary(A[i], A[j])) ret = max(ret, nussinov(i + 1, j - 1) + 1); 63 | for (int k=i+1;k j) return ""; 89 | 90 | if (nussinov(i, j) == nussinov(i + 1, j)) 91 | { 92 | string left = A.substr(i, 1); 93 | return left + get_bracketing(i + 1, j); 94 | } 95 | 96 | if (nussinov(i, j) == nussinov(i, j - 1)) 97 | { 98 | string right = A.substr(j, 1); 99 | return get_bracketing(i, j - 1) + right; 100 | } 101 | 102 | if (complementary(A[i], A[j]) && nussinov(i, j) == nussinov(i+1, j-1) + 1) 103 | { 104 | string left = A.substr(i, 1); 105 | string right = A.substr(j, 1); 106 | return "(" + left + get_bracketing(i+1, j-1) + right + ")"; 107 | } 108 | 109 | for (int k=i+1;k 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 500 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | 24 | struct Node 25 | { 26 | vector adj; 27 | }; 28 | Node graf[MAX_N]; 29 | 30 | struct Edge 31 | { 32 | int u, v, cap; 33 | int flow; 34 | }; 35 | vector E; 36 | 37 | int v, e; 38 | int s, t; 39 | int dist[MAX_N]; 40 | int upTo[MAX_N]; 41 | 42 | int idd = 0; 43 | 44 | //Dinicov algoritam za nalazenje maksimalnog protoka izmedju dva cvora u grafu 45 | //Slozenost: O(V^2 * E) 46 | 47 | inline bool BFS() 48 | { 49 | for (int i=1;i<=v;i++) dist[i] = -1; 50 | queue bfs_queue; 51 | bfs_queue.push(s); 52 | dist[s] = 0; 53 | while (!bfs_queue.empty()) 54 | { 55 | int xt = bfs_queue.front(); 56 | bfs_queue.pop(); 57 | for (int i=0;i 0) 86 | { 87 | E[currID].flow += aug; 88 | if (currID&1) currID--; else currID++; 89 | E[currID].flow -= aug; 90 | return aug; 91 | } 92 | upTo[xt]++; 93 | } 94 | return 0; 95 | } 96 | 97 | inline int Dinic() 98 | { 99 | int flow = 0; 100 | while (true) 101 | { 102 | if (!BFS()) break; 103 | for (int i=1;i<=v;i++) upTo[i] = 0; 104 | while (true) 105 | { 106 | int currFlow = DFS(s, INF); 107 | if (currFlow == 0) break; 108 | flow += currFlow; 109 | } 110 | } 111 | return flow; 112 | } 113 | 114 | inline void addEdge(int u, int v, int cap) 115 | { 116 | Edge E1, E2; 117 | 118 | E1.u = u, E1.v = v, E1.cap = cap, E1.flow = 0; 119 | E2.u = v, E2.v = u, E2.cap = 0, E2.flow = 0; 120 | 121 | graf[u].adj.push_back(idd++); 122 | E.push_back(E1); 123 | graf[v].adj.push_back(idd++); 124 | E.push_back(E2); 125 | } 126 | 127 | int main() 128 | { 129 | v = 4, e = 5; 130 | s = 1, t = 4; 131 | 132 | addEdge(1, 2, 40); 133 | addEdge(1, 4, 20); 134 | addEdge(2, 4, 20); 135 | addEdge(2, 3, 30); 136 | addEdge(3, 4, 10); 137 | 138 | printf("%d\n",Dinic()); 139 | 140 | return 0; 141 | } 142 | -------------------------------------------------------------------------------- /Graph Algorithms/Kosaraju's Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Kosaraju's Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define MAX_N 20001 21 | 22 | typedef long long lld; 23 | typedef unsigned long long llu; 24 | using namespace std; 25 | 26 | /* 27 | Kosaraju's algorithm aims to find all strongly connected components (SCCs) of 28 | a given input graph. It does so using two depth-first searches, and as such is 29 | less efficient than Tarjan's SCC algorithm, but is more intuitive. 30 | 31 | Complexity: O(V + E) 32 | */ 33 | 34 | int n, m; 35 | struct Node 36 | { 37 | vector adj; 38 | vector rev_adj; 39 | }; 40 | Node graf[MAX_N]; 41 | 42 | stack S; 43 | bool visited[MAX_N]; 44 | 45 | int component[MAX_N]; 46 | vector components[MAX_N]; 47 | int numComponents; 48 | 49 | void kosaraju_dfs_1(int x) 50 | { 51 | visited[x] = true; 52 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define DPRINTC(C) printf(#C " = %c\n", (C)) 24 | #define DPRINTS(S) printf(#S " = %s\n", (S)) 25 | #define DPRINTD(D) printf(#D " = %d\n", (D)) 26 | #define DPRINTLLD(LLD) printf(#LLD " = %lld\n", (LLD)) 27 | #define DPRINTLF(LF) printf(#LF " = %.5lf\n", (LF)) 28 | 29 | using namespace std; 30 | typedef long long lld; 31 | typedef unsigned long long llu; 32 | 33 | int n; 34 | vector > edges; 35 | 36 | /* 37 | The PageRank algorithm computes a relevance metric for nodes in a graph, 38 | by computing a stationary distribution of its corresponding ergodic 39 | Markov Chain (using the ``easily bored random web surfer'' model). 40 | 41 | Complexity: O(V + E) time (per iteration), O(V + E) memory 42 | */ 43 | 44 | double sum(double x, double y) 45 | { 46 | return x + y; 47 | } 48 | 49 | double sq_diff(double x, double y) 50 | { 51 | return (x - y) * (x - y); 52 | } 53 | 54 | vector pagerank(double alpha, double epsilon) 55 | { 56 | // initialise 57 | vector old_pi(n), pi(n); 58 | for (int i=0;i H(n), A(n), I(n); 65 | for (int i=0;i epsilon); 100 | 101 | return pi; 102 | } 103 | 104 | int main() 105 | { 106 | n = 7; 107 | edges.resize(7); 108 | 109 | edges[0].push_back(2); 110 | 111 | edges[1].push_back(1); 112 | edges[1].push_back(2); 113 | 114 | edges[2].push_back(0); 115 | edges[2].push_back(2); 116 | edges[2].push_back(3); 117 | 118 | edges[3].push_back(3); 119 | edges[3].push_back(4); 120 | 121 | edges[4].push_back(6); 122 | 123 | edges[5].push_back(5); 124 | edges[5].push_back(6); 125 | 126 | edges[6].push_back(3); 127 | edges[6].push_back(4); 128 | edges[6].push_back(6); 129 | 130 | pagerank(0.1, 1e-6); 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /Graph Algorithms/Prim's Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Prim's Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 101 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | int n; 24 | struct Node 25 | { 26 | vector adj; 27 | vector weight; 28 | }; 29 | Node graf[MAX_N]; 30 | bool mark[MAX_N]; 31 | 32 | struct edge 33 | { 34 | int u, v; 35 | double w; 36 | bool operator <(const edge &a) const 37 | { 38 | return (w>a.w); 39 | } 40 | }; 41 | 42 | priority_queue pq_prim; 43 | 44 | //Primov algoritam za racunanje minimalnog stabla razapinjanja datog tezinskog grafa 45 | //Slozenost: O((V+E)log V) 46 | 47 | inline int Prim() 48 | { 49 | int xt = 0; 50 | int ret = 0; 51 | int amt = 0; 52 | while (amt < n-1) 53 | { 54 | mark[xt]=true; 55 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define MAX_N 250001 26 | #define MAX_S 1000010 27 | #define MAX_K 26 28 | 29 | typedef long long lld; 30 | typedef unsigned long long llu; 31 | using namespace std; 32 | 33 | /* 34 | The suffix automaton is a minimal deterministic finite automaton (DFA) accepting all 35 | suffices of a given string. It is useful for a variety of actions, one of which is efficiently 36 | computing the longest common substring (LCS) between two strings. 37 | Complexity: O(n) for constructing the automaton (character by character) 38 | O(m) for computing the LCS 39 | */ 40 | 41 | char inp[MAX_N]; 42 | 43 | struct Node 44 | { 45 | int len, prev; 46 | int adj[MAX_K]; 47 | }; 48 | 49 | Node DFA[MAX_S]; 50 | int tot = 0, sink; 51 | 52 | inline void init_automaton() 53 | { 54 | DFA[0].len = 0; 55 | DFA[0].prev = -1; 56 | for (int i=0;i<26;i++) DFA[0].adj[i] = -1; 57 | sink = 0; 58 | tot = 1; 59 | } 60 | 61 | inline void extend_automaton(char ch) 62 | { 63 | int cc = ch - 'a'; 64 | 65 | int tail = tot++; 66 | DFA[tail].len = DFA[sink].len + 1; 67 | for (int i=0;i<26;i++) DFA[tail].adj[i] = -1; 68 | 69 | int curr = sink; 70 | while (curr != -1 && DFA[curr].adj[cc] == -1) 71 | { 72 | DFA[curr].adj[cc] = tail; 73 | curr = DFA[curr].prev; 74 | } 75 | 76 | if (curr == -1) 77 | { 78 | DFA[tail].prev = 0; 79 | } 80 | else 81 | { 82 | int nxt = DFA[curr].adj[cc]; 83 | if (DFA[nxt].len == DFA[curr].len + 1) 84 | { 85 | DFA[tail].prev = nxt; 86 | } 87 | else 88 | { 89 | int cl = tot++; 90 | DFA[cl].len = DFA[curr].len + 1; 91 | DFA[cl].prev = DFA[nxt].prev; 92 | for (int i=0;i<26;i++) DFA[cl].adj[i] = DFA[nxt].adj[i]; 93 | 94 | while (curr != -1 && DFA[curr].adj[cc] == nxt) 95 | { 96 | DFA[curr].adj[cc] = cl; 97 | curr = DFA[curr].prev; 98 | } 99 | 100 | DFA[tail].prev = DFA[nxt].prev = cl; 101 | } 102 | } 103 | sink = tail; 104 | } 105 | 106 | inline string lcs(string needle) 107 | { 108 | int curr_len = 0; 109 | int best_len = 0, best_pos = -1; 110 | int st = 0; 111 | 112 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define MAX_N 501 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | /* 24 | Algorithm for calculating the minimal cost of approximating a set of points with segments 25 | 26 | The cost of a particular set of segments is calculated as sum(i=1 -> n) E_i + c*L, 27 | where E_i is the error of the i-th point WRT its segment, 28 | c the cost of each segment, 29 | and L the amount of segments used 30 | 31 | Input: Set of points (from file) + Cost of each segment (from command line) 32 | Returns: The minimal cost (to command line) + segments used (to file) 33 | Complexity: O(n^2) time, O(n^2) memory 34 | */ 35 | 36 | int n = 1, c; 37 | 38 | struct Point 39 | { 40 | int x, y; 41 | bool operator <(const Point &p) const 42 | { 43 | return (x < p.x); 44 | } 45 | }; 46 | Point pts[MAX_N]; 47 | 48 | double err[MAX_N][MAX_N]; //err[i][j] - total error by approximating points [i..j] by a segment 49 | double a[MAX_N][MAX_N]; //a[i][j] - the slope of the segment used to approximate points [i..j] 50 | double b[MAX_N][MAX_N]; //b[i][j] - the y-intercept of the segment used to approximate points [i..j] 51 | 52 | int xySums[MAX_N], xSums[MAX_N], ySums[MAX_N], xSqrSums[MAX_N], ySqrSums[MAX_N]; //prefix sums for x_i * y_i, x_i, y_i, x_i * x_i and y_i * y_i 53 | 54 | double minCost[MAX_N]; //minCost[j] - optimal cost for points [1..j] 55 | int retIndex[MAX_N]; //the last segment in the optimal case for points [1..j] is [retIndex[j], j] 56 | 57 | struct Segment 58 | { 59 | double x1, y1, x2, y2; 60 | Segment() 61 | { 62 | this->x1 = 0; 63 | this->y1 = 0; 64 | this->x2 = 0; 65 | this->y2 = 0; 66 | } 67 | Segment(double x1, double y1, double x2, double y2) 68 | { 69 | this->x1 = x1; 70 | this->y1 = y1; 71 | this->x2 = x2; 72 | this->y2 = y2; 73 | } 74 | }; 75 | vector ret; //final solution 76 | 77 | inline void Precalculate() 78 | { 79 | sort(pts+1, pts+n+1); //can be omitted if points are guaranteed to be given in ascending X order 80 | 81 | for (int i=1;i<=n;i++) 82 | { 83 | xSums[i] = xSums[i-1] + pts[i].x; 84 | ySums[i] = ySums[i-1] + pts[i].y; 85 | xSqrSums[i] = xSqrSums[i-1] + pts[i].x * pts[i].x; 86 | xySums[i] = xySums[i-1] + pts[i].x * pts[i].y; 87 | ySqrSums[i] = ySqrSums[i-1] + pts[i].y * pts[i].y; 88 | } 89 | 90 | for (int i=1;i<=n;i++) 91 | { 92 | for (int j=i+1;j<=n;j++) 93 | { 94 | int nn = j - i + 1; 95 | int xySum = xySums[j] - xySums[i-1]; 96 | int xSum = xSums[j] - xSums[i-1]; 97 | int ySum = ySums[j] - ySums[i-1]; 98 | int xSqrSum = xSqrSums[j] - xSqrSums[i-1]; 99 | int ySqrSum = ySqrSums[j] - ySqrSums[i-1]; 100 | 101 | a[i][j] = ((nn * xySum - xSum * ySum) * 1.0) / ((nn * xSqrSum - xSum * xSum) * 1.0); 102 | b[i][j] = ((ySum - a[i][j] * xSum) * 1.0) / (nn * 1.0); 103 | 104 | err[i][j] = a[i][j] * a[i][j] * xSqrSum + 2.0 * a[i][j] * b[i][j] * xSum - 2.0 * a[i][j] * xySum + nn * b[i][j] * b[i][j] - 2.0 * b[i][j] * ySum + ySqrSum; 105 | } 106 | } 107 | } 108 | 109 | inline double SegmentedLeastSquares() 110 | { 111 | for (int j=1;j<=n;j++) 112 | { 113 | minCost[j] = err[1][j] + c; 114 | retIndex[j] = 1; 115 | 116 | for (int i=2;i<=j;i++) 117 | { 118 | if (minCost[i-1] + err[i][j] + c < minCost[j]) 119 | { 120 | minCost[j] = minCost[i-1] + err[i][j] + c; 121 | retIndex[j] = i; 122 | } 123 | } 124 | } 125 | 126 | return minCost[n]; 127 | } 128 | 129 | inline void getSegments() 130 | { 131 | stack S; 132 | int currInd = n; 133 | while (currInd > 1) 134 | { 135 | int nextInd = retIndex[currInd]; 136 | if (nextInd == currInd) 137 | { 138 | S.push(Segment(pts[currInd-1].x, pts[currInd-1].y, pts[currInd].x, pts[currInd].y)); 139 | } 140 | else 141 | { 142 | double x1 = pts[nextInd].x; 143 | double y1 = x1 * a[nextInd][currInd] + b[nextInd][currInd]; 144 | double x2 = pts[currInd].x; 145 | double y2 = x2 * a[nextInd][currInd] + b[nextInd][currInd]; 146 | S.push(Segment(x1, y1, x2, y2)); 147 | } 148 | currInd = nextInd - 1; 149 | } 150 | while (!S.empty()) 151 | { 152 | ret.push_back(S.top()); 153 | S.pop(); 154 | } 155 | } 156 | 157 | int main(int argc, char **argv) 158 | { 159 | sscanf(argv[1],"%d",&c); 160 | freopen("/Users/PetarV/.makedots","r",stdin); 161 | while (scanf("%d%d",&pts[n].x,&pts[n].y) == 2) n++; 162 | n--; 163 | Precalculate(); 164 | printf("%.10lf\n",SegmentedLeastSquares()); 165 | freopen("/Users/PetarV/.makedots-segments","w",stdout); 166 | getSegments(); 167 | for (int i=0;i 7 | #include 8 | #include 9 | 10 | typedef struct XORNode 11 | { 12 | int data; 13 | struct XORNode *XOR; 14 | } XNode; 15 | 16 | typedef struct XORLinkedList 17 | { 18 | XNode *first; 19 | XNode *last; 20 | } XLL; 21 | 22 | void initialize(XLL *l) 23 | { 24 | l -> first = l -> last = NULL; 25 | } 26 | 27 | XNode* addAfter(XLL *l, XNode *n, int data) 28 | { 29 | // PRECONDITION: l is empty, or n is in l 30 | 31 | if (l -> first == NULL) 32 | { 33 | XNode *new = (XNode*)malloc(sizeof(XNode)); 34 | new -> data = data; 35 | new -> XOR = NULL; 36 | l -> first = new; 37 | l -> last = new; 38 | 39 | return new; 40 | } 41 | else 42 | { 43 | XNode *prevPtr = NULL; 44 | XNode *currPtr = l -> first; 45 | XNode *nextPtr = l -> first -> XOR; 46 | while (currPtr != n) 47 | { 48 | prevPtr = currPtr; 49 | currPtr = nextPtr; 50 | nextPtr = (XNode*)((uintptr_t)prevPtr ^ (uintptr_t)(currPtr -> XOR)); 51 | } 52 | XNode *new = (XNode*)malloc(sizeof(XNode)); 53 | new -> data = data; 54 | new -> XOR = (XNode*)((uintptr_t)currPtr ^ (uintptr_t)nextPtr); 55 | 56 | currPtr -> XOR = (XNode*)((uintptr_t)(currPtr -> XOR) ^ (uintptr_t)nextPtr ^ (uintptr_t)new); 57 | if (nextPtr != NULL) nextPtr -> XOR = (XNode*)((uintptr_t)(nextPtr -> XOR) ^ (uintptr_t)currPtr ^ (uintptr_t)new); 58 | else l -> last = new; 59 | 60 | return new; 61 | } 62 | } 63 | 64 | XNode* addBefore(XLL *l, XNode *n, int data) 65 | { 66 | // PRECONDITION: l is empty, or n is in l 67 | 68 | if (l -> last == NULL) 69 | { 70 | XNode *new = (XNode*)malloc(sizeof(XNode)); 71 | new -> data = data; 72 | new -> XOR = NULL; 73 | l -> first = new; 74 | l -> last = new; 75 | 76 | return new; 77 | } 78 | else 79 | { 80 | XNode *prevPtr = NULL; 81 | XNode *currPtr = l -> last; 82 | XNode *nextPtr = l -> last -> XOR; 83 | while (currPtr != n) 84 | { 85 | prevPtr = currPtr; 86 | currPtr = nextPtr; 87 | nextPtr = (XNode*)((uintptr_t)prevPtr ^ (uintptr_t)(currPtr -> XOR)); 88 | } 89 | XNode *new = (XNode*)malloc(sizeof(XNode)); 90 | new -> data = data; 91 | new -> XOR = (XNode*)((uintptr_t)currPtr ^ (uintptr_t)nextPtr); 92 | 93 | currPtr -> XOR = (XNode*)((uintptr_t)(currPtr -> XOR) ^ (uintptr_t)nextPtr ^ (uintptr_t)new); 94 | if (nextPtr != NULL) nextPtr -> XOR = (XNode*)((uintptr_t)(nextPtr -> XOR) ^ (uintptr_t)currPtr ^ (uintptr_t)new); 95 | else l -> first = new; 96 | 97 | return new; 98 | } 99 | } 100 | 101 | void delete(XLL *l, XNode *n) 102 | { 103 | // PRECONDITION: n is in l 104 | 105 | if (l -> first == l -> last) 106 | { 107 | free(l -> first); 108 | l -> first = l -> last = NULL; 109 | } 110 | 111 | else 112 | { 113 | 114 | XNode *prevPtr = NULL; 115 | XNode *currPtr = l -> first; 116 | XNode *nextPtr = l -> first -> XOR; 117 | 118 | while (currPtr != n) 119 | { 120 | prevPtr = currPtr; 121 | currPtr = nextPtr; 122 | nextPtr = (XNode*)((uintptr_t)prevPtr ^ (uintptr_t)(currPtr -> XOR)); 123 | } 124 | 125 | if (prevPtr != NULL) prevPtr -> XOR = (XNode*)((uintptr_t)(prevPtr -> XOR) ^ (uintptr_t)currPtr ^ (uintptr_t)nextPtr); 126 | else l -> first = nextPtr; 127 | 128 | if (nextPtr != NULL) nextPtr -> XOR = (XNode*)((uintptr_t)(nextPtr -> XOR) ^ (uintptr_t)currPtr ^ (uintptr_t)prevPtr); 129 | else l -> last = prevPtr; 130 | 131 | } 132 | } 133 | 134 | void traverseForward(XLL *l) 135 | { 136 | if (l -> first == NULL) return; 137 | 138 | XNode *prevPtr = NULL; 139 | XNode *currPtr = l -> first; 140 | XNode *nextPtr = l -> first -> XOR; 141 | 142 | while (currPtr != NULL) 143 | { 144 | printf("%d ", currPtr -> data); 145 | prevPtr = currPtr; 146 | currPtr = nextPtr; 147 | if (currPtr != NULL) nextPtr = (XNode*)((uintptr_t)prevPtr ^ (uintptr_t)(currPtr -> XOR)); 148 | } 149 | 150 | printf("\n"); 151 | } 152 | 153 | void traverseBackward(XLL *l) 154 | { 155 | if (l -> last == NULL) return; 156 | 157 | XNode *prevPtr = NULL; 158 | XNode *currPtr = l -> last; 159 | XNode *nextPtr = l -> last -> XOR; 160 | 161 | while (currPtr != NULL) 162 | { 163 | printf("%d ", currPtr -> data); 164 | prevPtr = currPtr; 165 | currPtr = nextPtr; 166 | if (currPtr != NULL) nextPtr = (XNode*)((uintptr_t)prevPtr ^ (uintptr_t)(currPtr -> XOR)); 167 | } 168 | 169 | printf("\n"); 170 | } 171 | 172 | 173 | int main() 174 | { 175 | XLL *xlist = (XLL*)malloc(sizeof(XLL)); 176 | 177 | initialize(xlist); 178 | 179 | XNode *A = addAfter(xlist, NULL, 1); 180 | 181 | traverseForward(xlist); 182 | 183 | XNode *B = addAfter(xlist, A, 5); 184 | 185 | traverseForward(xlist); 186 | 187 | XNode *C = addBefore(xlist, A, 3); 188 | 189 | traverseForward(xlist); 190 | traverseBackward(xlist); 191 | 192 | delete(xlist, A); 193 | 194 | traverseForward(xlist); 195 | traverseBackward(xlist); 196 | 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /Compression Algorithms/Huffman Coding.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Huffman Coding 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | typedef long long lld; 21 | typedef unsigned long long llu; 22 | using namespace std; 23 | 24 | /* 25 | The Huffman coding scheme assigns a variable-length prefix code to each character 26 | in a given set of characters, constructing an optimal lossless coding scheme with 27 | respect to the character distribution's entropy. 28 | 29 | The version implemented here analyses a given ASCII character string in order to 30 | obtain optimal codes based on character frequencies in the string. A more general 31 | version would receive a probability distribution instead. 32 | 33 | Complexity: O(n) time to construct 34 | O(H) time (on average) to encode/decode, where H is the entropy 35 | */ 36 | 37 | // The string to analyse 38 | string str; 39 | 40 | // Maps the encountered characters to their relative frequencies 41 | map P; 42 | 43 | // The Huffman Tree 44 | struct HuffTreeNode 45 | { 46 | double p; 47 | bool leaf; 48 | char letter; 49 | 50 | HuffTreeNode *parent; 51 | HuffTreeNode *l; 52 | HuffTreeNode *r; 53 | 54 | // nonleaf node 55 | HuffTreeNode(double p, HuffTreeNode *l, HuffTreeNode *r) 56 | { 57 | this -> p = p; 58 | this -> leaf = false; 59 | this -> letter = '\0'; 60 | 61 | this -> parent = NULL; 62 | this -> l = l; 63 | this -> r = r; 64 | l -> parent = this; 65 | r -> parent = this; 66 | } 67 | 68 | // leaf node 69 | HuffTreeNode(double p, char c) 70 | { 71 | this -> p = p; 72 | this -> leaf = true; 73 | this -> letter = c; 74 | this -> parent = this -> l = this -> r = NULL; 75 | } 76 | }; 77 | 78 | // Comparator of two node pointers 79 | struct CmpNodePtrs 80 | { 81 | // As priority_queue is a max heap rather than min-heap, 82 | // invert the meaning of the < operator, 83 | // in order to get lower probabilities at the top 84 | bool operator()(const HuffTreeNode* lhs, const HuffTreeNode* rhs) const 85 | { 86 | return (lhs -> p) > (rhs -> p); 87 | } 88 | }; 89 | 90 | // the root of the tree 91 | HuffTreeNode *root; 92 | 93 | // mapping each character to its leaf node (for quick encoding) 94 | map leaf; 95 | 96 | // Produces the probability distribution (may be omitted if known in advance) 97 | inline void analyse() 98 | { 99 | for (int i=0;i first] = it -> second / str.length(); 106 | } 107 | } 108 | 109 | // Construct the Huffman Tree using the probability distribution 110 | inline void build_tree() 111 | { 112 | priority_queue, CmpNodePtrs> pq; 113 | 114 | // First construct the leaves, and fill the priority queue 115 | for (auto it = P.begin();it!=P.end();it++) 116 | { 117 | leaf[it -> first] = new HuffTreeNode(it -> second, it -> first); 118 | pq.push(leaf[it -> first]); 119 | } 120 | 121 | while (pq.size() > 1) 122 | { 123 | HuffTreeNode* L = pq.top(); pq.pop(); 124 | HuffTreeNode* R = pq.top(); pq.pop(); 125 | 126 | // Spawn a new node generating the children 127 | HuffTreeNode* par = new HuffTreeNode((L -> p) + (R -> p), L, R); 128 | pq.push(par); 129 | } 130 | 131 | root = pq.top(); pq.pop(); 132 | } 133 | 134 | // Huffman-encode a given character 135 | inline string encode(char c) 136 | { 137 | string ret = ""; 138 | 139 | HuffTreeNode* curr = leaf[c]; 140 | while (curr -> parent != NULL) 141 | { 142 | if (curr == curr -> parent -> l) ret += "0"; 143 | else if (curr == curr -> parent -> r) ret += "1"; 144 | 145 | curr = curr -> parent; 146 | } 147 | 148 | reverse(ret.begin(), ret.end()); 149 | return ret; 150 | } 151 | 152 | // Huffman-encode the given string 153 | inline string encode(string s) 154 | { 155 | string ret = ""; 156 | 157 | for (int i=0;i leaf)) 177 | { 178 | if (s[i++] == '0') curr = curr -> l; 179 | else curr = curr -> r; 180 | } 181 | ret += curr -> letter; 182 | } 183 | return ret; 184 | } 185 | 186 | int main() 187 | { 188 | str = "this is an example of a huffman tree"; 189 | 190 | analyse(); 191 | build_tree(); 192 | 193 | string test = " aefhimnstloprux"; 194 | for (int i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | typedef unsigned long long llu; 24 | 25 | /* 26 | Pairing Heap data structure satisfying the heap property, with highly efficient asymptotic bounds. 27 | Often outperforming Fibonacci heaps, and simple to implement. 28 | Complexity: O(1) for insert, first and merge 29 | O(log n) amortized for extractMin and delete 30 | O(log n) amortized for decreaseKey - not known if bound is tight; Omega(log log N). 31 | */ 32 | 33 | struct PNode 34 | { 35 | int key; 36 | PNode *b, *f, *c; 37 | 38 | PNode() 39 | { 40 | this -> key = 0; 41 | this -> b = this -> f = this -> c = NULL; 42 | } 43 | 44 | PNode(int key) 45 | { 46 | this -> key = key; 47 | this -> b = this -> f = this -> c = NULL; 48 | } 49 | }; 50 | 51 | class PHeap 52 | { 53 | PNode *root; 54 | 55 | public: 56 | PHeap(); 57 | PHeap(PNode*); 58 | bool isEmpty(); 59 | void insert(PNode*); 60 | void merge(PHeap*); 61 | PNode* first(); 62 | PNode* extractMin(); 63 | void decreaseKey(PNode*, int); 64 | void Delete(PNode*); 65 | }; 66 | 67 | PHeap::PHeap() 68 | { 69 | this -> root = NULL; 70 | } 71 | 72 | PHeap::PHeap(PNode *x) 73 | { 74 | this -> root = x; 75 | x -> b = x -> f = NULL; 76 | } 77 | 78 | bool PHeap::isEmpty() 79 | { 80 | return (this -> root == NULL); 81 | } 82 | 83 | void PHeap::insert(PNode *x) 84 | { 85 | this -> merge(new PHeap(x)); 86 | } 87 | 88 | void PHeap::merge(PHeap *ph) 89 | { 90 | if (ph -> isEmpty()) return; 91 | 92 | if (this -> isEmpty()) 93 | { 94 | this -> root = ph -> root; 95 | return; 96 | } 97 | 98 | else 99 | { 100 | if (this -> root -> key < ph -> root -> key) 101 | { 102 | PNode *fC = this -> root -> c; 103 | this -> root -> c = ph -> root; 104 | ph -> root -> b = this -> root; 105 | ph -> root -> f = fC; 106 | if (fC != NULL) fC -> b = ph -> root; 107 | } 108 | else 109 | { 110 | PNode *fC = ph -> root -> c; 111 | ph -> root -> c = this -> root; 112 | this -> root -> b = ph -> root; 113 | this -> root -> f = fC; 114 | if (fC != NULL) fC -> b = this -> root; 115 | this -> root = ph -> root; 116 | } 117 | } 118 | } 119 | 120 | PNode* PHeap::first() 121 | { 122 | return this -> root; 123 | } 124 | 125 | PNode* PHeap::extractMin() 126 | { 127 | PNode *ret = this -> first(); 128 | 129 | PNode *oldList = ret -> c; 130 | 131 | if (oldList == NULL) 132 | { 133 | this -> root = NULL; 134 | return ret; 135 | } 136 | 137 | queue heapFIFO; 138 | stack heapLIFO; 139 | 140 | while (oldList != NULL) 141 | { 142 | PNode *next = oldList -> f; 143 | heapFIFO.push(new PHeap(oldList)); 144 | oldList = next; 145 | } 146 | 147 | while (!heapFIFO.empty()) 148 | { 149 | PHeap *t1 = heapFIFO.front(); 150 | heapFIFO.pop(); 151 | if (!heapFIFO.empty()) 152 | { 153 | PHeap *t2 = heapFIFO.front(); 154 | heapFIFO.pop(); 155 | t1 -> merge(t2); 156 | } 157 | heapLIFO.push(t1); 158 | } 159 | 160 | while (heapLIFO.size() > 1) 161 | { 162 | PHeap *x = heapLIFO.top(); 163 | heapLIFO.pop(); 164 | PHeap *y = heapLIFO.top(); 165 | heapLIFO.pop(); 166 | x -> merge(y); 167 | heapLIFO.push(x); 168 | } 169 | 170 | this -> root = heapLIFO.top() -> root; 171 | 172 | return ret; 173 | } 174 | 175 | void PHeap::decreaseKey(PNode *x, int newKey) 176 | { 177 | x -> key = newKey; 178 | 179 | if (this -> root == x) return; 180 | 181 | if (x -> b -> c == x) 182 | { 183 | x -> b -> c = x -> f; 184 | if (x -> f != NULL) x -> f -> b = x -> b; 185 | } 186 | else 187 | { 188 | x -> b -> f = x -> f; 189 | if (x -> f != NULL) x -> f -> b = x -> b; 190 | } 191 | 192 | this -> merge(new PHeap(x)); 193 | } 194 | 195 | void PHeap::Delete(PNode *x) 196 | { 197 | if (this -> root == x) extractMin(); 198 | else 199 | { 200 | if (x -> b -> c == x) 201 | { 202 | x -> b -> c = x -> f; 203 | if (x -> f != NULL) x -> f -> b = x -> b; 204 | } 205 | else 206 | { 207 | x -> b -> f = x -> f; 208 | if (x -> f != NULL) x -> f -> b = x -> b; 209 | } 210 | 211 | PHeap *R = new PHeap(x); 212 | R -> extractMin(); 213 | this -> merge(R); 214 | } 215 | } 216 | 217 | int main() 218 | { 219 | PHeap *ph = new PHeap(); 220 | 221 | PNode *x = new PNode(11); 222 | PNode *y = new PNode(5); 223 | 224 | ph -> insert(x); 225 | ph -> insert(y); 226 | ph -> insert(new PNode(3)); 227 | ph -> insert(new PNode(8)); 228 | ph -> insert(new PNode(4)); 229 | 230 | ph -> decreaseKey(x, 2); 231 | ph -> Delete(y); 232 | 233 | while (!ph -> isEmpty()) 234 | { 235 | printf("%d ", ph -> extractMin() -> key); 236 | } 237 | 238 | printf("\n"); 239 | return 0; 240 | } 241 | 242 | -------------------------------------------------------------------------------- /Data Structures/Link-cut Tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Link/cut Tree 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define MAX_N 100001 26 | 27 | typedef long long lld; 28 | typedef unsigned long long llu; 29 | using namespace std; 30 | 31 | /* 32 | The link/cut tree data structure enables us to efficiently handle a dynamic forest of trees. 33 | It does so by storing a decomposition of the forest into "preferred paths", where a path is 34 | preferred to another when it has been more recently accessed. 35 | Each preferred path is stored in a splay tree which is keyed by depth. 36 | 37 | The tree supports the following operations: 38 | - make_tree(v): create a singleton tree containing the node v 39 | - find_root(v): find the root of the tree containing v 40 | - link(v, w): connect v to w 41 | (precondition: v is root of its own tree, 42 | and v and w are not in the same tree!) 43 | - cut(v): cut v off from its parent 44 | - path(v): access the path from the root of v's tree to v 45 | (in order to e.g. perform an aggregate query on that path) 46 | 47 | More complex operations and queries are possible that require the data structure 48 | to be augmented with additional data. Here I will demonstrate the LCA(p, q) 49 | (lowest common ancestor of p and q) operation. 50 | 51 | Complexity: O(1) for make_tree 52 | O(log n) amortized for all other operations 53 | */ 54 | 55 | int n, m; 56 | char cmd[101]; 57 | int p, q; 58 | 59 | struct Node 60 | { 61 | int L, R, P; 62 | int PP; 63 | }; 64 | 65 | Node LCT[MAX_N]; 66 | 67 | inline void make_tree(int v) 68 | { 69 | if (v == -1) return; 70 | LCT[v].L = LCT[v].R = LCT[v].P = LCT[v].PP = -1; 71 | } 72 | 73 | inline void rotate(int v) 74 | { 75 | if (v == -1) return; 76 | if (LCT[v].P == -1) return; 77 | int p = LCT[v].P; 78 | int g = LCT[p].P; 79 | if (LCT[p].L == v) 80 | { 81 | LCT[p].L = LCT[v].R; 82 | if (LCT[v].R != -1) 83 | { 84 | LCT[LCT[v].R].P = p; 85 | } 86 | LCT[v].R = p; 87 | LCT[p].P = v; 88 | } 89 | else 90 | { 91 | LCT[p].R = LCT[v].L; 92 | if (LCT[v].L != -1) 93 | { 94 | LCT[LCT[v].L].P = p; 95 | } 96 | LCT[v].L = p; 97 | LCT[p].P = v; 98 | } 99 | LCT[v].P = g; 100 | if (g != -1) 101 | { 102 | if (LCT[g].L == p) 103 | { 104 | LCT[g].L = v; 105 | } 106 | else 107 | { 108 | LCT[g].R = v; 109 | } 110 | } 111 | // must preserve path-pointer! 112 | // (this only has an effect when g is -1) 113 | LCT[v].PP = LCT[p].PP; 114 | LCT[p].PP = -1; 115 | } 116 | 117 | inline void splay(int v) 118 | { 119 | if (v == -1) return; 120 | while (LCT[v].P != -1) 121 | { 122 | int p = LCT[v].P; 123 | int g = LCT[p].P; 124 | if (g == -1) // zig 125 | { 126 | rotate(v); 127 | } 128 | else if ((LCT[p].L == v) == (LCT[g].L == p)) // zig-zig 129 | { 130 | rotate(p); 131 | rotate(v); 132 | } 133 | else // zig-zag 134 | { 135 | rotate(v); 136 | rotate(v); 137 | } 138 | } 139 | } 140 | 141 | inline void expose(int v) 142 | { 143 | if (v == -1) return; 144 | splay(v); // now v is root of its aux. tree 145 | if (LCT[v].R != -1) 146 | { 147 | LCT[LCT[v].R].PP = v; 148 | LCT[LCT[v].R].P = -1; 149 | LCT[v].R = -1; 150 | } 151 | while (LCT[v].PP != -1) 152 | { 153 | int w = LCT[v].PP; 154 | splay(w); 155 | if (LCT[w].R != -1) 156 | { 157 | LCT[LCT[w].R].PP = w; 158 | LCT[LCT[w].R].P = -1; 159 | } 160 | LCT[w].R = v; 161 | LCT[v].P = w; 162 | LCT[v].PP = -1; 163 | splay(v); 164 | } 165 | } 166 | 167 | inline int find_root(int v) 168 | { 169 | if (v == -1) return -1; 170 | expose(v); 171 | int ret = v; 172 | while (LCT[ret].L != -1) ret = LCT[ret].L; 173 | expose(ret); 174 | return ret; 175 | } 176 | 177 | inline void link(int v, int w) // attach v's root to w 178 | { 179 | if (v == -1 || w == -1) return; 180 | expose(v); 181 | expose(w); 182 | LCT[v].L = w; // the root can only have right children in its splay tree, so no need to check 183 | LCT[w].P = v; 184 | LCT[w].PP = -1; 185 | } 186 | 187 | inline void cut(int v) 188 | { 189 | if (v == -1) return; 190 | expose(v); 191 | if (LCT[v].L != -1) 192 | { 193 | LCT[LCT[v].L].P = -1; 194 | LCT[v].L = -1; 195 | } 196 | } 197 | 198 | inline int LCA(int p, int q) 199 | { 200 | expose(p); 201 | splay(q); 202 | if (LCT[q].R != -1) 203 | { 204 | LCT[LCT[q].R].PP = q; 205 | LCT[LCT[q].R].P = -1; 206 | LCT[q].R = -1; 207 | } 208 | 209 | int ret = q, t = q; 210 | while (LCT[t].PP != -1) 211 | { 212 | int w = LCT[t].PP; 213 | splay(w); 214 | if (LCT[w].PP == -1) ret = w; 215 | if (LCT[w].R != -1) 216 | { 217 | LCT[LCT[w].R].PP = w; 218 | LCT[LCT[w].R].P = -1; 219 | } 220 | LCT[w].R = t; 221 | LCT[t].P = w; 222 | LCT[t].PP = -1; 223 | t = w; 224 | } 225 | splay(q); 226 | 227 | return ret; 228 | } 229 | 230 | int main() 231 | { 232 | // This is the code I used for the problem Dynamic LCA (DYNALCA) 233 | // on Sphere Online Judge (SPOJ) 234 | scanf("%d%d", &n, &m); 235 | 236 | for (int i=1;i<=n;i++) make_tree(i); 237 | 238 | while (m--) 239 | { 240 | scanf("%s", cmd); 241 | if (strcmp(cmd, "link") == 0) 242 | { 243 | scanf("%d%d", &p, &q); 244 | link(p, q); 245 | } 246 | else if (strcmp(cmd, "cut") == 0) 247 | { 248 | scanf("%d", &p); 249 | cut(p); 250 | } 251 | else if (strcmp(cmd, "lca") == 0) 252 | { 253 | scanf("%d%d", &p, &q); 254 | printf("%d\n", LCA(p, q)); 255 | } 256 | } 257 | 258 | return 0; 259 | } 260 | -------------------------------------------------------------------------------- /Data Structures/Binomial Heap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Binomial Heap 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define INF 987654321 21 | #define MAX_N 100002 22 | using namespace std; 23 | typedef long long lld; 24 | typedef unsigned long long llu; 25 | 26 | /* 27 | Binomial Heap data structure satisfying the heap property, with an efficient merge operation. 28 | Useful for a priority queue implementation where merges are frequent. 29 | Complexity: O(1) for first 30 | O(log N) for insert, merge, extractMin, decreaseKey and delete 31 | */ 32 | 33 | struct BinNode 34 | { 35 | int key; 36 | int degree; 37 | BinNode *f, *p, *c; 38 | 39 | BinNode() 40 | { 41 | this -> key = 0; 42 | this -> degree = 0; 43 | this -> f = this -> p = this -> c = NULL; 44 | } 45 | 46 | BinNode(int key) 47 | { 48 | this -> key = key; 49 | this -> degree = 0; 50 | this -> f = this -> p = this -> c = NULL; 51 | } 52 | }; 53 | 54 | class BinHeap 55 | { 56 | BinNode *roots; 57 | BinNode *min; 58 | void linkTrees(BinNode*, BinNode*); 59 | BinNode* mergeRoots(BinHeap*, BinHeap*); 60 | 61 | public: 62 | BinHeap(); 63 | BinHeap(BinNode*); 64 | bool isEmpty(); 65 | void insert(BinNode*); 66 | void merge(BinHeap*); 67 | BinNode* first(); 68 | BinNode* extractMin(); 69 | void decreaseKey(BinNode*, int); 70 | void Delete(BinNode*); 71 | }; 72 | 73 | BinHeap::BinHeap() 74 | { 75 | this -> roots = NULL; 76 | } 77 | 78 | BinHeap::BinHeap(BinNode *x) 79 | { 80 | this -> roots = x; 81 | } 82 | 83 | bool BinHeap::isEmpty() 84 | { 85 | return (this -> roots == NULL); 86 | } 87 | 88 | void BinHeap::insert(BinNode *x) 89 | { 90 | this -> merge(new BinHeap(x)); 91 | } 92 | 93 | void BinHeap::linkTrees(BinNode *y, BinNode *z) 94 | { 95 | // Precondition: y -> key >= z -> key 96 | y -> p = z; 97 | y -> f = z -> c; 98 | z -> c = y; 99 | z -> degree = z -> degree + 1; 100 | } 101 | 102 | BinNode* BinHeap::mergeRoots(BinHeap *x, BinHeap *y) 103 | { 104 | BinNode *ret = new BinNode(); 105 | BinNode *end = ret; 106 | 107 | BinNode *L = x -> roots; 108 | BinNode *R = y -> roots; 109 | if (L == NULL) return R; 110 | if (R == NULL) return L; 111 | while (L != NULL || R != NULL) 112 | { 113 | if (L == NULL) 114 | { 115 | end -> f = R; 116 | end = end -> f; 117 | R = R -> f; 118 | } 119 | else if (R == NULL) 120 | { 121 | end -> f = L; 122 | end = end -> f; 123 | L = L -> f; 124 | } 125 | else 126 | { 127 | if (L -> degree < R -> degree) 128 | { 129 | end -> f = L; 130 | end = end -> f; 131 | L = L -> f; 132 | } 133 | else 134 | { 135 | end -> f = R; 136 | end = end -> f; 137 | R = R -> f; 138 | } 139 | } 140 | } 141 | return (ret -> f); 142 | } 143 | 144 | void BinHeap::merge(BinHeap *bh) 145 | { 146 | BinHeap *H = new BinHeap(); 147 | H -> roots = mergeRoots(this, bh); 148 | 149 | if (H -> roots == NULL) 150 | { 151 | this -> roots = NULL; 152 | this -> min = NULL; 153 | return; 154 | } 155 | 156 | BinNode *prevX = NULL; 157 | BinNode *x = H -> roots; 158 | BinNode *nextX = x -> f; 159 | while (nextX != NULL) 160 | { 161 | if (x -> degree != nextX -> degree || (nextX -> f != NULL && nextX -> f -> degree == x -> degree)) 162 | { 163 | prevX = x; 164 | x = nextX; 165 | } 166 | else if (x -> key <= nextX -> key) 167 | { 168 | x -> f = nextX -> f; 169 | linkTrees(nextX, x); 170 | } 171 | else 172 | { 173 | if (prevX == NULL) H -> roots = nextX; 174 | else prevX -> f = nextX; 175 | linkTrees(x, nextX); 176 | x = nextX; 177 | } 178 | nextX = x -> f; 179 | } 180 | 181 | this -> roots = H -> roots; 182 | this -> min = H -> roots; 183 | BinNode *cur = this -> roots; 184 | while (cur != NULL) 185 | { 186 | if (cur -> key < this -> min -> key) this -> min = cur; 187 | cur = cur -> f; 188 | } 189 | } 190 | 191 | BinNode* BinHeap::first() 192 | { 193 | return this -> min; 194 | } 195 | 196 | BinNode* BinHeap::extractMin() 197 | { 198 | BinNode *ret = this -> first(); 199 | 200 | // delete ret from the list of roots 201 | BinNode *prevX = NULL; 202 | BinNode *x = this -> roots; 203 | while (x != ret) 204 | { 205 | prevX = x; 206 | x = x -> f; 207 | } 208 | if (prevX == NULL) this -> roots = x -> f; 209 | else prevX -> f = x -> f; 210 | 211 | // reverse the list of ret's children 212 | BinNode *revChd = NULL; 213 | BinNode *cur = ret -> c; 214 | while (cur != NULL) 215 | { 216 | BinNode *next = cur -> f; 217 | cur -> f = revChd; 218 | revChd = cur; 219 | cur = next; 220 | } 221 | 222 | // merge the two lists 223 | BinHeap *H = new BinHeap(); 224 | H -> roots = revChd; 225 | this -> merge(H); 226 | 227 | return ret; 228 | } 229 | 230 | void BinHeap::decreaseKey(BinNode *x, int newKey) 231 | { 232 | // Precondition: x -> key > newKey 233 | x -> key = newKey; 234 | BinNode *y = x; 235 | BinNode *z = y -> p; 236 | while (z != NULL && y -> key < z -> key) 237 | { 238 | // swap contents 239 | swap(y -> key, z -> key); 240 | 241 | y = z; 242 | z = y -> p; 243 | } 244 | 245 | if (y -> key < this -> min -> key) this -> min = y; 246 | } 247 | 248 | void BinHeap::Delete(BinNode *x) 249 | { 250 | decreaseKey(x, -INF); 251 | extractMin(); 252 | } 253 | 254 | int main() 255 | { 256 | BinHeap *bh = new BinHeap(); 257 | 258 | BinNode *x = new BinNode(11); 259 | BinNode *y = new BinNode(5); 260 | 261 | bh -> insert(x); 262 | bh -> insert(y); 263 | bh -> insert(new BinNode(3)); 264 | bh -> insert(new BinNode(8)); 265 | bh -> insert(new BinNode(4)); 266 | 267 | bh -> decreaseKey(x, 2); 268 | 269 | while (!bh -> isEmpty()) 270 | { 271 | printf("%d ", bh -> extractMin() -> key); 272 | } 273 | printf("\n"); 274 | return 0; 275 | } -------------------------------------------------------------------------------- /Data Structures/Proto-vEB Tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Proto-vEB Tree 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | using namespace std; 21 | typedef long long lld; 22 | typedef unsigned long long llu; 23 | 24 | /* 25 | Proto-vEB Tree structure for holding a set of integers in a given universe. 26 | Complexity: O(log log u) for member 27 | O(log u) for insert, delete, min, max, extractMin, first and decreaseKey 28 | O(log u log log u) for pred, succ 29 | */ 30 | 31 | class Proto_vEBTree 32 | { 33 | llu u; 34 | Proto_vEBTree *summary; // used if u != 2 35 | Proto_vEBTree **cluster; // used if u != 2 36 | 37 | bool low, high; // used only when u == 2 38 | int n; // alternative for speeding up proto-vEB-Delete 39 | public: 40 | Proto_vEBTree(llu); 41 | 42 | bool member(llu); 43 | bool insert(llu); 44 | bool Delete(llu); 45 | llu min(); 46 | llu max(); 47 | llu pred(llu); 48 | llu succ(llu); 49 | 50 | llu extractMin(); 51 | llu first(); 52 | void decreaseKey(llu, llu); 53 | }; 54 | 55 | Proto_vEBTree::Proto_vEBTree(llu u) 56 | { 57 | this -> u = u; 58 | this -> n = 0; 59 | if (u == 2) 60 | { 61 | this -> low = this -> high = false; 62 | this -> summary = NULL; 63 | this -> cluster = NULL; 64 | } 65 | else 66 | { 67 | llu subSize = (llu)sqrt(u); 68 | this -> summary = new Proto_vEBTree(subSize); 69 | this -> cluster = new Proto_vEBTree*[subSize]; 70 | } 71 | } 72 | 73 | bool Proto_vEBTree::member(llu x) 74 | { 75 | if (u == 2) 76 | { 77 | if (x == 0) return low; 78 | else if (x == 1) return high; 79 | return false; 80 | } 81 | else 82 | { 83 | llu subSize = (llu)sqrt(u); 84 | llu hi = x / subSize, lo = x % subSize; 85 | if (cluster[hi] == NULL) return false; 86 | else return cluster[hi] -> member(lo); 87 | } 88 | } 89 | 90 | bool Proto_vEBTree::insert(llu x) 91 | { 92 | if (u == 2) 93 | { 94 | if (x == 0) 95 | { 96 | if (low) return false; 97 | low = true; 98 | n++; 99 | return true; 100 | } 101 | else if (x == 1) 102 | { 103 | if (high) return false; 104 | high = true; 105 | n++; 106 | return true; 107 | } 108 | else throw -1; 109 | } 110 | else 111 | { 112 | llu subSize = (llu)sqrt(u); 113 | llu hi = x / subSize, lo = x % subSize; 114 | if (cluster[hi] == NULL) 115 | { 116 | cluster[hi] = new Proto_vEBTree(subSize); 117 | cluster[hi] -> insert(lo); 118 | n++; 119 | summary -> insert(hi); 120 | return true; 121 | } 122 | else return cluster[hi] -> insert(lo); 123 | } 124 | } 125 | 126 | bool Proto_vEBTree::Delete(llu x) 127 | { 128 | if (u == 2) 129 | { 130 | if (x == 0) 131 | { 132 | low = false; 133 | n--; 134 | return !high; 135 | } 136 | else if (x == 1) 137 | { 138 | high = false; 139 | n--; 140 | return !low; 141 | } 142 | else throw -1; 143 | } 144 | else 145 | { 146 | llu subSize = (llu)sqrt(u); 147 | llu hi = x / subSize, lo = x % subSize; 148 | if (cluster[hi] -> Delete(lo)) 149 | { 150 | delete cluster[hi]; 151 | cluster[hi] = NULL; 152 | n--; 153 | if (n == 0) 154 | { 155 | summary -> Delete(hi); 156 | return true; 157 | } 158 | return false; 159 | } 160 | return false; 161 | } 162 | } 163 | 164 | llu Proto_vEBTree::min() 165 | { 166 | if (u == 2) 167 | { 168 | if (low) return 0; 169 | else if (high) return 1; 170 | else throw -1; // Proto-vEB is empty 171 | } 172 | else 173 | { 174 | llu subSize = (llu)sqrt(u); 175 | llu hi = summary -> min(); 176 | llu lo = cluster[hi] -> min(); 177 | return hi * subSize + lo; 178 | } 179 | } 180 | 181 | llu Proto_vEBTree::max() 182 | { 183 | if (u == 2) 184 | { 185 | if (high) return 1; 186 | else if (low) return 0; 187 | else throw -1; // Proto-vEB is empty 188 | } 189 | else 190 | { 191 | llu subSize = (llu)sqrt(u); 192 | llu hi = summary -> max(); 193 | llu lo = cluster[hi] -> max(); 194 | return hi * subSize + lo; 195 | } 196 | } 197 | 198 | llu Proto_vEBTree::pred(llu x) 199 | { 200 | if (u == 2) 201 | { 202 | if (x == 1 && low) return 0; 203 | else throw -1; // Predecessor does not exist 204 | } 205 | else 206 | { 207 | llu subSize = (llu)sqrt(u); 208 | llu hi = x / subSize; 209 | llu lo = x % subSize; 210 | if (cluster[hi] == NULL) 211 | { 212 | llu prev = summary -> pred(hi); 213 | return prev * subSize + cluster[prev] -> max(); 214 | } 215 | else 216 | { 217 | llu newLo, newHi = hi; 218 | try 219 | { 220 | newLo = cluster[hi] -> pred(lo); 221 | } 222 | catch (int e) 223 | { 224 | newHi = summary -> pred(hi); 225 | newLo = cluster[newHi] -> max(); 226 | } 227 | return newHi * subSize + newLo; 228 | } 229 | } 230 | } 231 | 232 | llu Proto_vEBTree::succ(llu x) 233 | { 234 | if (u == 2) 235 | { 236 | if (x == 0 && high) return 1; 237 | else throw -1; // Successor does not exist 238 | } 239 | else 240 | { 241 | llu subSize = (llu)sqrt(u); 242 | llu hi = x / subSize; 243 | llu lo = x % subSize; 244 | if (cluster[hi] == NULL) 245 | { 246 | llu next = summary -> succ(hi); 247 | return next * subSize + cluster[next] -> min(); 248 | } 249 | else 250 | { 251 | llu newLo, newHi = hi; 252 | try 253 | { 254 | newLo = cluster[hi] -> succ(lo); 255 | } 256 | catch (int e) 257 | { 258 | newHi = summary -> succ(hi); 259 | newLo = cluster[newHi] -> min(); 260 | } 261 | return newHi * subSize + newLo; 262 | } 263 | } 264 | } 265 | 266 | llu Proto_vEBTree::extractMin() 267 | { 268 | llu ret = this -> min(); 269 | this -> Delete(ret); 270 | return ret; 271 | } 272 | 273 | llu Proto_vEBTree::first() 274 | { 275 | return this -> min(); 276 | } 277 | 278 | void Proto_vEBTree::decreaseKey(llu x, llu y) 279 | { 280 | // Preconditions: y < x, x is in the tree, y is not in the tree 281 | 282 | this -> Delete(x); 283 | this -> insert(y); 284 | } 285 | 286 | int main() 287 | { 288 | Proto_vEBTree *vEB = new Proto_vEBTree(16); 289 | vEB -> insert(2); 290 | vEB -> insert(3); 291 | vEB -> insert(4); 292 | vEB -> insert(5); 293 | vEB -> insert(7); 294 | vEB -> insert(14); 295 | vEB -> insert(15); 296 | printf("%llu\n", vEB -> min()); 297 | printf("%llu\n", vEB -> max()); 298 | printf("%llu\n", vEB -> pred(9)); 299 | printf("%llu\n", vEB -> succ(9)); 300 | return 0; 301 | } 302 | 303 | -------------------------------------------------------------------------------- /Data Structures/Circular Doubly-Linked List.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Circular Doubly Linked List (Microchallenge) 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | using namespace std; 21 | typedef long long lld; 22 | 23 | /* 24 | An implementation of a Circular Doubly Linked List data structure. 25 | Used as an underlying data structure in the Fibonacci Heap implementation. 26 | Complexity: O(1) for: isEmpty, insert, getMinimum, decreaseKey and merge. 27 | O(N) for: extractMinimum and Delete (if we're deleting the minimum). 28 | */ 29 | 30 | class Node 31 | { 32 | public: 33 | int key; 34 | 35 | Node *left; 36 | Node *right; 37 | 38 | Node(); 39 | Node(int key); 40 | }; 41 | 42 | class CircularDoublyLinkedList 43 | { 44 | public: 45 | Node *first; 46 | Node *minimum; 47 | 48 | CircularDoublyLinkedList(); 49 | 50 | bool isEmpty(); 51 | void insert(Node *x); 52 | Node *getMinimum(); 53 | Node *extractMinimum(); 54 | void decreaseKey(Node *x, int newKey); 55 | void Delete(Node *x); 56 | void merge(CircularDoublyLinkedList *cdll); 57 | 58 | void print(); 59 | }; 60 | 61 | Node::Node() 62 | { 63 | this -> key = 0; 64 | this -> left = NULL; 65 | this -> right = NULL; 66 | } 67 | 68 | Node::Node(int key) 69 | { 70 | this -> key = key; 71 | this -> left = NULL; 72 | this -> right = NULL; 73 | } 74 | 75 | CircularDoublyLinkedList::CircularDoublyLinkedList() 76 | { 77 | this -> first = NULL; 78 | this -> minimum = NULL; 79 | } 80 | 81 | bool CircularDoublyLinkedList::isEmpty() 82 | { 83 | return (this -> first == NULL); 84 | } 85 | 86 | void CircularDoublyLinkedList::insert(Node *x) 87 | { 88 | if (isEmpty()) 89 | { 90 | this -> first = x; 91 | this -> minimum = x; 92 | x -> left = x; 93 | x -> right = x; 94 | } 95 | else 96 | { 97 | Node *last = this -> first -> left; 98 | last -> right = x; 99 | x -> left = last; 100 | this -> first -> left = x; 101 | x -> right = this -> first; 102 | if (x -> key < this -> minimum -> key) this -> minimum = x; 103 | } 104 | } 105 | 106 | Node* CircularDoublyLinkedList::getMinimum() 107 | { 108 | return this -> minimum; 109 | } 110 | 111 | Node* CircularDoublyLinkedList::extractMinimum() 112 | { 113 | if (isEmpty()) return NULL; 114 | Node *ret = this -> minimum; 115 | if (ret -> right == ret) 116 | { 117 | this -> first = NULL; 118 | this -> minimum = NULL; 119 | } 120 | else 121 | { 122 | Node *prev = ret -> left; 123 | Node *next = ret -> right; 124 | prev -> right = next; 125 | next -> left = prev; 126 | if (ret == this -> first) 127 | { 128 | this -> first = next; 129 | } 130 | this -> minimum = this -> first; 131 | Node *curr = this -> first -> right; 132 | while (curr != this -> first) 133 | { 134 | if (curr -> key < this -> minimum -> key) this -> minimum = curr; 135 | curr = curr -> right; 136 | } 137 | } 138 | return ret; 139 | } 140 | 141 | void CircularDoublyLinkedList::decreaseKey(Node *x, int newKey) 142 | { 143 | x -> key = newKey; 144 | if (x -> key < this -> minimum -> key) this -> minimum = x; 145 | } 146 | 147 | void CircularDoublyLinkedList::Delete(Node *x) 148 | { 149 | if (this -> minimum == x) extractMinimum(); 150 | else 151 | { 152 | Node *prev = x -> left; 153 | Node *next = x -> right; 154 | prev -> right = next; 155 | next -> left = prev; 156 | if (x == this -> first) 157 | { 158 | this -> first = next; 159 | } 160 | } 161 | } 162 | 163 | void CircularDoublyLinkedList::merge(CircularDoublyLinkedList *cdll) 164 | { 165 | /* 166 | Merging works by "clipping" the list to be merged before the first pointer 167 | and then inserting that entire list before the first pointer in the original list. 168 | 169 | For example, if our lists were A <-> B <-> C <-> A and D <-> E <-> D 170 | The merged list would look something like A <-> B <-> C <-> D <-> E <-> A 171 | */ 172 | 173 | if (cdll -> isEmpty()) return; 174 | if (this -> isEmpty()) 175 | { 176 | this -> first = cdll -> first; 177 | this -> minimum = cdll -> minimum; 178 | return; 179 | } 180 | Node *first1 = this -> first; 181 | Node *last1 = this -> first -> left; 182 | Node *first2 = cdll -> first; 183 | Node *last2 = cdll -> first -> left; 184 | first1 -> left = last2; 185 | last1 -> right = first2; 186 | first2 -> left = last1; 187 | last2 -> right = first1; 188 | if (cdll -> minimum -> key < this -> minimum -> key) this -> minimum = cdll -> minimum; 189 | } 190 | 191 | void CircularDoublyLinkedList::print() 192 | { 193 | if (isEmpty()) { printf("\n"); return; } 194 | else 195 | { 196 | if (this -> first == this -> minimum) printf("*%d*", this -> first -> key); 197 | else printf("%d", this -> first -> key); 198 | Node *curr = this -> first; 199 | do 200 | { 201 | curr = curr -> right; 202 | if (this -> minimum == curr) printf(" <-> *%d*", curr -> key); 203 | else printf(" <-> %d", curr -> key); 204 | } while (curr != this -> first); 205 | printf("\n"); 206 | } 207 | } 208 | 209 | int main() 210 | { 211 | char response[55]; 212 | 213 | printf("Do you want to write the results to file? (Y/N)\n"); 214 | while (true) 215 | { 216 | scanf("%s", response); 217 | if (response[0] == 'Y' || response[0] == 'y') break; 218 | else if (response[0] == 'N' || response[0] == 'n') break; 219 | printf("Incorrect character! You must input 'Y' or 'N'. Retry: \n"); 220 | } 221 | 222 | if (response[0] == 'Y' || response[0] == 'y') 223 | { 224 | freopen("/Users/PetarV/TestLogs/CDLL-Test.txt","w",stdout); 225 | } 226 | 227 | time_t t = time(0); 228 | struct tm *now = localtime(&t); 229 | 230 | printf("CDLL Microchallenge testing protocol started.\n"); 231 | printf("Testing carried out on %d-%d-%d, by Petar Velickovic.", now -> tm_year + 1900, now -> tm_mon + 1, now -> tm_mday); 232 | printf("\n---------------------------------------------------------------\n"); 233 | 234 | printf("Creating an empty CDLL.\n"); 235 | CircularDoublyLinkedList *CDLL = new CircularDoublyLinkedList(); 236 | printf("CDLL Contains:\n"); 237 | CDLL -> print(); 238 | printf("---------------------------------------------------------------\n"); 239 | 240 | printf("Creating two nodes, X(7) and Y(4).\n"); 241 | Node *X = new Node(7); 242 | Node *Y = new Node(4); 243 | 244 | printf("Inserting an anonymous node, with key 3.\n"); 245 | CDLL -> insert(new Node(3)); 246 | printf("CDLL Contains:\n"); 247 | CDLL -> print(); 248 | printf("---------------------------------------------------------------\n"); 249 | 250 | printf("Inserting X(7).\n"); 251 | CDLL -> insert(X); 252 | printf("CDLL Contains:\n"); 253 | CDLL -> print(); 254 | printf("---------------------------------------------------------------\n"); 255 | 256 | printf("Inserting an anonymous node, with key 2.\n"); 257 | CDLL -> insert(new Node(2)); 258 | printf("CDLL Contains:\n"); 259 | CDLL -> print(); 260 | printf("---------------------------------------------------------------\n"); 261 | 262 | printf("Inserting Y(4).\n"); 263 | CDLL -> insert(Y); 264 | printf("CDLL Contains:\n"); 265 | CDLL -> print(); 266 | printf("---------------------------------------------------------------\n"); 267 | 268 | printf("Decreasing the key of X(7) to -1.\n"); 269 | CDLL -> decreaseKey(X, -1); 270 | printf("CDLL Contains:\n"); 271 | CDLL -> print(); 272 | printf("---------------------------------------------------------------\n"); 273 | 274 | printf("Extracting the minimum.\n"); 275 | Node *M = CDLL -> extractMinimum(); 276 | printf("The minimum key is: %d.\n", M -> key); 277 | printf("CDLL Contains:\n"); 278 | CDLL -> print(); 279 | printf("---------------------------------------------------------------\n"); 280 | 281 | printf("Deleting Y(4).\n"); 282 | CDLL -> Delete(Y); 283 | printf("CDLL Contains:\n"); 284 | CDLL -> print(); 285 | printf("---------------------------------------------------------------\n"); 286 | 287 | printf("Merging with a CDLL containing 1 <-> 2 <-> 3 <-> 4 <-> 1.\n"); 288 | CircularDoublyLinkedList *toMerge = new CircularDoublyLinkedList(); 289 | toMerge -> insert(new Node(1)); 290 | toMerge -> insert(new Node(2)); 291 | toMerge -> insert(new Node(3)); 292 | toMerge -> insert(new Node(4)); 293 | CDLL -> merge(toMerge); 294 | printf("CDLL Contains:\n"); 295 | CDLL -> print(); 296 | printf("---------------------------------------------------------------\n"); 297 | 298 | printf("Testing completed.\n"); 299 | return 0; 300 | } 301 | -------------------------------------------------------------------------------- /Data Structures/Fibonacci Heap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: Fibonacci Heap 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define INF 987654321 21 | using namespace std; 22 | typedef long long lld; 23 | typedef unsigned long long llu; 24 | 25 | /* 26 | Fibonacci Heap data structure satisfying the heap property, with highly efficient asymptotic bounds. 27 | Useful for a priority queue implementation in Dijkstra's and Prim's algorithms. 28 | Complexity: O(1) for insert, first and merge 29 | O(1) amortized for decreaseKey 30 | O(log N) amortized for extractMin and delete 31 | */ 32 | 33 | struct FibNode 34 | { 35 | int key; 36 | bool marked; 37 | int degree; 38 | FibNode *b, *f, *p, *c; 39 | 40 | FibNode() 41 | { 42 | this -> key = 0; 43 | this -> marked = false; 44 | this -> degree = 0; 45 | this -> b = this -> f = this -> p = this -> c = NULL; 46 | } 47 | 48 | FibNode(int key) 49 | { 50 | this -> key = key; 51 | this -> marked = false; 52 | this -> degree = 0; 53 | this -> b = this -> f = this -> p = this -> c = NULL; 54 | } 55 | }; 56 | 57 | class FibHeap 58 | { 59 | FibNode *min; 60 | int N; 61 | 62 | public: 63 | FibHeap(); 64 | FibHeap(FibNode*); 65 | bool isEmpty(); 66 | void insert(FibNode*); 67 | void merge(FibHeap*); 68 | FibNode* first(); 69 | FibNode* extractMin(); 70 | void decreaseKey(FibNode*, int); 71 | void Delete(FibNode*); 72 | }; 73 | 74 | FibHeap::FibHeap() 75 | { 76 | this -> min = NULL; 77 | this -> N = 0; 78 | } 79 | 80 | FibHeap::FibHeap(FibNode *n) 81 | { 82 | this -> min = n; 83 | n -> b = n -> f = n; 84 | n -> p = n -> c = NULL; 85 | 86 | this -> N = 1; 87 | } 88 | 89 | bool FibHeap::isEmpty() 90 | { 91 | return (this -> min == NULL); 92 | } 93 | 94 | void FibHeap::insert(FibNode *n) 95 | { 96 | this -> merge(new FibHeap(n)); 97 | } 98 | 99 | void FibHeap::merge(FibHeap *h) 100 | { 101 | this -> N += h -> N; 102 | if (h -> isEmpty()) return; 103 | if (this -> isEmpty()) 104 | { 105 | this -> min = h -> min; 106 | return; 107 | } 108 | FibNode *first1 = this -> min; 109 | FibNode *last1 = this -> min -> b; 110 | FibNode *first2 = h -> min; 111 | FibNode *last2 = h -> min -> b; 112 | first1 -> b = last2; 113 | last1 -> f = first2; 114 | first2 -> b = last1; 115 | last2 -> f = first1; 116 | if (h -> min -> key < this -> min -> key) this -> min = h -> min; 117 | } 118 | 119 | FibNode* FibHeap::first() 120 | { 121 | return this -> min; 122 | } 123 | 124 | FibNode* FibHeap::extractMin() 125 | { 126 | FibNode *ret = this -> min; 127 | this -> N = this -> N - 1; 128 | 129 | if (ret -> f == ret) 130 | { 131 | this -> min = NULL; 132 | } 133 | else 134 | { 135 | FibNode *prev = ret -> b; 136 | FibNode *next = ret -> f; 137 | prev -> f = next; 138 | next -> b = prev; 139 | this -> min = next; // Not necessarily a minimum. This is for assisting with the merge w/ min's children. 140 | } 141 | 142 | if (ret -> c != NULL) 143 | { 144 | FibNode *firstChd = ret -> c; 145 | FibNode *currChd = firstChd; 146 | 147 | do 148 | { 149 | currChd -> p = NULL; 150 | currChd = currChd -> f; 151 | } while (currChd != firstChd); 152 | 153 | if (this -> isEmpty()) 154 | { 155 | this -> min = firstChd; 156 | } 157 | else 158 | { 159 | FibNode *first1 = this -> min; 160 | FibNode *last1 = this -> min -> b; 161 | FibNode *first2 = firstChd; 162 | FibNode *last2 = firstChd -> b; 163 | first1 -> b = last2; 164 | last1 -> f = first2; 165 | first2 -> b = last1; 166 | last2 -> f = first1; 167 | } 168 | } 169 | 170 | if (this -> min != NULL) 171 | { 172 | int maxAuxSize = 5 * (((int)log2(this -> N + 1)) + 1); 173 | FibNode *aux[maxAuxSize + 1]; 174 | for (int i=0;i<=maxAuxSize;i++) aux[i] = NULL; 175 | int maxDegree = 0; 176 | 177 | FibNode *curr = this -> min; 178 | 179 | do 180 | { 181 | FibNode *next = curr -> f; 182 | int deg = curr -> degree; 183 | FibNode *P = curr; 184 | while (aux[deg] != NULL) 185 | { 186 | FibNode *Q = aux[deg]; 187 | aux[deg] = NULL; 188 | 189 | if (P -> key > Q -> key) 190 | { 191 | FibNode *tmp = P; 192 | P = Q; 193 | Q = tmp; 194 | } 195 | 196 | Q -> p = P; 197 | if (P -> c == NULL) 198 | { 199 | P -> c = Q; 200 | Q -> b = Q -> f = Q; 201 | } 202 | else 203 | { 204 | FibNode *last = P -> c -> b; 205 | last -> f = Q; 206 | Q -> b = last; 207 | P -> c -> b = Q; 208 | Q -> f = P -> c; 209 | } 210 | 211 | deg++; 212 | P -> degree = deg; 213 | } 214 | aux[deg] = P; 215 | if (deg > maxDegree) maxDegree = deg; 216 | curr = next; 217 | } while (curr != this -> min); 218 | 219 | 220 | FibNode *previous = aux[maxDegree]; 221 | this -> min = previous; 222 | for (int i=0;i<=maxDegree;i++) 223 | { 224 | if (aux[i] != NULL) 225 | { 226 | previous -> f = aux[i]; 227 | aux[i] -> b = previous; 228 | if (aux[i] -> key < this -> min -> key) this -> min = aux[i]; 229 | previous = aux[i]; 230 | } 231 | } 232 | 233 | } 234 | 235 | return ret; 236 | } 237 | 238 | void FibHeap::decreaseKey(FibNode *n, int newKey) 239 | { 240 | // Precondition: newKey < n -> key 241 | n -> key = newKey; 242 | 243 | FibNode *curr = n; 244 | if (curr -> p != NULL) 245 | { 246 | if (curr -> key < curr -> p -> key) 247 | { 248 | FibNode *parent = curr -> p; 249 | curr -> marked = false; 250 | 251 | curr -> p = NULL; 252 | if (curr -> f == curr) parent -> c = NULL; 253 | else 254 | { 255 | FibNode *prev = curr -> b; 256 | FibNode *next = curr -> f; 257 | prev -> f = next; 258 | next -> b = prev; 259 | if (parent -> c == curr) parent -> c = prev; 260 | } 261 | parent -> degree = parent -> degree - 1; 262 | 263 | FibNode *last = this -> min -> b; 264 | last -> f = curr; 265 | curr -> b = last; 266 | this -> min -> b = curr; 267 | curr -> f = this -> min; 268 | 269 | if (curr -> key < this -> min -> key) this -> min = curr; 270 | 271 | while (parent -> p != NULL && parent -> marked) 272 | { 273 | curr = parent; 274 | parent = curr -> p; 275 | curr -> marked = false; 276 | 277 | curr -> p = NULL; 278 | if (curr -> f == curr) parent -> c = NULL; 279 | else 280 | { 281 | FibNode *prev = curr -> b; 282 | FibNode *next = curr -> f; 283 | prev -> f = next; 284 | next -> b = prev; 285 | if (parent -> c == curr) parent -> c = prev; 286 | } 287 | parent -> degree = parent -> degree - 1; 288 | 289 | FibNode *last = this -> min -> b; 290 | last -> f = curr; 291 | curr -> b = last; 292 | this -> min -> b = curr; 293 | curr -> f = this -> min; 294 | 295 | } 296 | if (parent -> p != NULL) parent -> marked = true; 297 | } 298 | } 299 | else if (n -> key < this -> min -> key) this -> min = n; 300 | } 301 | 302 | void FibHeap::Delete(FibNode *n) 303 | { 304 | this -> decreaseKey(n, -INF); 305 | this -> extractMin(); 306 | } 307 | 308 | int main() 309 | { 310 | FibHeap *fh = new FibHeap(); 311 | 312 | FibNode *x = new FibNode(11); 313 | FibNode *y = new FibNode(5); 314 | 315 | fh -> insert(x); 316 | fh -> insert(y); 317 | fh -> insert(new FibNode(3)); 318 | fh -> insert(new FibNode(8)); 319 | fh -> insert(new FibNode(4)); 320 | 321 | fh -> decreaseKey(x, 2); 322 | fh -> Delete(y); 323 | 324 | while (!fh -> isEmpty()) 325 | { 326 | printf("%d ", fh -> extractMin() -> key); 327 | } 328 | printf("\n"); 329 | return 0; 330 | } 331 | 332 | -------------------------------------------------------------------------------- /Data Structures/van Emde Boas Tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Data Structure: van Emde Boas Tree (vEB) 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | using namespace std; 21 | typedef long long lld; 22 | typedef unsigned long long llu; 23 | 24 | /* 25 | van Emde Boas Tree structure for holding a set of integers in a given universe. 26 | Complexity: O(1) for min, max and first 27 | O(log log u) for member, insert, delete, pred, succ, extractMin and decreaseKey 28 | */ 29 | 30 | class vEB 31 | { 32 | llu u; 33 | 34 | llu *m, *M; 35 | vEB *summary; // used if u != 2 36 | vEB **cluster; // used if u != 2 37 | 38 | public: 39 | vEB(llu); 40 | 41 | bool member(llu); 42 | void insert(llu); 43 | void Delete(llu); 44 | llu min(); 45 | llu max(); 46 | llu* pred(llu); 47 | llu* succ(llu); 48 | 49 | llu extractMin(); 50 | llu first(); 51 | void decreaseKey(llu, llu); 52 | }; 53 | 54 | vEB::vEB(llu u) 55 | { 56 | this -> u = u; 57 | this -> m = NULL; 58 | this -> M = NULL; 59 | 60 | if (u == 2) 61 | { 62 | this -> summary = NULL; 63 | this -> cluster = NULL; 64 | } 65 | 66 | else 67 | { 68 | llu subSize = (llu)sqrt(u); 69 | this -> summary = new vEB(subSize); 70 | this -> cluster = new vEB*[subSize]; 71 | } 72 | } 73 | 74 | bool vEB::member(llu x) 75 | { 76 | if (u == 2) 77 | { 78 | if (m == NULL) return false; 79 | if (x == 0) return ((*m) == 0); 80 | else if (x == 1) return ((*M) == 1); 81 | return false; 82 | } 83 | else 84 | { 85 | if (m == NULL) return false; 86 | if (x < (*m) || x > (*M)) return false; 87 | else if (x == (*m) || (x == (*M))) return true; 88 | else 89 | { 90 | llu subSize = (llu)sqrt(u); 91 | llu hi = x / subSize, lo = x % subSize; 92 | if (cluster[hi] == NULL) return false; 93 | else return cluster[hi] -> member(lo); 94 | } 95 | 96 | } 97 | } 98 | 99 | void vEB::insert(llu x) 100 | { 101 | if (u == 2) 102 | { 103 | if (x == 0) 104 | { 105 | if (m == NULL) 106 | { 107 | m = new llu; 108 | M = new llu; 109 | (*m) = (*M) = x; 110 | } 111 | else (*m) = x; 112 | } 113 | else if (x == 1) 114 | { 115 | if (M == NULL) 116 | { 117 | m = new llu; 118 | M = new llu; 119 | (*m) = (*M) = x; 120 | } 121 | else (*M) = x; 122 | } 123 | } 124 | else 125 | { 126 | if (m == NULL) 127 | { 128 | m = new llu; 129 | M = new llu; 130 | (*m) = (*M) = x; 131 | } 132 | else 133 | { 134 | if (x < (*m)) 135 | { 136 | llu currMin = (*m); 137 | (*m) = x; 138 | this -> insert(currMin); 139 | } 140 | else 141 | { 142 | llu subSize = (llu)sqrt(u); 143 | llu hi = x / subSize, lo = x % subSize; 144 | if (cluster[hi] == NULL) 145 | { 146 | cluster[hi] = new vEB(subSize); 147 | cluster[hi] -> insert(lo); 148 | summary -> insert(hi); 149 | } 150 | else cluster[hi] -> insert(lo); 151 | 152 | if (x > (*M)) (*M) = x; 153 | } 154 | } 155 | } 156 | } 157 | 158 | void vEB::Delete(llu x) 159 | { 160 | if (u == 2) 161 | { 162 | if (x == 0) 163 | { 164 | if ((*M) == 0) 165 | { 166 | m = M = NULL; 167 | } 168 | else (*m) = 1; 169 | } 170 | else if (x == 1) 171 | { 172 | if ((*m) == 1) 173 | { 174 | m = M = NULL; 175 | } 176 | else (*M) = 0; 177 | } 178 | } 179 | else 180 | { 181 | llu subSize = (llu)sqrt(u); 182 | llu hi = x / subSize, lo = x % subSize; 183 | 184 | if (x == (*m)) 185 | { 186 | if (x == (*M)) 187 | { 188 | m = M = NULL; 189 | } 190 | else 191 | { 192 | llu nextMinHi = summary -> min(); 193 | llu nextMinLo = cluster[summary -> min()] -> min(); 194 | llu nextMin = nextMinHi * subSize + nextMinLo; 195 | this -> Delete(nextMin); 196 | (*m) = nextMin; 197 | } 198 | } 199 | else 200 | { 201 | cluster[hi] -> Delete(lo); 202 | if (cluster[hi] -> m == NULL) 203 | { 204 | summary -> Delete(hi); 205 | delete cluster[hi]; 206 | cluster[hi] = NULL; 207 | } 208 | if (x == (*M)) 209 | { 210 | if (summary -> m == NULL) (*M) = (*m); 211 | else 212 | { 213 | llu nextMaxHi = summary -> max(); 214 | llu nextMaxLo = cluster[summary -> max()] -> max(); 215 | (*M) = nextMaxHi * subSize + nextMaxLo; 216 | } 217 | } 218 | } 219 | } 220 | } 221 | 222 | llu vEB::min() 223 | { 224 | return (*m); 225 | } 226 | 227 | llu vEB::max() 228 | { 229 | return (*M); 230 | } 231 | 232 | llu* vEB::pred(llu x) 233 | { 234 | if (u == 2) 235 | { 236 | if (x == 0) return NULL; 237 | else if (x == 1) 238 | { 239 | if (m == NULL) return NULL; 240 | if ((*m) == 1) return NULL; 241 | return m; 242 | } 243 | else return NULL; 244 | } 245 | else 246 | { 247 | if (m == NULL) return NULL; 248 | if (x <= (*m)) return NULL; 249 | if (x > (*M)) return M; 250 | llu subSize = (llu)sqrt(u); 251 | llu hi = x / subSize; 252 | llu lo = x % subSize; 253 | if (cluster[hi] == NULL) 254 | { 255 | llu* prev = summary -> pred(hi); 256 | llu* ret = new llu; 257 | (*ret) = (*prev) * subSize + cluster[(*prev)] -> max(); 258 | return ret; 259 | } 260 | else 261 | { 262 | llu *newLo, *newHi; 263 | newHi = new llu; 264 | newLo = new llu; 265 | (*newHi) = hi; 266 | llu minInCluster = cluster[hi] -> min(); 267 | if (lo > minInCluster) newLo = cluster[hi] -> pred(lo); 268 | else 269 | { 270 | newHi = summary -> pred(hi); 271 | (*newLo) = cluster[(*newHi)] -> max(); 272 | } 273 | llu *ret = new llu; 274 | (*ret) = (*newHi) * subSize + (*newLo); 275 | return ret; 276 | } 277 | } 278 | } 279 | 280 | llu* vEB::succ(llu x) 281 | { 282 | if (u == 2) 283 | { 284 | if (x == 1) return NULL; 285 | else if (x == 0) 286 | { 287 | if (M == NULL) return NULL; 288 | if ((*M) == 0) return NULL; 289 | return M; 290 | } 291 | else return NULL; 292 | } 293 | else 294 | { 295 | if (m == NULL) return NULL; 296 | if (x >= (*M)) return NULL; 297 | if (x < (*m)) return m; 298 | llu subSize = (llu)sqrt(u); 299 | llu hi = x / subSize; 300 | llu lo = x % subSize; 301 | if (cluster[hi] == NULL) 302 | { 303 | llu* next = summary -> succ(hi); 304 | llu* ret = new llu; 305 | (*ret) = (*next) * subSize + cluster[(*next)] -> min(); 306 | return ret; 307 | } 308 | else 309 | { 310 | llu *newLo, *newHi; 311 | newHi = new llu; 312 | newLo = new llu; 313 | (*newHi) = hi; 314 | llu maxInCluster = cluster[hi] -> max(); 315 | if (lo < maxInCluster) newLo = cluster[hi] -> succ(lo); 316 | else 317 | { 318 | newHi = summary -> succ(hi); 319 | (*newLo) = cluster[(*newHi)] -> min(); 320 | } 321 | llu *ret = new llu; 322 | (*ret) = (*newHi) * subSize + (*newLo); 323 | return ret; 324 | } 325 | } 326 | } 327 | 328 | llu vEB::extractMin() 329 | { 330 | llu ret = this -> min(); 331 | this -> Delete(ret); 332 | return ret; 333 | } 334 | 335 | llu vEB::first() 336 | { 337 | return this -> min(); 338 | } 339 | 340 | void vEB::decreaseKey(llu x, llu y) 341 | { 342 | // Preconditions: y < x, x is in the tree, y is not in the tree 343 | 344 | this -> Delete(x); 345 | this -> insert(y); 346 | } 347 | 348 | int main() 349 | { 350 | vEB *vEB = new class vEB(16); 351 | 352 | vEB -> insert(2); 353 | vEB -> insert(3); 354 | vEB -> insert(4); 355 | vEB -> insert(5); 356 | vEB -> insert(7); 357 | vEB -> insert(14); 358 | vEB -> insert(15); 359 | 360 | printf("%llu\n", vEB -> min()); 361 | printf("%llu\n", vEB -> max()); 362 | printf("%llu\n", (*vEB -> pred(9))); 363 | printf("%llu\n", (*vEB -> succ(9))); 364 | 365 | vEB -> Delete(7); 366 | vEB -> Delete(14); 367 | 368 | 369 | printf("%llu\n", (*vEB -> pred(9))); 370 | printf("%llu\n", (*vEB -> succ(9))); 371 | 372 | return 0; 373 | } -------------------------------------------------------------------------------- /Mathematical Algorithms/Strassen's Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Strassen's Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | typedef long long lld; 21 | 22 | /* 23 | Strassen's Algorithm for matrix multiplication 24 | Complexity: O(n^2.808) 25 | */ 26 | 27 | inline lld** MatrixMultiply(lld** a, lld** b, int n, int l, int m) 28 | { 29 | lld **c = new lld*[n]; 30 | for (int i=0;i> 1) + (n & 1); 57 | int adjL = (l >> 1) + (l & 1); 58 | int adjM = (m >> 1) + (m & 1); 59 | 60 | lld ****As = new lld***[2]; 61 | for (int x=0;x<2;x++) 62 | { 63 | As[x] = new lld**[2]; 64 | for (int y=0;y<2;y++) 65 | { 66 | As[x][y] = new lld*[adjN]; 67 | for (int i=0;i>1);j++) 288 | { 289 | delete[] p[i][j]; 290 | } 291 | delete[] p[i]; 292 | } 293 | delete[] p; 294 | 295 | return c; 296 | } 297 | 298 | int main() 299 | { 300 | lld **matA; 301 | matA = new lld*[2]; 302 | for (int i=0;i<2;i++) matA[i] = new lld[3]; 303 | matA[0][0] = 1; 304 | matA[0][1] = 2; 305 | matA[0][2] = 3; 306 | matA[1][0] = 4; 307 | matA[1][1] = 5; 308 | matA[1][2] = 6; 309 | 310 | lld **matB; 311 | matB = new lld*[3]; 312 | for (int i=0;i<3;i++) matB[i] = new lld[2]; 313 | matB[0][0] = 7; 314 | matB[0][1] = 8; 315 | matB[1][0] = 9; 316 | matB[1][1] = 10; 317 | matB[2][0] = 11; 318 | matB[2][1] = 12; 319 | 320 | lld **matC = Strassen(matA, matB, 2, 3, 2); 321 | for (int i=0;i<2;i++) 322 | { 323 | for (int j=0;j<2;j++) 324 | { 325 | printf("%lld ", matC[i][j]); 326 | } 327 | printf("\n"); 328 | } 329 | 330 | return 0; 331 | } -------------------------------------------------------------------------------- /Mathematical Algorithms/Simplex Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Petar 'PetarV' Velickovic 3 | Algorithm: Simplex Algorithm 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_N 1001 22 | #define MAX_M 1001 23 | 24 | typedef long long lld; 25 | typedef unsigned long long llu; 26 | using namespace std; 27 | 28 | /* 29 | The Simplex algorithm aims to solve a linear program - optimising a linear function subject 30 | to linear constraints. As such it is useful for a very wide range of applications. 31 | 32 | N.B. The linear program has to be given in *slack form*, which is as follows: 33 | maximise 34 | c_1 * x_1 + c_2 * x_2 + ... + c_n * x_n + v 35 | subj. to 36 | a_11 * x_1 + a_12 * x_2 + ... + a_1n * x_n + b_1 = s_1 37 | a_21 * x_1 + a_22 * x_2 + ... + a_2n * x_n + b_2 = s_2 38 | ... 39 | a_m1 * x_1 + a_m2 * x_2 + ... + a_mn * x_n + b_m = s_m 40 | and 41 | x_1, x_2, ..., x_n, s_1, s_2, ..., s_m >= 0 42 | 43 | Every linear program can be translated into slack form; the parameters to specify are: 44 | - the number of variables, n, and the number of constraints, m; 45 | - the matrix A = [[A_11, A_12, ..., A_1n], ..., [A_m1, A_m2, ..., A_mn]]; 46 | - the vector b = [b_1, b_2, ..., b_m]; 47 | - the vector c = [c_1, c_2, ..., c_n] and the constant v. 48 | 49 | Complexity: O(m^(n/2)) worst case 50 | O(n + m) average case (common) 51 | */ 52 | 53 | int n, m; 54 | double A[MAX_M][MAX_N], b[MAX_M], c[MAX_N], v; 55 | int N[MAX_N], B[MAX_M]; // nonbasic & basic 56 | 57 | // pivot yth variable around xth constraint 58 | inline void pivot(int x, int y) 59 | { 60 | printf("Pivoting variable %d around constraint %d.\n", y, x); 61 | 62 | // first rearrange the x-th row 63 | for (int j=0;j 0) 127 | { 128 | if (best_var == -1 || N[j] < ind) 129 | { 130 | ind = N[j]; 131 | best_var = j; 132 | } 133 | } 134 | } 135 | if (ind == -1) return 1; 136 | 137 | double max_constr = INFINITY; 138 | int best_constr = -1; 139 | for (int i=0;i= 0) // basic solution feasible! 173 | { 174 | for (int j=0;j n) N[j]--; 239 | for (int i=0;i n) B[i]--; 240 | 241 | for (int j=0;j, double> simplex() 277 | { 278 | if (initialise_simplex() == -1) 279 | { 280 | return make_pair(vector(n + m, -2), INFINITY); 281 | } 282 | 283 | int code; 284 | while (!(code = iterate_simplex())); 285 | 286 | if (code == -1) return make_pair(vector(n + m, -1), INFINITY); 287 | 288 | vector ret; 289 | ret.resize(n + m); 290 | for (int j=0;j, double> ret = simplex(); 353 | 354 | if (isinf(ret.second)) 355 | { 356 | if (ret.first[0] == -1) printf("Objective function unbounded!\n"); 357 | else if (ret.first[0] == -2) printf("Linear program infeasible!\n"); 358 | } 359 | else 360 | { 361 | printf("Solution: ("); 362 | for (int i=0;i