├── .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; false
otherwise.
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