├── .gitattributes ├── .gitignore ├── Code ├── Test │ ├── Test.cs │ └── Test.csproj ├── Utility.sln └── Utility │ ├── BinarySearchTree │ ├── KeyValue │ │ ├── AVLTree.cs │ │ ├── BinarySearchTree.cs │ │ ├── RedBlackTree.cs │ │ ├── ScapegoatTree.cs │ │ └── SplayTree.cs │ └── Value │ │ ├── AVLTree.cs │ │ ├── BinarySearchTree.cs │ │ ├── RedBlackTree.cs │ │ ├── ScapegoatTree.cs │ │ └── SplayTree.cs │ ├── ComputationalGeometry │ ├── ConvexHull.cs │ ├── Matrix.cs │ └── Vector.cs │ ├── DisjointSet │ └── UnionFind.cs │ ├── Graph │ ├── Graph.cs │ ├── GraphInterfaces.cs │ ├── MaxFlowMinCut.cs │ ├── MaximumFlow │ │ └── MaxFlowMinCut.cs │ ├── MinimumSpanningTree.cs │ ├── MinimumSpanningTree │ │ └── Kruskal.cs │ ├── Path.cs │ ├── ShortestPath.cs │ └── ShortestPath │ │ ├── BellmanFord.cs │ │ ├── BreadthFirstSearch.cs │ │ ├── Dijkstra.cs │ │ ├── FloydWarshall.cs │ │ └── Johnson.cs │ ├── PriorityQueue │ ├── DHeap.cs │ └── PairingHeap.cs │ ├── ProbabilisticStructures │ ├── BloomFilter.cs │ └── SkipList.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Search │ ├── BinaryInterpolationSearch.cs │ ├── BinarySearch.cs │ ├── GallopSearch.cs │ ├── InterpolationSearch.cs │ ├── Interpolator.cs │ └── RandomSearch.cs │ ├── Sort │ ├── BinaryInsertionSort.cs │ ├── BubbleSort.cs │ ├── CocktailSort.cs │ ├── CombInsertionSort.cs │ ├── CombSort.cs │ ├── CycleSort.cs │ ├── GnomeSort.cs │ ├── HeapSort.cs │ ├── InsertionSort.cs │ ├── JSort.cs │ ├── MergeSort.cs │ ├── OddEvenSort.cs │ ├── PatienceSort.cs │ ├── Quicksort.cs │ ├── SelectionSort.cs │ ├── ShellSort.cs │ ├── Sort.cs │ ├── StrandSort.cs │ ├── Timsort.cs │ └── TreeSort.cs │ ├── Trees │ └── Trie.cs │ └── Utility.csproj └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | *.md text eol=crlf 4 | 5 | # Custom for Visual Studio 6 | *.cs diff=csharp 7 | *.sln merge=union 8 | *.csproj merge=union 9 | *.vbproj merge=union 10 | *.fsproj merge=union 11 | *.dbproj merge=union 12 | 13 | # Standard to msysgit 14 | *.doc diff=astextplain 15 | *.DOC diff=astextplain 16 | *.docx diff=astextplain 17 | *.DOCX diff=astextplain 18 | *.dot diff=astextplain 19 | *.DOT diff=astextplain 20 | *.pdf diff=astextplain 21 | *.PDF diff=astextplain 22 | *.rtf diff=astextplain 23 | *.RTF diff=astextplain 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | 165 | ########## 166 | # Custom 167 | ########## 168 | 169 | TestData/ 170 | *.in 171 | *.out -------------------------------------------------------------------------------- /Code/Test/Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86} 9 | Exe 10 | Properties 11 | Test 12 | Test 13 | v4.0 14 | Client 15 | 512 16 | 17 | 18 | x86 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | x86 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | true 38 | bin\x64\Debug\ 39 | DEBUG;TRACE 40 | full 41 | x64 42 | bin\Debug\Test.exe.CodeAnalysisLog.xml 43 | true 44 | GlobalSuppressions.cs 45 | prompt 46 | MinimumRecommendedRules.ruleset 47 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\\Rule Sets 48 | true 49 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\FxCop\\Rules 50 | true 51 | 52 | 53 | bin\x64\Release\ 54 | TRACE 55 | true 56 | pdbonly 57 | x64 58 | bin\Release\Test.exe.CodeAnalysisLog.xml 59 | true 60 | GlobalSuppressions.cs 61 | prompt 62 | MinimumRecommendedRules.ruleset 63 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\\Rule Sets 64 | true 65 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\FxCop\\Rules 66 | true 67 | 68 | 69 | 70 | 71 | 72 | 73 | {78046F90-E5D0-4E41-AA1B-3D5265B53256} 74 | Utility 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 89 | -------------------------------------------------------------------------------- /Code/Utility.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utility", "Utility\Utility.csproj", "{78046F90-E5D0-4E41-AA1B-3D5265B53256}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{D3DDEDE6-28D5-46F1-82AF-3942264BBF86}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|Mixed Platforms = Debug|Mixed Platforms 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|Mixed Platforms = Release|Mixed Platforms 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 21 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 22 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Debug|x86.ActiveCfg = Debug|Any CPU 23 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Release|Mixed Platforms.ActiveCfg = Release|x64 26 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Release|Mixed Platforms.Build.0 = Release|x64 27 | {78046F90-E5D0-4E41-AA1B-3D5265B53256}.Release|x86.ActiveCfg = Release|Any CPU 28 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Debug|Any CPU.ActiveCfg = Debug|x86 29 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 30 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Debug|Mixed Platforms.Build.0 = Debug|x86 31 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Debug|x86.ActiveCfg = Debug|x86 32 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Debug|x86.Build.0 = Debug|x86 33 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Release|Any CPU.ActiveCfg = Release|x86 34 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Release|Mixed Platforms.ActiveCfg = Release|x64 35 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Release|Mixed Platforms.Build.0 = Release|x64 36 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Release|x86.ActiveCfg = Release|x86 37 | {D3DDEDE6-28D5-46F1-82AF-3942264BBF86}.Release|x86.Build.0 = Release|x86 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /Code/Utility/BinarySearchTree/KeyValue/AVLTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace BinarySearchTree 9 | { 10 | /// 11 | /// Represents a dictionary implemented by a balanced binary search tree. 12 | /// 13 | /// The type of the keys in the dictionary. 14 | /// The type of the values in the dictionary. 15 | public class AVLTree : BinarySearchTree 16 | where TKey : IComparable 17 | { 18 | /// 19 | /// Initialises a new instance of the AVLTree<TKey, TValue> class that is empty. 20 | /// 21 | public AVLTree() { } 22 | 23 | /// 24 | /// Initialises a new instance of the AVLTree<TKey, TValue> class that contains elements copied from the specified IDictionary<TKey, TValue>. 25 | /// 26 | /// The IDictionary<TKey, TValue> whose elements are copied to the new AVLTree<TKey, TValue>. 27 | public AVLTree(IDictionary collection) : base(collection) { } 28 | 29 | /// 30 | /// Adds the specified key and value to the AVLTree<TKey, TValue>. 31 | /// 32 | /// The key of the element to add. 33 | /// The value of the element to add. 34 | public override void Add(TKey key, TValue value) 35 | { 36 | AVLNode node = new AVLNode(key, value); 37 | base.Add(node); 38 | this.Rebalance(node.Parent); 39 | } 40 | 41 | protected override void Delete(TreeNode current) 42 | { 43 | base.Delete(current); 44 | this.Rebalance((AVLNode)current.Parent); 45 | } 46 | 47 | private void Rebalance(AVLNode start) 48 | { 49 | int height, left, right, diff, leftC, rightC, diffC; 50 | while (start != null) 51 | { 52 | height = start.Height; 53 | left = start.Left != null ? start.Left.Height : -1; 54 | right = start.Right != null ? start.Right.Height : -1; 55 | diff = left - right; 56 | 57 | if (diff == -2) 58 | { 59 | leftC = start.Right.Left != null ? start.Right.Left.Height : -1; 60 | rightC = start.Right.Right != null ? start.Right.Right.Height : -1; 61 | diffC = leftC - rightC; 62 | 63 | if (diffC == 1) 64 | this.RotateRight(start.Right); 65 | this.RotateLeft(start); 66 | 67 | start = start.Parent.Parent; 68 | continue; 69 | } 70 | else if (diff == 2) 71 | { 72 | leftC = start.Left.Left != null ? start.Left.Left.Height : -1; 73 | rightC = start.Left.Right != null ? start.Left.Right.Height : -1; 74 | diffC = leftC - rightC; 75 | 76 | if (diffC == -1) 77 | this.RotateLeft(start.Left); 78 | this.RotateRight(start); 79 | 80 | start = start.Parent.Parent; 81 | continue; 82 | } 83 | 84 | start.Height = Math.Max(left, right) + 1; 85 | if (height == start.Height) 86 | break; 87 | else 88 | start = start.Parent; 89 | } 90 | } 91 | 92 | protected void RotateLeft(AVLNode start) 93 | { 94 | base.RotateLeft(start); 95 | 96 | int left, right; 97 | left = start.Left != null ? start.Left.Height : -1; 98 | right = start.Right != null ? start.Right.Height : -1; 99 | start.Height = Math.Max(left, right) + 1; 100 | 101 | left = start.Height; 102 | right = start.Parent.Right != null ? start.Parent.Right.Height : -1; 103 | start.Parent.Height = Math.Max(left, right) + 1; 104 | } 105 | 106 | protected void RotateRight(AVLNode start) 107 | { 108 | base.RotateRight(start); 109 | 110 | int left, right; 111 | left = start.Left != null ? start.Left.Height : -1; 112 | right = start.Right != null ? start.Right.Height : -1; 113 | start.Height = Math.Max(left, right) + 1; 114 | 115 | left = start.Parent.Left != null ? start.Parent.Left.Height : -1; 116 | right = start.Height; 117 | start.Parent.Height = Math.Max(left, right) + 1; 118 | } 119 | 120 | protected class AVLNode : KeyValueTreeNode 121 | { 122 | public AVLNode(TKey key, TValue value) : base(key, value) { this.Height = 0; } 123 | 124 | public int Height { get; set; } 125 | public new AVLNode Parent { get { return (AVLNode)base.Parent; } set { base.Parent = value; } } 126 | public new AVLNode Left { get { return (AVLNode)base.Left; } set { base.Left = value; } } 127 | public new AVLNode Right { get { return (AVLNode)base.Right; } set { base.Right = value; } } 128 | } 129 | } 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /Code/Utility/BinarySearchTree/KeyValue/ScapegoatTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace BinarySearchTree 9 | { 10 | /// 11 | /// Represents a dictionary implemented by a balanced binary search tree. 12 | /// 13 | /// The type of the keys in the dictionary. 14 | /// The type of the values in the dictionary. 15 | public class ScapegoatTree : BinarySearchTree 16 | where TKey : IComparable 17 | { 18 | private float alpha; 19 | private int size, maxSize; 20 | 21 | /// 22 | /// Initialises a new instance of the ScapeGoatTree<TKey, TValue> class that is empty. 23 | /// 24 | /// The weight factor that is used when balancing the tree. 25 | public ScapegoatTree(float alpha = 0.75f) 26 | { 27 | this.alpha = alpha; 28 | this.size = 0; 29 | this.maxSize = 0; 30 | } 31 | 32 | /// 33 | /// Initialises a new instance of the ScapeGoatTree<TKey, TValue> class that contains elements copied from the specified IDictionary<TKey, TValue>. 34 | /// 35 | /// The IDictionary<TKey, TValue> whose elements are copied to the new ScapeGoatTree<TKey, TValue>. 36 | /// The weight factor that is used when balancing the tree. 37 | public ScapegoatTree(IDictionary collection, float alpha = 0.75f) 38 | : base() 39 | { 40 | this.alpha = alpha; 41 | this.size = 0; 42 | this.maxSize = 0; 43 | foreach (KeyValuePair t in collection) 44 | this.Add(t.Key, t.Value); 45 | } 46 | 47 | protected override KeyValueTreeNode Add(KeyValueTreeNode node) 48 | { 49 | int depth = 0; 50 | this.Count++; 51 | if (this.root == null) 52 | { 53 | this.root = node; 54 | this.size++; 55 | return node; 56 | } 57 | KeyValueTreeNode current = (KeyValueTreeNode)this.root; 58 | while (current != null) 59 | { 60 | depth++; 61 | int c = node.Key.CompareTo(current.Key); 62 | if (c < 0) 63 | { 64 | if (current.Left != null) 65 | current = current.Left; 66 | else 67 | { 68 | current.Left = node; 69 | break; 70 | } 71 | } 72 | else if (c > 0) 73 | { 74 | if (current.Right != null) 75 | current = current.Right; 76 | else 77 | { 78 | current.Right = node; 79 | break; 80 | } 81 | } 82 | else 83 | return null; 84 | } 85 | this.size++; 86 | this.maxSize = Math.Max(size, maxSize); 87 | node.Parent = current; 88 | 89 | if (depth > Math.Log(this.size, 1 / alpha)) 90 | this.Rebalance(node); 91 | 92 | return node; 93 | } 94 | 95 | /// 96 | /// Removes the value with the specified key from the ScapeGoatTree<TKey, TValue>. 97 | /// 98 | /// The key of the element to remove. 99 | /// true if the element is successfully found and removed; otherwise, false. 100 | public override bool Remove(TKey key) 101 | { 102 | KeyValueTreeNode current = this.Find(key); 103 | 104 | if (current == null) 105 | return false; 106 | 107 | if (current.Count > 1) 108 | { 109 | current.Count--; 110 | this.Count--; 111 | return true; 112 | } 113 | 114 | if (current.Left == null || current.Right == null) 115 | this.Delete(current); 116 | else 117 | { 118 | KeyValueTreeNode replace = (KeyValueTreeNode)this.Predecessor(current); 119 | if (replace == null) 120 | replace = (KeyValueTreeNode)this.Successor(current); 121 | 122 | current.Value = replace.Value; 123 | current.Count = replace.Count; 124 | 125 | this.Delete(replace); 126 | } 127 | 128 | this.Count--; 129 | this.size--; 130 | 131 | if (this.size <= this.maxSize / 2) 132 | { 133 | this.Flatten((KeyValueTreeNode)this.root, this.size); 134 | this.maxSize = this.size; 135 | } 136 | 137 | return true; 138 | } 139 | 140 | private void Rebalance(KeyValueTreeNode node) 141 | { 142 | int size = 1, leftSize, rightSize; 143 | bool leftC; 144 | while (node.Parent != null) 145 | { 146 | leftC = node.Parent.Left == node; 147 | node = node.Parent; 148 | if (leftC) 149 | { 150 | rightSize = this.Size(node.Right); 151 | leftSize = size; 152 | } 153 | else 154 | { 155 | leftSize = this.Size(node.Left); 156 | rightSize = size; 157 | } 158 | size = leftSize + rightSize + 1; 159 | 160 | if (leftSize > alpha * size || rightSize > alpha * size) 161 | { 162 | this.Flatten(node, size); 163 | return; 164 | } 165 | } 166 | } 167 | 168 | private void Flatten(KeyValueTreeNode node, int size) 169 | { 170 | if (node == null) 171 | return; 172 | 173 | KeyValueTreeNode[] nodes = new KeyValueTreeNode[size]; 174 | int index = 0; 175 | this.Flatten(node, nodes, ref index); 176 | this.InsertMedians(nodes, node.Parent); 177 | } 178 | 179 | private void Flatten(KeyValueTreeNode node, KeyValueTreeNode[] array, ref int index) 180 | { 181 | if (node == null) 182 | return; 183 | this.Flatten(node.Left, array, ref index); 184 | array[index++] = node; 185 | this.Flatten(node.Right, array, ref index); 186 | } 187 | 188 | private void InsertMedians(KeyValueTreeNode[] array, KeyValueTreeNode root) 189 | { 190 | int median = array.Length / 2; 191 | KeyValueTreeNode medianNode = new KeyValueTreeNode(array[median].Key, array[median].Value); 192 | medianNode.Parent = root; 193 | if (root == null) 194 | this.root = medianNode; 195 | else if (medianNode.Key.CompareTo(root.Key) < 0) 196 | root.Left = medianNode; 197 | else 198 | root.Right = medianNode; 199 | this.InsertMedians(array, medianNode, 0, median, true); 200 | this.InsertMedians(array, medianNode, median + 1, array.Length, false); 201 | } 202 | 203 | private void InsertMedians(KeyValueTreeNode[] array, KeyValueTreeNode root, int start, int end, bool left) 204 | { 205 | if (end == start) 206 | return; 207 | int median = (end - start) / 2 + start; 208 | KeyValueTreeNode node = new KeyValueTreeNode(array[median].Key, array[median].Value); 209 | this.AddAt(node, root, left); 210 | this.InsertMedians(array, node, start, median, true); 211 | this.InsertMedians(array, node, median + 1, end, false); 212 | } 213 | 214 | private void AddAt(KeyValueTreeNode node, KeyValueTreeNode root, bool left) 215 | { 216 | if (left) 217 | root.Left = node; 218 | else 219 | root.Right = node; 220 | node.Parent = root; 221 | } 222 | 223 | private int Size(KeyValueTreeNode node) 224 | { 225 | if (node == null) 226 | return 0; 227 | return this.Size(node.Left) + this.Size(node.Right) + 1; 228 | } 229 | 230 | public override void Clear() { base.Clear(); this.size = 0; } 231 | } 232 | } 233 | } 234 | } -------------------------------------------------------------------------------- /Code/Utility/BinarySearchTree/KeyValue/SplayTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace BinarySearchTree 9 | { 10 | /// 11 | /// Represents a dictionary implemented by a balanced binary search tree. 12 | /// 13 | /// The type of the keys in the dictionary. 14 | /// The type of the values in the dictionary. 15 | public class SplayTree : BinarySearchTree 16 | where TKey : IComparable 17 | { 18 | /// 19 | /// Initialises a new instance of the SplayTree<TKey, TValue> class that is empty. 20 | /// 21 | public SplayTree() { } 22 | 23 | /// 24 | /// Initialises a new instance of the SplayTree<TKey, TValue> class that contains elements copied from the specified IDictionary<TKey, TValue>. 25 | /// 26 | /// The IDictionary<TKey, TValue> whose elements are copied to the new SplayTree<TKey, TValue>. 27 | public SplayTree(IDictionary collection) : base(collection) { } 28 | 29 | /// 30 | /// Adds the specified key and value to the SplayTree<TKey, TValue>. 31 | /// 32 | /// The key of the element to add. 33 | /// The value of the element to add. 34 | public override void Add(TKey key, TValue value) 35 | { 36 | KeyValueTreeNode node = new KeyValueTreeNode(key, value); 37 | node = base.Add(node); 38 | this.Splay(node); 39 | } 40 | 41 | /// 42 | /// Removes the value with the specified key from the SplayTree<TKey, TValue>. 43 | /// 44 | /// The key of the element to remove. 45 | /// true if the element is successfully found and removed; otherwise, false. 46 | public override bool Remove(TKey key) 47 | { 48 | KeyValueTreeNode current = (KeyValueTreeNode)this.root, previous = null; 49 | while (current != null) 50 | { 51 | previous = current; 52 | if (key.CompareTo(current.Key) < 0) 53 | current = current.Left; 54 | else if (key.CompareTo(current.Key) > 0) 55 | current = current.Right; 56 | else 57 | break; 58 | } 59 | 60 | if (current == null) 61 | { 62 | this.Splay(previous); 63 | return false; 64 | } 65 | 66 | if (current.Left == null || current.Right == null) 67 | this.Delete(current); 68 | else 69 | { 70 | KeyValueTreeNode replace = (KeyValueTreeNode)this.Predecessor(current); 71 | if (replace == null) 72 | replace = (KeyValueTreeNode)this.Successor(current); 73 | 74 | current.Value = replace.Value; 75 | this.Delete(replace); 76 | } 77 | 78 | this.Count--; 79 | return true; 80 | } 81 | 82 | protected override void Delete(TreeNode current) 83 | { 84 | base.Delete(current); 85 | this.Splay((KeyValueTreeNode)current.Parent); 86 | } 87 | 88 | protected override KeyValueTreeNode Find(TKey key) 89 | { 90 | KeyValueTreeNode current = (KeyValueTreeNode)this.root, previous = null; 91 | while (current != null) 92 | { 93 | int c = key.CompareTo(current.Key); 94 | previous = current; 95 | if (c < 0) 96 | current = current.Left; 97 | else if (c > 0) 98 | current = current.Right; 99 | else 100 | break; 101 | } 102 | 103 | this.Splay(previous); 104 | return current; 105 | } 106 | 107 | private void Splay(KeyValueTreeNode start) 108 | { 109 | bool leftC, leftPC; 110 | 111 | if (this.root == start || start == null) 112 | return; 113 | 114 | leftC = start == start.Parent.Left; 115 | 116 | if (start.Parent.Parent == null) 117 | { 118 | if (leftC) 119 | this.RotateRight(start.Parent); 120 | else 121 | this.RotateLeft(start.Parent); 122 | return; 123 | } 124 | 125 | leftPC = start.Parent == start.Parent.Parent.Left; 126 | 127 | if (leftC && leftPC) 128 | { 129 | this.RotateRight(start.Parent.Parent); 130 | this.RotateRight(start.Parent); 131 | } 132 | else if (!leftC && !leftPC) 133 | { 134 | this.RotateLeft(start.Parent.Parent); 135 | this.RotateLeft(start.Parent); 136 | } 137 | else if (!leftC && leftPC) 138 | { 139 | this.RotateLeft(start.Parent); 140 | this.RotateRight(start.Parent); 141 | } 142 | else 143 | { 144 | this.RotateRight(start.Parent); 145 | this.RotateLeft(start.Parent); 146 | } 147 | 148 | this.Splay(start); 149 | } 150 | } 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /Code/Utility/BinarySearchTree/Value/AVLTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace BinarySearchTree 9 | { 10 | /// 11 | /// Represents a balanced binary search tree. 12 | /// 13 | /// The type of the values in the tree. 14 | public class AVLTree : BinarySearchTree 15 | where T : IComparable 16 | { 17 | /// 18 | /// Initialises a new instance of the AVLTree<T> class that is empty. 19 | /// 20 | public AVLTree() { } 21 | 22 | /// 23 | /// Initialises a new instance of the AVLTree<T> class that contains elements copied from the specified IEnumerable<T>. 24 | /// 25 | /// The IEnumerable<T> whose elements are copied to the new AVLTree<T>. 26 | public AVLTree(IEnumerable collection) : base(collection) { } 27 | 28 | /// 29 | /// Adds the specified value to the AVLTree<T>. 30 | /// 31 | /// The value to add. 32 | public override void Add(T item) 33 | { 34 | AVLNode node = new AVLNode(item); 35 | base.Add(node); 36 | this.Rebalance(node.Parent); 37 | } 38 | 39 | protected override void Delete(TreeNode current) 40 | { 41 | base.Delete(current); 42 | this.Rebalance((AVLNode)current.Parent); 43 | } 44 | 45 | private void Rebalance(AVLNode start) 46 | { 47 | int height, left, right, diff, leftC, rightC, diffC; 48 | while (start != null) 49 | { 50 | height = start.Height; 51 | left = start.Left != null ? start.Left.Height : -1; 52 | right = start.Right != null ? start.Right.Height : -1; 53 | diff = left - right; 54 | 55 | if (diff == -2) 56 | { 57 | leftC = start.Right.Left != null ? start.Right.Left.Height : -1; 58 | rightC = start.Right.Right != null ? start.Right.Right.Height : -1; 59 | diffC = leftC - rightC; 60 | 61 | if (diffC == 1) 62 | this.RotateRight(start.Right); 63 | this.RotateLeft(start); 64 | 65 | start = start.Parent.Parent; 66 | continue; 67 | } 68 | else if (diff == 2) 69 | { 70 | leftC = start.Left.Left != null ? start.Left.Left.Height : -1; 71 | rightC = start.Left.Right != null ? start.Left.Right.Height : -1; 72 | diffC = leftC - rightC; 73 | 74 | if (diffC == -1) 75 | this.RotateLeft(start.Left); 76 | this.RotateRight(start); 77 | 78 | start = start.Parent.Parent; 79 | continue; 80 | } 81 | 82 | start.Height = Math.Max(left, right) + 1; 83 | if (height == start.Height) 84 | break; 85 | else 86 | start = start.Parent; 87 | } 88 | } 89 | 90 | protected void RotateLeft(AVLNode start) 91 | { 92 | base.RotateLeft(start); 93 | 94 | int left, right; 95 | left = start.Left != null ? start.Left.Height : -1; 96 | right = start.Right != null ? start.Right.Height : -1; 97 | start.Height = Math.Max(left, right) + 1; 98 | 99 | left = start.Height; 100 | right = start.Parent.Right != null ? start.Parent.Right.Height : -1; 101 | start.Parent.Height = Math.Max(left, right) + 1; 102 | } 103 | 104 | protected void RotateRight(AVLNode start) 105 | { 106 | base.RotateRight(start); 107 | 108 | int left, right; 109 | left = start.Left != null ? start.Left.Height : -1; 110 | right = start.Right != null ? start.Right.Height : -1; 111 | start.Height = Math.Max(left, right) + 1; 112 | 113 | left = start.Parent.Left != null ? start.Parent.Left.Height : -1; 114 | right = start.Height; 115 | start.Parent.Height = Math.Max(left, right) + 1; 116 | } 117 | 118 | protected class AVLNode : ValueTreeNode 119 | { 120 | public AVLNode(T value) : base(value) { this.Height = 0; } 121 | 122 | public int Height { get; set; } 123 | public new AVLNode Parent { get { return (AVLNode)base.Parent; } set { base.Parent = value; } } 124 | public new AVLNode Left { get { return (AVLNode)base.Left; } set { base.Left = value; } } 125 | public new AVLNode Right { get { return (AVLNode)base.Right; } set { base.Right = value; } } 126 | } 127 | } 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /Code/Utility/BinarySearchTree/Value/ScapegoatTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace BinarySearchTree 9 | { 10 | /// 11 | /// Represents a balanced binary search tree. 12 | /// 13 | /// The type of the values in the tree. 14 | public class ScapegoatTree : BinarySearchTree 15 | where T : IComparable 16 | { 17 | private float alpha; 18 | private int size, maxSize; 19 | 20 | /// 21 | /// Initialises a new instance of the ScapeGoatTree<T> class that is empty. 22 | /// 23 | /// The weight factor that is used when balancing the tree. 24 | public ScapegoatTree(float alpha = 0.75f) 25 | { 26 | this.alpha = alpha; 27 | this.size = 0; 28 | this.maxSize = 0; 29 | } 30 | 31 | /// 32 | /// Initialises a new instance of the ScapeGoatTree<T> class that contains elements copied from the specified IEnumerable<T>. 33 | /// 34 | /// The IEnumerable<T> whose elements are copied to the new ScapeGoatTree<T>. 35 | /// The weight factor that is used when balancing the tree. 36 | public ScapegoatTree(IEnumerable collection, float alpha = 0.75f) 37 | : base() 38 | { 39 | this.alpha = alpha; 40 | this.size = 0; 41 | this.maxSize = 0; 42 | foreach (T t in collection) 43 | this.Add(t); 44 | } 45 | 46 | protected override ValueTreeNode Add(ValueTreeNode node) 47 | { 48 | int depth = 0; 49 | this.Count++; 50 | if (this.root == null) 51 | { 52 | this.root = node; 53 | this.size++; 54 | return node; 55 | } 56 | ValueTreeNode current = (ValueTreeNode)this.root; 57 | while (current != null) 58 | { 59 | depth++; 60 | int c = node.Value.CompareTo(current.Value); 61 | if (c < 0) 62 | { 63 | if (current.Left != null) 64 | current = current.Left; 65 | else 66 | { 67 | current.Left = node; 68 | break; 69 | } 70 | } 71 | else if (c > 0) 72 | { 73 | if (current.Right != null) 74 | current = current.Right; 75 | else 76 | { 77 | current.Right = node; 78 | break; 79 | } 80 | } 81 | else 82 | { 83 | current.Count++; 84 | return current; 85 | } 86 | } 87 | this.size++; 88 | this.maxSize = Math.Max(size, maxSize); 89 | node.Parent = current; 90 | 91 | if (depth > Math.Log(this.size, 1 / alpha)) 92 | this.Rebalance(node); 93 | 94 | return node; 95 | } 96 | 97 | /// 98 | /// Removes the specified value from the ScapeGoatTree<T>. 99 | /// 100 | /// The value to remove. 101 | /// true if item was successfully removed from the ScapeGoatTree<T>; otherwise, false. 102 | public override bool Remove(T item) 103 | { 104 | ValueTreeNode current = this.Find(item); 105 | 106 | if (current == null) 107 | return false; 108 | 109 | if (current.Count > 1) 110 | { 111 | current.Count--; 112 | this.Count--; 113 | return true; 114 | } 115 | 116 | if (current.Left == null || current.Right == null) 117 | this.Delete(current); 118 | else 119 | { 120 | ValueTreeNode replace = (ValueTreeNode)this.Predecessor(current); 121 | if (replace == null) 122 | replace = (ValueTreeNode)this.Successor(current); 123 | 124 | current.Value = replace.Value; 125 | current.Count = replace.Count; 126 | 127 | this.Delete(replace); 128 | } 129 | 130 | this.Count--; 131 | this.size--; 132 | 133 | if (this.size <= this.maxSize / 2) 134 | { 135 | this.Flatten((ValueTreeNode)this.root, this.size); 136 | this.maxSize = this.size; 137 | } 138 | 139 | return true; 140 | } 141 | 142 | private void Rebalance(ValueTreeNode node) 143 | { 144 | int size = 1, leftSize, rightSize; 145 | bool leftC; 146 | while (node.Parent != null) 147 | { 148 | leftC = node.Parent.Left == node; 149 | node = node.Parent; 150 | if (leftC) 151 | { 152 | rightSize = this.Size(node.Right); 153 | leftSize = size; 154 | } 155 | else 156 | { 157 | leftSize = this.Size(node.Left); 158 | rightSize = size; 159 | } 160 | size = leftSize + rightSize + 1; 161 | 162 | if (leftSize > alpha * size || rightSize > alpha * size) 163 | { 164 | this.Flatten(node, size); 165 | return; 166 | } 167 | } 168 | } 169 | 170 | private void Flatten(ValueTreeNode node, int size) 171 | { 172 | if (node == null) 173 | return; 174 | 175 | ValueTreeNode[] nodes = new ValueTreeNode[size]; 176 | int index = 0; 177 | this.Flatten(node, nodes, ref index); 178 | this.InsertMedians(nodes, node.Parent); 179 | } 180 | 181 | private void Flatten(ValueTreeNode node, ValueTreeNode[] array, ref int index) 182 | { 183 | if (node == null) 184 | return; 185 | this.Flatten(node.Left, array, ref index); 186 | array[index++] = node; 187 | this.Flatten(node.Right, array, ref index); 188 | } 189 | 190 | private void InsertMedians(ValueTreeNode[] array, ValueTreeNode root) 191 | { 192 | int median = array.Length / 2; 193 | ValueTreeNode medianNode = new ValueTreeNode(array[median].Value); 194 | medianNode.Count = array[median].Count; 195 | medianNode.Parent = root; 196 | if (root == null) 197 | this.root = medianNode; 198 | else if (medianNode.Value.CompareTo(root.Value) < 0) 199 | root.Left = medianNode; 200 | else 201 | root.Right = medianNode; 202 | this.InsertMedians(array, medianNode, 0, median, true); 203 | this.InsertMedians(array, medianNode, median + 1, array.Length, false); 204 | } 205 | 206 | private void InsertMedians(ValueTreeNode[] array, ValueTreeNode root, int start, int end, bool left) 207 | { 208 | if (end == start) 209 | return; 210 | int median = (end - start) / 2 + start; 211 | ValueTreeNode node = new ValueTreeNode(array[median].Value); 212 | node.Count = array[median].Count; 213 | this.AddAt(node, root, left); 214 | this.InsertMedians(array, node, start, median, true); 215 | this.InsertMedians(array, node, median + 1, end, false); 216 | } 217 | 218 | private void AddAt(ValueTreeNode node, ValueTreeNode root, bool left) 219 | { 220 | if (left) 221 | root.Left = node; 222 | else 223 | root.Right = node; 224 | node.Parent = root; 225 | } 226 | 227 | private int Size(ValueTreeNode node) 228 | { 229 | if (node == null) 230 | return 0; 231 | return this.Size(node.Left) + this.Size(node.Right) + 1; 232 | } 233 | 234 | public override void Clear() { base.Clear(); this.size = 0; } 235 | } 236 | } 237 | } 238 | } -------------------------------------------------------------------------------- /Code/Utility/BinarySearchTree/Value/SplayTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace BinarySearchTree 9 | { 10 | /// 11 | /// Represents a balanced binary search tree. 12 | /// 13 | /// The type of the values in the tree. 14 | public class SplayTree : BinarySearchTree 15 | where T : IComparable 16 | { 17 | /// 18 | /// Initialises a new instance of the SplayTree<T> class that is empty. 19 | /// 20 | public SplayTree() { } 21 | 22 | /// 23 | /// Initialises a new instance of the SplayTree<T> class that contains elements copied from the specified IEnumerable<T>. 24 | /// 25 | /// The IEnumerable<T> whose elements are copied to the new SplayTree<T>. 26 | public SplayTree(IEnumerable collection) : base(collection) { } 27 | 28 | /// 29 | /// Adds the specified value to the SplayTree<T>. 30 | /// 31 | /// The value to add. 32 | public override void Add(T item) 33 | { 34 | ValueTreeNode node = new ValueTreeNode(item); 35 | node = base.Add(node); 36 | this.Splay(node); 37 | } 38 | 39 | /// 40 | /// Removes the first occurrence of a specific object from the SplayTree<T>. 41 | /// 42 | /// The object to be removed. 43 | /// true if item was successfully removed from the SplayTree<T>; otherwise, false. 44 | public override bool Remove(T item) 45 | { 46 | ValueTreeNode current = (ValueTreeNode)this.root, previous = null; 47 | while (current != null) 48 | { 49 | previous = current; 50 | if (item.CompareTo(current.Value) < 0) 51 | current = current.Left; 52 | else if (item.CompareTo(current.Value) > 0) 53 | current = current.Right; 54 | else 55 | break; 56 | } 57 | 58 | if (current == null) 59 | { 60 | this.Splay(previous); 61 | return false; 62 | } 63 | 64 | if (current.Count > 1) 65 | { 66 | this.Splay(current); 67 | current.Count--; 68 | return true; 69 | } 70 | 71 | if (current.Left == null || current.Right == null) 72 | this.Delete(current); 73 | else 74 | { 75 | ValueTreeNode replace = (ValueTreeNode)this.Predecessor(current); 76 | if (replace == null) 77 | replace = (ValueTreeNode)this.Successor(current); 78 | 79 | current.Value = replace.Value; 80 | current.Count = replace.Count; 81 | 82 | this.Delete(replace); 83 | } 84 | 85 | this.Count--; 86 | return true; 87 | } 88 | 89 | protected override void Delete(TreeNode current) 90 | { 91 | base.Delete(current); 92 | this.Splay((ValueTreeNode)current.Parent); 93 | } 94 | 95 | protected override ValueTreeNode Find(T item) 96 | { 97 | ValueTreeNode current = (ValueTreeNode)this.root, previous = null; 98 | while (current != null) 99 | { 100 | int c = item.CompareTo(current.Value); 101 | previous = current; 102 | if (c < 0) 103 | current = current.Left; 104 | else if (c > 0) 105 | current = current.Right; 106 | else 107 | break; 108 | } 109 | 110 | this.Splay(previous); 111 | return current; 112 | } 113 | 114 | private void Splay(ValueTreeNode start) 115 | { 116 | bool leftC, leftPC; 117 | 118 | if (this.root == start || start == null) 119 | return; 120 | 121 | leftC = start == start.Parent.Left; 122 | 123 | if (start.Parent.Parent == null) 124 | { 125 | if (leftC) 126 | this.RotateRight(start.Parent); 127 | else 128 | this.RotateLeft(start.Parent); 129 | return; 130 | } 131 | 132 | leftPC = start.Parent == start.Parent.Parent.Left; 133 | 134 | if (leftC && leftPC) 135 | { 136 | this.RotateRight(start.Parent.Parent); 137 | this.RotateRight(start.Parent); 138 | } 139 | else if (!leftC && !leftPC) 140 | { 141 | this.RotateLeft(start.Parent.Parent); 142 | this.RotateLeft(start.Parent); 143 | } 144 | else if (!leftC && leftPC) 145 | { 146 | this.RotateLeft(start.Parent); 147 | this.RotateRight(start.Parent); 148 | } 149 | else 150 | { 151 | this.RotateRight(start.Parent); 152 | this.RotateLeft(start.Parent); 153 | } 154 | 155 | this.Splay(start); 156 | } 157 | } 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /Code/Utility/ComputationalGeometry/ConvexHull.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace ComputationalGeometry 9 | { 10 | /// 11 | /// A class containing methods for computational geometry. 12 | /// 13 | public static partial class ComputationalGeometry 14 | { 15 | /// 16 | /// Returns the smallest polygon that contains all the points in the input. 17 | /// 18 | /// The set of points to calculate the convex hull of. 19 | /// A list of points describing the convex hull in clockwise order. 20 | public static List ConvexHull(IEnumerable input) 21 | { 22 | if (input == null) 23 | throw new ArgumentNullException("input"); 24 | 25 | List points = new List(input); 26 | 27 | Vector2D start = new Vector2D(double.MaxValue, double.MaxValue); 28 | List indexes = new List(); 29 | for (int i = 0; i < points.Count; i++) 30 | { 31 | if (points[i].Y < start.Y || points[i].Y == start.Y && points[i].X < start.X) 32 | { 33 | start = points[i]; 34 | indexes.Clear(); 35 | indexes.Add(i); 36 | } 37 | else if (points[i] == start) 38 | indexes.Add(i); 39 | } 40 | for (int i = 0; i < indexes.Count; i++) 41 | points.RemoveAt(indexes[i] - i); 42 | 43 | AngleComparer comp = new AngleComparer(start); 44 | points.Sort(comp); 45 | 46 | List temp = new List(); 47 | for (int i = 0; i < points.Count; i++) 48 | { 49 | while (i < points.Count - 1 && comp.Compare(points[i], points[i + 1]) == 0) 50 | { 51 | if (Vector2D.Distance(points[i], start) - Vector2D.Distance(points[i + 1], start) <= 0) 52 | i++; 53 | else 54 | { 55 | Vector2D t = points[i]; 56 | points[i] = points[i + 1]; 57 | points[i + 1] = t; 58 | i++; 59 | } 60 | } 61 | temp.Add(points[i]); 62 | } 63 | points = temp; 64 | 65 | if (points.Count < 2) 66 | return null; 67 | 68 | Stack hull = new Stack(); 69 | hull.Push(start); 70 | hull.Push(points[0]); 71 | hull.Push(points[1]); 72 | 73 | Vector2D top, belowTop; 74 | for (int i = 2; i < points.Count; i++) 75 | { 76 | top = hull.Pop(); 77 | belowTop = hull.Pop(); 78 | while (!LeftTurn(belowTop, top, points[i])) 79 | { 80 | top = belowTop; 81 | belowTop = hull.Pop(); 82 | } 83 | hull.Push(belowTop); 84 | hull.Push(top); 85 | hull.Push(points[i]); 86 | } 87 | 88 | points.Clear(); 89 | while (hull.Count > 0) 90 | points.Add(hull.Pop()); 91 | return points; 92 | } 93 | 94 | private static bool LeftTurn(Vector2D p1, Vector2D p2, Vector2D p3) 95 | { 96 | return Vector2D.Cross(p2 - p1, p3 - p1) < 0; 97 | } 98 | 99 | private class AngleComparer : IComparer 100 | { 101 | Vector2D origin; 102 | 103 | public AngleComparer(Vector2D origin) { this.origin = origin; } 104 | 105 | public int Compare(Vector2D vector1, Vector2D vector2) 106 | { 107 | double c = Vector2D.Cross(vector1 - this.origin, vector2 - this.origin); 108 | if (c < 0) 109 | return -1; 110 | if (c > 0) 111 | return 1; 112 | return 0; 113 | } 114 | } 115 | } 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /Code/Utility/DisjointSet/UnionFind.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace DataStructures 7 | { 8 | namespace DisjointSet 9 | { 10 | /// 11 | /// A class for performing disjoint-set operations. 12 | /// 13 | /// The type of values in the sets. 14 | public class UnionFind 15 | { 16 | private Dictionary nodes = new Dictionary(); 17 | 18 | /// 19 | /// Makes a new set containing only the specified value. 20 | /// 21 | /// The value to store in the new set. 22 | public void Make(T value) 23 | { 24 | if (nodes.ContainsKey(value)) 25 | throw new ArgumentException("That value has already been added.", "value"); 26 | 27 | UnionNode node = new UnionNode(value, 0); 28 | nodes[value] = node; 29 | } 30 | 31 | /// 32 | /// Finds the representative of a value and applies path compression. 33 | /// 34 | /// The value of which the representative is to be found. 35 | /// The representative of the given node. 36 | public T Find(T value) 37 | { 38 | UnionNode n; 39 | if (!nodes.TryGetValue(value, out n)) 40 | throw new ArgumentException("There is no set containing that value.", "node"); 41 | 42 | return this.Find(n).Value; 43 | } 44 | 45 | /// 46 | /// Performs a union by rank on the two sets that and are in. 47 | /// 48 | /// A value in the set to perform a union on. 49 | /// A value in the set to perform a union on. 50 | public void Union(T node1, T node2) 51 | { 52 | UnionNode a, b; 53 | if (!nodes.TryGetValue(node1, out a)) 54 | throw new ArgumentException("There is no set containing that value.", "node1"); 55 | if (!nodes.TryGetValue(node2, out b)) 56 | throw new ArgumentException("There is no set containing that value.", "node2"); 57 | 58 | this.Union(a, b); 59 | } 60 | 61 | private UnionNode Find(UnionNode node) 62 | { 63 | if (node.Parent != node) 64 | node.Parent = Find(node.Parent); 65 | return node.Parent; 66 | } 67 | 68 | private void Union(UnionNode node1, UnionNode node2) 69 | { 70 | UnionNode root1 = Find(node1), root2 = Find(node2); 71 | if (root1 == root2) 72 | return; 73 | 74 | if (root1.Rank > root2.Rank) 75 | root2.Parent = root1; 76 | else if (root2.Rank > root1.Rank) 77 | root1.Parent = root2; 78 | else 79 | { 80 | root2.Parent = root1; 81 | root1.Rank++; 82 | } 83 | } 84 | 85 | /// 86 | /// Stores items and their parent pointers for use in the UnionFind<T> methods. 87 | /// 88 | /// The type of elements in the sets. 89 | private class UnionNode 90 | { 91 | public UnionNode(T value, uint rank) 92 | { 93 | this.Value = value; 94 | this.Parent = this; 95 | this.Rank = rank; 96 | } 97 | 98 | /// 99 | /// The value stored in this UnionNode<T>. 100 | /// 101 | public T Value { get; set; } 102 | /// 103 | /// The representative of this UnionNode<T>. 104 | /// 105 | public UnionNode Parent { get; set; } 106 | /// 107 | /// The rank of this set. Only accurate if this UnionNode<T> is the representative of its set. 108 | /// 109 | public uint Rank { get; set; } 110 | } 111 | } 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/Graph.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | /// 11 | /// Represents a variety of graph types. 12 | /// 13 | public partial class Graph 14 | { 15 | /// 16 | /// The set of vertices in the graph, indexed by ID. 17 | /// 18 | public Dictionary Vertices = new Dictionary(); 19 | 20 | /// 21 | /// The set of edges in the graph. 22 | /// 23 | public List Edges = new List(); 24 | 25 | /// 26 | /// Add a vertex to the graph. 27 | /// 28 | /// The ID of the vertex to be added. 29 | public void AddVertex(uint id) { this.Vertices.Add(id, new Vertex(id)); } 30 | 31 | /// 32 | /// Add an edge to the graph. 33 | /// 34 | /// The ID of the first endpoint of the edge. A new vertex will be created if it does not exist. 35 | /// The ID of the second endpoint of the edge. A new vertex will be created if it does not exist. 36 | /// Indicates whether this edge is directed or not. 37 | /// The weight of the edge. 38 | /// The capacity of the edge. 39 | public void AddEdge(uint from, uint to, bool directed = false, int weight = 1, uint capacity = 1) 40 | { 41 | Vertex v1, v2; 42 | if (!this.Vertices.TryGetValue(from, out v1)) 43 | { 44 | v1 = new Vertex(from); 45 | this.Vertices[from] = v1; 46 | } 47 | if (!this.Vertices.TryGetValue(to, out v2)) 48 | { 49 | v2 = new Vertex(to); 50 | this.Vertices[to] = v2; 51 | } 52 | 53 | Edge e1 = new Edge(from, to, weight, capacity); 54 | v1.Neighbours.Add(to, e1); 55 | this.Edges.Add(e1); 56 | if (!directed) 57 | { 58 | Edge e2 = new Edge(to, from, weight, capacity); 59 | v2.Neighbours.Add(from, e2); 60 | this.Edges.Add(e2); 61 | } 62 | } 63 | 64 | /// 65 | /// Removes a vertex from the graph. 66 | /// 67 | /// The ID of the vertex to be removed. 68 | /// true if the vertex was successfully removed; false if it does not exist. 69 | public bool RemoveVertex(uint id) 70 | { 71 | if (!this.Vertices.ContainsKey(id)) 72 | return false; 73 | 74 | this.Vertices.Remove(id); 75 | 76 | List newEdges = new List(); 77 | foreach (Edge e in this.Edges) 78 | if (e.From == id) 79 | continue; 80 | else if (e.To == id) 81 | this.Vertices[e.From].Neighbours.Remove(id); 82 | else 83 | newEdges.Add(e); 84 | 85 | this.Edges = newEdges; 86 | return true; 87 | } 88 | 89 | /// 90 | /// Test whether the graph contains a vertex with a specific ID. 91 | /// 92 | /// The ID of the vertex to be found. 93 | /// true if the vertex exists; falseotherwise. 94 | public bool HasVertex(uint id) { return this.Vertices.ContainsKey(id); } 95 | 96 | /// 97 | /// Test whether the graph contains an edge between the two specified endpoints. 98 | /// 99 | /// The ID of the first endpoint of the edge to be found. 100 | /// The ID of the second endpoint of the edge to be found. 101 | /// true if the edge exists; false otherwise. 102 | public bool HasEdge(uint from, uint to) { return this.Vertices.ContainsKey(from) && this.Vertices[from].Neighbours.ContainsKey(to); } 103 | } 104 | 105 | /// 106 | /// Represents a vertex of a graph. 107 | /// 108 | public class Vertex 109 | { 110 | /// 111 | /// The ID of the vertex. 112 | /// 113 | public uint ID; 114 | 115 | /// 116 | /// The neighbours of the vertex. 117 | /// 118 | public Dictionary Neighbours; 119 | 120 | /// 121 | /// Initialises a new instance of the Vertex class with the specified ID. 122 | /// 123 | /// The ID of the new vertex. 124 | public Vertex(uint id) : this(id, new Dictionary()) { } 125 | 126 | /// 127 | /// Initialises a new instance of the Vertex class with the specified ID and neighbours. 128 | /// 129 | /// The ID of the new vertex. 130 | /// The neighbours of the new vertex. 131 | public Vertex(uint id, Dictionary neighbours) { this.ID = id; this.Neighbours = neighbours; } 132 | } 133 | 134 | /// 135 | /// Represents an edge of a graph. 136 | /// 137 | public class Edge 138 | { 139 | /// 140 | /// The ID of the first endpoint of the edge. 141 | /// 142 | public uint From; 143 | 144 | /// 145 | /// The ID of the second endpoint of the edge. 146 | /// 147 | public uint To; 148 | 149 | /// 150 | /// The capacity of the edge. 151 | /// 152 | public uint Capacity; 153 | 154 | /// 155 | /// The weight of the edge. 156 | /// 157 | public int Weight; 158 | 159 | 160 | /// 161 | /// Initialises a new instance of the Edge class with the specified endpoints, weight and capacity. 162 | /// 163 | /// The ID of the first endpoint of the new edge. 164 | /// The ID of the second endpoint of the new edge. 165 | /// The weight of the new edge. 166 | /// The capacity of the new edge. 167 | public Edge(uint from, uint to, int weight, uint capacity) 168 | { 169 | this.From = from; 170 | this.To = to; 171 | this.Weight = weight; 172 | this.Capacity = capacity; 173 | } 174 | } 175 | } 176 | } 177 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/GraphInterfaces.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | /// 11 | /// Represents a graph by its nodes and edges. 12 | /// 13 | /// The type of edges this graph has. 14 | public interface IGraph 15 | where T : IGraphEdge 16 | { 17 | /// 18 | /// The nodes in the graph. 19 | /// 20 | Dictionary> Nodes { get; } 21 | /// 22 | /// The edges in the graph. 23 | /// 24 | Dictionary> Edges { get; } 25 | } 26 | 27 | /// 28 | /// Interface for graph nodes. 29 | /// 30 | /// The type of edges this node connects to. 31 | public interface IGraphNode 32 | where T : IGraphEdge 33 | { 34 | /// 35 | /// The unique identifier for this node. 36 | /// 37 | uint ID { get; } 38 | /// 39 | /// Edges from this node to neighbours. 40 | /// 41 | IEnumerable Neighbours { get; } 42 | } 43 | 44 | /// 45 | /// Interface for graph edges. 46 | /// 47 | public interface IGraphEdge 48 | { 49 | /// 50 | /// Starting point of this edge. 51 | /// 52 | uint From { get; } 53 | /// 54 | /// Endpoint of this edge. 55 | /// 56 | uint To { get; } 57 | } 58 | 59 | /// 60 | /// Interface for weighted graph edges. 61 | /// 62 | public interface IWeightedGraphEdge : IGraphEdge 63 | { 64 | /// 65 | /// The weight associated with this edge. 66 | /// 67 | uint Weight { get; } 68 | } 69 | 70 | /// 71 | /// Interface for graph edges with flow capacity. 72 | /// 73 | public interface IFlowGraphEdge : IGraphEdge 74 | { 75 | /// 76 | /// The flow capacity of this edge. 77 | /// 78 | uint Capacity { get; } 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/MaxFlowMinCut.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | /// 11 | /// Static class containing graph algorithms. 12 | /// 13 | public static partial class Graph 14 | { 15 | /// 16 | /// Returns the lightest set of edges that would divide the graph in two components should they be removed. 17 | /// 18 | /// The flow graph to calculate the minimum cut of. 19 | /// The source of the flow. 20 | /// The sink of the flow. 21 | /// A list containing the edges that make up the minimum cut. 22 | public static List MinCut(IGraph graph, uint source, uint sink) 23 | { 24 | Dictionary> flowGraph = BuildFlowGraph(graph); 25 | MaxFlow(flowGraph, source, sink); 26 | 27 | List cut = new List(); 28 | HashSet reachable = new HashSet(); 29 | Queue open = new Queue(); 30 | 31 | open.Enqueue(source); 32 | reachable.Add(source); 33 | while (open.Count > 0) 34 | { 35 | uint i = open.Dequeue(); 36 | foreach (uint j in flowGraph[i].Keys) 37 | if (!reachable.Contains(j) && flowGraph[i][j].Residual > 0) 38 | { 39 | open.Enqueue(j); 40 | reachable.Add(j); 41 | } 42 | } 43 | 44 | foreach (uint i in reachable) 45 | { 46 | foreach (uint j in flowGraph[i].Keys) 47 | if (!reachable.Contains(j)) 48 | cut.Add(flowGraph[i][j].Original); 49 | } 50 | 51 | return cut; 52 | } 53 | 54 | /// 55 | /// Returns the maximum amount of flow that can move from the source to the sink. 56 | /// 57 | /// The flow graph to calculate the maximum flow of. 58 | /// The source of the flow. 59 | /// The sink of the flow. 60 | /// The maximum amount of flow that can move from the source to the sink. 61 | public static ulong MaxFlow(IGraph graph, uint source, uint sink) 62 | { 63 | return MaxFlow(BuildFlowGraph(graph), source, sink); 64 | } 65 | 66 | private static Dictionary> BuildFlowGraph(IGraph graph) 67 | { 68 | Dictionary> flowGraph = new Dictionary>(); 69 | Dictionary dict; 70 | 71 | foreach (IGraphNode n in graph.Nodes.Values) 72 | foreach (IFlowGraphEdge e in n.Neighbours) 73 | { 74 | if (!flowGraph.TryGetValue(e.From, out dict)) 75 | { 76 | dict = new Dictionary(); 77 | flowGraph.Add(e.From, dict); 78 | } 79 | dict.Add(e.To, new FlowEdge(e.From, e.To, e.Capacity, e)); 80 | 81 | if (!flowGraph.TryGetValue(e.To, out dict)) 82 | { 83 | dict = new Dictionary(); 84 | flowGraph.Add(e.To, dict); 85 | } 86 | dict.Add(e.From, new FlowEdge(e.To, e.From, e.Capacity, e)); 87 | } 88 | 89 | return flowGraph; 90 | } 91 | 92 | private static ulong MaxFlow(Dictionary> neighbours, uint source, uint sink) 93 | { 94 | FlowNode path; 95 | ulong maxFlow = 0; 96 | uint flow; 97 | FlowEdge e1, e2; 98 | while (BFS(neighbours, source, sink, out path)) 99 | { 100 | flow = path.Capacity; 101 | maxFlow += flow; 102 | while (path.Parent != null) 103 | { 104 | e1 = neighbours[path.Parent.Node][path.Node]; 105 | e2 = neighbours[path.Node][path.Parent.Node]; 106 | e1.Residual -= flow; 107 | e2.Residual += flow; 108 | path = path.Parent; 109 | } 110 | } 111 | return maxFlow; 112 | } 113 | 114 | private static bool BFS(Dictionary> neighbours, uint source, uint sink, out FlowNode path) 115 | { 116 | path = null; 117 | Queue open = new Queue(); 118 | open.Enqueue(new FlowNode(source, null, int.MaxValue)); 119 | 120 | HashSet done = new HashSet(); 121 | done.Add(source); 122 | 123 | FlowNode node; 124 | while (open.Count > 0) 125 | { 126 | node = open.Dequeue(); 127 | foreach (uint i in neighbours[node.Node].Keys) 128 | { 129 | if (done.Contains(i) || neighbours[node.Node][i].Residual == 0) 130 | continue; 131 | if (i == sink) 132 | { 133 | path = new FlowNode(i, node, Math.Min(neighbours[node.Node][i].Residual, node.Capacity)); 134 | return true; 135 | } 136 | open.Enqueue(new FlowNode(i, node, Math.Min(neighbours[node.Node][i].Residual, node.Capacity))); 137 | done.Add(i); 138 | } 139 | } 140 | 141 | return false; 142 | } 143 | 144 | private class FlowEdge 145 | { 146 | public FlowEdge(uint node1, uint node2, uint capacity, IFlowGraphEdge original) 147 | { 148 | this.Node1 = node1; 149 | this.Node2 = node2; 150 | this.Capacity = capacity; 151 | this.Residual = capacity; 152 | this.Original = original; 153 | } 154 | 155 | public uint Node1 { get; private set; } 156 | public uint Node2 { get; private set; } 157 | public uint Capacity { get; private set; } 158 | public uint Residual { get; set; } 159 | public IFlowGraphEdge Original { get; private set; } 160 | } 161 | 162 | private class FlowNode 163 | { 164 | public FlowNode(uint node, FlowNode parent, uint capacity) 165 | { 166 | this.Node = node; 167 | this.Parent = parent; 168 | this.Capacity = capacity; 169 | } 170 | 171 | public uint Node { get; private set; } 172 | public FlowNode Parent { get; private set; } 173 | public uint Capacity { get; private set; } 174 | } 175 | } 176 | } 177 | } 178 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/MaximumFlow/MaxFlowMinCut.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | public partial class Graph 11 | { 12 | /// 13 | /// Returns the lightest set of edges that would divide the graph in two components should they be removed. 14 | /// 15 | /// The source of the flow. 16 | /// The sink of the flow. 17 | /// A list containing the edges that make up the minimum cut. 18 | public List MinCut(uint source, uint sink) 19 | { 20 | Dictionary> flowGraph = BuildFlowGraph(this); 21 | MaxFlow(flowGraph, source, sink); 22 | 23 | List cut = new List(); 24 | HashSet reachable = new HashSet(); 25 | Queue open = new Queue(); 26 | 27 | open.Enqueue(source); 28 | reachable.Add(source); 29 | while (open.Count > 0) 30 | { 31 | uint i = open.Dequeue(); 32 | foreach (uint j in flowGraph[i].Keys) 33 | if (!reachable.Contains(j) && flowGraph[i][j].Residual > 0) 34 | { 35 | open.Enqueue(j); 36 | reachable.Add(j); 37 | } 38 | } 39 | 40 | foreach (uint i in reachable) 41 | { 42 | foreach (uint j in flowGraph[i].Keys) 43 | if (!reachable.Contains(j)) 44 | cut.Add(flowGraph[i][j].Original); 45 | } 46 | 47 | return cut; 48 | } 49 | 50 | /// 51 | /// Returns the maximum amount of flow that can move from the source to the sink. 52 | /// 53 | /// The source of the flow. 54 | /// The sink of the flow. 55 | /// The maximum amount of flow that can move from the source to the sink. 56 | public ulong MaxFlow(uint source, uint sink) { return MaxFlow(BuildFlowGraph(this), source, sink); } 57 | 58 | private static Dictionary> BuildFlowGraph(Graph graph) 59 | { 60 | Dictionary> flowGraph = new Dictionary>(); 61 | Dictionary dict; 62 | 63 | foreach (Vertex v in graph.Vertices.Values) 64 | foreach (Edge e in v.Neighbours.Values) 65 | { 66 | if (!flowGraph.TryGetValue(e.From, out dict)) 67 | { 68 | dict = new Dictionary(); 69 | flowGraph.Add(e.From, dict); 70 | } 71 | dict.Add(e.To, new FlowEdge(e.From, e.To, e.Capacity, e)); 72 | 73 | if (!flowGraph.TryGetValue(e.To, out dict)) 74 | { 75 | dict = new Dictionary(); 76 | flowGraph.Add(e.To, dict); 77 | } 78 | dict.Add(e.From, new FlowEdge(e.To, e.From, e.Capacity, e)); 79 | } 80 | 81 | return flowGraph; 82 | } 83 | 84 | private static ulong MaxFlow(Dictionary> neighbours, uint source, uint sink) 85 | { 86 | FlowNode path; 87 | ulong maxFlow = 0; 88 | uint flow; 89 | FlowEdge e1, e2; 90 | while (BFS(neighbours, source, sink, out path)) 91 | { 92 | flow = path.Capacity; 93 | maxFlow += flow; 94 | while (path.Parent != null) 95 | { 96 | e1 = neighbours[path.Parent.Node][path.Node]; 97 | e2 = neighbours[path.Node][path.Parent.Node]; 98 | e1.Residual -= flow; 99 | e2.Residual += flow; 100 | path = path.Parent; 101 | } 102 | } 103 | return maxFlow; 104 | } 105 | 106 | private static bool BFS(Dictionary> neighbours, uint source, uint sink, out FlowNode path) 107 | { 108 | path = null; 109 | Queue open = new Queue(); 110 | open.Enqueue(new FlowNode(source, null, int.MaxValue)); 111 | 112 | HashSet done = new HashSet(); 113 | done.Add(source); 114 | 115 | FlowNode node; 116 | while (open.Count > 0) 117 | { 118 | node = open.Dequeue(); 119 | foreach (uint i in neighbours[node.Node].Keys) 120 | { 121 | if (done.Contains(i) || neighbours[node.Node][i].Residual == 0) 122 | continue; 123 | if (i == sink) 124 | { 125 | path = new FlowNode(i, node, Math.Min(neighbours[node.Node][i].Residual, node.Capacity)); 126 | return true; 127 | } 128 | open.Enqueue(new FlowNode(i, node, Math.Min(neighbours[node.Node][i].Residual, node.Capacity))); 129 | done.Add(i); 130 | } 131 | } 132 | 133 | return false; 134 | } 135 | 136 | private class FlowEdge 137 | { 138 | public FlowEdge(uint node1, uint node2, uint capacity, Edge original) 139 | { 140 | this.Node1 = node1; 141 | this.Node2 = node2; 142 | this.Capacity = capacity; 143 | this.Residual = capacity; 144 | this.Original = original; 145 | } 146 | 147 | public uint Node1 { get; private set; } 148 | public uint Node2 { get; private set; } 149 | public uint Capacity { get; private set; } 150 | public uint Residual { get; set; } 151 | public Edge Original { get; private set; } 152 | } 153 | 154 | private class FlowNode 155 | { 156 | public FlowNode(uint node, FlowNode parent, uint capacity) 157 | { 158 | this.Node = node; 159 | this.Parent = parent; 160 | this.Capacity = capacity; 161 | } 162 | 163 | public uint Node { get; private set; } 164 | public FlowNode Parent { get; private set; } 165 | public uint Capacity { get; private set; } 166 | } 167 | } 168 | } 169 | } 170 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/MinimumSpanningTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Utility.DataStructures.DisjointSet; 4 | 5 | namespace Utility 6 | { 7 | namespace Algorithms 8 | { 9 | namespace Graph 10 | { 11 | public static partial class Graph 12 | { 13 | /// 14 | /// Returns the lightest tree that connects all the node in the graph. 15 | /// 16 | /// The graph to calculate the minimum spanning tree of. 17 | /// A list of edges that make up the minimum spanning tree. 18 | public static List MinimumSpanningTree(IGraph graph) 19 | { 20 | List mst = new List(); 21 | List edges = new List(); 22 | UnionFind unionFind = new UnionFind(); 23 | foreach (Dictionary dict in graph.Edges.Values) 24 | foreach (IWeightedGraphEdge e in dict.Values) 25 | edges.Add(e); 26 | 27 | edges.Sort((x, y) => { return x.Weight.CompareTo(y.Weight); }); 28 | foreach (IGraphNode n in graph.Nodes.Values) 29 | unionFind.Make(n.ID); 30 | 31 | foreach (IWeightedGraphEdge e in edges) 32 | if (unionFind.Find(e.From) != unionFind.Find(e.To)) 33 | { 34 | mst.Add(e); 35 | unionFind.Union(e.From, e.To); 36 | } 37 | 38 | return mst; 39 | } 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/MinimumSpanningTree/Kruskal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Utility.DataStructures.DisjointSet; 4 | 5 | namespace Utility 6 | { 7 | namespace Algorithms 8 | { 9 | namespace Graph 10 | { 11 | public partial class Graph 12 | { 13 | /// 14 | /// Returns the lightest tree that connects all the vertices in the graph. 15 | /// 16 | /// A list of edges that make up the minimum spanning tree. 17 | public List Kruskal() 18 | { 19 | List mst = new List(); 20 | List edges = new List(); 21 | UnionFind unionFind = new UnionFind(); 22 | foreach (Vertex v in this.Vertices.Values) 23 | foreach (Edge e in v.Neighbours.Values) 24 | edges.Add(e); 25 | 26 | edges.Sort((x, y) => { return x.Weight.CompareTo(y.Weight); }); 27 | foreach (Vertex v in this.Vertices.Values) 28 | unionFind.Make(v.ID); 29 | 30 | foreach (Edge e in edges) 31 | if (unionFind.Find(e.From) != unionFind.Find(e.To)) 32 | { 33 | mst.Add(e); 34 | unionFind.Union(e.From, e.To); 35 | } 36 | 37 | return mst; 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/Path.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | /// 11 | /// Represents a path through a graph. 12 | /// 13 | public class Path 14 | { 15 | /// 16 | /// The edges the path traverses, in order. 17 | /// 18 | public List Edges = new List(); 19 | 20 | /// 21 | /// The vertices the path traverses, in order. 22 | /// 23 | public List Vertices = new List(); 24 | 25 | /// 26 | /// The total weight of all edges on the path. 27 | /// 28 | public int Weight = 0; 29 | 30 | /// 31 | /// The minimum capacity of all edges on the path. 32 | /// 33 | public uint Capacity = uint.MaxValue; 34 | 35 | /// 36 | /// Generate a path from a set of single-source parent pointers. 37 | /// 38 | /// The start of the path. 39 | /// The end of the path. 40 | /// The set of single-source parent pointers. 41 | /// The graph to find the path in. 42 | /// The path between and , if one exists; null otherwise. 43 | public static Path FromParents(uint from, uint to, Dictionary parents, Graph graph) 44 | { 45 | if (!parents.ContainsKey(to)) 46 | return null; 47 | 48 | Path path = new Path(); 49 | 50 | path.Vertices.Add(graph.Vertices[to]); 51 | uint current = to, parent; 52 | while (parents.TryGetValue(current, out parent)) 53 | { 54 | Vertex v = graph.Vertices[parent]; 55 | Edge e = v.Neighbours[current]; 56 | path.Edges.Add(e); 57 | path.Vertices.Add(v); 58 | path.Weight += e.Weight; 59 | path.Capacity = Math.Min(path.Capacity, e.Capacity); 60 | current = parent; 61 | } 62 | 63 | path.Edges.Reverse(); 64 | path.Vertices.Reverse(); 65 | 66 | return path; 67 | } 68 | 69 | /// 70 | /// Generate a path from a set of all-pairs parent pointers. 71 | /// 72 | /// The start of the path. 73 | /// The end of the path. 74 | /// The set of all-pairs parent pointers. 75 | /// The graph to find the path in. 76 | /// The path between and , if one exists; null otherwise. 77 | public static Path FromParents(uint from, uint to, Dictionary> parents, Graph graph) 78 | { 79 | if (!parents[from].ContainsKey(to)) 80 | return null; 81 | 82 | Path path = new Path(); 83 | path.Vertices.Add(graph.Vertices[from]); 84 | uint next; 85 | while (from != to) 86 | { 87 | next = parents[from][to]; 88 | 89 | Edge e = graph.Vertices[from].Neighbours[next]; 90 | path.Edges.Add(e); 91 | path.Vertices.Add(graph.Vertices[next]); 92 | path.Weight += e.Weight; 93 | path.Capacity = Math.Min(path.Capacity, e.Capacity); 94 | 95 | from = next; 96 | } 97 | 98 | return path; 99 | } 100 | } 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/ShortestPath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Utility.DataStructures.PriorityQueue; 4 | 5 | namespace Utility 6 | { 7 | namespace Algorithms 8 | { 9 | namespace Graph 10 | { 11 | public static partial class Graph 12 | { 13 | /// 14 | /// Returns true if there is a path between two given nodes in the given, unweighted graph; false otherwise. 15 | /// 16 | /// The graph to find the path in. 17 | /// The start of the path. 18 | /// The end of the path. 19 | /// A list containing the edges of the path that was found, in order. Empty if there is no path. 20 | /// true if there is a path; false otherwise. 21 | public static bool ShortestPath(IGraph graph, IGraphNode start, IGraphNode end, out List path) 22 | { 23 | path = new List(); 24 | Queue open = new Queue(); 25 | open.Enqueue(new BFSNode(start, null, null)); 26 | 27 | HashSet closed = new HashSet(); 28 | closed.Add(start.ID); 29 | 30 | BFSNode node; 31 | while (open.Count > 0) 32 | { 33 | node = open.Dequeue(); 34 | foreach (IGraphEdge e in node.Node.Neighbours) 35 | { 36 | if (closed.Contains(e.To)) 37 | continue; 38 | else if (e.To == end.ID) 39 | { 40 | path.Add(e); 41 | while (node.Parent != null) 42 | { 43 | path.Add(node.Edge); 44 | node = node.Parent; 45 | } 46 | path.Reverse(); 47 | return true; 48 | } 49 | open.Enqueue(new BFSNode(graph.Nodes[e.To], e, node)); 50 | } 51 | } 52 | 53 | return false; 54 | } 55 | 56 | /// 57 | /// Returns true if there is a path between two given nodes in the given, weighted graph; false otherwise. 58 | /// 59 | /// The graph to find the path in. 60 | /// The start of the path. 61 | /// The end of the path. 62 | /// A list containing the edges of the path that was found, in order. Empty if there is no path. 63 | /// true if there is a path; false otherwise. 64 | public static bool ShortestPath(IGraph graph, IGraphNode start, IGraphNode end, out List path) 65 | { 66 | path = new List(); 67 | DMinHeap open = new DMinHeap(); 68 | open.Add(new DijkstraNode(start, null, null)); 69 | 70 | HashSet closed = new HashSet(); 71 | closed.Add(start.ID); 72 | 73 | DijkstraNode node; 74 | while (open.Count > 0) 75 | { 76 | node = open.Extract(); 77 | foreach (IWeightedGraphEdge e in node.Node.Neighbours) 78 | { 79 | if (closed.Contains(e.To)) 80 | continue; 81 | else if (e.To == end.ID) 82 | { 83 | path.Add(e); 84 | while (node.Parent != null) 85 | { 86 | path.Add(node.Edge); 87 | node = node.Parent; 88 | } 89 | path.Reverse(); 90 | 91 | return true; 92 | } 93 | open.Add(new DijkstraNode(graph.Nodes[e.To], e, node)); 94 | } 95 | } 96 | 97 | return false; 98 | } 99 | 100 | private class BFSNode 101 | { 102 | public BFSNode(IGraphNode node, IGraphEdge edge, BFSNode parent) 103 | { 104 | this.Node = node; 105 | this.Edge = edge; 106 | this.Parent = parent; 107 | } 108 | 109 | public IGraphNode Node { get; private set; } 110 | public IGraphEdge Edge { get; private set; } 111 | public BFSNode Parent { get; private set; } 112 | } 113 | 114 | private class DijkstraNode : IComparable 115 | { 116 | public DijkstraNode(IGraphNode node, IWeightedGraphEdge edge, DijkstraNode parent) 117 | { 118 | this.Node = node; 119 | this.Edge = edge; 120 | this.Parent = parent; 121 | 122 | if (parent != null) 123 | this.Weight = parent.Weight + edge.Weight; 124 | else 125 | this.Weight = 0; 126 | } 127 | 128 | public int CompareTo(DijkstraNode other) { return this.Weight.CompareTo(other.Weight); } 129 | 130 | public IGraphNode Node { get; private set; } 131 | public IWeightedGraphEdge Edge { get; private set; } 132 | public DijkstraNode Parent { get; private set; } 133 | public uint Weight { get; private set; } 134 | } 135 | } 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/ShortestPath/BellmanFord.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Graph 8 | { 9 | public partial class Graph 10 | { 11 | /// 12 | /// Finds the lengths of the shortest paths from a given vertex to all other vertices, if no negative cycle is reachable from the start. 13 | /// 14 | /// The vertex to calculate the lengths of the shortest paths from. 15 | /// The lengths of the shortest paths if no negative cycles are present; null otherwise. 16 | public Dictionary BellmanFord(uint from) 17 | { 18 | Dictionary lengths; 19 | Dictionary parents; 20 | if (!this.BellmanFord(from, out lengths, out parents)) 21 | return null; 22 | return lengths; 23 | } 24 | 25 | /// 26 | /// Finds the shortest path from a given vertex to all other vertices, if no negative cycle is reachable from the start. 27 | /// 28 | /// The vertex to calculate the shortest paths from. 29 | /// The lengths of the shortest paths to all vertices. 30 | /// The parent-pointers for the paths to all vertices. 31 | /// true if there are no negative cycles reachable from the start; false otherwise. 32 | public bool BellmanFord(uint from, out Dictionary lengths, out Dictionary parents) 33 | { 34 | lengths = new Dictionary(); 35 | parents = new Dictionary(); 36 | 37 | foreach (uint v in this.Vertices.Keys) 38 | lengths[v] = int.MaxValue; 39 | lengths[from] = 0; 40 | 41 | 42 | for (int i = 0; i < this.Vertices.Count - 1; i++) 43 | { 44 | bool changed = false; 45 | foreach (Edge e in this.Edges) 46 | { 47 | int newDist = lengths[e.From] + e.Weight; 48 | if (newDist < lengths[e.To]) 49 | { 50 | lengths[e.To] = newDist; 51 | parents[e.To] = e.From; 52 | changed = true; 53 | } 54 | } 55 | 56 | if (!changed) 57 | break; 58 | } 59 | 60 | foreach (Edge e in this.Edges) 61 | if (lengths[e.From] + e.Weight < lengths[e.To]) 62 | return false; 63 | 64 | return true; 65 | } 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/ShortestPath/BreadthFirstSearch.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Graph 8 | { 9 | public partial class Graph 10 | { 11 | /// 12 | /// Finds the shortest, unweighted path between two vertices, if one exists. 13 | /// 14 | /// The start of the path. 15 | /// The end of the path. 16 | /// The path that was found. null if there is no path. 17 | /// true if there is a path; false otherwise. 18 | public bool BreadthFirstSearch(uint from, uint to, out Path path) 19 | { 20 | path = null; 21 | Queue fringe = new Queue(); 22 | fringe.Enqueue(from); 23 | 24 | Dictionary parents = new Dictionary(); 25 | HashSet closed = new HashSet(); 26 | closed.Add(from); 27 | 28 | while (fringe.Count > 0) 29 | { 30 | uint node = fringe.Dequeue(); 31 | foreach (Edge e in this.Vertices[node].Neighbours.Values) 32 | { 33 | if (closed.Contains(e.To)) 34 | continue; 35 | else if (e.To == to) 36 | { 37 | parents[to] = node; 38 | path = Path.FromParents(from, to, parents, this); 39 | return true; 40 | } 41 | fringe.Enqueue(e.To); 42 | parents[e.To] = e.From; 43 | closed.Add(e.To); 44 | } 45 | } 46 | 47 | return false; 48 | } 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/ShortestPath/Dijkstra.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Utility.DataStructures.PriorityQueue; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | public partial class Graph 11 | { 12 | /// 13 | /// Finds the shortest, weighted path between two vertices, if one exists. Assumes there are no negative-weight edges in the graph. 14 | /// 15 | /// The start of the path. 16 | /// The end of the path. 17 | /// The path that was found. null if there is no path. 18 | /// true if there is a path; false otherwise. 19 | public bool Dijkstra(uint from, uint to, out Path path) 20 | { 21 | path = null; 22 | DMinHeap fringe = new DMinHeap(); 23 | Dictionary parents = new Dictionary(); 24 | Dictionary dist = new Dictionary(); 25 | 26 | this.DijkstraInit(from, dist, fringe); 27 | 28 | uint current; 29 | while (fringe.Count > 0) 30 | { 31 | current = fringe.Extract(); 32 | 33 | if (current == to) 34 | { 35 | path = Path.FromParents(from, to, parents, this); 36 | return true; 37 | } 38 | 39 | this.DijkstraRelax(current, dist, parents, fringe); 40 | } 41 | 42 | return false; 43 | } 44 | 45 | /// 46 | /// Find the shortest, weighted paths from a given vertex to all other vertices. Assumes there are no negative-weight edges in the graph. 47 | /// 48 | /// The vertex to calculate the shortest paths from. 49 | /// The lengths of the shortest paths to all vertices. 50 | /// The parent-pointers for the paths to all vertices. 51 | public void Dijkstra(uint from, out Dictionary lengths, out Dictionary parents) 52 | { 53 | DMinHeap fringe = new DMinHeap(); 54 | parents = new Dictionary(); 55 | lengths = new Dictionary(); 56 | 57 | this.DijkstraInit(from, lengths, fringe); 58 | 59 | uint current; 60 | while (fringe.Count > 0) 61 | { 62 | current = fringe.Extract(); 63 | this.DijkstraRelax(current, lengths, parents, fringe); 64 | } 65 | } 66 | 67 | private void DijkstraInit(uint from, Dictionary dist, DMinHeap fringe) 68 | { 69 | foreach (uint v in this.Vertices.Keys) 70 | { 71 | if (v == from) 72 | dist[v] = 0; 73 | else 74 | dist[v] = int.MaxValue; 75 | fringe.Add(v, dist[v]); 76 | } 77 | } 78 | 79 | private void DijkstraRelax(uint current, Dictionary dist, Dictionary parents, DMinHeap fringe) 80 | { 81 | foreach (Edge e in this.Vertices[current].Neighbours.Values) 82 | { 83 | if (!fringe.ContainsValue(e.To)) 84 | continue; 85 | 86 | int newDist = dist[current] + e.Weight; 87 | if (newDist < dist[e.To]) 88 | { 89 | dist[e.To] = newDist; 90 | parents[e.To] = current; 91 | fringe.ChangeKey(e.To, newDist); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/ShortestPath/FloydWarshall.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Graph 8 | { 9 | public partial class Graph 10 | { 11 | /// 12 | /// Finds the lengths of the shortest paths between all pairs of vertices in the graph, if no negative cycles are present. 13 | /// 14 | /// The lengths of the shortest paths between all pairs of vertices if no negative cycles are present; null otherwise. 15 | public Dictionary> FloydWarshall() 16 | { 17 | Dictionary> lengths; 18 | Dictionary> parents; 19 | if (!this.FloydWarshall(out lengths, out parents)) 20 | return null; 21 | return lengths; 22 | } 23 | 24 | /// 25 | /// Finds the shortest path between all pairs of vertices in the graph, if no negative cycles are present. 26 | /// 27 | /// The lengths of the shortest paths between all pairs of vertices. 28 | /// The parent-pointers for the paths between all pairs of vertices. 29 | /// true if there are no negative cycles; false otherwise. 30 | public bool FloydWarshall(out Dictionary> lengths, out Dictionary> parents) 31 | { 32 | lengths = new Dictionary>(); 33 | parents = new Dictionary>(); 34 | 35 | foreach (Vertex x in this.Vertices.Values) 36 | { 37 | uint u = x.ID; 38 | lengths[u] = new Dictionary(); 39 | parents[u] = new Dictionary(); 40 | foreach (uint v in this.Vertices.Keys) 41 | lengths[u][v] = int.MaxValue; 42 | 43 | lengths[u][u] = 0; 44 | foreach (Edge e in x.Neighbours.Values) 45 | { 46 | lengths[u][e.To] = e.Weight; 47 | parents[u][e.To] = e.To; 48 | } 49 | } 50 | 51 | foreach (uint k in this.Vertices.Keys) 52 | foreach (uint i in this.Vertices.Keys) 53 | foreach (uint j in this.Vertices.Keys) 54 | { 55 | int ik = lengths[i][k]; 56 | if (ik == int.MaxValue) 57 | continue; 58 | 59 | int kj = lengths[k][j]; 60 | if (kj == int.MaxValue) 61 | continue; 62 | 63 | int newDist = ik + kj; 64 | if (newDist < lengths[i][j]) 65 | { 66 | lengths[i][j] = newDist; 67 | parents[i][j] = parents[i][k]; 68 | } 69 | } 70 | 71 | foreach (uint v in this.Vertices.Keys) 72 | if (lengths[v][v] < 0) 73 | return false; 74 | 75 | return true; 76 | } 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /Code/Utility/Graph/ShortestPath/Johnson.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Utility.DataStructures.PriorityQueue; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Graph 9 | { 10 | public partial class Graph 11 | { 12 | /// 13 | /// Finds the lengths of the shortest paths between all pairs of vertices in the graph, if no negative cycles are present. 14 | /// 15 | /// The lengths of the shortest paths between all pairs of vertices if no negative cycles are present; null otherwise. 16 | public Dictionary> Johnson() 17 | { 18 | Dictionary> lengths; 19 | Dictionary> parents; 20 | if (!this.Johnson(out lengths, out parents)) 21 | return null; 22 | return lengths; 23 | } 24 | 25 | /// 26 | /// Finds the shortest path between all pairs of vertices in the graph, if no negative cycles are present. 27 | /// 28 | /// The lengths of the shortest paths between all pairs of vertices. 29 | /// The parent-pointers for the paths between all pairs of vertices. 30 | /// true if there are no negative cycles; false otherwise. 31 | public bool Johnson(out Dictionary> lengths, out Dictionary> parents) 32 | { 33 | lengths = null; 34 | parents = null; 35 | 36 | uint free = 0; 37 | foreach (uint v in this.Vertices.Keys) 38 | if (v >= free) 39 | free = v + 1; 40 | 41 | Graph g = new Graph(); 42 | foreach (Edge e in this.Edges) 43 | g.AddEdge(e.From, e.To, false, e.Weight, e.Capacity); 44 | foreach (uint v in this.Vertices.Keys) 45 | g.AddEdge(free, v, true, 0); 46 | 47 | Dictionary l; 48 | Dictionary p; 49 | if (!this.BellmanFord(free, out l, out p)) 50 | return false; 51 | 52 | foreach (Edge e in g.Edges) 53 | e.Weight += l[e.From] - l[e.To]; 54 | 55 | g.RemoveVertex(free); 56 | 57 | lengths = new Dictionary>(); 58 | parents = new Dictionary>(); 59 | foreach (uint v in g.Vertices.Keys) 60 | { 61 | g.Dijkstra(v, out l, out p); 62 | lengths[v] = l; 63 | parents[v] = p; 64 | } 65 | 66 | return true; 67 | } 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Code/Utility/ProbabilisticStructures/BloomFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace DataStructures 6 | { 7 | namespace Probabilistic 8 | { 9 | /// 10 | /// Represents a Bloom filter. 11 | /// 12 | /// The type of values the Bloom filter should work with. 13 | public class BloomFilter 14 | { 15 | /// 16 | /// Represents a function that takes an object of type and returns a hash of this object. 17 | /// 18 | /// The object to hash. 19 | /// An unsigned integer containing the hash value of . 20 | public delegate uint HashFunction(T item); 21 | 22 | private uint[] filter; 23 | private uint size, hashCount; 24 | private HashFunction primaryHash, secondaryHash; 25 | 26 | /// 27 | /// Initialises a new BloomFilter<T> with an optimal size and number of hash functions given the desired capacity and error rate. 28 | /// 29 | /// The expected number of items that will be stored in the BloomFilter<T>. 30 | /// The desired probability of false positives occurring when the capacity has been filled. 31 | /// The first hash function. 32 | /// The second hash function. 33 | public BloomFilter(uint capacity, double errorRate, HashFunction primaryHash, HashFunction secondaryHash) 34 | { 35 | this.size = OptimalSize(capacity, errorRate); 36 | this.hashCount = OptimalHashCount(capacity, this.size); 37 | this.primaryHash = primaryHash; 38 | this.secondaryHash = secondaryHash; 39 | 40 | this.filter = new uint[this.size]; 41 | this.filter.Initialize(); 42 | } 43 | 44 | /// 45 | /// Initialises a new BloomFilter<T> with the given size and number of hash functions. 46 | /// 47 | /// The size of the BloomFilter<T>. 48 | /// The number of hash functions to use. 49 | /// The first hash function. 50 | /// The second hash function. 51 | public BloomFilter(uint arraySize, uint numberOfHashFunctions, HashFunction primaryHash, HashFunction secondaryHash) 52 | { 53 | this.size = arraySize; 54 | this.hashCount = numberOfHashFunctions; 55 | this.primaryHash = primaryHash; 56 | this.secondaryHash = secondaryHash; 57 | 58 | this.filter = new uint[this.size]; 59 | this.filter.Initialize(); 60 | } 61 | 62 | /// 63 | /// Adds a new item to the BloomFilter<T>. 64 | /// 65 | /// The item to add. 66 | public void Add(T item) 67 | { 68 | uint[] hashes = this.GetHashes(item); 69 | foreach (uint u in hashes) 70 | this.filter[u]++; 71 | this.Count++; 72 | } 73 | 74 | /// 75 | /// Tries to delete an item from the BloomFilter<T>. 76 | /// 77 | /// The item that should be deleted. 78 | /// true if the item might have been in the BloomFilter<T> and was deleted; false if the item was definitely not in the BloomFilter<T>. 79 | public bool Delete(T item) 80 | { 81 | double conf; 82 | return this.Delete(item, out conf); 83 | } 84 | 85 | /// 86 | /// Tries to delete an item from the BloomFilter<T>. 87 | /// 88 | /// The item that should be deleted. 89 | /// The confidence that was in the BloomFilter<T> before deletion. 90 | /// true if the item might have been in the BloomFilter<T> and was deleted; false if the item was definitely not in the BloomFilter<T>. 91 | public bool Delete(T item, out double confidence) 92 | { 93 | uint[] hashes; 94 | confidence = 1; 95 | 96 | if (!this.Contains(item, out hashes)) 97 | return false; 98 | 99 | for (int i = 0; i < hashCount; i++) 100 | this.filter[hashes[i]]--; 101 | 102 | this.Count--; 103 | 104 | return true; 105 | } 106 | 107 | /// 108 | /// Determines if an element possibly is or definitely is not contained in the BloomFilter<T>. 109 | /// 110 | /// The item to locate in the BloomFilter<T>. 111 | /// true if the BloomFilter<T> possibly contains , false if it definitely does not. 112 | public bool Contains(T item) 113 | { 114 | double conf; 115 | return this.Contains(item, out conf); 116 | } 117 | 118 | /// 119 | /// Determines if an element possibly is or definitely is not contained in the BloomFilter<T>. 120 | /// 121 | /// The item to locate in the BloomFilter<T>. 122 | /// The confidence that is in the BloomFilter<T>. 123 | /// true if the BloomFilter<T> possibly contains , false if it definitely does not. 124 | public bool Contains(T item, out double confidence) 125 | { 126 | uint[] hashes; 127 | confidence = 1; 128 | return this.Contains(item, out hashes); 129 | } 130 | 131 | private bool Contains(T item, out uint[] hashes) 132 | { 133 | hashes = new uint[hashCount]; 134 | uint[] h = this.GetHashes(item); 135 | 136 | for (int i = 0; i < hashCount; i++) 137 | if (this.filter[h[i]] == 0) 138 | return false; 139 | 140 | Buffer.BlockCopy(h, 0, hashes, 0, (int)hashCount); 141 | return true; 142 | } 143 | 144 | /// 145 | /// The confidence that when an item is found, it is actually contained in the BloomFilter<T>. 146 | /// 147 | public double Confidence { get { return 1 - Math.Pow(1 - Math.Pow(1 - 1.0 / size, hashCount * this.Count), hashCount); } } 148 | 149 | /// 150 | /// The number of items in the BloomFilter<T>. 151 | /// 152 | public int Count { get; private set; } 153 | 154 | private uint[] GetHashes(T item) 155 | { 156 | uint[] hashes = new uint[hashCount]; 157 | uint hash1 = this.primaryHash(item), hash2 = this.secondaryHash(item); 158 | 159 | for (uint i = 0; i < hashCount; i++) 160 | hashes[i] = (hash1 + i * hash2 + i * i) % size; 161 | 162 | return hashes; 163 | } 164 | 165 | /// 166 | /// Returns the optimal number of hash functions for the given capacity and size. 167 | /// 168 | /// The expected number of items that will be stored in the BloomFilter<T>. 169 | /// The size of the BloomFilter<T>. 170 | /// The number of hash functions that minimise the probability of false positives. 171 | public static uint OptimalHashCount(uint capacity, uint size) 172 | { 173 | return (uint)(((double)size / capacity) * Math.Log(2)); 174 | } 175 | 176 | /// 177 | /// Returns the optimal size of the BloomFilter<T> for the given capacity and error rate. 178 | /// 179 | /// The expected number of items that will be stored in the BloomFilter<T>. 180 | /// The probability of false positives occurring when the capacity has been filled. 181 | /// The smallest size for which the desired error rate can be achieved when the capacity has been filled. 182 | public static uint OptimalSize(uint capacity, double errorRate) 183 | { 184 | return (uint)(-capacity * Math.Log(errorRate) / (Math.Log(2) * Math.Log(2))); 185 | } 186 | 187 | /// 188 | /// Returns the probability of false positives occurring for a BloomFilter<T> with a given size and number of hash functions when the capacity has been filled. 189 | /// 190 | /// The expected number of items that will be stored in the BloomFilter<T>. 191 | /// The size of the BloomFilter<T>. 192 | /// The number of hash functions the BloomFilter<T> uses. 193 | /// The probability of false positives occurring when the capacity has been filled. 194 | public static double ErrorRate(uint capacity, uint size, uint hashCount) 195 | { 196 | return Math.Pow(1 - Math.Pow(1 - 1.0 / size, hashCount * capacity), hashCount); 197 | } 198 | } 199 | } 200 | } 201 | } -------------------------------------------------------------------------------- /Code/Utility/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Utility")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Utility")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("53c0c266-0b7a-4dde-96ea-e93eb82c7465")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Code/Utility/Search/BinaryInterpolationSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Search 8 | { 9 | public static partial class Search 10 | where T : IComparable 11 | { 12 | /// 13 | /// Performs a binary/interpolation search hybrid for in . 14 | /// 15 | /// The array to search. 16 | /// The item to search for. 17 | /// The class that defines how to interpolate between values of type . 18 | /// An integer indicating the index of the largest element that is smaller than or equal to . 19 | public static int BinaryInterpolationSearch(T[] array, T item, IInterpolator interpolator) 20 | { 21 | return BinaryInterpolationSearch(array, item, 0, array.Length - 1, interpolator.Interpolate); 22 | } 23 | 24 | /// 25 | /// Performs a binary/interpolation search hybrid for in . 26 | /// 27 | /// The array to search. 28 | /// The item to search for. 29 | /// A function that defines how to interpolate between values of type . 30 | /// An integer indicating the index of the largest element that is smaller than or equal to . 31 | public static int BinaryInterpolationSearch(T[] array, T item, Interpolation interpolate) 32 | { 33 | return BinaryInterpolationSearch(array, item, 0, array.Length - 1, interpolate); 34 | } 35 | 36 | /// 37 | /// Performs a binary/interpolation search hybrid for in . 38 | /// 39 | /// The array to search. 40 | /// The item to search for. 41 | /// The lowest index to look at. 42 | /// The highest index to look at. 43 | /// The class that defines how to interpolate between values of type . 44 | /// An integer indicating the index of the largest element that is smaller than or equal to . 45 | public static int BinaryInterpolationSearch(T[] array, T item, int start, int end, IInterpolator interpolator) 46 | { 47 | return BinaryInterpolationSearch(array, item, 0, array.Length - 1, interpolator.Interpolate); 48 | } 49 | 50 | /// 51 | /// Performs a binary/interpolation search hybrid for in . 52 | /// 53 | /// The array to search. 54 | /// The item to search for. 55 | /// The lowest index to look at. 56 | /// The highest index to look at. 57 | /// A function that defines how to interpolate between values of type . 58 | /// An integer indicating the index of the largest element that is smaller than or equal to . 59 | public static int BinaryInterpolationSearch(T[] array, T item, int start, int end, Interpolation interpolate) 60 | { 61 | int half, s = 0; 62 | T low; 63 | while (end > start + 1) 64 | { 65 | if (s == 0) 66 | half = (end + start) / 2; 67 | else 68 | { 69 | low = array[start]; 70 | half = (int)((start + 1) + (end - start - 1) * interpolate(item, low, array[end])); 71 | } 72 | 73 | if (array[half].CompareTo(item) <= 0) 74 | start = half; 75 | else 76 | end = half; 77 | 78 | s = (s + 1) % 2; 79 | } 80 | 81 | if (start == 0 && item.CompareTo(array[start]) < 0) 82 | return -1; 83 | if (start == array.Length - 1 && item.CompareTo(array[start]) > 0) 84 | return array.Length; 85 | 86 | return start; 87 | } 88 | } 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /Code/Utility/Search/BinarySearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Search 8 | { 9 | /// 10 | /// Static class containing methods that search for items in sorted arrays. 11 | /// 12 | /// The type of value to search for. 13 | public static partial class Search 14 | where T : IComparable 15 | { 16 | /// 17 | /// Performs a binary search for in . 18 | /// 19 | /// The array to search. 20 | /// The item to search for. 21 | /// An integer indicating the index of the largest element that is smaller than or equal to . 22 | public static int BinarySearch(T[] array, T item) 23 | { 24 | return BinarySearch(array, item, -1, array.Length); 25 | } 26 | 27 | /// 28 | /// Performs a binary search for in between and . 29 | /// 30 | /// The array to search. 31 | /// The item to search for. 32 | /// The lowest index to look at. 33 | /// The highest index to look at. 34 | /// An integer indicating the index of the largest element that is smaller than or equal to . 35 | public static int BinarySearch(T[] array, T item, int start, int end) 36 | { 37 | int half; 38 | while (end > start + 1) 39 | { 40 | half = (end + start) / 2; 41 | if (array[half].CompareTo(item) <= 0) 42 | start = half; 43 | else 44 | end = half; 45 | } 46 | return start; 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Code/Utility/Search/GallopSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Search 8 | { 9 | public static partial class Search 10 | where T : IComparable 11 | { 12 | public static int GallopSearch(T[] array, T item) { return GallopSearchRight(array, item, 0, array.Length); } 13 | 14 | public static int GallopSearchRight(T[] array, T item, int start, int end) 15 | { 16 | int previous, off = 0; 17 | do 18 | { 19 | previous = start; 20 | off = 2 * off + 1; 21 | start += off; 22 | if (start >= end) 23 | { 24 | start = end; 25 | break; 26 | } 27 | } 28 | while (array[start].CompareTo(item) <= 0); 29 | 30 | return BinarySearch(array, item, previous, start); 31 | } 32 | 33 | public static int GallopSearchLeft(T[] array, T item, int start, int end) 34 | { 35 | int previous, off = 0; 36 | do 37 | { 38 | previous = end; 39 | off = 2 * off + 1; 40 | end -= off; 41 | if (end <= start) 42 | { 43 | end = start; 44 | break; 45 | } 46 | } 47 | while (array[end].CompareTo(item) > 0); 48 | 49 | return BinarySearch(array, item, end, previous); 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Code/Utility/Search/InterpolationSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Search 8 | { 9 | public static partial class Search 10 | where T : IComparable 11 | { 12 | /// 13 | /// Performs an interpolation search for in . 14 | /// 15 | /// The array to search. 16 | /// The item to search for. 17 | /// The class that defines how to interpolate between values of type . 18 | /// An integer indicating the index of the largest element that is smaller than or equal to . 19 | public static int InterpolationSearch(T[] array, T item, IInterpolator interpolator) 20 | { 21 | return InterpolationSearch(array, item, 0, array.Length - 1, interpolator.Interpolate); 22 | } 23 | 24 | /// 25 | /// Performs an interpolation search for in . 26 | /// 27 | /// The array to search. 28 | /// The item to search for. 29 | /// A function that defines how to interpolate between values of type . 30 | /// An integer indicating the index of the largest element that is smaller than or equal to . 31 | public static int InterpolationSearch(T[] array, T item, Interpolation interpolate) 32 | { 33 | return InterpolationSearch(array, item, 0, array.Length - 1, interpolate); 34 | } 35 | 36 | /// 37 | /// Performs an interpolation search for in . 38 | /// 39 | /// The array to search. 40 | /// The item to search for. 41 | /// The lowest index to look at. 42 | /// The highest index to look at. 43 | /// The class that defines how to interpolate between values of type . 44 | /// An integer indicating the index of the largest element that is smaller than or equal to . 45 | public static int InterpolationSearch(T[] array, T item, int start, int end, IInterpolator interpolator) 46 | { 47 | return InterpolationSearch(array, item, 0, array.Length - 1, interpolator.Interpolate); 48 | } 49 | 50 | /// 51 | /// Performs an interpolation search for in . 52 | /// 53 | /// The array to search. 54 | /// The item to search for. 55 | /// The lowest index to look at. 56 | /// The highest index to look at. 57 | /// A function that defines how to interpolate between values of type . 58 | /// An integer indicating the index of the largest element that is smaller than or equal to . 59 | public static int InterpolationSearch(T[] array, T item, int start, int end, Interpolation interpolate) 60 | { 61 | int guess; 62 | T low; 63 | while (end > start + 1) 64 | { 65 | low = array[start]; 66 | guess = (int)((start + 1) + (end - start - 1) * interpolate(item, low, array[end])); 67 | 68 | if (array[guess].CompareTo(item) <= 0) 69 | start = guess; 70 | else 71 | end = guess; 72 | } 73 | 74 | if (start == 0 && item.CompareTo(array[start]) < 0) 75 | return -1; 76 | if (start == array.Length - 1 && item.CompareTo(array[start]) > 0) 77 | return array.Length; 78 | 79 | return start; 80 | } 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /Code/Utility/Search/Interpolator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Search 8 | { 9 | /// 10 | /// Defines a function that gives the position of , interpolated between and . 11 | /// 12 | /// The type of value to interpolate. 13 | /// The item of which the position within the range of and is to be calculated. 14 | /// The lower bound of the interpolation. 15 | /// The upper bound of the interpolation. 16 | /// A value between 0 and 1, indicating the position of between and 17 | public delegate double Interpolation(T item, T lower, T upper); 18 | 19 | /// 20 | /// Represents a class that can be used to calculate the position of one value between two other values. 21 | /// 22 | /// The type of value to interpolate. 23 | public abstract class Interpolator : IInterpolator 24 | { 25 | private Interpolation interpolate; 26 | 27 | protected Interpolator() { } 28 | 29 | /// 30 | /// Creates an instance of Interpolator<T> with the specified interpolation method. 31 | /// 32 | /// The function to use for interpolation. 33 | /// An instance of Interpolator<T> with the specified interpolation method. 34 | public static Interpolator Create(Interpolation interpolation) 35 | { 36 | return new InterpolatorImplementation(interpolation); 37 | } 38 | 39 | /// 40 | /// Calculates the relative position of between and . 41 | /// 42 | /// The item of which the position within the range of and is to be calculated. 43 | /// The lower bound of the interpolation. 44 | /// The upper bound of the interpolation. 45 | /// 46 | public virtual double Interpolate(T item, T lower, T upper) 47 | { 48 | return interpolate(item, lower, upper); 49 | } 50 | 51 | private class InterpolatorImplementation : Interpolator 52 | { 53 | public InterpolatorImplementation(Interpolation interpolate) { base.interpolate = interpolate; } 54 | } 55 | } 56 | 57 | /// 58 | /// Defines an interface for classes that can perform interpolation. 59 | /// 60 | /// The type of value to interpolate. 61 | public interface IInterpolator 62 | { 63 | double Interpolate(T item, T lower, T upper); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Code/Utility/Search/RandomSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Search 8 | { 9 | public static partial class Search 10 | where T : IComparable 11 | { 12 | /// 13 | /// Performs a search for in by repeatedly looking at a random element between the upper and lower bound. 14 | /// 15 | /// The array to search. 16 | /// The item to search for. 17 | /// An integer indicating the index of the largest element that is smaller than or equal to . 18 | public static int RandomSearch(T[] array, T item) 19 | { 20 | return RandomSearch(array, item, -1, array.Length); 21 | } 22 | 23 | /// 24 | /// Performs a search for in between and by repeatedly looking at a random element between the upper and lower bound. 25 | /// 26 | /// The array to search. 27 | /// The item to search for. 28 | /// The lowest index to look at. 29 | /// The highest index to look at. 30 | /// An integer indicating the index of the largest element that is smaller than or equal to . 31 | public static int RandomSearch(T[] array, T item, int start, int end) 32 | { 33 | Random r = new Random(); 34 | int random; 35 | while (end > start + 1) 36 | { 37 | random = start + 1 + r.Next(end - start - 1); 38 | if (array[random].CompareTo(item) <= 0) 39 | start = random; 40 | else 41 | end = random; 42 | } 43 | return start; 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/BinaryInsertionSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] BinaryInsertionSort(T[] input) { return BinaryInsertionSort(input, 0, input.Length); } 13 | 14 | public static T[] BinaryInsertionSort(T[] input, int start) { return BinaryInsertionSort(input, start, input.Length - start); } 15 | 16 | public static T[] BinaryInsertionSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | T current; 21 | int upper, lower, half = 0; 22 | 23 | if (length <= 1) 24 | return input; 25 | 26 | if (length > 1 && input[start].CompareTo(input[start + 1]) > 0) 27 | { 28 | current = input[start]; 29 | input[start] = input[start + 1]; 30 | input[start + 1] = current; 31 | } 32 | 33 | for (int i = start + 2; i < start + length; i++) 34 | { 35 | current = input[i]; 36 | upper = i; 37 | lower = start - 1; 38 | while (upper > lower + 1) 39 | { 40 | half = (upper + lower) / 2; 41 | if (input[half].CompareTo(current) <= 0) 42 | lower = half; 43 | else 44 | upper = half; 45 | } 46 | 47 | Buffer.BlockCopy(input, (lower + 1) * sizeof(int), input, (lower + 2) * sizeof(int), (i - lower - 1) * sizeof(int)); 48 | input[lower + 1] = current; 49 | } 50 | 51 | return input; 52 | } 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/BubbleSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] BubbleSort(T[] input) { return BubbleSort(input, 0, input.Length); } 13 | 14 | public static T[] BubbleSort(T[] input, int start) { return BubbleSort(input, start, input.Length - start); } 15 | 16 | public static T[] BubbleSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | T temp; 21 | int newEnd, end; 22 | 23 | while (length > 1) 24 | { 25 | newEnd = 0; 26 | end = start + length - 1; 27 | for (int i = start; i < end; i++) 28 | { 29 | if (input[i].CompareTo(input[i + 1]) > 0) 30 | { 31 | temp = input[i]; 32 | input[i] = input[i + 1]; 33 | input[i + 1] = temp; 34 | newEnd = i; 35 | } 36 | } 37 | length = newEnd - start + 1; 38 | } 39 | 40 | return input; 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/CocktailSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] CocktailSort(T[] input) { return CocktailSort(input, 0, input.Length); } 13 | 14 | public static T[] CocktailSort(T[] input, int start) { return CocktailSort(input, start, input.Length - start); } 15 | 16 | public static T[] CocktailSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | T temp; 21 | int newLength, i = start, j = start + length - 1; 22 | 23 | while (length > 1) 24 | { 25 | newLength = 0; 26 | for (int k = i; k < j; k++) 27 | { 28 | if (input[k].CompareTo(input[k + 1]) > 0) 29 | { 30 | temp = input[k]; 31 | input[k] = input[k + 1]; 32 | input[k + 1] = temp; 33 | newLength = k - i; 34 | } 35 | } 36 | length = newLength; 37 | if (length == 1) 38 | break; 39 | j = i + length; 40 | for (int l = j; l > 0; l--) 41 | { 42 | if (input[l].CompareTo(input[l - 1]) < 0) 43 | { 44 | temp = input[l]; 45 | input[l] = input[l - 1]; 46 | input[l - 1] = temp; 47 | newLength = j - l - 1; 48 | } 49 | } 50 | length = newLength; 51 | i = j - length; 52 | } 53 | 54 | return input; 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/CombInsertionSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] CombInsertionSort(T[] input) { return CombInsertionSort(input, 0, input.Length); } 13 | 14 | public static T[] CombInsertionSort(T[] input, int start) { return CombInsertionSort(input, start, input.Length - start); } 15 | 16 | public static T[] CombInsertionSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | int gap = length; 21 | T temp; 22 | 23 | while (gap > 1) 24 | { 25 | gap = Math.Max(1, (int)(gap / 1.3f)); 26 | 27 | for (int i = start; i < start + length - gap; i++) 28 | { 29 | if (input[i].CompareTo(input[i + gap]) > 0) 30 | { 31 | temp = input[i]; 32 | input[i] = input[i + gap]; 33 | input[i + gap] = temp; 34 | } 35 | } 36 | } 37 | 38 | return InsertionSort(input, start, length); 39 | } 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/CombSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] CombSort(T[] input) { return CombSort(input, 0, input.Length); } 13 | 14 | public static T[] CombSort(T[] input, int start) { return CombSort(input, start, input.Length - start); } 15 | 16 | public static T[] CombSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | int gap = length; 21 | T temp; 22 | 23 | while (gap > 1) 24 | { 25 | gap = Math.Max(1, (int)(gap / 1.3f)); 26 | 27 | for (int i = start; i < start + length - gap; i++) 28 | { 29 | if (input[i].CompareTo(input[i + gap]) > 0) 30 | { 31 | temp = input[i]; 32 | input[i] = input[i + gap]; 33 | input[i + gap] = temp; 34 | } 35 | } 36 | } 37 | 38 | return BubbleSort(input, start, length); 39 | } 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/CycleSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] CycleSort(T[] input) { return CycleSort(input, 0, input.Length); } 13 | 14 | public static T[] CycleSort(T[] input, int start) { return CycleSort(input, start, input.Length - start); } 15 | 16 | public static T[] CycleSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | T item, temp; 21 | int pos, end = start + length; 22 | 23 | for (int i = start; i < start + length - 1; i++) 24 | { 25 | item = input[i]; 26 | pos = i; 27 | 28 | for (int j = i + 1; j < end; j++) 29 | if (input[j].CompareTo(item) < 0) 30 | pos++; 31 | 32 | if (pos == i) 33 | continue; 34 | 35 | while (item.CompareTo(input[pos]) == 0) 36 | pos++; 37 | 38 | temp = input[pos]; 39 | input[pos] = item; 40 | item = temp; 41 | 42 | while (pos != i) 43 | { 44 | pos = i; 45 | for (int j = i + 1; j < end; j++) 46 | if (input[j].CompareTo(item) < 0) 47 | pos++; 48 | 49 | while (item.CompareTo(input[pos]) == 0) 50 | pos++; 51 | 52 | temp = input[pos]; 53 | input[pos] = item; 54 | item = temp; 55 | } 56 | } 57 | 58 | return input; 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/GnomeSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] GnomeSort(T[] input) { return GnomeSort(input, 0, input.Length); } 13 | 14 | public static T[] GnomeSort(T[] input, int start) { return GnomeSort(input, start, input.Length - start); } 15 | 16 | public static T[] GnomeSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | int position = start + 1, previous = start; 21 | T temp; 22 | 23 | while (position < start + length) 24 | { 25 | if (input[position].CompareTo(input[position - 1]) >= 0) 26 | { 27 | if (previous != 0) 28 | { 29 | position = previous; 30 | previous = 0; 31 | } 32 | position++; 33 | } 34 | else 35 | { 36 | temp = input[position]; 37 | input[position] = input[position - 1]; 38 | input[position - 1] = temp; 39 | if (position > 1) 40 | { 41 | if (previous == 0) 42 | previous = position; 43 | position--; 44 | } 45 | else 46 | position++; 47 | } 48 | } 49 | 50 | return input; 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/HeapSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] Heapsort(T[] input) { return Heapsort(input, 0, input.Length); } 13 | 14 | public static T[] Heapsort(T[] input, int start) { return Heapsort(input, start, input.Length - start); } 15 | 16 | public static T[] Heapsort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | int startHeapify = start + (length - 2) / 5; 21 | 22 | for (; startHeapify >= start; startHeapify--) 23 | PushDown(input, start + length, startHeapify); 24 | 25 | while (length > 0) 26 | { 27 | Switch(input, 0, --length); 28 | PushDown(input, length, 0); 29 | } 30 | return input; 31 | } 32 | 33 | private static void PushDown(T[] heap, int end, int root) 34 | { 35 | int l, c1, c2, c3, c4, s; 36 | while ((l = Left(root, end)) != -1) 37 | { 38 | c1 = l + 1; 39 | c2 = l + 2; 40 | c3 = l + 3; 41 | c4 = l + 4; 42 | s = root; 43 | if (heap[s].CompareTo(heap[l]) < 0) 44 | s = l; 45 | if (c1 < end && heap[s].CompareTo(heap[c1]) < 0) 46 | s = c1; 47 | if (c2 < end && heap[s].CompareTo(heap[c2]) < 0) 48 | s = c2; 49 | if (c3 < end && heap[s].CompareTo(heap[c3]) < 0) 50 | s = c3; 51 | if (c4 < end && heap[s].CompareTo(heap[c4]) < 0) 52 | s = c4; 53 | if (s != root) 54 | { 55 | Switch(heap, s, root); 56 | root = s; 57 | } 58 | else 59 | return; 60 | } 61 | } 62 | 63 | private static int Left(int node, int end) 64 | { 65 | int l = node * 5 + 1; 66 | if (l < end) 67 | return l; 68 | return -1; 69 | } 70 | 71 | private static void Switch(T[] heap, int i1, int i2) 72 | { 73 | T temp = heap[i1]; 74 | heap[i1] = heap[i2]; 75 | heap[i2] = temp; 76 | } 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/InsertionSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] InsertionSort(T[] input) { return InsertionSort(input, 0, input.Length); } 13 | 14 | public static T[] InsertionSort(T[] input, int start) { return InsertionSort(input, start, input.Length - start); } 15 | 16 | public static T[] InsertionSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | T current; 21 | int j; 22 | for (int i = start + 1; i < start + length; i++) 23 | { 24 | current = input[i]; 25 | for (j = i; j > start; j--) 26 | { 27 | if (input[j - 1].CompareTo(current) <= 0) 28 | break; 29 | } 30 | Buffer.BlockCopy(input, j * sizeof(int), input, (j + 1) * sizeof(int), (i - j) * sizeof(int)); 31 | input[j] = current; 32 | } 33 | return input; 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/JSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] JSort(T[] input) { return JSort(input, 0, input.Length); } 13 | 14 | public static T[] JSort(T[] input, int start) { return JSort(input, start, input.Length - start); } 15 | 16 | public static T[] JSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | int l, r, s, end = start + length, startHeapify = (end - 2) / 2, root; 21 | T temp; 22 | for (; startHeapify >= start; startHeapify--) 23 | { 24 | root = startHeapify; 25 | while ((l = (root + 1) * 2 - 1) < end) 26 | { 27 | r = l + 1; 28 | s = root; 29 | if (input[s].CompareTo(input[l]) > 0) 30 | s = l; 31 | if (r < end && input[s].CompareTo(input[r]) > 0) 32 | s = r; 33 | if (s != root) 34 | { 35 | temp = input[s]; 36 | input[s] = input[root]; 37 | input[root] = temp; 38 | root = s; 39 | } 40 | else 41 | break; 42 | } 43 | } 44 | 45 | startHeapify = end - (end - 2) / 2 - 1; 46 | for (; startHeapify < end; startHeapify++) 47 | { 48 | root = startHeapify; 49 | while ((l = end - (end - root - 1) * 2 - 2) >= 0) 50 | { 51 | r = l - 1; 52 | s = root; 53 | if (input[s].CompareTo(input[l]) < 0) 54 | s = l; 55 | if (r >= 0 && input[s].CompareTo(input[r]) < 0) 56 | s = r; 57 | if (s != root) 58 | { 59 | temp = input[s]; 60 | input[s] = input[root]; 61 | input[root] = temp; 62 | root = s; 63 | } 64 | else 65 | break; 66 | } 67 | } 68 | 69 | return BinaryInsertionSort(input, start, length); 70 | } 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/MergeSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] MergeSort(T[] input) { return MergeSort(input, 0, input.Length); } 13 | 14 | public static T[] MergeSort(T[] input, int start) { return MergeSort(input, start, input.Length - start); } 15 | 16 | public static T[] MergeSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | T[] temp, output = new T[input.Length]; 21 | int p1, p2, pLeft, pRight, pEnd, end = start + length; 22 | for (int i = start + 1; i < end; i *= 2) 23 | { 24 | for (int j = start; j < end; j += 2 * i) 25 | { 26 | pLeft = p1 = j; 27 | pRight = p2 = Math.Min(i + j, end); 28 | pEnd = Math.Min(2 * i + j, end); 29 | 30 | for (int k = p1; k < pEnd; k++) 31 | { 32 | if (p1 < pRight && (p2 >= pEnd || input[p1].CompareTo(input[p2]) < 0)) 33 | output[k] = input[p1++]; 34 | else 35 | output[k] = input[p2++]; 36 | } 37 | } 38 | 39 | temp = input; 40 | input = output; 41 | output = temp; 42 | } 43 | return input; 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/OddEvenSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] OddEvenSort(T[] input) { return OddEvenSort(input, 0, input.Length); } 13 | 14 | public static T[] OddEvenSort(T[] input, int start) { return OddEvenSort(input, start, input.Length - start); } 15 | 16 | public static T[] OddEvenSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | bool swapped = true; 21 | T temp; 22 | 23 | while (swapped) 24 | { 25 | swapped = false; 26 | for (int i = start + 1; i < start + length - 1; i += 2) 27 | { 28 | if (input[i].CompareTo(input[i + 1]) > 0) 29 | { 30 | swapped = true; 31 | temp = input[i]; 32 | input[i] = input[i + 1]; 33 | input[i + 1] = temp; 34 | } 35 | } 36 | 37 | for (int i = start; i < start + length - 1; i += 2) 38 | { 39 | if (input[i].CompareTo(input[i + 1]) > 0) 40 | { 41 | swapped = true; 42 | temp = input[i]; 43 | input[i] = input[i + 1]; 44 | input[i + 1] = temp; 45 | } 46 | } 47 | } 48 | 49 | return input; 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/PatienceSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Utility.DataStructures.PriorityQueue; 4 | 5 | namespace Utility 6 | { 7 | namespace Algorithms 8 | { 9 | namespace Sort 10 | { 11 | public static partial class Sort 12 | where T : IComparable 13 | { 14 | public static T[] PatienceSort(T[] input) { return PatienceSort(input, 0, input.Length); } 15 | 16 | public static T[] PatienceSort(T[] input, int start) { return PatienceSort(input, start, input.Length - start); } 17 | 18 | public static T[] PatienceSort(T[] input, int start, int length) 19 | { 20 | CheckArguments(input, start, length); 21 | 22 | List> stacks = new List>(); 23 | 24 | for (int i = start; i < start + length; i++) 25 | { 26 | Stack stack = new Stack(); 27 | stack.Push(input[i]); 28 | int index = stacks.BinarySearch(stack); 29 | if (index < 0) 30 | index = ~index; 31 | if (index != stacks.Count) 32 | stacks[index].Push(input[i]); 33 | else 34 | stacks.Add(stack); 35 | } 36 | 37 | DMinHeap> heap = new DMinHeap>(3); 38 | foreach (Stack s in stacks) 39 | heap.Add(s, s.Peek()); 40 | 41 | for (int i = start; i < start + length; i++) 42 | { 43 | Stack stack = heap.Extract(); 44 | input[i] = stack.Pop(); 45 | if (stack.Count != 0) 46 | heap.Add(stack, stack.Peek()); 47 | } 48 | 49 | return input; 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/Quicksort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] Quicksort(T[] input) { return Quicksort(input, 0, input.Length); } 13 | 14 | public static T[] Quicksort(T[] input, int start) { return Quicksort(input, start, input.Length - start); } 15 | 16 | public static T[] Quicksort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | Quicksort(input, start, start + length - 1, new Random()); 21 | return input; 22 | } 23 | 24 | private static void Quicksort(T[] input, int start, int end, Random random) 25 | { 26 | if (end - start < 20) 27 | { 28 | T current; 29 | int j; 30 | for (int i = start + 1; i <= end; i++) 31 | { 32 | current = input[i]; 33 | for (j = i; j > start; j--) 34 | { 35 | if (input[j - 1].CompareTo(current) <= 0) 36 | break; 37 | } 38 | Buffer.BlockCopy(input, j * sizeof(int), input, (j + 1) * sizeof(int), (i - j) * sizeof(int)); 39 | input[j] = current; 40 | } 41 | return; 42 | } 43 | 44 | int l = start + 1, g = end - 1; 45 | T temp, p1, p2; 46 | 47 | int _p1 = 0, _p2 = 0; 48 | while (_p1 == _p2) 49 | { 50 | _p1 = random.Next(start, end + 1); 51 | _p2 = random.Next(start, end + 1); 52 | } 53 | 54 | p1 = input[_p1]; 55 | p2 = input[_p2]; 56 | 57 | if (p1.CompareTo(p2) > 0) 58 | { 59 | temp = p1; 60 | p1 = p2; 61 | p2 = temp; 62 | } 63 | 64 | input[_p1] = input[start]; 65 | input[start] = p1; 66 | 67 | if (start == _p2) 68 | _p2 = _p1; 69 | 70 | input[_p2] = input[end]; 71 | input[end] = p2; 72 | 73 | bool pivotValueEqual = input[start].CompareTo(input[end]) == 0; 74 | 75 | for (int i = l; i <= g; i++) 76 | { 77 | temp = input[i]; 78 | if (temp.CompareTo(p1) < 0) 79 | { 80 | input[i] = input[l]; 81 | input[l++] = temp; 82 | } 83 | else if (temp.CompareTo(p2) > 0) 84 | { 85 | while (input[g].CompareTo(p2) > 0 && i < g) 86 | g--; 87 | input[i] = input[g]; 88 | input[g--] = temp; 89 | i--; 90 | } 91 | } 92 | 93 | input[start] = input[l - 1]; 94 | input[l - 1] = p1; 95 | 96 | input[end] = input[g + 1]; 97 | input[g + 1] = p2; 98 | 99 | Quicksort(input, start, l - 2, random); 100 | Quicksort(input, g + 2, end, random); 101 | if (!pivotValueEqual) 102 | Quicksort(input, l, g, random); 103 | } 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/SelectionSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | public static T[] SelectionSort(T[] input) { return SelectionSort(input, 0, input.Length); } 13 | 14 | public static T[] SelectionSort(T[] input, int start) { return SelectionSort(input, start, input.Length - start); } 15 | 16 | public static T[] SelectionSort(T[] input, int start, int length) 17 | { 18 | CheckArguments(input, start, length); 19 | 20 | int p, q; 21 | T temp1, temp2; 22 | bool odd = length % 2 == 1; 23 | 24 | for (int i = start; i < start + length - 1; i += 2) 25 | { 26 | p = i; 27 | q = i + 1; 28 | if (input[q].CompareTo(input[p]) < 0) 29 | { 30 | p = i + 1; 31 | q = i; 32 | } 33 | for (int j = i + 2; j < start + length - 1; j += 2) 34 | { 35 | if (input[j].CompareTo(input[j + 1]) > 0) 36 | { 37 | temp1 = input[j]; 38 | input[j] = input[j + 1]; 39 | input[j + 1] = temp1; 40 | } 41 | if (input[j].CompareTo(input[p]) < 0) 42 | { 43 | if (input[j + 1].CompareTo(input[p]) < 0) 44 | q = j + 1; 45 | else 46 | q = p; 47 | p = j; 48 | } 49 | else if (input[j].CompareTo(input[q]) < 0) 50 | q = j; 51 | } 52 | 53 | if (odd) 54 | { 55 | if (input[start + length - 1].CompareTo(input[p]) < 0) 56 | { 57 | q = p; 58 | p = input.Length - 1; 59 | } 60 | else if (input[start + length - 1].CompareTo(input[q]) < 0) 61 | q = input.Length - 1; 62 | } 63 | 64 | temp1 = input[p]; 65 | temp2 = input[q]; 66 | 67 | if (i == q) 68 | q = p; 69 | 70 | input[p] = input[i]; 71 | input[i] = temp1; 72 | 73 | input[q] = input[i + 1]; 74 | input[i + 1] = temp2; 75 | } 76 | 77 | return input; 78 | } 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/ShellSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Sort 9 | { 10 | public static partial class Sort 11 | where T : IComparable 12 | { 13 | public static T[] ShellSort(T[] input) { return ShellSort(input, 0, input.Length); } 14 | 15 | public static T[] ShellSort(T[] input, int start) { return ShellSort(input, start, input.Length - start); } 16 | 17 | public static T[] ShellSort(T[] input, int start, int length) 18 | { 19 | CheckArguments(input, start, length); 20 | 21 | int gap = 1, k; 22 | T current; 23 | List gaps = new List(); 24 | 25 | while (gap < length) 26 | { 27 | gaps.Add(gap); 28 | gap = (int)Math.Ceiling(2.25 * gaps[gaps.Count - 1]); 29 | } 30 | 31 | for (int i = gaps.Count - 1; i >= 0; i--) 32 | { 33 | gap = gaps[i]; 34 | for (int j = gap; j < start + length; j++) 35 | { 36 | current = input[j]; 37 | for (k = j; k >= gap; k -= gap) 38 | { 39 | if (input[k - gap].CompareTo(current) > 0) 40 | input[k] = input[k - gap]; 41 | else 42 | break; 43 | } 44 | input[k] = current; 45 | } 46 | } 47 | 48 | return input; 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/Sort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Utility 4 | { 5 | namespace Algorithms 6 | { 7 | namespace Sort 8 | { 9 | public static partial class Sort 10 | where T : IComparable 11 | { 12 | private static void CheckArguments(T[] input, int start, int length) 13 | { 14 | if (input == null) 15 | throw new ArgumentNullException("input"); 16 | if (start < 0 || start >= input.Length) 17 | throw new ArgumentOutOfRangeException("start", start, "The start argument must be non-negative and smaller than the length of the array."); 18 | if (length < 0 || start + length > input.Length) 19 | throw new ArgumentOutOfRangeException("length", length, "The length argument must be non-negative and the number of elements in the input array from start must be at least equal to length."); 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/StrandSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Sort 9 | { 10 | public static partial class Sort 11 | where T : IComparable 12 | { 13 | public static T[] StrandSort(T[] input) { return StrandSort(input, 0, input.Length); } 14 | 15 | public static T[] StrandSort(T[] input, int start) { return StrandSort(input, start, input.Length - start); } 16 | 17 | public static T[] StrandSort(T[] input, int start, int length) 18 | { 19 | CheckArguments(input, start, length); 20 | 21 | List sublist = new List(); 22 | int i = start; 23 | while (i < start + length - 1 && input[i].CompareTo(input[i + 1]) < 0) 24 | i++; 25 | int j = i + 1; 26 | while (i < start + length - 1) 27 | { 28 | if (j < start + length && (sublist.Count == 0 || input[j].CompareTo(sublist[sublist.Count - 1]) > 0)) 29 | sublist.Add(input[j++]); 30 | else 31 | { 32 | int k = i, l = sublist.Count; 33 | while (sublist.Count > 0) 34 | { 35 | if (k < 0 || input[k].CompareTo(sublist[sublist.Count - 1]) < 0) 36 | { 37 | input[k + sublist.Count] = sublist[sublist.Count - 1]; 38 | sublist.RemoveAt(sublist.Count - 1); 39 | } 40 | else 41 | { 42 | input[k + sublist.Count] = input[k]; 43 | k--; 44 | } 45 | } 46 | sublist.Clear(); 47 | i += l; 48 | } 49 | } 50 | return input; 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Code/Utility/Sort/TreeSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Utility.DataStructures.BinarySearchTree; 3 | 4 | namespace Utility 5 | { 6 | namespace Algorithms 7 | { 8 | namespace Sort 9 | { 10 | public static partial class Sort 11 | where T : IComparable 12 | { 13 | public static T[] TreeSort(T[] input) { return TreeSort(input, 0, input.Length); } 14 | 15 | public static T[] TreeSort(T[] input, int start) { return TreeSort(input, start, input.Length - start); } 16 | 17 | public static T[] TreeSort(T[] input, int start, int length) 18 | { 19 | CheckArguments(input, start, length); 20 | 21 | T[] data = new T[length]; 22 | Buffer.BlockCopy(input, start * sizeof(int), data, 0, length * sizeof(int)); 23 | 24 | AVLTree tree = new AVLTree(data); 25 | tree.CopyTo(input, start); 26 | return input; 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Code/Utility/Trees/Trie.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections; 4 | 5 | namespace Utility 6 | { 7 | namespace DataStructures 8 | { 9 | namespace Trees 10 | { 11 | public class Trie : ICollection 12 | { 13 | public delegate TKey[] Split(TIn item); 14 | public delegate TIn Join(TKey[] keys); 15 | public delegate int Index(TKey key); 16 | 17 | private Split SplitFunction; 18 | private Join JoinFunction; 19 | private Index IndexFunction; 20 | private TKey[] keys; 21 | 22 | private TrieNode root; 23 | 24 | public Trie(TKey[] keys, Split split, Join join, Index index) 25 | { 26 | this.root = new TrieNode(null, keys.Length); 27 | this.keys = keys; 28 | this.SplitFunction = split; 29 | this.JoinFunction = join; 30 | this.IndexFunction = index; 31 | } 32 | 33 | public void Add(TIn item) 34 | { 35 | TKey[] keys = this.SplitFunction(item); 36 | 37 | TrieNode current = this.root; 38 | foreach (TKey key in keys) 39 | { 40 | int index = this.IndexFunction(key); 41 | if (current[index] == null) 42 | current[index] = new TrieNode(current, this.keys.Length); 43 | current = current[index]; 44 | } 45 | current.Count++; 46 | this.Count++; 47 | } 48 | 49 | public void AddRange(IEnumerable collection) 50 | { 51 | if (collection == null) 52 | throw new ArgumentNullException("collection"); 53 | 54 | foreach (TIn t in collection) 55 | this.Add(t); 56 | } 57 | 58 | public bool Remove(TIn item) 59 | { 60 | TKey[] keys = this.SplitFunction(item); 61 | TrieNode node = this.Find(keys); 62 | if (node == null) 63 | return false; 64 | 65 | if (node.Count > 1) 66 | node.Count--; 67 | else 68 | { 69 | if (node.NumberOfChildren > 0) 70 | node.Count--; 71 | else 72 | { 73 | int index = this.IndexFunction(keys[0]); 74 | for (int i = keys.Length - 1; i >= 0; i--) 75 | { 76 | index = this.IndexFunction(keys[i]); 77 | node = node.Parent; 78 | 79 | if (node.Count > 0 || node.NumberOfChildren > 1) 80 | break; 81 | } 82 | node[index] = null; 83 | } 84 | } 85 | 86 | this.Count--; 87 | return true; 88 | } 89 | 90 | public bool Contains(TIn item) { return this.Find(this.SplitFunction(item)) != null; } 91 | 92 | public TIn LongestPrefixMatch(TIn item) 93 | { 94 | TKey[] keys = this.SplitFunction(item); 95 | TrieNode current = this.root; 96 | List currentValue = new List(); 97 | TKey[] value = new TKey[0]; 98 | foreach (TKey key in keys) 99 | { 100 | int index = this.IndexFunction(key); 101 | if (current[index] == null) 102 | break; 103 | current = current[index]; 104 | currentValue.Add(this.keys[index]); 105 | if (current.Count > 0) 106 | value = currentValue.ToArray(); 107 | } 108 | 109 | return this.JoinFunction(value); 110 | } 111 | 112 | public void Clear() { this.root = new TrieNode(null, keys.Length); this.Count = 0; } 113 | 114 | public void CopyTo(TIn[] array, int arrayIndex) 115 | { 116 | if (array == null) 117 | throw new ArgumentNullException("array"); 118 | if (arrayIndex < 0) 119 | throw new ArgumentOutOfRangeException("arrayIndex"); 120 | if (array.Length - arrayIndex < this.Count) 121 | throw new ArgumentException("The number of elements in the Trie is greater than the available space from arrayIndex to the end of the destination array."); 122 | 123 | foreach (TIn t in this) 124 | array[arrayIndex++] = t; 125 | } 126 | 127 | public int Count { get; private set; } 128 | 129 | public bool IsReadOnly { get { return false; } } 130 | 131 | IEnumerator IEnumerable.GetEnumerator() { return new TrieEnumerator(this); } 132 | 133 | IEnumerator IEnumerable.GetEnumerator() { return new TrieEnumerator(this); } 134 | 135 | private TrieNode Find(TKey[] keys) 136 | { 137 | TrieNode current = this.root; 138 | foreach (TKey key in keys) 139 | { 140 | int index = this.IndexFunction(key); 141 | if (current[index] == null) 142 | return null; 143 | current = current[index]; 144 | } 145 | 146 | if (current.Count == 0) 147 | return null; 148 | 149 | return current; 150 | } 151 | 152 | private class TrieNode 153 | { 154 | private TrieNode[] children; 155 | 156 | public TrieNode(TrieNode parent, int keyCount) 157 | { 158 | this.children = new TrieNode[keyCount]; 159 | this.Parent = parent; 160 | this.Count = 0; 161 | } 162 | 163 | public TrieNode this[int index] 164 | { 165 | get { return this.children[index]; } 166 | set 167 | { 168 | if (this.children[index] == null) 169 | this.NumberOfChildren++; 170 | else if (value == null) 171 | this.NumberOfChildren--; 172 | this.children[index] = value; 173 | } 174 | } 175 | 176 | public TrieNode Parent { get; set; } 177 | 178 | public uint Count { get; set; } 179 | 180 | public uint NumberOfChildren { get; set; } 181 | } 182 | 183 | private class TrieEnumerator : IEnumerator 184 | { 185 | private Trie trie; 186 | private TrieNode currentNode; 187 | private int currentCount = 0, currentIndex = 0; 188 | private List currentValue = new List(); 189 | private Stack stack = new Stack(); 190 | 191 | public TrieEnumerator(Trie trie) 192 | { 193 | this.trie = trie; 194 | this.currentNode = this.trie.root; 195 | this.stack.Push(0); 196 | } 197 | 198 | public virtual bool MoveNext() 199 | { 200 | if (this.currentNode.Count > this.currentCount) 201 | { 202 | this.currentCount++; 203 | return true; 204 | } 205 | 206 | this.currentCount = 0; 207 | while (this.stack.Count > 0) 208 | { 209 | bool hasChild = false; 210 | for (int i = this.currentIndex; i < this.trie.keys.Length; i++) 211 | if (this.currentNode[i] != null) 212 | { 213 | hasChild = true; 214 | this.currentNode = this.currentNode[i]; 215 | this.stack.Push(i); 216 | this.currentIndex = 0; 217 | this.currentValue.Add(this.trie.keys[i]); 218 | 219 | if (this.currentNode.Count > 0) 220 | { 221 | this.currentCount = 1; 222 | return true; 223 | } 224 | else 225 | break; 226 | } 227 | 228 | if (!hasChild) 229 | { 230 | if (currentNode.Parent == null) 231 | return false; 232 | 233 | this.currentNode = this.currentNode.Parent; 234 | this.currentValue.RemoveAt(this.currentValue.Count - 1); 235 | this.currentIndex = this.stack.Pop() + 1; 236 | } 237 | } 238 | 239 | return false; 240 | } 241 | 242 | public void Reset() 243 | { 244 | this.stack.Clear(); 245 | this.stack.Push(0); 246 | this.currentNode = this.trie.root; 247 | this.currentValue.Clear(); 248 | this.currentIndex = 0; 249 | this.currentCount = 0; 250 | } 251 | 252 | void IDisposable.Dispose() { } 253 | 254 | public TIn Current { get { return this.trie.JoinFunction(currentValue.ToArray()); } } 255 | 256 | object IEnumerator.Current { get { return this.trie.JoinFunction(currentValue.ToArray()); } } 257 | } 258 | } 259 | } 260 | } 261 | } -------------------------------------------------------------------------------- /Code/Utility/Utility.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {78046F90-E5D0-4E41-AA1B-3D5265B53256} 9 | Library 10 | Properties 11 | Utility 12 | Utility 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | true 35 | bin\x64\Debug\ 36 | DEBUG;TRACE 37 | full 38 | x64 39 | bin\Debug\Utility.dll.CodeAnalysisLog.xml 40 | true 41 | GlobalSuppressions.cs 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\\Rule Sets 45 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\FxCop\\Rules 46 | 47 | 48 | bin\x64\Release\ 49 | TRACE 50 | true 51 | pdbonly 52 | x64 53 | bin\Release\Utility.dll.CodeAnalysisLog.xml 54 | true 55 | GlobalSuppressions.cs 56 | prompt 57 | MinimumRecommendedRules.ruleset 58 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\\Rule Sets 59 | false 60 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\FxCop\\Rules 61 | false 62 | false 63 | 64 | 65 | true 66 | bin\x86\Debug\ 67 | DEBUG;TRACE 68 | full 69 | x86 70 | bin\Debug\Utility.dll.CodeAnalysisLog.xml 71 | true 72 | GlobalSuppressions.cs 73 | prompt 74 | MinimumRecommendedRules.ruleset 75 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\\Rule Sets 76 | false 77 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\FxCop\\Rules 78 | false 79 | 80 | 81 | bin\x86\Release\ 82 | TRACE 83 | true 84 | pdbonly 85 | x86 86 | bin\Release\Utility.dll.CodeAnalysisLog.xml 87 | true 88 | GlobalSuppressions.cs 89 | prompt 90 | MinimumRecommendedRules.ruleset 91 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\\Rule Sets 92 | false 93 | ;D:\Microsoft Visual Studio 2010\Team Tools\Static Analysis Tools\FxCop\\Rules 94 | false 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 172 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A collection of various algorithms and data structures made in C# 2 | 3 | Currently has: 4 | 5 | --- 6 | 7 | # ALGORITHMS 8 | 9 | ## Computational geometry 10 | - Convex hull — uses Graham's scan to find the smallest polygon that contains all the points in a set 11 | 12 | ## Graphs 13 | - Minimum cut — calculates the lightest set of edges that would divide the graph in two components should they be removed 14 | - Minimum spanning tree — calculates the lightest tree that connects all the node in the graph using Kruskal's algorithm 15 | - Maximum flow — calculates the maximum amount of flow that can move from the source to the sink 16 | - Shortest path — find the shortest path between to nodes in a graph using Dijkstra's algorithm for weighted graphs and a simple breadth-first search for unweigthed graphs 17 | 18 | ## Searching 19 | - Binary-Interpolation search — alternating passes of binary search and interpolation search 20 | - Binary search — find an item by repeatedly halving the range it could be in 21 | - Gallop search — search that favours finding elements close to the start of the search, looks for exponentially increasing ranges and then performs binary search on the range that contains the item 22 | - Interpolation search — find an item by interpolation between the upper and lower bound of the search, giving O(log log n) search time for evenly distributed arrays 23 | - Random search — find an item by repeatedly splitting the range it could be in at a random point 24 | 25 | ## Sorting 26 | - Binary insertion sort — performs a binary search on the sorted part to determine where to place the next element 27 | - Bubble sort — optimised by keeping track of the place of the last swap, everything after that is sorted 28 | - Cocktail sort — one pass of Bubble sort left-to-right, followed by a pass right-to-left 29 | - Comb sort — repeated Bubble sort with decreasing gaps, calls to Bubble sort when the gap reaches 1 for final sorting 30 | - Comb-Insertion sort — same as Comb sort, but calls to Insertion sort for final sorting 31 | - Cycle sort — achieves the theoretical minimum number of writes to the original array 32 | - Gnome sort — optimised by making the gnome remember his position before walking back 33 | - Heapsort — using a binary heap with Floyd's method for constructing a heap in O(n) time 34 | - Insertion sort — no fancy stuff here, just plain old Insertion sort 35 | - JSort — builds a min-heap from the lowest index followed by a max-heap from the highest index, then sorts completely with Insertion sort 36 | - Merge sort — bottom-up merging, requires only one extra array of length n 37 | - Odd-Even sort — swap odd-even pairs when out of order, then swap even-odd pairs 38 | - Patience sort — build stacks with elements in order, then repeatedly extract the value of the stack with the smallest top 39 | - Quicksort — dual-pivot randomized quicksort as proposed by Vladimir Yaroslavskiy 40 | - Selection sort — uses an optimisation that finds the two smallest elements in 3n/2 - 2 comparisons 41 | - Shellsort — repeated Insertion sort over decreasing gaps, using the gap sequence h(n) = ⌈2.25 * h(n - 1)⌉, with h(0) = 1 42 | - Strand sort — looks for sequences of input that are already sorted and merges them with the sorted part of the array 43 | - Timsort — highly adaptive merge sort, builds runs out of data already in order and merges those 44 | - Tree sort — uses an AVL Tree, adds all elements and retrieves them in order 45 | 46 | --- 47 | 48 | # DATASTRUCTURES 49 | 50 | ## Binary search tree 51 | - AVL tree — height-balanced tree with worst-case O(log n) operations 52 | - Binary search tree — base class for all other BSTs, no balancing, implemented as ICollection<T> and IDictionary<TKey, TValue> 53 | - Red-black tree — height-balanced tree with worst-case O(log n) operations 54 | - Scapegoat tree — weight-balanced tree with O(log n) lookup, amortized O(log n) insertion and deletion 55 | - Splay tree — height-balanced tree with amortized O(log n) operations 56 | 57 | ## Disjoint-set 58 | - Union Find — implements union by rank and path compression 59 | 60 | ## Priority queue 61 | - d-ary heap — generalisation of a binary heap with d children, uses Floyd's method for constructing a heap in O(n) time, implements ICollection<T> 62 | - Pairing heap — heap with amortised O(log n) extraction, O(1) merge and insertion, and amortised Ω(log log n) change key, implements ICollection<T> 63 | 64 | ## Probabilistic structures 65 | - Bloom filter — test whether an element might be in a set (with a known margin of error), or that it is definitely not in the set, without storing the actual elements 66 | - Skip list — an alternative to balanced BSTs, offers average case O(log n) operations, but worst case O(n) --------------------------------------------------------------------------------