├── .gitignore ├── .travis.yml ├── Algorithms.sln ├── Algorithms ├── Algorithms.csproj ├── App.config ├── CrackingTheCodeInterview │ ├── 01ChapterStringArray │ │ ├── Array.cs │ │ └── String.cs │ ├── 02ChapterLinkedLists │ │ └── LinkedList.cs │ ├── 03ChapterStackQueue │ │ ├── QueueBasedOnStacks.cs │ │ ├── StackExt.cs │ │ ├── StackSet.cs │ │ └── StackWithMin.cs │ └── 04ChapterTreeGraph │ │ └── Tree.cs ├── DataStructures │ ├── Graph │ │ ├── Graph.cs │ │ └── GraphNode.cs │ ├── HashTable │ │ ├── DoubleHashTable.cs │ │ ├── HashTableItem.cs │ │ ├── HashTableWithLinkedList.cs │ │ ├── IHashTable.cs │ │ ├── LinearHashTable.cs │ │ └── QuadraticHashTable.cs │ ├── Heap │ │ └── Heap.cs │ ├── LinkedList │ │ ├── LinkedList.cs │ │ └── LinkedListNode.cs │ └── Tree │ │ ├── AVLTree.cs │ │ ├── AVLTreeNode.cs │ │ ├── BinarySearchTree.cs │ │ ├── BinarySearchTreeNode.cs │ │ ├── ITree.cs │ │ ├── ITreeNode.cs │ │ ├── RedBlackTree.cs │ │ └── RedBlackTreeNode.cs ├── Helpers │ ├── PrimeList.cs │ └── SortHelper.cs ├── Properties │ └── AssemblyInfo.cs └── SortAlgorithms │ ├── ISorter.cs │ ├── NonComparison │ ├── BucketSorter.cs │ ├── CountingSorter.cs │ ├── CountingStableSorter.cs │ ├── LSDRadixSorter.cs │ └── MSDRadixSorter.cs │ ├── Stable │ ├── BubbleSorter.cs │ ├── CocktailSorter.cs │ ├── GnomeSorter.cs │ ├── InsertionSorter.cs │ ├── MergeSorter.cs │ └── OddEvenSorter.cs │ └── Unstable │ ├── HeapSorter.cs │ ├── QuickSorter.cs │ ├── SelectionSorter.cs │ └── ShellSorter.cs ├── AlgorithmsTests ├── AlgorithmsTests.csproj ├── CrackingTheCodeInterview │ ├── 01ChapterStringArray │ │ ├── ArrayTests.cs │ │ └── StringTests.cs │ ├── 02ChapterLinkedLists │ │ └── LinkedListTests.cs │ ├── 03ChapterStackQueue │ │ ├── QueueTests.cs │ │ └── StackTests.cs │ └── 04ChapterTreeGraph │ │ └── TreeTests.cs ├── DataStructures │ ├── Graph │ │ └── GraphTests.cs │ ├── HashTable │ │ └── HashTableTestsFactory.cs │ ├── Heap │ │ └── HeapTests.cs │ └── Tree │ │ ├── AVLTreeTests.cs │ │ ├── BinarySearchTreeNodeTests.cs │ │ ├── BinarySearchTreeTests.cs │ │ └── RedBlackTreeTests.cs ├── HelperTests │ └── PrimeListTests.cs ├── Properties │ └── AssemblyInfo.cs ├── SortAlgorithms │ ├── SorterTestsFactory.cs │ └── SorterTestsHelper.cs ├── SorterHelper │ ├── ISorterTester.cs │ ├── SorterCharTester.cs │ ├── SorterDoubleTester.cs │ ├── SorterIntegerTester.cs │ └── SorterStringTester.cs └── packages.config ├── LICENSE ├── README.md └── appveyor.yml /.gitignore: -------------------------------------------------------------------------------- 1 | Algorithms/bin/* 2 | Algorithms/obj/* 3 | .vs/Algorithms/v14/.suo 4 | AlgorithmsTests/bin/* 5 | AlgorithmsTests/obj/* 6 | packages/* 7 | */*.csproj.user 8 | *.DotSettings.user 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | solution: Algorithms.sln 3 | install: 4 | - nuget restore Algorithms.sln 5 | - nuget install NUnit.Console -Version 3.4.1 -OutputDirectory testrunner 6 | script: 7 | - xbuild Algorithms.sln /p:Configuration=Debug 8 | - mono ./testrunner/NUnit.ConsoleRunner.3.4.1/tools/nunit3-console.exe ./AlgorithmsTests/bin/Debug/AlgorithmsTests.dll -------------------------------------------------------------------------------- /Algorithms.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algorithms", "Algorithms\Algorithms.csproj", "{80FA8F11-8329-4C23-891C-BD4F9FADAA91}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlgorithmsTests", "AlgorithmsTests\AlgorithmsTests.csproj", "{3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Release|Any CPU = Release|Any CPU 15 | Release|x64 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Debug|x64.ActiveCfg = Debug|x64 21 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Debug|x64.Build.0 = Debug|x64 22 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Release|x64.ActiveCfg = Release|x64 25 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91}.Release|x64.Build.0 = Release|x64 26 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Debug|x64.ActiveCfg = Debug|x64 29 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Debug|x64.Build.0 = Debug|x64 30 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Release|x64.ActiveCfg = Release|Any CPU 33 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D}.Release|x64.Build.0 = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /Algorithms/Algorithms.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {80FA8F11-8329-4C23-891C-BD4F9FADAA91} 8 | Library 9 | Properties 10 | Algorithms 11 | Algorithms 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | true 40 | bin\x64\Debug\ 41 | DEBUG;TRACE 42 | full 43 | x64 44 | prompt 45 | MinimumRecommendedRules.ruleset 46 | true 47 | 48 | 49 | bin\x64\Release\ 50 | TRACE 51 | true 52 | pdbonly 53 | x64 54 | prompt 55 | MinimumRecommendedRules.ruleset 56 | true 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 128 | -------------------------------------------------------------------------------- /Algorithms/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/01ChapterStringArray/Array.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.Interview.Chapter1 2 | { 3 | public static class Array 4 | { 5 | /// 6 | /// Rotating square array on 90 degrees clockwise 7 | /// 8 | /// Input array 9 | public static void Rotate(this T[,] array) 10 | { 11 | if (array == null || array.GetLength(0) != array.GetLength(1)) 12 | { 13 | return; 14 | } 15 | 16 | // goes by layers 17 | for (var layer = 0; layer < array.GetLength(0) / 2; layer++) 18 | { 19 | var first = layer; 20 | var last = array.GetLength(0) - layer - 1; 21 | 22 | // goes by elements 23 | for (var j = first; j < last; j++) 24 | { 25 | var offset = j - first; 26 | 27 | // save top 28 | var temp = array[layer, j]; 29 | 30 | // left to top 31 | array[layer, j] = array[last - offset, layer]; 32 | 33 | // bottom to left 34 | array[last - offset, layer] = array[last, last - offset]; 35 | 36 | // right to bottom 37 | array[last, last - offset] = array[j, last]; 38 | 39 | // top to right 40 | array[j, last] = temp; 41 | } 42 | } 43 | } 44 | 45 | /// 46 | /// Set zero in columns and rows where array has at least 1 zero 47 | /// 48 | /// Input array 49 | public static void Zerofy(this int[,] array) 50 | { 51 | if (array == null) 52 | { 53 | return; 54 | } 55 | 56 | bool[] zeroRows = new bool[array.GetLength(0)]; 57 | bool[] zeroColumns = new bool[array.GetLength(1)]; 58 | 59 | for (var i = 0; i < array.GetLength(0); i++) 60 | { 61 | for (var j = 0; j < array.GetLength(1); j++) 62 | { 63 | if (array[i,j] == 0) 64 | { 65 | zeroRows[i] = true; 66 | zeroColumns[j] = true; 67 | } 68 | } 69 | } 70 | 71 | for (var i = 0; i < array.GetLength(0); i++) 72 | { 73 | for (var j = 0; j < array.GetLength(1); j++) 74 | { 75 | if (zeroRows[i] || zeroColumns[j]) 76 | { 77 | array[i, j] = 0; 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/01ChapterStringArray/String.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.Interview.Chapter1 5 | { 6 | /// 7 | /// Solutions for tasks from chapter1: strings and arrays 8 | /// 9 | public static class String 10 | { 11 | private static int asciiLength = 256; 12 | 13 | /// 14 | /// This methos guess that string is using only ASCII 15 | /// 16 | /// String to check 17 | /// True if all chars are unique 18 | public static bool IsUniqueChars(this string s) 19 | { 20 | if (string.IsNullOrEmpty(s)) 21 | { 22 | return true; 23 | } 24 | 25 | /// ASCII has only 256 characters 26 | if (s.Length > asciiLength) 27 | { 28 | return false; 29 | } 30 | 31 | var presenceCheck = new bool[asciiLength]; 32 | for (var i = 0; i < s.Length; i++) 33 | { 34 | var charCode = s[i]; 35 | if (presenceCheck[charCode]) 36 | { 37 | return false; 38 | } 39 | 40 | presenceCheck[charCode] = true; 41 | } 42 | 43 | return true; 44 | } 45 | 46 | /// 47 | /// Reverse string 48 | /// 49 | /// String to reverse 50 | public static string Reverse(this string s) 51 | { 52 | if (string.IsNullOrEmpty(s)) 53 | { 54 | return string.Empty; 55 | } 56 | 57 | var charArray = s.ToCharArray(); 58 | for (var i = 0; i < s.Length / 2; i++) 59 | { 60 | var endIndex = s.Length - i - 1; 61 | SortHelper.swap(charArray, i, endIndex); 62 | } 63 | 64 | return new string(charArray); 65 | } 66 | 67 | /// 68 | /// Checks if this string is permutation of another string 69 | /// 70 | /// String to check 71 | /// Another string 72 | /// True if this string is permutation 73 | /// 74 | /// Case sensitive? Assume yes 75 | /// Space sensitive? Assume yes 76 | /// ASCII or UNICODE? Assume ASCII 77 | /// 78 | public static bool IsPermutationOf(this string s1, string s2) 79 | { 80 | if (string.IsNullOrEmpty(s1) || string.IsNullOrEmpty(s2)) 81 | { 82 | return false; 83 | } 84 | 85 | if (s1.Length != s2.Length) 86 | { 87 | return false; 88 | } 89 | 90 | var counter = getAsciiCounter(s1); 91 | 92 | for (var i = 0; i < s2.Length; i++) 93 | { 94 | if (--counter[s2[i]] < 0) 95 | { 96 | return false; 97 | } 98 | } 99 | 100 | return true; 101 | } 102 | 103 | /// 104 | /// Replace space to %20 105 | /// 106 | /// input string 107 | /// String with replacements 108 | public static string ReplaceSpace(this string s) 109 | { 110 | if (string.IsNullOrEmpty(s)) 111 | { 112 | return s; 113 | } 114 | 115 | var spaceCounts = 0; 116 | for (var i = 0; i < s.Length; i++) 117 | { 118 | if (s[i] == ' ') 119 | { 120 | spaceCounts++; 121 | } 122 | } 123 | 124 | if (spaceCounts == 0) 125 | { 126 | return s; 127 | } 128 | 129 | var inputArray = s.ToCharArray(); 130 | var currentLength = inputArray.Length + spaceCounts * 2; 131 | var result = new char[currentLength]; 132 | currentLength--; 133 | for (var i = s.Length - 1; i >= 0; i--) 134 | { 135 | if (s[i] == ' ') 136 | { 137 | result[currentLength--] = '0'; 138 | result[currentLength--] = '2'; 139 | result[currentLength--] = '%'; 140 | } 141 | else 142 | { 143 | result[currentLength--] = s[i]; 144 | } 145 | } 146 | 147 | return new string(result); 148 | } 149 | 150 | /// 151 | /// Check is current string is permutation of palindrome 152 | /// 153 | /// String to check 154 | /// True if current string is permutation of palindrome 155 | /// 156 | /// Case sensetive? Assume, yes 157 | /// Space sensitive? Assume, yes 158 | /// ASCII or UNICODE? Assume ASCII 159 | /// 160 | public static bool IsPermutationOfPalindrome(this string s) 161 | { 162 | if (string.IsNullOrEmpty(s)) 163 | { 164 | return false; 165 | } 166 | 167 | var counter = new bool[asciiLength]; 168 | for (var i = 0; i < s.Length; i++) 169 | { 170 | counter[s[i]] = !counter[s[i]]; 171 | } 172 | 173 | var hasSingleChar = false; 174 | for (var i = 0; i < counter.Length; i++) 175 | { 176 | if (counter[i]) 177 | { 178 | if (hasSingleChar) 179 | { 180 | return false; 181 | } 182 | else 183 | { 184 | hasSingleChar = true; 185 | } 186 | } 187 | } 188 | 189 | return true; 190 | } 191 | 192 | /// 193 | /// Check if current string differ from another with just 1 edit/add/remove 194 | /// 195 | /// Current string 196 | /// Another string 197 | /// True of current string differ from another with just 1 edit/add/remove 198 | public static bool IsSimilarLike(this string s1, string s2) 199 | { 200 | if (string.IsNullOrEmpty(s1) || string.IsNullOrEmpty(s2)) 201 | { 202 | return false; 203 | } 204 | 205 | var l1 = s1.Length; 206 | var l2 = s2.Length; 207 | 208 | if (l1 == l2) 209 | { 210 | return checkSingleEdit(s1, s2); 211 | } 212 | else if (l1 - l2 == 1) 213 | { 214 | return checkSingleRemoval(s1, s2); 215 | } 216 | else if (l2 - l1 == 1) 217 | { 218 | return checkSingleRemoval(s2, s1); 219 | } 220 | else 221 | { 222 | return false; 223 | } 224 | } 225 | 226 | /// 227 | /// Archiving string: aaabbc -> a3b2c1 only if result less than origin 228 | /// 229 | /// Origin string to acrhive 230 | /// Archived string or origin of its less 231 | public static string Archive(this string s) 232 | { 233 | if (string.IsNullOrEmpty(s)) 234 | { 235 | return string.Empty; 236 | } 237 | 238 | var result = new StringBuilder(); 239 | char currentChar = s[0]; 240 | var currentLength = 1; 241 | for (var i = 1; i < s.Length; i++) 242 | { 243 | if (s[i] != currentChar) 244 | { 245 | result.Append(currentChar); 246 | result.Append(currentLength); 247 | currentChar = s[i]; 248 | currentLength = 1; 249 | } 250 | else 251 | { 252 | currentLength++; 253 | } 254 | } 255 | 256 | result.Append(currentChar); 257 | result.Append(currentLength); 258 | 259 | return s.Length >= result.Length ? result.ToString() : s; 260 | } 261 | 262 | /// 263 | /// Using Contains method, checks is other string - cycle shift of original 264 | /// 265 | /// Original string 266 | /// String to check 267 | /// True if other string is cycle substring of origin 268 | public static bool IsCycleShift(this string s1, string s2) 269 | { 270 | if (string.IsNullOrEmpty(s1) || string.IsNullOrEmpty(s2)) 271 | { 272 | return false; 273 | } 274 | 275 | if (s1.Length != s2.Length) 276 | { 277 | return false; 278 | } 279 | 280 | return (s2 + s2).Contains(s1); 281 | } 282 | 283 | private static int[] getAsciiCounter(string s) 284 | { 285 | var counter = new int[asciiLength]; 286 | 287 | for (var i = 0; i < asciiLength; i++) 288 | { 289 | counter[i] = 0; 290 | } 291 | 292 | for (var i = 0; i < s.Length; i++) 293 | { 294 | counter[s[i]]++; 295 | } 296 | 297 | return counter; 298 | } 299 | 300 | private static bool checkSingleEdit(string s1, string s2) 301 | { 302 | var foundEdit = false; 303 | for (var i = 0; i < s1.Length; i++) 304 | { 305 | if (s1[i] != s2[i]) 306 | { 307 | if (foundEdit) 308 | { 309 | return false; 310 | } 311 | 312 | foundEdit = true; 313 | } 314 | } 315 | 316 | return true; 317 | } 318 | 319 | /// 320 | /// Check can we remove 1 char from s1 and get s2 321 | /// 322 | /// String where we can remove 1 symbol 323 | /// String where 1 symbol already removed 324 | /// True if we remove 1 char from s1 and get s2 325 | private static bool checkSingleRemoval(string s1, string s2) 326 | { 327 | var index1 = 0; 328 | var index2 = 0; 329 | 330 | while (index1 < s1.Length && index2 < s2.Length) 331 | { 332 | if (s1[index1] != s2[index2]) 333 | { 334 | if (index1 != index2) 335 | { 336 | return false; 337 | } 338 | 339 | index1++; 340 | } 341 | else 342 | { 343 | index1++; 344 | index2++; 345 | } 346 | } 347 | 348 | return true; 349 | } 350 | } 351 | } 352 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/02ChapterLinkedLists/LinkedList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.Interview.Chapter2 5 | { 6 | public static class LinkedListExtension 7 | { 8 | /// 9 | /// Remove duplicates from list 10 | /// 11 | /// Type of list's content 12 | /// Linked list 13 | public static void RemoveDuplicates(this DataStructures.LinkedList.LinkedList list) 14 | { 15 | if (list == null || list.IsEmpty) 16 | { 17 | return; 18 | } 19 | 20 | var valuesHash = new HashSet(); 21 | var previous = list.Head; 22 | var currentListItem = list.Head; 23 | 24 | while (currentListItem != null) 25 | { 26 | if (valuesHash.Contains(currentListItem.Content)) 27 | { 28 | previous.Next = currentListItem.Next; 29 | currentListItem = currentListItem.Next; 30 | } 31 | else 32 | { 33 | valuesHash.Add(currentListItem.Content); 34 | previous = currentListItem; 35 | currentListItem = currentListItem.Next; 36 | } 37 | } 38 | } 39 | 40 | /// 41 | /// Get k-th element from end of linked list (based 0) 42 | /// 43 | /// Type of list's content 44 | /// Linked list 45 | /// K-th element from end or null if length of list is less 46 | public static DataStructures.LinkedList.LinkedListNode GetKFromEnd(this DataStructures.LinkedList.LinkedList list, int k) 47 | { 48 | if (list == null || list.IsEmpty) 49 | { 50 | return null; 51 | } 52 | 53 | var secondRunner = list.Head; 54 | var currentPosition = 0; 55 | while (secondRunner != null && secondRunner.Next != null && currentPosition < k) 56 | { 57 | secondRunner = secondRunner.Next; 58 | currentPosition++; 59 | } 60 | 61 | if (currentPosition < k) 62 | { 63 | return null; 64 | } 65 | 66 | var firstRunner = list.Head; 67 | while (secondRunner.Next != null) 68 | { 69 | secondRunner = secondRunner.Next; 70 | firstRunner = firstRunner.Next; 71 | } 72 | 73 | return firstRunner; 74 | } 75 | 76 | /// 77 | /// Removed given element from list 78 | /// 79 | /// Type of list's content 80 | /// Linked list node 81 | public static void RemoveFromMiddle(this DataStructures.LinkedList.LinkedListNode node) 82 | { 83 | if (node == null || node.Next == null) 84 | { 85 | return; 86 | } 87 | 88 | node.Content = node.Next.Content; 89 | node.Next = node.Next.Next; 90 | } 91 | 92 | /// 93 | /// Sort linked list: all items less X should in left part, and greater or equals - in right part 94 | /// 95 | /// Type of list's content 96 | /// Linked list 97 | /// Content to be X 98 | public static void SortAround(this DataStructures.LinkedList.LinkedList list, T content) where T : IComparable 99 | { 100 | if (list == null || list.IsEmpty) 101 | { 102 | return; 103 | } 104 | 105 | DataStructures.LinkedList.LinkedListNode listBeforeHead = null; 106 | DataStructures.LinkedList.LinkedListNode listAfterHead = null; 107 | DataStructures.LinkedList.LinkedListNode currentBefore = null; 108 | DataStructures.LinkedList.LinkedListNode currentAfter = null; 109 | 110 | var current = list.Head; 111 | 112 | while (current != null) 113 | { 114 | if (content.CompareTo(current.Content) > 0) 115 | { 116 | if (listBeforeHead == null) 117 | { 118 | listBeforeHead = currentBefore = current; 119 | } 120 | else 121 | { 122 | currentBefore.Next = current; 123 | currentBefore = current; 124 | } 125 | } 126 | else 127 | { 128 | if (listAfterHead == null) 129 | { 130 | listAfterHead = currentAfter = current; 131 | } 132 | else 133 | { 134 | currentAfter.Next = current; 135 | currentAfter = current; 136 | } 137 | } 138 | 139 | current = current.Next; 140 | } 141 | 142 | if (listBeforeHead != null) 143 | { 144 | list.Head = listBeforeHead; 145 | currentBefore.Next = listAfterHead; 146 | } 147 | else if (listAfterHead != null) 148 | { 149 | list.Head = listAfterHead; 150 | 151 | } 152 | 153 | if (currentAfter != null) 154 | { 155 | currentAfter.Next = null; 156 | } 157 | } 158 | 159 | /// 160 | /// Calculates sum of numbers stored on linked list in reversed order 161 | /// 162 | /// First summand 163 | /// Second summand 164 | /// Sum result in linked list 165 | public static DataStructures.LinkedList.LinkedList SumReversed(this DataStructures.LinkedList.LinkedList a, DataStructures.LinkedList.LinkedList b) 166 | { 167 | if (a == null || a.IsEmpty) 168 | { 169 | return b; 170 | } 171 | 172 | if (b == null || b.IsEmpty) 173 | { 174 | return a; 175 | } 176 | 177 | var result = new DataStructures.LinkedList.LinkedList(); 178 | var overflow = 0; 179 | var first = a.Head; 180 | var second = b.Head; 181 | 182 | while (first != null || second != null) 183 | { 184 | var sum = (first?.Content ?? 0) + (second?.Content ?? 0) + overflow; 185 | var currentValue = sum % 10; 186 | overflow = sum / 10; 187 | result.AddToEnd(currentValue); 188 | 189 | first = first?.Next; 190 | second = second?.Next; 191 | } 192 | 193 | if (overflow > 0) 194 | { 195 | result.AddToEnd(overflow); 196 | } 197 | 198 | return result; 199 | } 200 | 201 | /// 202 | /// Calculates sum of numbers stored on linked list in odinal order 203 | /// 204 | /// First summand 205 | /// Second summand 206 | /// Sum result in linked list 207 | public static DataStructures.LinkedList.LinkedList Sum(this DataStructures.LinkedList.LinkedList a, DataStructures.LinkedList.LinkedList b) 208 | { 209 | if (a == null || a.IsEmpty) 210 | { 211 | return b; 212 | } 213 | 214 | if (b == null || b.IsEmpty) 215 | { 216 | return a; 217 | } 218 | 219 | int length1 = a.Length; 220 | int length2 = b.Length; 221 | 222 | if (length1 < length2) 223 | { 224 | padLeft(a, length2 - length1); 225 | } 226 | 227 | if (length2 < length1) 228 | { 229 | padLeft(b, length1 - length2); 230 | } 231 | 232 | var result = sumHelper(a.Head, b.Head); 233 | if (result.Overflow > 0) 234 | { 235 | result.result.AddToBegin(result.Overflow); 236 | } 237 | 238 | return result.result; 239 | } 240 | 241 | private static void padLeft(DataStructures.LinkedList.LinkedList list, int count) 242 | { 243 | for (var i = 0; i < count; i++) 244 | { 245 | list.AddToBegin(0); 246 | } 247 | } 248 | 249 | private static SumResult sumHelper(DataStructures.LinkedList.LinkedListNode a, DataStructures.LinkedList.LinkedListNode b) 250 | { 251 | if (a == null || b == null) 252 | { 253 | return new SumResult(); 254 | } 255 | 256 | var result = sumHelper(a.Next, b.Next); 257 | 258 | var sum = result.Overflow + a.Content + b.Content; 259 | result.result.AddToBegin(sum % 10); 260 | result.Overflow = sum / 10; 261 | 262 | return result; 263 | } 264 | 265 | /// 266 | /// Checks is given list is palindrome 267 | /// 268 | /// Content type 269 | /// Given list 270 | /// First intersection node 271 | public static bool IsPalindrome(this DataStructures.LinkedList.LinkedList list) 272 | { 273 | if (list == null || list.IsEmpty) 274 | { 275 | return false; 276 | } 277 | 278 | var fast = list.Head; 279 | var slow = list.Head; 280 | var stack = new Stack(); 281 | 282 | while (fast != null && fast.Next != null) 283 | { 284 | stack.Push(slow.Content); 285 | slow = slow.Next; 286 | fast = fast.Next.Next; 287 | } 288 | 289 | // odd length 290 | if (fast != null) 291 | { 292 | slow = slow.Next; 293 | } 294 | 295 | while (stack.Count > 0) 296 | { 297 | if (!stack.Pop().Equals(slow.Content)) 298 | { 299 | return false; 300 | } 301 | 302 | slow = slow.Next; 303 | } 304 | 305 | return true; 306 | } 307 | 308 | /// 309 | /// Return node of intersecion (by ref) between lists. Is no intersection - return null 310 | /// 311 | /// Content type 312 | /// First list 313 | /// Second list 314 | /// Node of intersection 315 | public static DataStructures.LinkedList.LinkedListNode GetIntersection(this DataStructures.LinkedList.LinkedList list1, DataStructures.LinkedList.LinkedList list2) 316 | { 317 | if (list1 == null || list1.IsEmpty || list2 == null || list2.IsEmpty) 318 | { 319 | return null; 320 | } 321 | 322 | var countAndTail1 = GetCountAndTail(list1); 323 | var countAndTail2 = GetCountAndTail(list2); 324 | 325 | if (countAndTail1.Tail != countAndTail2.Tail) 326 | { 327 | return null; 328 | } 329 | 330 | var shorter = countAndTail1.Count < countAndTail2.Count 331 | ? list1.Head : list2.Head; 332 | 333 | var longer = countAndTail1.Count < countAndTail2.Count 334 | ? list2.Head : list1.Head; 335 | 336 | for (var i = 0; i < Math.Abs(countAndTail1.Count - countAndTail2.Count); i++) 337 | { 338 | longer = longer.Next; 339 | } 340 | 341 | while (shorter != null) 342 | { 343 | if (shorter == longer) 344 | { 345 | return shorter; 346 | } 347 | 348 | shorter = shorter.Next; 349 | longer = longer.Next; 350 | } 351 | 352 | return null; 353 | } 354 | 355 | private static CountAndTail GetCountAndTail(DataStructures.LinkedList.LinkedList list) 356 | { 357 | var result = new CountAndTail(); 358 | var current = list.Head; 359 | 360 | while (current != null) 361 | { 362 | result.Count++; 363 | result.Tail = current; 364 | current = current.Next; 365 | } 366 | 367 | return result; 368 | } 369 | 370 | /// 371 | /// Returns start of loop if it exists 372 | /// 373 | /// Content type 374 | /// Linked list 375 | /// Start of loop is exists 376 | public static DataStructures.LinkedList.LinkedListNode GetStartOfLoop(this DataStructures.LinkedList.LinkedList list) 377 | { 378 | if (list == null || list.IsEmpty) 379 | { 380 | return null; 381 | } 382 | 383 | var slow = list.Head; 384 | var fast = list.Head; 385 | 386 | // after K steps: slow is on the beginning of the loop, fast in the loop. 387 | // Distance between them = loop length - k 388 | // after more LL - k steps, they are collised at K steps before loop start 389 | while (fast != null && fast.Next != null) 390 | { 391 | slow = slow.Next; 392 | fast = fast.Next.Next; 393 | 394 | if (fast == slow) 395 | { 396 | break; 397 | } 398 | } 399 | 400 | // no loop 401 | if (fast == null || fast.Next == null) 402 | { 403 | return null; 404 | } 405 | 406 | // move slow to Head and go K steps until collision = loop start 407 | slow = list.Head; 408 | while (slow != fast) 409 | { 410 | slow = slow.Next; 411 | fast = fast.Next; 412 | } 413 | 414 | return slow; 415 | } 416 | } 417 | 418 | class SumResult 419 | { 420 | public DataStructures.LinkedList.LinkedList result; 421 | public int Overflow; 422 | 423 | public SumResult() 424 | { 425 | this.result = new DataStructures.LinkedList.LinkedList(); 426 | this.Overflow = 0; 427 | } 428 | } 429 | 430 | class CountAndTail 431 | { 432 | public int Count = 0; 433 | public DataStructures.LinkedList.LinkedListNode Tail; 434 | } 435 | } 436 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/03ChapterStackQueue/QueueBasedOnStacks.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.Interview.Chapter3 4 | { 5 | /// 6 | /// Implementation of queue based on 2 stacks 7 | /// 8 | /// Content type 9 | public class QueueBasedOnStacks 10 | { 11 | private Stack inputStack; 12 | private Stack outputStack; 13 | 14 | public QueueBasedOnStacks() 15 | { 16 | this.inputStack = new Stack(); 17 | this.outputStack = new Stack(); 18 | } 19 | 20 | public void Enqueue(T value) 21 | { 22 | this.inputStack.Push(value); 23 | } 24 | 25 | public T Dequeue() 26 | { 27 | if (this.outputStack.Count == 0) 28 | { 29 | this.MoveInputToOutput(); 30 | } 31 | 32 | return this.outputStack.Pop(); 33 | } 34 | 35 | private void MoveInputToOutput() 36 | { 37 | while (this.inputStack.Count > 0) 38 | { 39 | this.outputStack.Push(this.inputStack.Pop()); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/03ChapterStackQueue/StackExt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.Interview.Chapter3 5 | { 6 | public static class StackExt 7 | { 8 | /// 9 | /// Sorting of stack with usage of just 1 stack. Minimal element of result should be on top 10 | /// 11 | /// Content type 12 | /// Stack to sort 13 | /// Sorted stack 14 | public static Stack Sort(this Stack stack) where T : IComparable 15 | { 16 | var result = new Stack(); 17 | 18 | while (stack.Count > 0) 19 | { 20 | var currentValue = stack.Pop(); 21 | if (result.Count == 0 || result.Peek().CompareTo(currentValue) >= 0) 22 | { 23 | result.Push(currentValue); 24 | } 25 | else 26 | { 27 | var countOfMoved = 0; 28 | while (result.Count > 0 && result.Peek().CompareTo(currentValue) < 0) 29 | { 30 | stack.Push(result.Pop()); 31 | countOfMoved++; 32 | } 33 | 34 | result.Push(currentValue); 35 | 36 | for (var i = 0; i < countOfMoved; i++) 37 | { 38 | result.Push(stack.Pop()); 39 | } 40 | } 41 | } 42 | 43 | return result; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/03ChapterStackQueue/StackSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.Interview.Chapter3 5 | { 6 | /// 7 | /// Implementation of stack set 8 | /// 9 | /// Content type 10 | public class StackSet 11 | { 12 | private List> stackSet; 13 | private int maxStackCapacity; 14 | 15 | public StackSet(int maxStackCapacity) 16 | { 17 | this.maxStackCapacity = maxStackCapacity; 18 | this.stackSet = new List>(); 19 | 20 | this.stackSet.Add(new Stack()); 21 | } 22 | 23 | public void Push(T value) 24 | { 25 | var currentStack = this.GetCurrentStack(); 26 | if (currentStack.Count >= this.maxStackCapacity) 27 | { 28 | var newStack = new Stack(); 29 | newStack.Push(value); 30 | this.stackSet.Add(newStack); 31 | } 32 | else 33 | { 34 | currentStack.Push(value); 35 | } 36 | } 37 | 38 | public T Pop() 39 | { 40 | var currentStack = this.GetCurrentStack(); 41 | return this.PopFromStack(currentStack, this.stackSet.Count - 1); 42 | } 43 | 44 | public T PopAt(int stackIndex) 45 | { 46 | if (stackIndex >= this.stackSet.Count) 47 | { 48 | throw new OverflowException(); 49 | } 50 | 51 | var stack = this.stackSet[stackIndex]; 52 | return this.PopFromStack(stack, stackIndex); 53 | } 54 | 55 | private T PopFromStack(Stack stack, int stackIndex) 56 | { 57 | var value = stack.Pop(); 58 | if (stack.Count == 0 && this.stackSet.Count > 1) 59 | { 60 | this.stackSet.RemoveAt(stackIndex); 61 | } 62 | 63 | return value; 64 | } 65 | 66 | private Stack GetCurrentStack() 67 | { 68 | return this.stackSet[this.stackSet.Count - 1]; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/03ChapterStackQueue/StackWithMin.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.Interview.Chapter3 4 | { 5 | public class StackWithMin : Stack 6 | { 7 | private Stack stackOfMins; 8 | 9 | public StackWithMin() : base() 10 | { 11 | this.stackOfMins = new Stack(); 12 | } 13 | 14 | public int Min 15 | { 16 | get 17 | { 18 | return this.stackOfMins.Count == 0 19 | ? int.MaxValue 20 | : stackOfMins.Peek(); 21 | } 22 | } 23 | 24 | public new void Push(int value) 25 | { 26 | if (value <= this.Min) 27 | { 28 | this.stackOfMins.Push(value); 29 | } 30 | 31 | base.Push(value); 32 | } 33 | 34 | public new int Pop() 35 | { 36 | var value = base.Pop(); 37 | if (value == this.Min) 38 | { 39 | this.stackOfMins.Pop(); 40 | } 41 | 42 | return value; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Algorithms/CrackingTheCodeInterview/04ChapterTreeGraph/Tree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.DataStructures.Tree; 3 | 4 | namespace Algorithms.Interview.Chapter4 5 | { 6 | public static class TreeExtensions 7 | { 8 | /// 9 | /// Created balanced binary search tree from sorted array 10 | /// 11 | /// Sorted values 12 | public static BinarySearchTree CreateBalancedBinarySearchTreeFromSortedArray(T[] values) 13 | where T:IComparable 14 | { 15 | var tree = new BinarySearchTree(); 16 | tree.Root = CreateBST(values, 0, values.Length - 1); 17 | 18 | return tree; 19 | } 20 | 21 | private static BinarySearchTreeNode CreateBST(T[] values, int start, int end) 22 | where T:IComparable 23 | { 24 | if (end < start) 25 | { 26 | return null; 27 | } 28 | 29 | int middle = (int)Math.Ceiling((start + end) / 2.0); 30 | var node = new BinarySearchTreeNode(values[middle]); 31 | 32 | node.Left = CreateBST(values, start, middle - 1); 33 | node.Right = CreateBST(values, middle + 1, end); 34 | 35 | return node; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Graph/Graph.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Algorithms.DataStructures.Graph 6 | { 7 | /// 8 | /// Graph, could be oriented or not 9 | /// 10 | /// Content type 11 | public class Graph 12 | { 13 | public List> Nodes { get; } 14 | 15 | public Graph() 16 | { 17 | this.Nodes = new List>(); 18 | } 19 | 20 | public bool IsEmpty 21 | { 22 | get 23 | { 24 | return this.Nodes.Count == 0; 25 | } 26 | } 27 | 28 | public GraphNode AddNode(T value) 29 | { 30 | var newNode = new GraphNode(value); 31 | this.Nodes.Add(newNode); 32 | return newNode; 33 | } 34 | 35 | public bool AddEdge(GraphNode node1, GraphNode node2, bool directed = false) 36 | { 37 | if (!this.Nodes.Contains(node1) || !this.Nodes.Contains(node2)) 38 | { 39 | return false; 40 | } 41 | 42 | this.AddToCollection(node1.OutputNodes, node2); 43 | this.AddToCollection(node2.InputNodes, node1); 44 | 45 | if (!directed) 46 | { 47 | this.AddToCollection(node2.OutputNodes, node1); 48 | this.AddToCollection(node1.InputNodes, node2); 49 | } 50 | 51 | return true; 52 | } 53 | 54 | public bool RemoveEdge(GraphNode node1, GraphNode node2, bool directed = false) 55 | { 56 | if (!this.Nodes.Contains(node1) || !this.Nodes.Contains(node2)) 57 | { 58 | return false; 59 | } 60 | 61 | this.RemoveFromCollection(node1.OutputNodes, node2); 62 | this.RemoveFromCollection(node2.InputNodes, node1); 63 | 64 | if (!directed) 65 | { 66 | this.RemoveFromCollection(node2.OutputNodes, node1); 67 | this.RemoveFromCollection(node1.InputNodes, node2); 68 | } 69 | 70 | return true; 71 | } 72 | 73 | public bool RemoveNode(GraphNode node) 74 | { 75 | if (!this.Nodes.Contains(node)) 76 | { 77 | return false; 78 | } 79 | 80 | foreach (var edge in node.InputNodes) 81 | { 82 | this.RemoveFromCollection(edge.OutputNodes, node); 83 | } 84 | 85 | foreach (var edge in node.OutputNodes) 86 | { 87 | this.RemoveFromCollection(edge.InputNodes, node); 88 | } 89 | 90 | this.Nodes.Remove(node); 91 | return true; 92 | } 93 | 94 | public void ResetVisited() 95 | { 96 | foreach (var node in this.Nodes) 97 | { 98 | node.Visited = false; 99 | } 100 | } 101 | 102 | public bool AreConnected(GraphNode node1, GraphNode node2) 103 | { 104 | if (!this.Nodes.Contains(node1) || !this.Nodes.Contains(node2)) 105 | { 106 | return false; 107 | } 108 | 109 | this.ResetVisited(); 110 | 111 | var nodesToVisit = new Queue>(); 112 | nodesToVisit.Enqueue(node1); 113 | 114 | while (nodesToVisit.Count > 0) 115 | { 116 | var currentNode = nodesToVisit.Dequeue(); 117 | if (currentNode.Visited) 118 | { 119 | continue; 120 | } 121 | 122 | currentNode.Visited = true; 123 | if (currentNode.OutputNodes.Contains(node2)) 124 | { 125 | return true; 126 | } 127 | 128 | foreach (var node in currentNode.OutputNodes) 129 | { 130 | nodesToVisit.Enqueue(node); 131 | } 132 | } 133 | 134 | return false; 135 | } 136 | 137 | public List> GetLexicographicOrder() 138 | { 139 | var result = new List>(); 140 | 141 | while (!this.IsEmpty) 142 | { 143 | var freeNodes = this.GetNodesWithoutInput(); 144 | 145 | if (freeNodes.Count == 0) 146 | { 147 | throw new InvalidOperationException(); 148 | } 149 | 150 | result.AddRange(freeNodes); 151 | 152 | foreach (var node in freeNodes) 153 | { 154 | this.RemoveNode(node); 155 | } 156 | } 157 | 158 | return result; 159 | } 160 | 161 | private List> GetNodesWithoutInput() 162 | { 163 | return this.Nodes.Where(x => x.InputNodes.Count() == 0).ToList(); 164 | } 165 | 166 | private void AddToCollection(HashSet> nodes, GraphNode node) 167 | { 168 | if (!nodes.Contains(node)) 169 | { 170 | nodes.Add(node); 171 | } 172 | } 173 | 174 | private void RemoveFromCollection(HashSet> nodes, GraphNode node) 175 | { 176 | if (nodes.Contains(node)) 177 | { 178 | nodes.Remove(node); 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Graph/GraphNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Graph 4 | { 5 | /// 6 | /// Graph node 7 | /// 8 | /// Content type 9 | public class GraphNode 10 | { 11 | public T Content { get; set; } 12 | public HashSet> OutputNodes { get; } 13 | public HashSet> InputNodes { get; } 14 | public bool Visited { get; set; } 15 | 16 | public GraphNode(T value) 17 | { 18 | this.Content = value; 19 | this.OutputNodes = new HashSet>(); 20 | this.InputNodes = new HashSet>(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/HashTable/DoubleHashTable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using Algorithms.Helpers; 4 | 5 | namespace Algorithms.DataStructures.HashTable 6 | { 7 | /// 8 | /// Implementation of hash tabl with doule hashing 9 | /// 10 | public class DoubleHashTable : IEnumerable, IHashTable 11 | { 12 | private int HashPrime { get; set; } 13 | private int Size { get; set; } 14 | private int Count { get; set; } 15 | private HashTableItem[] Storage { get; set; } 16 | 17 | public DoubleHashTable() 18 | : this(10) 19 | { 20 | } 21 | 22 | public DoubleHashTable(int size) 23 | { 24 | this.Size = PrimeList.GetNextPrime(size); 25 | this.HashPrime = PrimeList.GetNextPrime(this.Size); 26 | this.Storage = new HashTableItem[this.Size]; 27 | this.Count = 0; 28 | } 29 | 30 | public bool Add(int value) 31 | { 32 | if (this.Count >= this.Size) 33 | { 34 | this.Rebuild(); 35 | } 36 | 37 | var baseIndex = this.GetHash(value); 38 | var index = baseIndex; 39 | var step = 0; 40 | while (this.Storage[index] != null && 41 | (!this.Storage[index].IsDeleted || !this.Storage[index].IsEmpty)) 42 | { 43 | index = this.GetNextProbingIndex(baseIndex, step, value); 44 | if (step < this.Size) 45 | { 46 | step++; 47 | } 48 | else 49 | { 50 | return false; 51 | } 52 | } 53 | 54 | if (this.Storage[index] == null) 55 | { 56 | this.Storage[index] = new HashTableItem(); 57 | } 58 | 59 | this.Storage[index].Content = value; 60 | this.Storage[index].IsDeleted = false; 61 | this.Storage[index].IsEmpty = false; 62 | this.Count++; 63 | return true; 64 | } 65 | 66 | public bool Contains(int value) 67 | { 68 | var baseIndex = this.GetHash(value); 69 | var index = baseIndex; 70 | var step = 0; 71 | while (true) 72 | { 73 | if (this.Storage[index] == null 74 | || this.Storage[index].IsDeleted == true 75 | || this.Storage[index].IsEmpty == true) 76 | { 77 | return false; 78 | } 79 | 80 | if (this.Storage[index].Content == value) 81 | { 82 | return true; 83 | } 84 | 85 | if (step < this.Size) 86 | { 87 | step++; 88 | } 89 | else 90 | { 91 | return false; 92 | } 93 | 94 | index = this.GetNextProbingIndex(baseIndex, step, value); 95 | } 96 | } 97 | 98 | public bool Remove(int value) 99 | { 100 | var baseIndex = this.GetHash(value); 101 | var index = baseIndex; 102 | var step = 0; 103 | while (true) 104 | { 105 | if (this.Storage[index] == null 106 | || this.Storage[index].IsEmpty == true) 107 | { 108 | return false; 109 | } 110 | 111 | if (this.Storage[index].Content == value) 112 | { 113 | this.Storage[index].IsDeleted = true; 114 | this.Storage[index].IsEmpty = true; 115 | this.Count--; 116 | return true; 117 | } 118 | 119 | if (step < this.Size) 120 | { 121 | step++; 122 | } 123 | else 124 | { 125 | return false; 126 | } 127 | 128 | index = this.GetNextProbingIndex(baseIndex, step, value); 129 | } 130 | } 131 | 132 | public void Clear() 133 | { 134 | foreach (var item in this.Storage) 135 | { 136 | if (item != null) 137 | { 138 | item.IsEmpty = true; 139 | item.IsDeleted = false; 140 | } 141 | } 142 | } 143 | 144 | private void Rebuild() 145 | { 146 | this.Size = PrimeList.GetNextPrime(this.Size); 147 | this.HashPrime = PrimeList.GetNextPrime(this.Size); 148 | var newStorageItems = new List(); 149 | foreach (var item in this) 150 | { 151 | newStorageItems.Add(item); 152 | } 153 | 154 | this.Count = 0; 155 | this.Storage = new HashTableItem[this.Size]; 156 | foreach (var item in newStorageItems) 157 | { 158 | this.Add(item); 159 | } 160 | } 161 | 162 | private int GetHash(int value) 163 | { 164 | return value % this.Size; 165 | } 166 | 167 | private int GetNextProbingIndex(int index, int step, int value) 168 | { 169 | var hash = this.HashPrime - value % this.HashPrime; 170 | return (index + step * hash) % this.Size; 171 | } 172 | 173 | public IEnumerator GetEnumerator() 174 | { 175 | foreach (var item in this.Storage) 176 | { 177 | if (item != null && !item.IsDeleted && !item.IsEmpty) 178 | { 179 | yield return item.Content; 180 | } 181 | } 182 | } 183 | 184 | IEnumerator IEnumerable.GetEnumerator() 185 | { 186 | return this.GetEnumerator(); 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/HashTable/HashTableItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.HashTable 4 | { 5 | internal class HashTableItem where T:IComparable 6 | { 7 | public T Content { get; set; } 8 | public bool IsEmpty { get; set; } 9 | public bool IsDeleted { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/HashTable/HashTableWithLinkedList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.DataStructures.HashTable 5 | { 6 | /// 7 | /// Implements hash table with using linked list 8 | /// 9 | public class HashTableWithLinkedList: IEnumerable, IHashTable 10 | { 11 | private int Size { get; set; } 12 | private int Count { get; set; } 13 | private LinkedList[] Storage { get; set; } 14 | 15 | public HashTableWithLinkedList() 16 | : this(16) 17 | { 18 | } 19 | 20 | public HashTableWithLinkedList(int size) 21 | { 22 | this.Size = size; 23 | this.Storage = new LinkedList[this.Size]; 24 | this.Count = 0; 25 | } 26 | 27 | public bool Add(int value) 28 | { 29 | if (this.Count >= this.Size) 30 | { 31 | this.Rebuild(); 32 | } 33 | 34 | var index = this.GetHash(value); 35 | if (this.Storage[index] == null) 36 | { 37 | this.Storage[index] = new LinkedList(); 38 | } 39 | 40 | this.Storage[index].AddLast(value); 41 | this.Count++; 42 | return true; 43 | } 44 | 45 | public bool Contains(int value) 46 | { 47 | var index = this.GetHash(value); 48 | if (this.Storage[index] == null) 49 | { 50 | return false; 51 | } 52 | 53 | return this.Storage[index].Contains(value); 54 | } 55 | 56 | public bool Remove(int value) 57 | { 58 | var index = this.GetHash(value); 59 | if (this.Storage[index] == null) 60 | { 61 | return false; 62 | } 63 | 64 | this.Count--; 65 | return this.Storage[index].Remove(value); 66 | } 67 | 68 | public void Clear() 69 | { 70 | foreach (var list in this.Storage) 71 | { 72 | if (list != null && list.Count > 0) 73 | { 74 | list.Clear(); 75 | } 76 | } 77 | } 78 | 79 | private void Rebuild() 80 | { 81 | this.Size = this.Size * 2; 82 | var newStorageItems = new List(); 83 | foreach(var item in this) 84 | { 85 | newStorageItems.Add(item); 86 | } 87 | 88 | this.Count = 0; 89 | this.Storage = new LinkedList[this.Size]; 90 | foreach (var item in newStorageItems) 91 | { 92 | this.Add(item); 93 | } 94 | } 95 | 96 | private int GetHash(int value) 97 | { 98 | return value % this.Size; 99 | } 100 | 101 | public IEnumerator GetEnumerator() 102 | { 103 | foreach (var list in this.Storage) 104 | { 105 | if (list != null) 106 | { 107 | foreach(var item in list) 108 | { 109 | yield return item; 110 | } 111 | } 112 | } 113 | } 114 | 115 | IEnumerator IEnumerable.GetEnumerator() 116 | { 117 | return this.GetEnumerator(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/HashTable/IHashTable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.HashTable 4 | { 5 | /// 6 | /// Average: O(1) 7 | /// Worst: O(n) 8 | /// 9 | public interface IHashTable : IEnumerable 10 | { 11 | bool Add(int value); 12 | 13 | bool Contains(int value); 14 | 15 | bool Remove(int value); 16 | 17 | void Clear(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/HashTable/LinearHashTable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using Algorithms.Helpers; 4 | 5 | namespace Algorithms.DataStructures.HashTable 6 | { 7 | /// 8 | /// Implementation of hash tabl with linear probing 9 | /// 10 | public class LinearHashTable : IEnumerable, IHashTable 11 | { 12 | private int Size { get; set; } 13 | private int Count { get; set; } 14 | private HashTableItem[] Storage { get; set; } 15 | 16 | public LinearHashTable() 17 | : this(10) 18 | { 19 | } 20 | 21 | public LinearHashTable(int size) 22 | { 23 | this.Size = PrimeList.GetNextPrime(size); 24 | this.Storage = new HashTableItem[this.Size]; 25 | this.Count = 0; 26 | } 27 | 28 | public bool Add(int value) 29 | { 30 | if (this.Count >= this.Size) 31 | { 32 | this.Rebuild(); 33 | } 34 | 35 | var index = this.GetHash(value); 36 | while (this.Storage[index] != null && 37 | (!this.Storage[index].IsDeleted || !this.Storage[index].IsEmpty)) 38 | { 39 | index = this.GetNextProbingIndex(index); 40 | } 41 | 42 | if (this.Storage[index] == null) 43 | { 44 | this.Storage[index] = new HashTableItem(); 45 | } 46 | 47 | this.Storage[index].Content = value; 48 | this.Storage[index].IsDeleted = false; 49 | this.Storage[index].IsEmpty = false; 50 | this.Count++; 51 | return true; 52 | } 53 | 54 | public bool Contains(int value) 55 | { 56 | var index = this.GetHash(value); 57 | while (true) 58 | { 59 | if (this.Storage[index] == null 60 | || this.Storage[index].IsDeleted == true 61 | || this.Storage[index].IsEmpty == true) 62 | { 63 | return false; 64 | } 65 | 66 | if (this.Storage[index].Content == value) 67 | { 68 | return true; 69 | } 70 | 71 | index = this.GetNextProbingIndex(index); 72 | } 73 | } 74 | 75 | public bool Remove(int value) 76 | { 77 | var index = this.GetHash(value); 78 | while (true) 79 | { 80 | if (this.Storage[index] == null 81 | || this.Storage[index].IsEmpty == true) 82 | { 83 | return false; 84 | } 85 | 86 | if (this.Storage[index].Content == value) 87 | { 88 | this.Storage[index].IsDeleted = true; 89 | this.Count--; 90 | return true; 91 | } 92 | 93 | index = this.GetNextProbingIndex(index); 94 | } 95 | } 96 | 97 | public void Clear() 98 | { 99 | foreach (var item in this.Storage) 100 | { 101 | if (item != null) 102 | { 103 | item.IsEmpty = true; 104 | item.IsDeleted = false; 105 | } 106 | } 107 | } 108 | 109 | private void Rebuild() 110 | { 111 | this.Size = PrimeList.GetNextPrime(this.Size); 112 | var newStorageItems = new List(); 113 | foreach (var item in this) 114 | { 115 | newStorageItems.Add(item); 116 | } 117 | 118 | this.Count = 0; 119 | this.Storage = new HashTableItem[this.Size]; 120 | foreach (var item in newStorageItems) 121 | { 122 | this.Add(item); 123 | } 124 | } 125 | 126 | private int GetHash(int value) 127 | { 128 | return value % this.Size; 129 | } 130 | 131 | private int GetNextProbingIndex(int index) 132 | { 133 | return (index + 1) % this.Size; 134 | } 135 | 136 | public IEnumerator GetEnumerator() 137 | { 138 | foreach (var item in this.Storage) 139 | { 140 | if (item != null && !item.IsDeleted && !item.IsEmpty) 141 | { 142 | yield return item.Content; 143 | } 144 | } 145 | } 146 | 147 | IEnumerator IEnumerable.GetEnumerator() 148 | { 149 | return this.GetEnumerator(); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/HashTable/QuadraticHashTable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using Algorithms.Helpers; 4 | 5 | namespace Algorithms.DataStructures.HashTable 6 | { 7 | /// 8 | /// Implementation of hash tabl with qiadric probing 9 | /// 10 | public class QuadraticHashTable : IEnumerable, IHashTable 11 | { 12 | private int Size { get; set; } 13 | private int Count { get; set; } 14 | private HashTableItem[] Storage { get; set; } 15 | 16 | public QuadraticHashTable() 17 | : this(10) 18 | { 19 | } 20 | 21 | public QuadraticHashTable(int size) 22 | { 23 | this.Size = PrimeList.GetNextPrime(size); 24 | this.Storage = new HashTableItem[this.Size]; 25 | this.Count = 0; 26 | } 27 | 28 | public bool Add(int value) 29 | { 30 | if (this.Count >= this.Size) 31 | { 32 | this.Rebuild(); 33 | } 34 | 35 | var baseIndex = this.GetHash(value); 36 | var index = baseIndex; 37 | var step = 0; 38 | while (this.Storage[index] != null && 39 | (!this.Storage[index].IsDeleted || !this.Storage[index].IsEmpty)) 40 | { 41 | index = this.GetNextProbingIndex(baseIndex, step); 42 | if (step < this.Size) 43 | { 44 | step++; 45 | } 46 | else 47 | { 48 | return false; 49 | } 50 | } 51 | 52 | if (this.Storage[index] == null) 53 | { 54 | this.Storage[index] = new HashTableItem(); 55 | } 56 | 57 | this.Storage[index].Content = value; 58 | this.Storage[index].IsDeleted = false; 59 | this.Storage[index].IsEmpty = false; 60 | this.Count++; 61 | return true; 62 | } 63 | 64 | public bool Contains(int value) 65 | { 66 | var baseIndex = this.GetHash(value); 67 | var index = baseIndex; 68 | var step = 0; 69 | while (true) 70 | { 71 | if (this.Storage[index] == null 72 | || this.Storage[index].IsDeleted == true 73 | || this.Storage[index].IsEmpty == true) 74 | { 75 | return false; 76 | } 77 | 78 | if (this.Storage[index].Content == value) 79 | { 80 | return true; 81 | } 82 | 83 | if (step < this.Size) 84 | { 85 | step++; 86 | } 87 | else 88 | { 89 | return false; 90 | } 91 | 92 | index = this.GetNextProbingIndex(baseIndex, step); 93 | } 94 | } 95 | 96 | public bool Remove(int value) 97 | { 98 | var baseIndex = this.GetHash(value); 99 | var index = baseIndex; 100 | var step = 0; 101 | while (true) 102 | { 103 | if (this.Storage[index] == null 104 | || this.Storage[index].IsEmpty == true) 105 | { 106 | return false; 107 | } 108 | 109 | if (this.Storage[index].Content == value) 110 | { 111 | this.Storage[index].IsDeleted = true; 112 | this.Storage[index].IsEmpty = true; 113 | this.Count--; 114 | return true; 115 | } 116 | 117 | if (step < this.Size) 118 | { 119 | step++; 120 | } 121 | else 122 | { 123 | return false; 124 | } 125 | 126 | index = this.GetNextProbingIndex(baseIndex, step); 127 | } 128 | } 129 | 130 | public void Clear() 131 | { 132 | foreach (var item in this.Storage) 133 | { 134 | if (item != null) 135 | { 136 | item.IsEmpty = true; 137 | item.IsDeleted = false; 138 | } 139 | } 140 | } 141 | 142 | private void Rebuild() 143 | { 144 | this.Size = PrimeList.GetNextPrime(this.Size); 145 | var newStorageItems = new List(); 146 | foreach (var item in this) 147 | { 148 | newStorageItems.Add(item); 149 | } 150 | 151 | this.Count = 0; 152 | this.Storage = new HashTableItem[this.Size]; 153 | foreach (var item in newStorageItems) 154 | { 155 | this.Add(item); 156 | } 157 | } 158 | 159 | private int GetHash(int value) 160 | { 161 | return value % this.Size; 162 | } 163 | 164 | private int GetNextProbingIndex(int index, int step) 165 | { 166 | return (index + step * step) % this.Size; 167 | } 168 | 169 | public IEnumerator GetEnumerator() 170 | { 171 | foreach (var item in this.Storage) 172 | { 173 | if (item != null && !item.IsDeleted && !item.IsEmpty) 174 | { 175 | yield return item.Content; 176 | } 177 | } 178 | } 179 | 180 | IEnumerator IEnumerable.GetEnumerator() 181 | { 182 | return this.GetEnumerator(); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Heap/Heap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Heap 4 | { 5 | /// 6 | /// Heap is the abstract data type which allows to store partially sorted data 7 | /// On the practice - this is array where 8 | /// For min heap: a[i] < a[2i + 1] and a[i] < a[2i + 2] 9 | /// For max heap: a[i] > a[2i + 1] and a[i] > a[2i + 2] 10 | /// 11 | /// Insert: O(lg n) 12 | /// Remove top: O(lg n) 13 | /// 14 | public class Heap 15 | { 16 | List heap; 17 | private bool isMinHeap; 18 | 19 | public Heap(bool minHeap) 20 | { 21 | this.heap = new List(); 22 | this.isMinHeap = minHeap; 23 | } 24 | 25 | public int Count() 26 | { 27 | return this.heap.Count; 28 | } 29 | 30 | public int Peek() 31 | { 32 | if (this.heap.Count == 0) 33 | { 34 | return 0; 35 | } 36 | 37 | return this.heap[0]; 38 | } 39 | 40 | public void Add(int item) 41 | { 42 | this.heap.Add(item); 43 | this.Up(this.heap.Count - 1); 44 | } 45 | 46 | public int ExtractTop() 47 | { 48 | if (this.heap.Count == 0) 49 | { 50 | return 0; 51 | } 52 | 53 | var min = this.heap[0]; 54 | this.Switch(0, this.heap.Count - 1); 55 | this.heap.RemoveAt(this.heap.Count - 1); 56 | this.Down(0); 57 | 58 | return min; 59 | } 60 | 61 | public bool Validate() 62 | { 63 | if (this.heap.Count == 0) 64 | { 65 | return true; 66 | } 67 | 68 | for (var i = 0; i < this.heap.Count / 2; i++) 69 | { 70 | var child1Index = 2 * i + 1; 71 | var child2Index = 2 * i + 2; 72 | 73 | if (child1Index < this.heap.Count) 74 | { 75 | if (this.isMinHeap && this.heap[i] > this.heap[child1Index] 76 | || !this.isMinHeap && this.heap[i] < this.heap[child1Index]) 77 | { 78 | return false; 79 | } 80 | } 81 | 82 | if (child2Index < this.heap.Count) 83 | { 84 | if (this.isMinHeap && this.heap[i] > this.heap[child2Index] 85 | || !this.isMinHeap && this.heap[i] < this.heap[child2Index]) 86 | { 87 | return false; 88 | } 89 | } 90 | } 91 | 92 | return true; 93 | } 94 | 95 | private void Up(int index) 96 | { 97 | if (index == 0 || index >= this.heap.Count) 98 | { 99 | return; 100 | } 101 | 102 | int parent = (index - 1) / 2; 103 | if (this.isMinHeap && this.heap[parent] > this.heap[index] 104 | || !this.isMinHeap && this.heap[parent] < this.heap[index]) 105 | { 106 | this.Switch(index, parent); 107 | this.Up(parent); 108 | } 109 | } 110 | 111 | private void Down(int index) 112 | { 113 | if (2 * index + 1 >= this.heap.Count) 114 | { 115 | return; 116 | } 117 | 118 | var childIndex1 = 2 * index + 1; 119 | var childIndex2 = 2 * index + 2; 120 | var minIndex = index; 121 | 122 | if (childIndex1 < this.heap.Count && 123 | (this.isMinHeap && this.heap[childIndex1] < this.heap[minIndex] 124 | || !this.isMinHeap && this.heap[childIndex1] > this.heap[minIndex])) 125 | { 126 | minIndex = childIndex1; 127 | } 128 | 129 | if (childIndex2 < this.heap.Count && 130 | (this.isMinHeap && this.heap[childIndex2] < this.heap[minIndex] 131 | || !this.isMinHeap && this.heap[childIndex2] > this.heap[minIndex])) 132 | { 133 | minIndex = childIndex2; 134 | } 135 | 136 | if (minIndex != index) 137 | { 138 | this.Switch(index, minIndex); 139 | this.Down(minIndex); 140 | } 141 | } 142 | 143 | private void Switch(int index1, int index2) 144 | { 145 | if (index1 < 0 || index1 >= this.heap.Count 146 | || index2 < 0 || index2 >= this.heap.Count) 147 | { 148 | return; 149 | } 150 | 151 | var temp = this.heap[index1]; 152 | this.heap[index1] = this.heap[index2]; 153 | this.heap[index2] = temp; 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/LinkedList/LinkedList.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.DataStructures.LinkedList 2 | { 3 | public class LinkedList 4 | { 5 | public LinkedListNode Head { internal set; get; } 6 | 7 | public LinkedList() 8 | { 9 | } 10 | 11 | public bool IsEmpty 12 | { 13 | get 14 | { 15 | return this.Head == null; 16 | } 17 | } 18 | 19 | public int Length 20 | { 21 | get 22 | { 23 | var current = this.Head; 24 | var length = 0; 25 | while (current != null) 26 | { 27 | length++; 28 | current = current.Next; 29 | } 30 | 31 | return length; 32 | } 33 | } 34 | 35 | public LinkedList(T[] values) : this() 36 | { 37 | if (values == null || values.Length == 0) 38 | { 39 | return; 40 | } 41 | 42 | this.Head = new LinkedListNode(values[0]); 43 | var current = this.Head; 44 | for (var i = 1; i < values.Length; i++) 45 | { 46 | var nextNode = new LinkedListNode(values[i]); 47 | current.Next = nextNode; 48 | current = nextNode; 49 | } 50 | } 51 | 52 | public void AddToBegin(T value) 53 | { 54 | if (this.IsEmpty) 55 | { 56 | this.Head = new LinkedListNode(value); 57 | return; 58 | } 59 | 60 | var newNode = new LinkedListNode(value); 61 | newNode.Next = this.Head; 62 | this.Head = newNode; 63 | } 64 | 65 | public void AddToEnd(T value) 66 | { 67 | if (this.IsEmpty) 68 | { 69 | this.Head = new LinkedListNode(value); 70 | return; 71 | } 72 | 73 | var tail = this.Head; 74 | while(tail.Next != null) 75 | { 76 | tail = tail.Next; 77 | } 78 | 79 | tail.Next = new LinkedListNode(value); 80 | } 81 | 82 | public bool IsSameListAs(LinkedList other) 83 | { 84 | if (other == null) 85 | { 86 | return false; 87 | } 88 | 89 | var thisCurrent = this.Head; 90 | var anotherCurrent = other.Head; 91 | 92 | if (!this.IsEmpty && other.IsEmpty 93 | || this.IsEmpty && !other.IsEmpty) 94 | { 95 | return false; 96 | } 97 | 98 | while (thisCurrent != null && anotherCurrent != null) 99 | { 100 | if (!thisCurrent.Content.Equals(anotherCurrent.Content)) 101 | { 102 | return false; 103 | } 104 | 105 | thisCurrent = thisCurrent.Next; 106 | anotherCurrent = anotherCurrent.Next; 107 | } 108 | 109 | return thisCurrent == null && anotherCurrent == null; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/LinkedList/LinkedListNode.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.DataStructures.LinkedList 2 | { 3 | public class LinkedListNode 4 | { 5 | public T Content { get; set; } 6 | public LinkedListNode Next { get; set; } 7 | 8 | public LinkedListNode() { } 9 | 10 | public LinkedListNode(T value) : this() 11 | { 12 | this.Content = value; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/AVLTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | /// 6 | /// Self-balansing binary search tree. 7 | /// The heights of the 2 child subtrees of any node differ by at most one. 8 | /// If at any time they differ by more than 1 - rebalancing is done to restore this property. 9 | /// Add: O(log n) 10 | /// Search: O(log n) 11 | /// Remove: O(log n) 12 | /// 13 | /// BalanceFactor has values in {-1, 0, 1} for each node in the tree 14 | /// If node has BF = -1 then it called "left-heavy" 15 | /// If node has BF = 1 then it called "right-heavy" 16 | /// If node has BF = 0 then it called "balanced" 17 | /// 18 | /// Type of data 19 | /// 20 | /// For lookup-intensive applications, faster than 21 | /// because they are more stricly balanced. 22 | /// Both are height-balanced, not weight-balanced. 23 | /// So sibling nodes can have hugely differing numbers of descendants 24 | /// 25 | public class AVLTree : BinarySearchTree> where T : IComparable 26 | { 27 | /// 28 | /// Insert content with balancing 29 | /// 30 | /// Content to insert 31 | /// Does element was added 32 | public override bool Insert(T content) 33 | { 34 | if (this.Root == null) 35 | { 36 | this.Root = new AVLTreeNode(content); 37 | return true; 38 | } 39 | 40 | if (this.FindIn(this.Root, content) != null) 41 | { 42 | return false; 43 | } 44 | 45 | var insertedNode = new AVLTreeNode(content); 46 | base.InsertNodeTo(this.Root, insertedNode); 47 | this.RebalanceIn(insertedNode); 48 | return true; 49 | } 50 | 51 | public override void MergeWith(AVLTree treeToMerge) 52 | { 53 | throw new NotSupportedException("Merge AVL trees currently doesn't supported"); 54 | } 55 | 56 | public override AVLTree SplitByKey(T key) 57 | { 58 | throw new NotSupportedException("Splitting AVL trees currently doesn't supported"); 59 | } 60 | 61 | /// 62 | /// Manual rotation doesn't allowed in AVL tree 63 | /// 64 | public override void RotateLeft() 65 | { 66 | throw new NotSupportedException("Manual rotating AVL trees currently doesn't supported"); 67 | } 68 | 69 | /// 70 | /// Manual rotation doesn't allowed in AVL tree 71 | /// 72 | public override void RotateRight() 73 | { 74 | throw new NotSupportedException("Manual rotating AVL trees currently doesn't supported"); 75 | } 76 | 77 | /// 78 | /// Verifying AVL tree node 79 | /// 80 | /// Tree node 81 | /// Tree min node 82 | /// Tree max node 83 | /// True if AVL tree node is valid 84 | protected override bool VerifyIn(BinarySearchTreeNode node, BinarySearchTreeNode min = null, BinarySearchTreeNode max = null) 85 | { 86 | var avlNode = node as AVLTreeNode; 87 | 88 | return avlNode.CalculatedHeight == avlNode.Height 89 | && Math.Abs(avlNode.BalanceFactor) < 2 90 | && base.VerifyIn(node, min, max); 91 | } 92 | 93 | protected override void Remove(BinarySearchTreeNode node) 94 | { 95 | if (node.IsTerminate) 96 | { 97 | var parentNode = node.Parent as AVLTreeNode; 98 | this.RemoveLeaf(node); 99 | this.RebalanceIn(parentNode as AVLTreeNode); 100 | } 101 | else 102 | { 103 | var leftHeight = node.Left?.Height ?? 0; 104 | var rightHeight = node.Right?.Height ?? 0; 105 | var nodeToReplace = leftHeight > rightHeight 106 | ? this.GetPredecessor(node.Content) 107 | : this.GetSuccessor(node.Content); 108 | 109 | node.Content = nodeToReplace.Content; 110 | this.Remove(nodeToReplace); 111 | } 112 | } 113 | 114 | /// 115 | /// Rebalancing tree 116 | /// 117 | /// Node to start rebalance 118 | private void RebalanceIn(AVLTreeNode node) 119 | { 120 | var currentNode = node; 121 | while (currentNode != null) 122 | { 123 | this.UpdateHeight(currentNode); 124 | 125 | var leftChild = currentNode.Left as AVLTreeNode; 126 | var rightChild = currentNode.Right as AVLTreeNode; 127 | 128 | if (currentNode.BalanceFactor == 2) 129 | { 130 | if (rightChild.BalanceFactor < 0) 131 | { 132 | currentNode.Right.Height--; 133 | currentNode.Right = this.RotateRight(currentNode.Right); 134 | currentNode.Right.Height++; 135 | } 136 | 137 | currentNode.Height -= 2; 138 | this.RotateLeft(currentNode); 139 | } 140 | 141 | if (currentNode.BalanceFactor == -2) 142 | { 143 | if (leftChild.BalanceFactor > 0) 144 | { 145 | currentNode.Left.Height--; 146 | currentNode.Left = this.RotateLeft(currentNode.Left); 147 | currentNode.Left.Height++; 148 | } 149 | 150 | currentNode.Height -= 2; 151 | this.RotateRight(currentNode); 152 | } 153 | 154 | currentNode = currentNode.Parent as AVLTreeNode; 155 | } 156 | } 157 | 158 | private void UpdateHeight(AVLTreeNode node) 159 | { 160 | if (node.IsTerminate) 161 | { 162 | node.Height = 0; 163 | return; 164 | } 165 | 166 | var leftChild = node.Left as AVLTreeNode; 167 | var rightChild = node.Right as AVLTreeNode; 168 | 169 | node.Height = 1 + Math.Max( 170 | leftChild?.Height ?? 0, 171 | rightChild?.Height ?? 0); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/AVLTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | /// 6 | /// AVL tree node. 7 | /// Contains left node which content less than this.Content 8 | /// Contains right node which content >= this.Content 9 | /// 10 | /// Type of content 11 | public class AVLTreeNode : BinarySearchTreeNode where T : IComparable 12 | { 13 | public AVLTreeNode(T content) 14 | : base(content) 15 | { 16 | } 17 | 18 | public int BalanceFactor 19 | { 20 | get { return ((this.Right as AVLTreeNode)?.Height ?? -1) - ((this.Left as AVLTreeNode)?.Height ?? -1); } 21 | } 22 | 23 | private int height = 0; 24 | public override int Height 25 | { 26 | get 27 | { 28 | return this.height; 29 | } 30 | set 31 | { 32 | this.height = value; 33 | } 34 | } 35 | 36 | public override bool HasLeft 37 | { 38 | get 39 | { 40 | return this.Left is AVLTreeNode; 41 | } 42 | } 43 | 44 | public override bool HasRight 45 | { 46 | get 47 | { 48 | return this.Right is AVLTreeNode; 49 | } 50 | } 51 | 52 | internal int CalculatedHeight 53 | { 54 | get { return base.Height; } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | /// 6 | /// Binary search tree node. 7 | /// Contains left node which content less than this.Content 8 | /// Contains right node which content >= this.Content 9 | /// 10 | /// Type of content 11 | public class BinarySearchTreeNode : ITreeNode> where T : IComparable 12 | { 13 | public T Content { get; set; } 14 | public BinarySearchTreeNode Parent { get; set; } 15 | public BinarySearchTreeNode Left { get; set; } 16 | public BinarySearchTreeNode Right { get; set; } 17 | 18 | public BinarySearchTreeNode(T content) 19 | { 20 | this.Content = content; 21 | } 22 | 23 | /// 24 | /// Has left child 25 | /// 26 | public virtual bool HasLeft 27 | { 28 | get { return this.Left != null; } 29 | } 30 | 31 | /// 32 | /// Has right child 33 | /// 34 | public virtual bool HasRight 35 | { 36 | get { return this.Right != null; } 37 | } 38 | 39 | /// 40 | /// Is this node - left child of its parent 41 | /// 42 | public bool IsLeftChild 43 | { 44 | get { return this.Parent != null && this.Parent.Left == this; } 45 | } 46 | 47 | /// 48 | /// Is this node - right child of its parent 49 | /// 50 | public bool IsRightChild 51 | { 52 | get { return this.Parent != null && this.Parent.Right == this; } 53 | } 54 | 55 | /// 56 | /// Is this node terminate (leaf) 57 | /// 58 | public bool IsTerminate 59 | { 60 | get { return !this.HasRight && !this.HasLeft; } 61 | } 62 | 63 | /// 64 | /// Is this node has parent 65 | /// 66 | public virtual bool HasParent 67 | { 68 | get { return this.Parent != null; } 69 | } 70 | 71 | /// 72 | /// Count of node's subtree (+ current node) 73 | /// 74 | public int Count 75 | { 76 | get { return 1 + (this.Left?.Count ?? 0) + (this.Right?.Count ?? 0); } 77 | } 78 | 79 | /// 80 | /// Height of the node (0 for leaf) 81 | /// 82 | public virtual int Height 83 | { 84 | get { return this.GetHeight(this); } 85 | set { } 86 | } 87 | 88 | /// 89 | /// Degree of outgoing nodes 90 | /// 91 | public int Degree 92 | { 93 | get { return (this.HasLeft ? 1 : 0) + (this.HasRight ? 1 : 0); } 94 | } 95 | 96 | public int Depth 97 | { 98 | get 99 | { 100 | if (this.Parent == null) 101 | { 102 | return 0; 103 | } 104 | 105 | return 1 + this.Parent.Depth; 106 | } 107 | } 108 | 109 | public int Level 110 | { 111 | get { return this.Depth + 1; } 112 | } 113 | 114 | public BinarySearchTreeNode Sibling 115 | { 116 | get 117 | { 118 | return this.IsRightChild 119 | ? this.Parent.Left 120 | : this.Parent?.Right; 121 | } 122 | } 123 | 124 | public BinarySearchTreeNode Uncle 125 | { 126 | get { return this.Parent?.Sibling; } 127 | } 128 | 129 | public BinarySearchTreeNode Grandparent 130 | { 131 | get { return this.Parent?.Parent; } 132 | } 133 | 134 | private int GetHeight(BinarySearchTreeNode node) 135 | { 136 | if (node.IsTerminate) 137 | { 138 | return 0; 139 | } 140 | 141 | var leftHeight = node.Left?.Height ?? 0; 142 | var rightHeight = node.Right?.Height ?? 0; 143 | 144 | return 1 + Math.Max(leftHeight, rightHeight); 145 | } 146 | 147 | public int CompareTo(ITreeNode> other) 148 | { 149 | return this.Content != null && other != null 150 | ? this.Content.CompareTo(other.Content) 151 | : -1; 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/ITree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | /// 6 | /// Tree - abstract data type that simulates a hierarchical tree structure with a root value 7 | /// and subtrees of children with a parent node, represented as a set of linked nodes. 8 | /// 9 | /// Can be defined recursively as a collection of the nodes (starting as a root node) 10 | /// where each node is a data structure consisting of a value together with a list of references to the nodes ("children") 11 | /// with the constraint that no reference is duplicated and none points to the root. 12 | /// 13 | /// Altenativaly: connected grapth without cylcles, edges are not oriented and without weight. 14 | /// 15 | /// Restrictions: 16 | /// 1. Root node cannot reference to itself - root couldn't has a parent 17 | /// 2. No Cycles - node can have only 1 parent 18 | /// 3. Connected parts - only 1 root. 19 | /// 20 | /// Definitions: 21 | /// Root - top node of a tree 22 | /// Child - A node directly connected to another when moving away from the root 23 | /// Parent - converse notation of the Child 24 | /// Siblings - group of nodes with the same parent 25 | /// Descendant - node reachable by repeated proceeding from parent to child 26 | /// Ascendant - node reachable by repeated proceeding from child to parent 27 | /// Leaf (external node) - node without children 28 | /// Branch (internal node) - node with at least one child 29 | /// Edge - connection between nodes 30 | /// Path - sequence of nodes and edges connecting node with descendant 31 | /// Height of node = number of edges on the longest path between node and a leaf 32 | /// Height of tree = height of its root node 33 | /// Forest - set of n >= 0 disjoing trees 34 | /// 35 | /// Definitions for balancing: 36 | /// Balance Factor of node = Height(node.Right) - Height(node.Left) 37 | /// 38 | /// 39 | /// Common usage: 40 | /// Representing hierarchical data 41 | /// Storing data in a way that makes it efficiently searchable 42 | /// Representing sorted lists of data 43 | /// As a workflow for compositing digital images for visual effects 44 | /// Routing algorithms 45 | /// 46 | public interface ITree where T : IComparable 47 | where NodeType : ITreeNode 48 | where TreeType : ITree 49 | { 50 | NodeType Root { get; set; } 51 | 52 | bool Insert(T content); 53 | NodeType Find(T content); 54 | bool Remove(T content); 55 | void Traverse(TraverseDirection direction, Action action, bool iterativeImplementation = false); 56 | bool Verify(); 57 | T GetMin(); 58 | T GetMax(); 59 | NodeType GetPredecessor(T key); 60 | NodeType GetSuccessor(T key); 61 | T GetKElementInOrder(int index); 62 | TreeType SplitByKey(T key); 63 | void MergeWith(TreeType treeToMerge); 64 | void RotateLeft(); 65 | void RotateRight(); 66 | NodeType GetCommonRoot(T nodeContent1, T nodeContent2); 67 | int DistanceBetween(T nodeContent1, T nodeContent2); 68 | } 69 | 70 | public enum TraverseDirection 71 | { 72 | // Depth first: 73 | Infix, 74 | Prefix, 75 | Postfix, 76 | // Breadth first: 77 | Breadth 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/ITreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | /// 6 | /// Tree node. 7 | /// 8 | /// Definitions: 9 | /// Height = number of edges on the longest path between node and a leaf 10 | /// Degree = number of subtrees of the node 11 | /// Depth = number of edges from the root to the node 12 | /// Level = 1 + (number of connections between node and the root) = 1 + Depth 13 | /// 14 | /// Type of content 15 | public interface ITreeNode : IComparable> 16 | where T : IComparable 17 | where NodeType : ITreeNode 18 | { 19 | T Content { get; set; } 20 | NodeType Parent { get; set; } 21 | 22 | bool HasParent { get; } 23 | bool IsTerminate { get; } 24 | int Count { get; } 25 | int Height { get; } 26 | int Degree { get; } 27 | int Depth { get; } 28 | int Level { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/RedBlackTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | /// 6 | /// Self-balansing binary search tree. 7 | /// Root is always black 8 | /// All leaves (NIL) are black 9 | /// Both children of red node are black 10 | /// Every path from a given node to any of its descendant NIL nodes contains the same number of black nodes. 11 | /// 12 | /// It leads to the critical property: 13 | /// The path from the root to the farthest leaf is no more than twice as long as 14 | /// the path form the root to the nearest leaf. 15 | /// Result of that - rought height-balanced. 16 | /// It leads that worst case of Inserting/Searching/Removing to be more efficient unlike 17 | /// 18 | /// Definitions: 19 | /// Black depth of node = number of black nodes from the root to a node 20 | /// Black height of RB tree = uniform number of black nodes in all paths from root to leaves 21 | /// Add: O(log n) 22 | /// Search: O(log n) 23 | /// Remove: O(log n) 24 | /// 25 | /// Type of data 26 | /// 27 | /// Is height-balanced, not weight-balanced. 28 | /// So sibling nodes can have hugely differing numbers of descendants 29 | /// 30 | public class RedBlackTree : BinarySearchTree> where T : IComparable 31 | { 32 | /// 33 | /// Insert content with balancing 34 | /// 35 | /// Content to insert 36 | /// Does element was added 37 | public override bool Insert(T content) 38 | { 39 | if (this.Root == null) 40 | { 41 | this.Root = new RedBlackTreeNode(content, NodeColor.Black); 42 | return true; 43 | } 44 | 45 | if (this.FindIn(this.Root, content) != null) 46 | { 47 | return false; 48 | } 49 | 50 | var insertedNode = new RedBlackTreeNode(content, NodeColor.Red); 51 | base.InsertNodeTo(this.Root, insertedNode); 52 | this.UpdateColorOnInsert(insertedNode); 53 | 54 | return true; 55 | } 56 | 57 | public override void MergeWith(RedBlackTree treeToMerge) 58 | { 59 | throw new NotSupportedException("Merge RB trees currently doesn't supported"); 60 | } 61 | 62 | public override RedBlackTree SplitByKey(T key) 63 | { 64 | throw new NotSupportedException("Splitting RB trees currently doesn't supported"); 65 | } 66 | 67 | /// 68 | /// Manual rotation doesn't allowed in RB tree 69 | /// 70 | public override void RotateLeft() 71 | { 72 | throw new NotSupportedException("Manual rotating RB trees currently doesn't supported"); 73 | } 74 | 75 | /// 76 | /// Manual rotation doesn't allowed in RB tree 77 | /// 78 | public override void RotateRight() 79 | { 80 | throw new NotSupportedException("Manual rotating RB trees currently doesn't supported"); 81 | } 82 | 83 | /// 84 | /// Verifying RB tree node 85 | /// 86 | /// Tree node 87 | /// Tree min node 88 | /// Tree max node 89 | /// True if RB tree node is valid 90 | protected override bool VerifyIn(BinarySearchTreeNode node, BinarySearchTreeNode min = null, BinarySearchTreeNode max = null) 91 | { 92 | var redBlackNode = node as RedBlackTreeNode; 93 | var left = node.Left as RedBlackTreeNode; 94 | var right = node.Right as RedBlackTreeNode; 95 | var root = this.Root as RedBlackTreeNode; 96 | 97 | var isColorMatching = redBlackNode.IsRed 98 | ? ((!node.HasLeft || left.IsBlack) && (!node.HasRight || right.IsBlack)) 99 | : true; 100 | 101 | return root.IsBlack 102 | && isColorMatching 103 | && (left?.BlackHeight ?? 1) == (right?.BlackHeight ?? 1) 104 | && base.VerifyIn(node, min, max); 105 | } 106 | 107 | protected override void Remove(BinarySearchTreeNode node) 108 | { 109 | if (node.HasRight && node.HasLeft) 110 | { 111 | var leftHeight = node.Left?.Height ?? 0; 112 | var rightHeight = node.Right?.Height ?? 0; 113 | var nodeToReplace = leftHeight > rightHeight 114 | ? this.GetPredecessor(node.Content) 115 | : this.GetSuccessor(node.Content); 116 | 117 | node.Content = nodeToReplace.Content; 118 | node = nodeToReplace; 119 | } 120 | 121 | // has 1 or 0 child 122 | var redBlackNode = node as RedBlackTreeNode; 123 | 124 | // if red and has no more than 1 child - it hasn't child 125 | if (redBlackNode.IsRed) 126 | { 127 | this.RemoveLeaf(node); 128 | return; 129 | } 130 | 131 | // node is black 132 | var child = (node.HasLeft 133 | ? node.Left 134 | : node.Right) as RedBlackTreeNode; 135 | 136 | // if black node has only 1 red child - copy content and remove child 137 | // (red child cannot contain any nodes) 138 | if (child != null && child.IsRed) 139 | { 140 | node.Content = child.Content; 141 | this.RemoveLeaf(child); 142 | return; 143 | } 144 | 145 | // node is black and no childs (black node cannot has just 1 black child) 146 | this.UpdateColorOnRemove(redBlackNode); 147 | this.RemoveLeaf(node); 148 | } 149 | 150 | private void UpdateColorOnInsert(RedBlackTreeNode node) 151 | { 152 | if (node == this.Root) 153 | { 154 | node.Color = NodeColor.Black; 155 | return; 156 | } 157 | 158 | node.Color = NodeColor.Red; 159 | 160 | var parent = node.Parent as RedBlackTreeNode; 161 | // if parent is black then nothing to do - all properties are still valid 162 | if (parent.IsBlack) 163 | { 164 | return; 165 | } 166 | 167 | // else we have parent as red so node has grandparent and uncle (uncle can be NIL) 168 | var uncle = node.Uncle as RedBlackTreeNode; 169 | var grandParent = node.Grandparent as RedBlackTreeNode; 170 | if (uncle != null && uncle.IsRed) 171 | { 172 | // if parent and uncle boths reds then recoloring them to black 173 | // and recoloring grandparent to red 174 | parent.Color = NodeColor.Black; 175 | uncle.Color = NodeColor.Black; 176 | this.UpdateColorOnInsert(grandParent); 177 | } 178 | else 179 | { 180 | // parent is red and uncle is black (real or NIL) 181 | // rotating of node "between" parent and uncle in ordering 182 | if (node.IsRightChild && node.Parent.IsLeftChild) 183 | { 184 | parent = this.RotateLeft(node.Parent) as RedBlackTreeNode; 185 | node = parent.Left as RedBlackTreeNode; 186 | } 187 | else if (node.IsLeftChild && node.Parent.IsRightChild) 188 | { 189 | parent = this.RotateRight(node.Parent) as RedBlackTreeNode; 190 | node = parent.Right as RedBlackTreeNode; 191 | } 192 | 193 | // parent is red and uncle is black (real or NIL) and node is greater or lesser boths 194 | // then rotating tree in the grandparent 195 | grandParent.Color = NodeColor.Red; 196 | parent.Color = NodeColor.Black; 197 | if (node.IsLeftChild && node.Parent.IsLeftChild) 198 | { 199 | this.RotateRight(node.Grandparent); 200 | } 201 | else 202 | { 203 | this.RotateLeft(node.Grandparent); 204 | } 205 | } 206 | } 207 | 208 | private void UpdateColorOnRemove(RedBlackTreeNode node) 209 | { 210 | if (!node.HasParent) 211 | { 212 | return; 213 | } 214 | 215 | // node is black 216 | var parent = node.Parent as RedBlackTreeNode; 217 | var sibling = node.Sibling as RedBlackTreeNode; 218 | 219 | if (sibling != null && sibling.IsRed) 220 | { 221 | sibling.Color = NodeColor.Black; 222 | parent.Color = NodeColor.Red; 223 | 224 | if (sibling.IsRightChild) 225 | { 226 | this.RotateLeft(parent); 227 | sibling = parent.Right as RedBlackTreeNode; 228 | } 229 | else 230 | { 231 | this.RotateRight(parent); 232 | sibling = parent.Left as RedBlackTreeNode; 233 | } 234 | } 235 | 236 | // after that sibling is black 237 | 238 | // if node, parent and sibling is black and terminate - recolor sibling to red and update color of parent 239 | if (parent.IsBlack && sibling.IsBlack && sibling.IsTerminate) 240 | { 241 | sibling.Color = NodeColor.Red; 242 | UpdateColorOnRemove(parent); 243 | return; 244 | } 245 | 246 | // if parent is red, sibling is black nd terminate - just recolor and that's all 247 | if (parent.IsRed && sibling.IsBlack && sibling.IsTerminate) 248 | { 249 | parent.Color = NodeColor.Black; 250 | sibling.Color = NodeColor.Red; 251 | return; 252 | } 253 | 254 | var leftChildOfSibling = sibling.Left as RedBlackTreeNode; 255 | var rightChildOfSibling = sibling.Right as RedBlackTreeNode; 256 | // cases when sibling has one red child "between" 257 | if (node.IsLeftChild 258 | && rightChildOfSibling == null 259 | && leftChildOfSibling != null 260 | && leftChildOfSibling.IsRed) 261 | { 262 | sibling.Color = NodeColor.Red; 263 | leftChildOfSibling.Color = NodeColor.Black; 264 | this.RotateRight(sibling); 265 | sibling = sibling.Parent as RedBlackTreeNode; 266 | } 267 | 268 | if (node.IsRightChild 269 | && leftChildOfSibling == null 270 | && rightChildOfSibling != null 271 | && rightChildOfSibling.IsRed) 272 | { 273 | sibling.Color = NodeColor.Red; 274 | rightChildOfSibling.Color = NodeColor.Black; 275 | this.RotateLeft(sibling); 276 | sibling = sibling.Parent as RedBlackTreeNode; 277 | } 278 | 279 | rightChildOfSibling = sibling.Right as RedBlackTreeNode; 280 | leftChildOfSibling = sibling.Left as RedBlackTreeNode; 281 | if (node.IsLeftChild 282 | && rightChildOfSibling != null 283 | && rightChildOfSibling.IsRed) 284 | { 285 | sibling.Color = parent.Color; 286 | parent.Color = NodeColor.Black; 287 | rightChildOfSibling.Color = NodeColor.Black; 288 | this.RotateLeft(parent); 289 | } 290 | else if (node.IsRightChild 291 | && leftChildOfSibling != null 292 | && leftChildOfSibling.IsRed) 293 | { 294 | sibling.Color = parent.Color; 295 | parent.Color = NodeColor.Black; 296 | leftChildOfSibling.Color = NodeColor.Black; 297 | this.RotateRight(parent); 298 | } 299 | } 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /Algorithms/DataStructures/Tree/RedBlackTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Tree 4 | { 5 | public enum NodeColor 6 | { 7 | Red, 8 | Black 9 | } 10 | 11 | /// 12 | /// Red black tree node. 13 | /// Contains left node which content less than this.Content 14 | /// Contains right node which content >= this.Content 15 | /// 16 | /// Type of content 17 | public class RedBlackTreeNode : BinarySearchTreeNode where T : IComparable 18 | { 19 | public RedBlackTreeNode(T content, NodeColor color) 20 | : base(content) 21 | { 22 | this.Color = color; 23 | } 24 | 25 | public NodeColor Color { get; set; } 26 | 27 | public bool IsRed 28 | { 29 | get { return this.Color == NodeColor.Red; } 30 | } 31 | 32 | public bool IsBlack 33 | { 34 | get { return this.Color == NodeColor.Black; } 35 | } 36 | 37 | public int BlackHeight 38 | { 39 | get 40 | { 41 | var thisNodeBlackAdditionalHeight = this.IsBlack ? 1 : 0; 42 | if (this.IsTerminate) 43 | { 44 | return 1 + thisNodeBlackAdditionalHeight; 45 | } 46 | 47 | if (this.HasLeft) 48 | { 49 | return (this.Left as RedBlackTreeNode).BlackHeight + thisNodeBlackAdditionalHeight; 50 | } 51 | else 52 | { 53 | return (this.Right as RedBlackTreeNode).BlackHeight + thisNodeBlackAdditionalHeight; 54 | } 55 | } 56 | } 57 | 58 | public override bool HasLeft 59 | { 60 | get 61 | { 62 | return this.Left is RedBlackTreeNode; 63 | } 64 | } 65 | 66 | public override bool HasRight 67 | { 68 | get 69 | { 70 | return this.Right is RedBlackTreeNode; 71 | } 72 | } 73 | 74 | public override bool HasParent 75 | { 76 | get 77 | { 78 | return this.Parent is RedBlackTreeNode; 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Algorithms/Helpers/PrimeList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.Helpers 4 | { 5 | public static class PrimeList 6 | { 7 | public static int GetNextPrime(int currentPrime) 8 | { 9 | var found = false; 10 | var nextPrime = currentPrime; 11 | while (!found) 12 | { 13 | nextPrime++; 14 | found = isPrime(nextPrime); 15 | } 16 | 17 | return nextPrime; 18 | } 19 | 20 | private static bool isPrime(int number) 21 | { 22 | if (number < 2) 23 | { 24 | return false; 25 | } 26 | 27 | if (number == 2) 28 | { 29 | return true; 30 | } 31 | 32 | var isPrime = true; 33 | for (int i = 2; i < Math.Max(Math.Sqrt(number), 3); i++) 34 | { 35 | if (number % i == 0) 36 | { 37 | isPrime = false; 38 | break; 39 | } 40 | } 41 | 42 | return isPrime; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Algorithms/Helpers/SortHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.Helpers 2 | { 3 | static class SortHelper 4 | { 5 | public static void swap(T[] array, int i, int j) 6 | { 7 | if (i == j || i < 0 || j < 0 || i >= array.Length || j >= array.Length) 8 | { 9 | return; 10 | } 11 | 12 | T temp = array[i]; 13 | array[i] = array[j]; 14 | array[j] = temp; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Algorithms/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("Algorithms")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Algorithms")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 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("80fa8f11-8329-4c23-891c-bd4f9fadaa91")] 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 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/ISorter.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.SortAlgorithms 2 | { 3 | /// 4 | /// O upper limit accurate assessment is unknown less or equals 5 | /// o upper limit not an accurate assessment less 6 | /// Theta upper, bottom limit equals 7 | /// Omega big bottom limit accurate assessment is unknown greater or equals 8 | /// Omega small bottom limit not an accurate assessment greater 9 | /// 10 | /// Stabtility - maintain the relative order of records with equal keys (values) 11 | /// Adaptability - whether or not the presortedness of the input affects the running time 12 | /// In-place - transforms input without additional data structures, only additional flat variables. Input usually overwrittern by output. 13 | /// 14 | /// Binary search tree: 15 | /// 1. Depth D or D-1 16 | /// 2. Value in vertex greater or equals than its leafs 17 | /// Implementation in array: 18 | /// A[i] >= A[2i + 1] 19 | /// A[i] >= A[2i + 2], 0 <= i <= n/2 20 | /// 21 | /// Type of array's elements 22 | public interface ISorter 23 | { 24 | void sort(T[] array); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/NonComparison/BucketSorter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.SortAlgorithms 4 | { 5 | /// 6 | /// Place items in the backet 7 | /// Best: Omega(n + k) 8 | /// Average: Theta(n + k) 9 | /// Worst: O(n^2) 10 | /// Additional memory: n + k 11 | /// where 0 < a[i] < k 12 | /// 13 | public class BucketSorter : ISorter 14 | { 15 | public void sort(int[] array) 16 | { 17 | if (array.Length < 2) 18 | { 19 | return; 20 | } 21 | 22 | var maxValue = array[0]; 23 | var minValue = array[0]; 24 | 25 | for (var i = 1; i < array.Length; i++) // find min and max to understand how much backets we need 26 | { 27 | if (array[i] > maxValue) 28 | { 29 | maxValue = array[i]; 30 | } 31 | 32 | if (array[i] < minValue) 33 | { 34 | minValue = array[i]; 35 | } 36 | } 37 | 38 | IList[] buckets = new List[maxValue - minValue + 1]; // creating buckets 39 | for (var i = 0; i < buckets.Length; i++) 40 | { 41 | buckets[i] = new List(); 42 | } 43 | 44 | for (var i = 0; i < array.Length; i++) // put items to the buckets 45 | { 46 | buckets[array[i] - minValue].Add(array[i]); 47 | } 48 | 49 | int position = 0; 50 | for (var i = 0; i < buckets.Length; i++) // place items back to array 51 | { 52 | if (buckets[i].Count > 0) 53 | { 54 | for (var j = 0; j < buckets[i].Count; j++) 55 | { 56 | array[position] = buckets[i][j]; 57 | position++; 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/NonComparison/CountingSorter.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.SortAlgorithms 2 | { 3 | /// 4 | /// Count how much items we have for each number 5 | /// Best: n + k 6 | /// Average: n + k 7 | /// Worst: n + k 8 | /// Additional memory: n + k 9 | /// where 0 < a[i] < k 10 | /// 11 | /// 12 | /// Unstable 13 | /// 14 | public class CountingSorter : ISorter 15 | { 16 | public void sort(int[] array) 17 | { 18 | if (array.Length < 2) 19 | { 20 | return; 21 | } 22 | 23 | var maxValue = array[0]; 24 | var minValue = array[0]; 25 | 26 | for (var i = 1; i < array.Length; i++) // find min and max to understand how much array length 27 | { 28 | if (array[i] > maxValue) 29 | { 30 | maxValue = array[i]; 31 | } 32 | 33 | if (array[i] < minValue) 34 | { 35 | minValue = array[i]; 36 | } 37 | } 38 | 39 | int[] counter = new int[maxValue - minValue + 1]; 40 | for (var i = 0; i < counter.Length; i++) 41 | { 42 | counter[i] = 0; 43 | } 44 | 45 | for (var i = 0; i < array.Length; i++) // put items to the counter 46 | { 47 | counter[array[i] - minValue]++; 48 | } 49 | 50 | int position = 0; 51 | for (var i = 0; i < counter.Length; i++) // place items back to array 52 | { 53 | while (counter[i] > 0) 54 | { 55 | array[position] = i + minValue; 56 | position++; 57 | counter[i]--; 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/NonComparison/CountingStableSorter.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.SortAlgorithms 2 | { 3 | /// 4 | /// Count how much items we have for each number 5 | /// Best: n + k 6 | /// Average: n + k 7 | /// Worst: n + k 8 | /// Additional memory: n + k 9 | /// where 0 < a[i] < k 10 | /// 11 | /// 12 | /// Stable 13 | /// 14 | public class CountingStableSorter : ISorter 15 | { 16 | public void sort(int[] array) 17 | { 18 | if (array.Length < 2) 19 | { 20 | return; 21 | } 22 | 23 | var maxValue = array[0]; 24 | var minValue = array[0]; 25 | 26 | for (var i = 1; i < array.Length; i++) // find min and max to understand how much array length 27 | { 28 | if (array[i] > maxValue) 29 | { 30 | maxValue = array[i]; 31 | } 32 | 33 | if (array[i] < minValue) 34 | { 35 | minValue = array[i]; 36 | } 37 | } 38 | 39 | int[] counter = new int[maxValue - minValue + 1]; 40 | for (var i = 0; i < counter.Length; i++) 41 | { 42 | counter[i] = 0; 43 | } 44 | 45 | for (var i = 0; i < array.Length; i++) // put items to the counter 46 | { 47 | counter[array[i] - minValue]++; 48 | } 49 | 50 | for (var i = 1; i < counter.Length; i++) 51 | { 52 | counter[i] += counter[i - 1]; 53 | } 54 | 55 | var resultArray = new int[array.Length]; 56 | for (var i = array.Length - 1; i >= 0; i--) // place items back to array 57 | { 58 | counter[array[i] - minValue]--; 59 | resultArray[counter[array[i] - minValue]] = array[i]; 60 | } 61 | 62 | for (var i = 0; i < array.Length; i++) // put items to the counter 63 | { 64 | array[i] = resultArray[i]; 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/NonComparison/LSDRadixSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// LSD - least significant digit 8 | /// Best: O(wn) 9 | /// Average: O(wn) 10 | /// Worst: O(wn) 11 | /// Additional memory: w + n 12 | /// where w - word size 13 | /// 14 | /// 15 | /// Applicable for numbers: 1, 2, 3, 10, 15 16 | /// Supports sorting negative numbers 17 | /// 18 | public class LSDRadixSorter : ISorter 19 | { 20 | public void sort(int[] array) 21 | { 22 | List negativeNumbers = new List(); 23 | List positiveNumbers = new List(); 24 | 25 | for (var i = 0; i < array.Length; i++) 26 | { 27 | if (array[i] >= 0) 28 | { 29 | positiveNumbers.Add(array[i]); 30 | } 31 | else 32 | { 33 | negativeNumbers.Add(-array[i]); 34 | } 35 | } 36 | 37 | this.internalSort(positiveNumbers); 38 | this.internalSort(negativeNumbers); 39 | 40 | var position = 0; 41 | for (var i = negativeNumbers.Count - 1; i >= 0; i--) 42 | { 43 | array[position] = -negativeNumbers[i]; 44 | position++; 45 | } 46 | 47 | for (var i = 0; i < positiveNumbers.Count; i++) 48 | { 49 | array[position] = positiveNumbers[i]; 50 | position++; 51 | } 52 | } 53 | 54 | private void internalSort(List array) 55 | { 56 | bool isFinished = false; 57 | int digitPosition = 0; 58 | 59 | Queue[] buckets = new Queue[10]; 60 | for (int i = 0; i < buckets.Length; i++) 61 | { 62 | buckets[i] = new Queue(); 63 | } 64 | 65 | while (!isFinished) 66 | { 67 | isFinished = true; 68 | 69 | foreach (int value in array) 70 | { 71 | int bucketNumber = (value / (int)Math.Pow(10, digitPosition)) % 10; 72 | if (bucketNumber > 0) 73 | { 74 | isFinished = false; 75 | } 76 | 77 | buckets[bucketNumber].Enqueue(value); 78 | } 79 | 80 | int i = 0; 81 | foreach (var bucket in buckets) 82 | { 83 | while (bucket.Count > 0) 84 | { 85 | array[i] = bucket.Dequeue(); 86 | i++; 87 | } 88 | } 89 | 90 | digitPosition++; 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/NonComparison/MSDRadixSorter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.SortAlgorithms 4 | { 5 | /// 6 | /// MSD - most significant digit 7 | /// Best: O(wn) 8 | /// Average: O(wn) 9 | /// Worst: O(wn) 10 | /// Additional memory: w + n 11 | /// where w - word size 12 | /// 13 | /// 14 | /// Applicable for string: b, ba, c, d, e, f, g, h, i, j 15 | /// - Recursive 16 | /// - If w is small and alphabet is big - many space is wasting 17 | /// 18 | public class MSDRadixSorter : ISorter 19 | { 20 | public void sort(string[] array) 21 | { 22 | this.internalSort(array, 0); 23 | } 24 | 25 | private void internalSort(string[] array, int charPosition) 26 | { 27 | if (array.Length <= 1) 28 | { 29 | return; 30 | } 31 | 32 | List[] buckets = new List[128]; 33 | for (var i = 0; i < buckets.Length; i++) 34 | { 35 | buckets[i] = new List(); 36 | } 37 | 38 | foreach (string value in array) 39 | { 40 | int bucketNumber = value.Length > charPosition 41 | ? value[charPosition] 42 | : 0; 43 | 44 | buckets[bucketNumber].Add(value); 45 | } 46 | 47 | charPosition++; 48 | int position = 0; 49 | foreach (var bucket in buckets) 50 | { 51 | if (bucket.Count > 0) 52 | { 53 | var sortedBucket = bucket.ToArray(); 54 | this.internalSort(sortedBucket, charPosition); 55 | 56 | foreach (var item in sortedBucket) 57 | { 58 | array[position] = item; 59 | position++; 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Stable/BubbleSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Best: O(n) 8 | /// Average: O(n^2) 9 | /// Worst: O(n^2) 10 | /// Additional memory: 1 11 | /// 12 | /// 13 | /// Stable 14 | /// 15 | /// Type of array's elements 16 | public class BubbleSorter : ISorter where T : IComparable 17 | { 18 | public void sort(T[] array) 19 | { 20 | for (var i = 0; i < array.Length - 1; i++) 21 | { 22 | for (var j = i; j < array.Length - 1; j++) 23 | { 24 | if (array[i].CompareTo(array[j + 1]) > 0) 25 | { 26 | SortHelper.swap(array, i, j + 1); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Stable/CocktailSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Goes back and forth, checking only part between last swaps 8 | /// Best: O(n) 9 | /// Average: O(n^2) 10 | /// Worst: O(n^2) 11 | /// Additional memory: 1 12 | /// 13 | /// 14 | /// Could be better than 15 | /// Stable 16 | /// 17 | /// Type of array's elements 18 | public class CocktailSorter : ISorter where T : IComparable 19 | { 20 | public void sort(T[] array) 21 | { 22 | var left = 0; 23 | var right = array.Length - 1; 24 | 25 | while (left <= right) 26 | { 27 | for (var i = left; i < right; i++) 28 | { 29 | if (array[i].CompareTo(array[i + 1]) > 0) 30 | { 31 | SortHelper.swap(array, i, i + 1); 32 | } 33 | 34 | } 35 | right--; 36 | 37 | for (var i = right; i > left; i--) 38 | { 39 | if (array[i - 1].CompareTo(array[i]) > 0) 40 | { 41 | SortHelper.swap(array, i - 1, i); 42 | } 43 | 44 | } 45 | left++; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Stable/GnomeSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Searching first place with incorrect pair and swapping them 8 | /// Best: O(n) 9 | /// Average: O(n^2) 10 | /// Worst: O(n^2) 11 | /// Additional memory: 1 12 | /// 13 | /// 14 | /// Similar like but before insertion swap series occurs, instead of shifts 15 | /// Can works with similar speed as 16 | /// j-optimization allows to jump to the latest compare place 17 | /// 18 | /// Type of array's elements 19 | public class GnomeSorter : ISorter where T : IComparable 20 | { 21 | public void sort(T[] array) 22 | { 23 | var i = 1; 24 | var j = 2; 25 | 26 | while (i < array.Length) 27 | { 28 | if (array[i - 1].CompareTo(array[i]) < 0) 29 | { 30 | i = j; 31 | j++; 32 | } 33 | else 34 | { 35 | SortHelper.swap(array, i - 1, i); 36 | i--; 37 | 38 | if (i == 0) 39 | { 40 | i = j; 41 | j++; 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Stable/InsertionSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.SortAlgorithms 4 | { 5 | /// 6 | /// Take next element and insert into sorted sequence 7 | /// Best: O(n) 8 | /// Average: O(n^2) 9 | /// Worst: O(n^2) 10 | /// Additional memory: 1 11 | /// 12 | /// 13 | /// + Simple implementation 14 | /// + Efficient for quite small data sets 15 | /// + More efficient than and 16 | /// + Adaptive 17 | /// + Stable 18 | /// + Online 19 | /// 20 | /// Type of array's elements 21 | public class InsertionSorter : ISorter where T : IComparable 22 | { 23 | public void sort(T[] array) 24 | { 25 | for (var i = 1; i < array.Length; i++) 26 | { 27 | var key = array[i]; // key to be inserted into sorted sequence 28 | var j = i - 1; 29 | 30 | while (j >= 0 && array[j].CompareTo(key) > 0) 31 | { 32 | array[j + 1] = array[j]; // shift sorted sequence while key is smaller 33 | j--; 34 | } 35 | 36 | array[j + 1] = key; // insrt key to the correct place 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Stable/MergeSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.SortAlgorithms 4 | { 5 | /// 6 | /// "Divide and conquer" 7 | /// Best: O(n log(n)) 8 | /// Average: O(n log(n)) 9 | /// Worst: O(n log(n)) 10 | /// Additional memory: O(n) 11 | /// 12 | /// 13 | /// + Works on strucctures with sequential access 14 | /// + Hasn't "bad" inputs 15 | /// + Stable 16 | /// - Best = Worst 17 | /// - Require O(n) additional memoty 18 | /// 19 | /// Type of array's elements 20 | public class MergeSorter : ISorter where T : IComparable 21 | { 22 | public void sort(T[] array) 23 | { 24 | this.mergeSort(array, 0, array.Length - 1); 25 | } 26 | 27 | private void mergeSort(T[] array, int begin, int end) 28 | { 29 | if (begin >= end) 30 | { 31 | return; 32 | } 33 | 34 | int middle = (begin + end) / 2; 35 | 36 | this.mergeSort(array, begin, middle); 37 | this.mergeSort(array, middle + 1, end); 38 | 39 | this.merge(array, begin, end, middle); 40 | } 41 | 42 | private void merge(T[] array, int begin, int end, int middle) 43 | { 44 | var result = new T[array.Length]; 45 | var left = begin; 46 | var right = middle + 1; 47 | var length = end - begin + 1; 48 | 49 | for (var i = begin; i <= end; i++) 50 | { 51 | if (left <= middle && right <= end) //if we have both arrays 52 | { 53 | if (array[left].CompareTo(array[right]) < 0) 54 | { 55 | result[i] = array[left]; // add minimal value 56 | left++; 57 | } 58 | else 59 | { 60 | result[i] = array[right]; 61 | right++; 62 | } 63 | } 64 | else if (left <= middle) // we have only left array 65 | { 66 | result[i] = array[left]; 67 | left++; 68 | } 69 | else // we have only right array 70 | { 71 | result[i] = array[right]; 72 | right++; 73 | } 74 | } 75 | 76 | for (var i = 0; i < length; i++) 77 | { 78 | array[end] = result[end]; 79 | end--; 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Stable/OddEvenSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Best: O(n) 8 | /// Average: O(n^2) 9 | /// Worst: O(n^2) 10 | /// Additional memory: 1 11 | /// 12 | /// 13 | /// Could be run in parallel processors easily 14 | /// Stable 15 | /// 16 | /// Type of array's elements 17 | public class OddEvenSorter : ISorter where T : IComparable 18 | { 19 | public void sort(T[] array) 20 | { 21 | var sorted = false; 22 | 23 | while (!sorted) 24 | { 25 | sorted = true; 26 | for (var i = 1; i < array.Length - 1; i += 2) 27 | { 28 | if (array[i].CompareTo(array[i + 1]) > 0) 29 | { 30 | SortHelper.swap(array, i, i + 1); 31 | sorted = false; 32 | } 33 | } 34 | 35 | for (var i = 0; i < array.Length - 1; i += 2) 36 | { 37 | if (array[i].CompareTo(array[i + 1]) > 0) 38 | { 39 | SortHelper.swap(array, i, i + 1); 40 | sorted = false; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Unstable/HeapSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Using binary search tree 8 | /// Best: O(n log(n)) 9 | /// Average: O(n log(n)) 10 | /// Worst: O(n log(n)) 11 | /// Additional memory: 1 12 | /// 13 | /// 14 | /// + In-place 15 | /// + In worst case: n log(n) 16 | /// - Not simple in implementation 17 | /// - In each step - chaotic read in array -> bad works with caching 18 | /// - Doesn't work with linked lists 19 | /// - Worst = Best 20 | /// - Not stable 21 | /// uses more memory but faster (O(n log(n)) with less const) and doesn't degradate. 22 | /// 23 | /// Type of array's elements 24 | public class HeapSorter : ISorter where T : IComparable 25 | { 26 | public void sort(T[] array) 27 | { 28 | int heapLength = array.Length; 29 | 30 | for (var i = (heapLength - 1) / 2; i >= 0; i--) 31 | { 32 | this.heapify(array, heapLength, i); 33 | } 34 | 35 | for (var i = array.Length - 1; i > 0; i--) 36 | { 37 | SortHelper.swap(array, 0, i); // put largest element from heap head to the end of array 38 | 39 | heapLength--; 40 | this.heapify(array, heapLength, 0); 41 | } 42 | } 43 | 44 | private void heapify(T[] array, int length, int begin) 45 | { 46 | int left = begin * 2 + 1; 47 | int right = begin * 2 + 2; 48 | int indexOfLargestElement = 0; 49 | 50 | if (left < length && array[left].CompareTo(array[begin]) > 0) // find largest element of i, 2i + 1 and 2i + 2 51 | { 52 | indexOfLargestElement = left; 53 | } 54 | else 55 | { 56 | indexOfLargestElement = begin; 57 | } 58 | 59 | if (right < length && array[right].CompareTo(array[indexOfLargestElement]) > 0) 60 | { 61 | indexOfLargestElement = right; 62 | } 63 | 64 | if (indexOfLargestElement != begin) 65 | { 66 | SortHelper.swap(array, indexOfLargestElement, begin); // put largest element to i-place and run heapify for replaced element 67 | 68 | this.heapify(array, length, indexOfLargestElement); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Unstable/QuickSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Speed based on selected pivot 8 | /// Best: O(n log(n)) 9 | /// Average: O(n log(n)) 10 | /// Worst: O(n^2) 11 | /// Additional memory: O(n log(n)) 12 | /// 13 | /// 14 | /// + In 3-way Best could be O(n) 15 | /// + Fatest in practice 16 | /// + Could be simple parallelized 17 | /// + Works with linked lists 18 | /// - Recursive 19 | /// - Fast degradation in "bad" inputes 20 | /// - Not stable 21 | /// 22 | /// Type of array's elements 23 | public class QuickSorter : ISorter where T : IComparable 24 | { 25 | public void sort(T[] array) 26 | { 27 | this.quickSort(array, 0, array.Length - 1); 28 | } 29 | 30 | private void quickSort(T[] array, int begin, int end) 31 | { 32 | if (begin >= end) 33 | { 34 | return; 35 | } 36 | 37 | int pivotIndex = this.partition(array, begin, end); 38 | 39 | this.quickSort(array, begin, pivotIndex - 1); 40 | this.quickSort(array, pivotIndex + 1, end); 41 | } 42 | 43 | private int partition(T[] array, int begin, int end) 44 | { 45 | T pivot = array[end]; 46 | int i = begin; // index to insert values 47 | 48 | for (int j = begin; j < end; j++) 49 | { 50 | if (array[j].CompareTo(pivot) <= 0) // if element less tham pivot - move to i-place 51 | { 52 | SortHelper.swap(array, i, j); 53 | i++; 54 | } 55 | } 56 | 57 | SortHelper.swap(array, i, end); // place pivot to middle between 'less' and 'greater' 58 | 59 | return i; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Unstable/SelectionSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Helpers; 3 | 4 | namespace Algorithms.SortAlgorithms 5 | { 6 | /// 7 | /// Best: O(n^2) 8 | /// Average: O(n^2) 9 | /// Worst: O(n^2) 10 | /// Additional memory: 1 11 | /// 12 | /// 13 | /// Find min 14 | /// Place in begin 15 | /// Begin ++ 16 | /// 17 | /// Type of array's elements 18 | public class SelectionSorter : ISorter where T : IComparable 19 | { 20 | public void sort(T[] array) 21 | { 22 | for (var i = 0; i < array.Length - 1; i++) 23 | { 24 | var min = i; 25 | for (var j = i + 1; j < array.Length; j++) // find minimal value 26 | { 27 | if (array[j].CompareTo(array[min]) < 0) 28 | { 29 | min = j; 30 | } 31 | } 32 | 33 | SortHelper.swap(array, i, min); // insert in the beginning 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Algorithms/SortAlgorithms/Unstable/ShellSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.SortAlgorithms 4 | { 5 | /// 6 | /// Take d (Fibonaccy sequense or (N, N/2, etc) or 2^i - 1 and etc 7 | /// Get all elements which indecies i and i+d 8 | /// Swap if needed 9 | /// Best: O(n log(n)) 10 | /// Average: O(n log(n)^2) 11 | /// Worst: O(n log(n)^2) 12 | /// Additional memory: 1 13 | /// 14 | /// 15 | /// + No callstack 16 | /// + O(1) additional memoty 17 | /// + No degradation in "bad" data cases 18 | /// 19 | /// Type of array's elements 20 | public class ShellSorter : ISorter where T : IComparable 21 | { 22 | public void sort(T[] array) 23 | { 24 | for (var d = array.Length / 2; d > 0; d /= 2) // go throw d sequence 25 | { 26 | for (var i = d; i < array.Length; i++) // go from d element to the end 27 | { 28 | var temp = array[i]; 29 | var j = i; 30 | for (j = i; j >= d; j -= d) // see back with step = d till begin 31 | { 32 | if (temp.CompareTo(array[j - d]) < 0) // find place to insert temp, until element is bigger 33 | { 34 | array[j] = array[j - d]; // insert sort 35 | } 36 | else 37 | { 38 | break; 39 | } 40 | } 41 | 42 | array[j] = temp; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AlgorithmsTests/AlgorithmsTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {3EA5ACEF-6FFF-4EA6-B1B5-FB5CBF96E02D} 7 | Library 8 | Properties 9 | AlgorithmsTests 10 | AlgorithmsTests 11 | v4.5.2 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | true 39 | bin\x64\Debug\ 40 | DEBUG;TRACE 41 | full 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | 46 | 47 | bin\x64\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | x64 52 | prompt 53 | MinimumRecommendedRules.ruleset 54 | 55 | 56 | 57 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll 58 | True 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | False 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | {80fa8f11-8329-4c23-891c-bd4f9fadaa91} 103 | Algorithms 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | False 115 | 116 | 117 | False 118 | 119 | 120 | False 121 | 122 | 123 | False 124 | 125 | 126 | 127 | 128 | 129 | 130 | 137 | -------------------------------------------------------------------------------- /AlgorithmsTests/CrackingTheCodeInterview/01ChapterStringArray/ArrayTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Interview.Chapter1; 2 | using NUnit.Framework; 3 | 4 | namespace AlgorithmsTests.CrackingTheCodeInterview._01ChapterStringArray 5 | { 6 | class ArrayTests 7 | { 8 | [Test] 9 | public void TestRotateArray() 10 | { 11 | var testArray = new int[10, 5]; 12 | Assert.DoesNotThrow(() => testArray.Rotate(), "not square array should just exit"); 13 | testArray = null; 14 | Assert.DoesNotThrow(() => testArray.Rotate(), "null array should just exit"); 15 | 16 | var array = new int[5, 5]; 17 | for (var i = 0; i < array.GetLength(0); i++) 18 | { 19 | for (var j = 0; j < array.GetLength(1); j++) 20 | { 21 | array[i, j] = (i + 1) * (j + 2); 22 | } 23 | } 24 | 25 | array.Rotate(); 26 | 27 | for (var i = 0; i < array.GetLength(0); i++) 28 | { 29 | for (var j = 0; j < array.GetLength(1); j++) 30 | { 31 | Assert.AreEqual((i + 2) * (array.GetLength(1) - j), array[i, j]); 32 | } 33 | } 34 | } 35 | 36 | [Test] 37 | public void TestZerofyArray() 38 | { 39 | int[,] testArray = null; 40 | Assert.DoesNotThrow(() => testArray.Zerofy(), "null array should just exit"); 41 | 42 | var array = new int[6, 5]; 43 | int zeroColumn = 1; 44 | int zeroRow = 4; 45 | for (var i = 0; i < array.GetLength(0); i++) 46 | { 47 | for (var j = 0; j < array.GetLength(1); j++) 48 | { 49 | if (i == zeroRow && j == zeroColumn) 50 | { 51 | array[i, j] = 0; 52 | } 53 | else 54 | { 55 | array[i, j] = 1; 56 | 57 | } 58 | } 59 | } 60 | 61 | array.Zerofy(); 62 | 63 | for (var i = 0; i < array.GetLength(0); i++) 64 | { 65 | for (var j = 0; j < array.GetLength(1); j++) 66 | { 67 | if (i == zeroRow || j == zeroColumn) 68 | { 69 | Assert.AreEqual(0, array[i, j]); 70 | } 71 | else 72 | { 73 | Assert.AreEqual(1, array[i, j]); 74 | } 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /AlgorithmsTests/CrackingTheCodeInterview/01ChapterStringArray/StringTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Interview.Chapter1; 2 | using NUnit.Framework; 3 | 4 | namespace AlgorithmsTests.Interview.Chapter1 5 | { 6 | class StringTests 7 | { 8 | [Test] 9 | public void TestUniqueStrings() 10 | { 11 | Assert.IsTrue("".IsUniqueChars(), "empty string has all unique chars"); 12 | Assert.IsTrue("abcde".IsUniqueChars(), "abcde has all unique chars"); 13 | Assert.IsFalse("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".IsUniqueChars(), "string too long to be unique"); 14 | Assert.IsFalse("abcdee".IsUniqueChars(), "abcde has all unique chars"); 15 | } 16 | 17 | [Test] 18 | public void TestReverse() 19 | { 20 | Assert.AreEqual("", "".Reverse(), "empty string has empty reverse"); 21 | Assert.AreEqual("1", "1".Reverse(), "Reverse string with 1 char works"); 22 | Assert.AreEqual("12", "21".Reverse(), "Reverse string with 2 chars works"); 23 | Assert.AreEqual("121", "121".Reverse(), "Reverse string with 3 chars works"); 24 | Assert.AreEqual("abcde", "edcba".Reverse(), "Reverse string with 5 chars works"); 25 | } 26 | 27 | [Test] 28 | public void TestPermutation() 29 | { 30 | Assert.IsFalse("".IsPermutationOf(""), "empty cannot be permutation"); 31 | Assert.IsTrue("1".IsPermutationOf("1"), "check permutation of string"); 32 | Assert.IsTrue("12".IsPermutationOf("21"), "check permutation of string"); 33 | Assert.IsTrue("1233".IsPermutationOf("3321"), "check permutation of string"); 34 | Assert.IsTrue("12 33".IsPermutationOf("332 1"), "check permutation of string"); 35 | Assert.IsFalse("12 33".IsPermutationOf("33 1"), "check permutation of string"); 36 | Assert.IsFalse("12 33".IsPermutationOf("abc"), "check permutation of string"); 37 | } 38 | 39 | [Test] 40 | public void TestReplacingSpace() 41 | { 42 | Assert.AreEqual("", "".ReplaceSpace(), "empty string has 0 replacement"); 43 | Assert.AreEqual("1", "1".ReplaceSpace(), "string without spaces has 0 replacement"); 44 | Assert.AreEqual("%20", " ".ReplaceSpace(), "string with 1 spaces has 1 replacement"); 45 | Assert.AreEqual("%201", " 1".ReplaceSpace(), "string with 1 spaces has 1 replacement"); 46 | Assert.AreEqual("%201%20", " 1 ".ReplaceSpace(), "string with 2 spaces has 2 replacements"); 47 | } 48 | 49 | [Test] 50 | public void TestIsPermutationOfPalindrome() 51 | { 52 | Assert.IsFalse("".IsPermutationOfPalindrome(), "empty cannot be permutation of palindrome"); 53 | Assert.IsTrue(" ".IsPermutationOfPalindrome(), "Space is permutation of palindrome"); 54 | Assert.IsTrue(" 11 ".IsPermutationOfPalindrome(), "Test is permutation of palindrome"); 55 | Assert.IsTrue(" 121 ".IsPermutationOfPalindrome(), "Test is permutation of palindrome"); 56 | Assert.IsTrue("1 1211 ".IsPermutationOfPalindrome(), "Test is permutation of palindrome"); 57 | Assert.IsFalse("1 1333211 ".IsPermutationOfPalindrome(), "Test is permutation of palindrome"); 58 | Assert.IsFalse("1 133211 ".IsPermutationOfPalindrome(), "Test is permutation of palindrome"); 59 | } 60 | 61 | [Test] 62 | public void TestSimilar() 63 | { 64 | Assert.IsFalse("".IsSimilarLike(""), "empty cannot be similar"); 65 | Assert.IsTrue("1".IsSimilarLike("12"), "test on adding"); 66 | Assert.IsTrue("123".IsSimilarLike("12"), "test on removing"); 67 | Assert.IsTrue("123".IsSimilarLike("124"), "test on editing"); 68 | Assert.IsFalse("12345".IsSimilarLike("12444"), "test on failure edit"); 69 | Assert.IsFalse("12345".IsSimilarLike("124"), "test on failure removal"); 70 | Assert.IsFalse("12345".IsSimilarLike("1225"), "test on failure removal"); 71 | Assert.IsFalse("12 45".IsSimilarLike("124"), "test on failure removal"); 72 | } 73 | 74 | [Test] 75 | public void TestAcrhiving() 76 | { 77 | Assert.AreEqual("", "".Archive(), "empty string has empty archive"); 78 | Assert.AreEqual("a", "a".Archive(), "single string has same archive"); 79 | Assert.AreEqual("a2", "aa".Archive(), "simple archiving"); 80 | Assert.AreEqual("a3", "aaa".Archive(), "string should be archived"); 81 | Assert.AreEqual("abc", "abc".Archive(), "string should be not archived"); 82 | Assert.AreEqual("a11b2c1", "aaaaaaaaaaabbc".Archive(), "string should be archived"); 83 | } 84 | 85 | [Test] 86 | public void TestIsCycleShift() 87 | { 88 | Assert.IsFalse("".IsCycleShift(""), "empty cannot be cycle shift"); 89 | Assert.IsTrue("1".IsCycleShift("1"), "test on cycle shift single char"); 90 | Assert.IsTrue("12".IsCycleShift("21"), "test on cycle shift string"); 91 | Assert.IsTrue("abcde".IsCycleShift("deabc"), "test on cycle shift string"); 92 | Assert.IsFalse("12345".IsCycleShift("12444"), "test on failure cycle shifting"); 93 | Assert.IsFalse("12345".IsCycleShift("144"), "test on failure cycle shifting"); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /AlgorithmsTests/CrackingTheCodeInterview/02ChapterLinkedLists/LinkedListTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.LinkedList; 2 | using Algorithms.Interview.Chapter2; 3 | using NUnit.Framework; 4 | 5 | namespace AlgorithmsTests.Interview.Chapter2 6 | { 7 | class LinkedListTests 8 | { 9 | [Test] 10 | public static void TestRemoveDuplicates() 11 | { 12 | LinkedList list = null; 13 | Assert.DoesNotThrow(() => list.RemoveDuplicates(), "empty list hasn't duplicates"); 14 | list = new LinkedList(); 15 | list.RemoveDuplicates(); 16 | Assert.IsNull(list.Head, "empty list hasn't duplicates"); 17 | 18 | list = new LinkedList(new int[] { }); 19 | list.RemoveDuplicates(); 20 | Assert.IsNull(list.Head, "empty list hasn't duplicates"); 21 | 22 | list = new LinkedList(new int[] { 5, 5, 5, 5, 6, 6 }); 23 | list.RemoveDuplicates(); 24 | 25 | Assert.IsTrue(list.IsSameListAs(new LinkedList(new int[] { 5, 6 })), "check that dulicated are removed"); 26 | 27 | list = new LinkedList(); 28 | list.AddToBegin(10); 29 | list.RemoveDuplicates(); 30 | Assert.IsTrue(list.IsSameListAs(new LinkedList(new int[] { 10 })), "check that if no duplicates - then list is the same"); 31 | } 32 | 33 | [Test] 34 | public void TestGetKFromEnd() 35 | { 36 | LinkedList list = null; 37 | Assert.DoesNotThrow(() => list.GetKFromEnd(1), "empty list hasn't duplicates"); 38 | list = new LinkedList(new int[] { 5, 4, 3, 2, 1, 0 }); 39 | Assert.AreEqual(5, list.GetKFromEnd(5).Content, "check getting first element"); 40 | Assert.AreEqual(3, list.GetKFromEnd(3).Content, "check getting middle element"); 41 | Assert.AreEqual(0, list.GetKFromEnd(0).Content, "check getting last element"); 42 | Assert.IsNull(list.GetKFromEnd(6), "check when k > lengt"); 43 | } 44 | 45 | [Test] 46 | public void TestRemoveFromMiddle() 47 | { 48 | LinkedList list = new LinkedList(); 49 | Assert.DoesNotThrow(() => list.Head.RemoveFromMiddle(), "cannot return first element"); 50 | list = new LinkedList(new int[] { 0, 1, 2 }); 51 | 52 | Assert.DoesNotThrow(() => list.Head.Next.RemoveFromMiddle(), "cannot return first element"); 53 | Assert.IsTrue(list.IsSameListAs(new LinkedList(new int[] { 0, 2 })), "check that middle element has been removed"); 54 | } 55 | 56 | [Test] 57 | public void TestSortAround() 58 | { 59 | LinkedList list = null; 60 | Assert.DoesNotThrow(() => list.SortAround(1), "empty list doesn't run sorting"); 61 | 62 | list = new LinkedList(); 63 | Assert.DoesNotThrow(() => list.SortAround(0), "if list is empty then no sort executed"); 64 | 65 | list = new LinkedList(new int[] { 2, 5, 3, 5, 0, 1, 2 }); 66 | list.SortAround(5); 67 | Assert.IsTrue(list.IsSameListAs(new LinkedList(new int[] { 2, 3, 0, 1, 2, 5, 5 })), "check that sort around works as expected"); 68 | list.SortAround(10); 69 | Assert.IsTrue(list.IsSameListAs(new LinkedList(new int[] { 2, 3, 0, 1, 2, 5, 5 })), "check that sort around by not-existed element works as expected"); 70 | list.AddToBegin(-1); 71 | list.SortAround(-5); 72 | Assert.IsTrue(list.IsSameListAs(new LinkedList(new int[] { -1, 2, 3, 0, 1, 2, 5, 5 })), "check that sort around by first element works as expected"); 73 | Assert.IsFalse(list.IsSameListAs(new LinkedList(new int[] { })), "check that sort around by first element works as expected"); 74 | Assert.IsFalse(list.IsSameListAs(new LinkedList(new int[] { -1, 1 })), "check that sort around by first element works as expected"); 75 | Assert.IsFalse(list.IsSameListAs(null), "check that sort around by first element works as expected"); 76 | } 77 | 78 | [Test] 79 | public void TestSumReversed() 80 | { 81 | LinkedList list = null; 82 | Assert.DoesNotThrow(() => list.SumReversed(null), "empty list doesn't sum something"); 83 | 84 | list = new LinkedList(); 85 | list.AddToBegin(5); 86 | Assert.IsTrue(list.SumReversed(null).IsSameListAs(list), "check that sum with empty return same list"); 87 | list = new LinkedList(new int[] { 3, 0, 1 }); 88 | LinkedList list2 = new LinkedList(new int[] { 0, 1 }); 89 | Assert.IsTrue(list.SumReversed(list2).IsSameListAs(new LinkedList(new int[] { 3, 1, 1 })), "check that sum works correct with different length"); 90 | 91 | LinkedList list3 = new LinkedList(new int[] { 0, 0, 9 }); 92 | Assert.IsTrue(list.SumReversed(list3).IsSameListAs(new LinkedList(new int[] { 3, 0, 0, 1 })), "check that sum works correct with different length"); 93 | } 94 | 95 | [Test] 96 | public void TestSum() 97 | { 98 | LinkedList list = null; 99 | Assert.DoesNotThrow(() => list.Sum(null), "empty list doesn't sum something"); 100 | 101 | list = new LinkedList(); 102 | list.AddToBegin(5); 103 | Assert.IsTrue(list.Sum(null).IsSameListAs(list), "check that sum with empty return same list"); 104 | list = new LinkedList(new int[] { 1, 0, 5 }); 105 | LinkedList list2 = new LinkedList(new int[] { 1, 5 }); 106 | Assert.IsTrue(list.Sum(list2).IsSameListAs(new LinkedList(new int[] { 1, 2, 0 })), "check that sum works correct with different length"); 107 | 108 | LinkedList list3 = new LinkedList(new int[] { 9, 1, 0 }); 109 | Assert.IsTrue(list.Sum(list3).IsSameListAs(new LinkedList(new int[] { 1, 0, 1, 5 })), "check that sum works correct with different length"); 110 | 111 | LinkedList list4 = new LinkedList(new int[] { 1, 9, 1, 0 }); 112 | Assert.IsTrue(list.Sum(list4).IsSameListAs(new LinkedList(new int[] { 2, 0, 1, 5 })), "check that sum works correct with different length"); 113 | } 114 | 115 | [Test] 116 | public void TestIsPalindrome() 117 | { 118 | LinkedList list = null; 119 | Assert.DoesNotThrow(() => list.IsPalindrome(), "empty list is not palindrome"); 120 | 121 | list = new LinkedList(new int[] { 1 }); 122 | Assert.IsTrue(list.IsPalindrome(), "list of 1 element is always palindrome"); 123 | 124 | list = new LinkedList(new int[] { 1, 2 }); 125 | Assert.IsFalse(list.IsPalindrome(), "list of 2 different elements is not palindrome"); 126 | 127 | list = new LinkedList(new int[] { 1, 2, 1 }); 128 | Assert.IsTrue(list.IsPalindrome(), "check that list of 3 elements is palindrome"); 129 | 130 | list = new LinkedList(new int[] { 1, 2, 2, 1 }); 131 | Assert.IsTrue(list.IsPalindrome(), "check that list of 4 elements is palindrome"); 132 | } 133 | 134 | [Test] 135 | public void TestIntersection() 136 | { 137 | LinkedList list = null; 138 | Assert.IsNull(list.GetIntersection(null), "empty lists han't intersection"); 139 | 140 | list = new LinkedList(new int[] { 1, 2 }); 141 | var list2 = new LinkedList(new int[] { 1, 2 }); 142 | 143 | Assert.IsNull(list.GetIntersection(list2), "different lists hasn't intersection"); 144 | 145 | list2 = new LinkedList(); 146 | list2.AddToBegin(5); 147 | list2.Head.Next = list.Head.Next; 148 | 149 | Assert.IsNotNull(list.GetIntersection(list2), "test on intersection with same length"); 150 | Assert.AreEqual(2, list.GetIntersection(list2).Content, "test on intersection with same length"); 151 | 152 | list2.AddToBegin(1); 153 | Assert.IsNotNull(list.GetIntersection(list2), "test on intersection with different length"); 154 | Assert.AreEqual(2, list.GetIntersection(list2).Content, "test on intersection with different length"); 155 | } 156 | 157 | [Test] 158 | public void TestLoopStart() 159 | { 160 | LinkedList list = null; 161 | Assert.IsNull(list.GetStartOfLoop(), "empty lists hasn't loop"); 162 | 163 | list = new LinkedList(new int[] { 1, 2 }); 164 | 165 | Assert.IsNull(list.GetStartOfLoop(), "simple list hasn't loop"); 166 | list.AddToEnd(3); 167 | list.Head.Next.Next.Next = list.Head.Next; 168 | 169 | Assert.IsNotNull(list.GetStartOfLoop(), "loop list has loop"); 170 | Assert.AreEqual(2, list.GetStartOfLoop().Content, "loop list has loop"); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /AlgorithmsTests/CrackingTheCodeInterview/03ChapterStackQueue/QueueTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Interview.Chapter3; 2 | using NUnit.Framework; 3 | 4 | namespace AlgorithmsTests.Interview.Chapter3 5 | { 6 | class QueueTests 7 | { 8 | [Test] 9 | public void TestQueueBasedOnStacks() 10 | { 11 | var queue = new QueueBasedOnStacks(); 12 | 13 | queue.Enqueue(1); 14 | queue.Enqueue(2); 15 | queue.Enqueue(3); 16 | 17 | Assert.AreEqual(1, queue.Dequeue(), "queue should dequeue correct element"); 18 | Assert.AreEqual(2, queue.Dequeue(), "queue should dequeue correct element"); 19 | Assert.AreEqual(3, queue.Dequeue(), "queue should dequeue correct element"); 20 | 21 | queue.Enqueue(1); 22 | queue.Enqueue(2); 23 | Assert.AreEqual(1, queue.Dequeue(), "queue should dequeue correct element"); 24 | 25 | queue.Enqueue(3); 26 | Assert.AreEqual(2, queue.Dequeue(), "queue should dequeue correct element"); 27 | Assert.AreEqual(3, queue.Dequeue(), "queue should dequeue correct element"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /AlgorithmsTests/CrackingTheCodeInterview/03ChapterStackQueue/StackTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Algorithms.Interview.Chapter3; 4 | using NUnit.Framework; 5 | 6 | namespace AlgorithmsTests.Interview.Chapter3 7 | { 8 | class StackTests 9 | { 10 | [Test] 11 | public void TestStackWithMin() 12 | { 13 | var stack = new StackWithMin(); 14 | 15 | stack.Push(1); 16 | Assert.AreEqual(1, stack.Min, "stack has correct min value after pushing"); 17 | 18 | stack.Push(2); 19 | Assert.AreEqual(1, stack.Min, "stack has correct min value after pushing"); 20 | 21 | stack.Push(0); 22 | Assert.AreEqual(0, stack.Min, "stack has correct min value after pushing"); 23 | 24 | stack.Pop(); 25 | Assert.AreEqual(1, stack.Min, "stack has correct min value after popping"); 26 | } 27 | 28 | [Test] 29 | public void TestStackSet() 30 | { 31 | var stackSet = new StackSet(2); 32 | 33 | stackSet.Push(1); 34 | stackSet.Push(2); 35 | stackSet.Push(3); 36 | stackSet.Push(4); 37 | Assert.AreEqual(4, stackSet.Pop(), "stack set has correct top value"); 38 | 39 | stackSet.Push(4); 40 | stackSet.Push(5); 41 | Assert.AreEqual(2, stackSet.PopAt(0), "stack set has correct top value in first stack"); 42 | Assert.AreEqual(1, stackSet.PopAt(0), "stack set has correct top value in first stack"); 43 | Assert.AreEqual(5, stackSet.PopAt(1), "stack set has correct top value in first stack"); 44 | 45 | Assert.Throws(() => stackSet.PopAt(2), "stack set has only 2 stacks"); 46 | } 47 | 48 | [Test] 49 | public void TestStackSorting() 50 | { 51 | var stack = new Stack(); 52 | 53 | stack.Push(1); 54 | stack.Push(2); 55 | stack.Push(3); 56 | 57 | stack = stack.Sort(); 58 | Assert.AreEqual(1, stack.Pop(), "test stack sorting"); 59 | Assert.AreEqual(2, stack.Pop(), "test stack sorting"); 60 | Assert.AreEqual(3, stack.Pop(), "test stack sorting"); 61 | 62 | stack.Push(2); 63 | stack.Push(1); 64 | stack.Push(3); 65 | stack = stack.Sort(); 66 | 67 | Assert.AreEqual(1, stack.Pop(), "test stack sorting"); 68 | Assert.AreEqual(2, stack.Pop(), "test stack sorting"); 69 | Assert.AreEqual(3, stack.Pop(), "test stack sorting"); 70 | 71 | stack.Push(3); 72 | stack.Push(2); 73 | stack.Push(1); 74 | stack = stack.Sort(); 75 | 76 | Assert.AreEqual(1, stack.Pop(), "test stack sorting"); 77 | Assert.AreEqual(2, stack.Pop(), "test stack sorting"); 78 | Assert.AreEqual(3, stack.Pop(), "test stack sorting"); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /AlgorithmsTests/CrackingTheCodeInterview/04ChapterTreeGraph/TreeTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Interview.Chapter4; 2 | using NUnit.Framework; 3 | 4 | namespace AlgorithmsTests.Interview.Chapter4 5 | { 6 | class TreeTests 7 | { 8 | [Test] 9 | public void TestGeneratingBSTFromSortedArray() 10 | { 11 | var array = new int[] { 1, 2, 3, 4, 5, 6 }; 12 | 13 | var tree = TreeExtensions.CreateBalancedBinarySearchTreeFromSortedArray(array); 14 | Assert.AreEqual(4, tree.Root.Content, "root should be middle of array"); 15 | Assert.AreEqual(2, tree.Root.Left.Content, "check correctness of created BST"); 16 | Assert.AreEqual(6, tree.Root.Right.Content, "check correctness of created BST"); 17 | 18 | Assert.AreEqual(1, tree.Root.Left.Left.Content, "check correctness of created BST"); 19 | Assert.AreEqual(3, tree.Root.Left.Right.Content, "check correctness of created BST"); 20 | 21 | Assert.AreEqual(5, tree.Root.Right.Left.Content, "check correctness of created BST"); 22 | Assert.IsNull(tree.Root.Right.Right, "check correctness of created BST"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /AlgorithmsTests/DataStructures/Graph/GraphTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.DataStructures.Graph; 3 | using NUnit.Framework; 4 | 5 | namespace AlgorithmsTests.DataStructures.Graph 6 | { 7 | class GraphTests 8 | { 9 | [Test] 10 | public void TestGraphAreConnected() 11 | { 12 | var graph = new Graph(); 13 | var node1 = graph.AddNode(1); 14 | var node2 = graph.AddNode(2); 15 | var node3 = graph.AddNode(3); 16 | var node4 = graph.AddNode(4); 17 | 18 | graph.AddEdge(node1, node2); 19 | graph.AddEdge(node2, node3); 20 | 21 | Assert.IsTrue(graph.AreConnected(node1, node3), "nodes are connected via node2"); 22 | Assert.IsFalse(graph.AreConnected(node1, node4), "nodes are not connected"); 23 | 24 | var node5 = new GraphNode(5); 25 | Assert.IsFalse(graph.AreConnected(node1, node5), "nodes are not connected"); 26 | 27 | graph.AddEdge(node1, node1); 28 | Assert.IsFalse(graph.AddEdge(node1, node5), "cannot add edge between nodes not from graph"); 29 | Assert.IsFalse(graph.RemoveEdge(node1, node5), "cannot remove edge between nodes not from graph"); 30 | Assert.IsTrue(graph.AreConnected(node1, node3), "nodes are connected via node2"); 31 | } 32 | 33 | [Test] 34 | public void TestLexicographicOrder() 35 | { 36 | var graph = new Graph(); 37 | var node1 = graph.AddNode(1); 38 | var node2 = graph.AddNode(2); 39 | 40 | graph.AddEdge(node1, node2); 41 | Assert.Throws(() => graph.GetLexicographicOrder(), "graph with dual dependencies hasn't lexicographic order"); 42 | 43 | graph.RemoveEdge(node1, node2); 44 | var node3 = graph.AddNode(3); 45 | var node4 = graph.AddNode(4); 46 | 47 | graph.AddEdge(node1, node2, true); 48 | graph.AddEdge(node1, node3, true); 49 | graph.AddEdge(node1, node4, true); 50 | graph.AddEdge(node4, node2, true); 51 | 52 | var node5 = new GraphNode(5); 53 | Assert.IsFalse(graph.RemoveNode(node5), "cannot remove node if graph hasn't this node"); 54 | node5 = graph.AddNode(5); 55 | graph.AddEdge(node5, node1); 56 | graph.RemoveNode(node5); 57 | 58 | var order = graph.GetLexicographicOrder(); 59 | Assert.AreEqual(4, order.Count, "order should has same count as nodes count"); 60 | Assert.AreEqual(1, order[0].Content, "order should has same count as nodes count"); 61 | Assert.AreEqual(3, order[1].Content, "order should has same count as nodes count"); 62 | Assert.AreEqual(4, order[2].Content, "order should has same count as nodes count"); 63 | Assert.AreEqual(2, order[3].Content, "order should has same count as nodes count"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /AlgorithmsTests/DataStructures/HashTable/HashTableTestsFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Algorithms.DataStructures.HashTable; 4 | using NUnit.Framework; 5 | 6 | namespace AlgorithmsTests.SortAlgorithms.DataStructures.LinkedList 7 | { 8 | [TestFixture] 9 | public class HashTableTestsFactory 10 | { 11 | Type[] hashTableTypes; 12 | public HashTableTestsFactory() 13 | { 14 | Type sorterType = typeof(IHashTable); 15 | 16 | this.hashTableTypes = AppDomain 17 | .CurrentDomain 18 | .GetAssemblies() 19 | .SelectMany(assembly => assembly.GetTypes()) 20 | .Where(type => sorterType.IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface) 21 | .ToArray(); 22 | } 23 | 24 | [Test] 25 | public void HashTableCreationTest() 26 | { 27 | foreach (Type hashTableType in this.hashTableTypes) 28 | { 29 | IHashTable hashTable = Activator.CreateInstance(hashTableType) as IHashTable; 30 | 31 | Assert.IsNotNull(hashTable); 32 | Assert.IsFalse(hashTable.Contains(5), 33 | "hash table [{0}] should not contains any value after creation", 34 | hashTableType.Name); 35 | } 36 | } 37 | 38 | [Test] 39 | public void HashTableAddingTest() 40 | { 41 | foreach (Type hashTableType in this.hashTableTypes) 42 | { 43 | IHashTable hashTable = Activator.CreateInstance(hashTableType) as IHashTable; 44 | Assert.IsTrue(hashTable.Add(5)); 45 | 46 | Assert.IsTrue(hashTable.Contains(5), 47 | "hash table [{0}] should contains added value", 48 | hashTableType.Name); 49 | } 50 | } 51 | 52 | [Test] 53 | public void HashTableClearTest() 54 | { 55 | foreach (Type hashTableType in this.hashTableTypes) 56 | { 57 | IHashTable hashTable = Activator.CreateInstance(hashTableType) as IHashTable; 58 | Assert.IsTrue(hashTable.Add(5)); 59 | hashTable.Clear(); 60 | 61 | Assert.IsTrue(hashTable.Count() == 0, 62 | "hash table [{0}] should contains 0 elements after clearing", 63 | hashTableType.Name); 64 | } 65 | } 66 | 67 | [Test] 68 | public void HashTableRemovingTest() 69 | { 70 | foreach (Type hashTableType in this.hashTableTypes) 71 | { 72 | IHashTable hashTable = Activator.CreateInstance(hashTableType) as IHashTable; 73 | Assert.IsTrue(hashTable.Add(5)); 74 | Assert.IsTrue(hashTable.Add(15)); 75 | Assert.IsTrue(hashTable.Add(14)); 76 | 77 | Assert.IsTrue(hashTable.Remove(15), 78 | "hash table [{0}] should remove existed element", 79 | hashTableType.Name); 80 | 81 | Assert.IsFalse(hashTable.Remove(17), 82 | "hash table [{0}] should not be able to remove not existed element", 83 | hashTableType.Name); 84 | 85 | Assert.IsTrue(hashTable.Contains(5), 86 | "hash table [{0}] should contains not removed element", 87 | hashTableType.Name); 88 | 89 | Assert.IsFalse(hashTable.Contains(15), 90 | "hash table [{0}] should not contains removed element", 91 | hashTableType.Name); 92 | } 93 | } 94 | 95 | [Test] 96 | public void HashTableRebuildTest() 97 | { 98 | foreach (Type hashTableType in this.hashTableTypes) 99 | { 100 | IHashTable hashTable = Activator.CreateInstance(hashTableType, 2) as IHashTable; 101 | Assert.IsTrue(hashTable.Add(5)); 102 | Assert.IsTrue(hashTable.Add(15)); 103 | Assert.IsTrue(hashTable.Add(13)); 104 | Assert.IsTrue(hashTable.Add(17)); 105 | 106 | Assert.IsTrue(hashTable.Contains(15), 107 | "hash table [{0}] should contains element 15 after rebuilding", 108 | hashTableType.Name); 109 | 110 | Assert.IsTrue(hashTable.Contains(5), 111 | "hash table [{0}] should contains element 5 after rebuilding", 112 | hashTableType.Name); 113 | 114 | Assert.IsTrue(hashTable.Contains(13), 115 | "hash table [{0}] should contains element 14 after rebuilding", 116 | hashTableType.Name); 117 | } 118 | } 119 | 120 | [Test] 121 | public void HashTableEnumeratorTest() 122 | { 123 | foreach (Type hashTableType in this.hashTableTypes) 124 | { 125 | IHashTable hashTable = Activator.CreateInstance(hashTableType, 2) as IHashTable; 126 | 127 | var items = new int[] { 5, 15, 13 }; 128 | foreach (var item in items) 129 | { 130 | hashTable.Add(item); 131 | } 132 | 133 | hashTable.Add(31); 134 | hashTable.Remove(31); 135 | 136 | foreach (var item in hashTable) 137 | { 138 | Assert.IsTrue(items.Contains(item), 139 | "hash table [{0}] should contains element [{1}] in enumerator", 140 | hashTableType.Name, 141 | item); 142 | } 143 | } 144 | } 145 | 146 | [Test] 147 | public void QuadraticHashTableOverloadingAddingTest() 148 | { 149 | IHashTable hashTable = new QuadraticHashTable(2); 150 | Assert.IsTrue(hashTable.Add(3)); 151 | Assert.IsTrue(hashTable.Add(3)); 152 | Assert.IsFalse(hashTable.Add(3), 153 | "quadritic hash table should not be able to add element"); 154 | 155 | Assert.IsTrue(hashTable.Count() == 2, 156 | "quadritic hash table count should be 2 after not-successfull adding"); 157 | } 158 | 159 | [Test] 160 | public void QuadraticHashTableOverloadingContainsTest() 161 | { 162 | IHashTable hashTable = new QuadraticHashTable(2); 163 | Assert.IsTrue(hashTable.Add(3)); 164 | Assert.IsTrue(hashTable.Add(3)); 165 | Assert.IsFalse(hashTable.Add(6), 166 | "quadritic hash table should not be able to add element"); 167 | 168 | Assert.IsFalse(hashTable.Contains(6), 169 | "quadritic hash table should not contains not added element"); 170 | } 171 | 172 | [Test] 173 | public void QuadraticHashTableOverloadingRemoveTest() 174 | { 175 | IHashTable hashTable = new QuadraticHashTable(2); 176 | Assert.IsTrue(hashTable.Add(3)); 177 | Assert.IsTrue(hashTable.Add(3)); 178 | Assert.IsFalse(hashTable.Add(6), 179 | "quadritic hash table should not be able to add element"); 180 | 181 | Assert.IsFalse(hashTable.Remove(6), 182 | "quadritic hash table should not be able to remove not-added element"); 183 | 184 | Assert.IsTrue(hashTable.Remove(3), 185 | "quadritic hash table should be able to remove existed element"); 186 | 187 | Assert.IsTrue(hashTable.Add(3), 188 | "quadritic hash table should be able to add element again"); 189 | 190 | Assert.IsTrue(hashTable.Count() == 2, 191 | "quadritic hash table has 2 elements after testing"); 192 | } 193 | 194 | [Test] 195 | public void DoubleHashTableOverloadingRemoveTest() 196 | { 197 | IHashTable hashTable = new DoubleHashTable(2); 198 | Assert.IsTrue(hashTable.Add(3)); 199 | Assert.IsTrue(hashTable.Add(18)); 200 | 201 | Assert.IsFalse(hashTable.Remove(16), 202 | "quadritic hash table should not be able to remove not-added element"); 203 | 204 | Assert.IsTrue(hashTable.Remove(18), 205 | "quadritic hash table should be able to remove existed element"); 206 | 207 | Assert.IsTrue(hashTable.Add(18), 208 | "quadritic hash table should be able to add element again"); 209 | 210 | Assert.IsTrue(hashTable.Count() == 2, 211 | "quadritic hash table has 2 elements after testing"); 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /AlgorithmsTests/DataStructures/Heap/HeapTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace AlgorithmsTests.DataStructures.Heap 4 | { 5 | public class HeapTests 6 | { 7 | [Test] 8 | public void TestMinHeap() 9 | { 10 | var minHeap = new Algorithms.DataStructures.Heap.Heap(true); 11 | Assert.AreEqual(0, minHeap.Count(), "Empty heap should contain 0 elements"); 12 | Assert.AreEqual(0, minHeap.Peek(), "Empty heap should contain 0 at the top"); 13 | Assert.AreEqual(0, minHeap.ExtractTop(), "Heap should contain 0 at the top"); 14 | minHeap.Add(10); 15 | Assert.AreEqual(10, minHeap.Peek(), "Heap should contain 10 at the top"); 16 | minHeap.Add(9); 17 | minHeap.Add(3); 18 | minHeap.Add(13); 19 | 20 | Assert.AreEqual(3, minHeap.Peek(), "Heap should contain 3 at the top"); 21 | Assert.AreEqual(3, minHeap.ExtractTop(), "Heap should contain 3 at the top"); 22 | Assert.AreEqual(9, minHeap.Peek(), "Heap should contain 9 at the top"); 23 | Assert.IsTrue(minHeap.Validate(), "Heap should be valid"); 24 | } 25 | 26 | [Test] 27 | public void TestMaxHeap() 28 | { 29 | var maxHeap = new Algorithms.DataStructures.Heap.Heap(false); 30 | Assert.AreEqual(0, maxHeap.Count(), "Empty heap should contain 0 elements"); 31 | Assert.AreEqual(0, maxHeap.Peek(), "Empty heap should contain 0 at the top"); 32 | Assert.IsTrue(maxHeap.Validate(), "Heap should be valid"); 33 | maxHeap.Add(10); 34 | Assert.AreEqual(10, maxHeap.Peek(), "Heap should contain 10 at the top"); 35 | maxHeap.Add(9); 36 | maxHeap.Add(3); 37 | maxHeap.Add(13); 38 | 39 | Assert.AreEqual(13, maxHeap.Peek(), "Heap should contain 13 at the top"); 40 | Assert.AreEqual(13, maxHeap.ExtractTop(), "Heap should contain 13 at the top"); 41 | Assert.AreEqual(10, maxHeap.Peek(), "Heap should contain 10 at the top"); 42 | Assert.IsTrue(maxHeap.Validate(), "Heap should be valid"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AlgorithmsTests/DataStructures/Tree/BinarySearchTreeNodeTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Tree; 2 | using NUnit.Framework; 3 | 4 | namespace AlgorithmsTests.DataStructures.Tree 5 | { 6 | public class BinarySearchTreeNodeTests 7 | { 8 | [Test] 9 | public void BinarySearchTreeNodeDegreeTest() 10 | { 11 | var tree = new BinarySearchTree(); 12 | tree.Insert(5); 13 | tree.Insert(4); 14 | tree.Insert(6); 15 | 16 | Assert.AreEqual(2, tree.Root.Degree, "Root node should has 2 degree"); 17 | Assert.AreEqual(0, tree.Root.Left.Degree, "Left node should has 0 degree"); 18 | } 19 | 20 | [Test] 21 | public void BinarySearchTreeNodeDepthTest() 22 | { 23 | var tree = new BinarySearchTree(); 24 | tree.Insert(5); 25 | tree.Insert(4); 26 | tree.Insert(6); 27 | 28 | Assert.AreEqual(0, tree.Root.Depth, "Root node should has 0 depth"); 29 | Assert.AreEqual(1, tree.Root.Left.Depth, "Left node should has 1 depth"); 30 | } 31 | 32 | [Test] 33 | public void BinarySearchTreeNodeLevelTest() 34 | { 35 | var tree = new BinarySearchTree(); 36 | tree.Insert(5); 37 | tree.Insert(4); 38 | tree.Insert(6); 39 | 40 | Assert.AreEqual(1, tree.Root.Level, "Root node should has 1 level"); 41 | Assert.AreEqual(2, tree.Root.Left.Level, "Left node should has 2 level"); 42 | } 43 | 44 | [Test] 45 | public void BinarySearchTreeNodeHeightTest() 46 | { 47 | var tree = new BinarySearchTree(); 48 | tree.Insert(5); 49 | tree.Insert(4); 50 | tree.Insert(6); 51 | 52 | Assert.AreEqual(1, tree.Root.Height, "Root node should has 1 height"); 53 | tree.Root.Height = 4; 54 | 55 | Assert.AreEqual(1, tree.Root.Height, "Root node should not changed manually"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AlgorithmsTests/DataStructures/Tree/RedBlackTreeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.DataStructures.Tree; 3 | using NUnit.Framework; 4 | 5 | namespace AlgorithmsTests.DataStructures.Tree 6 | { 7 | public class RedBlackTreeTests 8 | { 9 | [Test] 10 | public void RedBlackTreeInsertTest() 11 | { 12 | var tree = new RedBlackTree(); 13 | tree.Insert(4); 14 | tree.Insert(2); 15 | tree.Insert(1); 16 | Assert.IsFalse(tree.Insert(1), "RB tree shouldn't be able to insert duplicated element"); 17 | 18 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after insertion"); 19 | Assert.AreEqual(2, tree.Root.Content, "RB tree should be rebalanced after insert and has root == 2"); 20 | } 21 | 22 | [Test] 23 | public void RedBlackTreeRebalanceTest() 24 | { 25 | var tree = new RedBlackTree(); 26 | tree.Insert(2); 27 | tree.Insert(6); 28 | tree.Insert(1); 29 | tree.Insert(3); 30 | tree.Insert(11); 31 | tree.Insert(15); 32 | 33 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after insertion"); 34 | Assert.AreEqual(2, tree.Root.Content, "RB tree should be rebalanced after insert and has root == 2"); 35 | 36 | tree.Insert(5); 37 | tree.Insert(4); 38 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after insertion"); 39 | 40 | tree.Insert(8); 41 | tree.Insert(7); 42 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after insertion"); 43 | tree.Insert(9); 44 | tree.Insert(10); 45 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after insertion"); 46 | 47 | tree.Insert(12); 48 | tree.Insert(13); 49 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after insertion"); 50 | } 51 | 52 | [Test] 53 | public void RedBlackTreeNotSupportedOperationTest() 54 | { 55 | var tree = new RedBlackTree(); 56 | tree.Insert(2); 57 | tree.Insert(6); 58 | tree.Insert(1); 59 | tree.Insert(3); 60 | tree.Insert(11); 61 | tree.Insert(12); 62 | 63 | Assert.Throws(() => tree.RotateLeft(), "RB tree doesn't allow rotating"); 64 | Assert.Throws(() => tree.RotateRight(), "RB tree doesn't allow rotating"); 65 | Assert.Throws(() => tree.SplitByKey(0), "RB tree doesn't allow splitting"); 66 | Assert.Throws(() => tree.MergeWith(new RedBlackTree()), "RB tree doesn't allow merging"); 67 | } 68 | 69 | [Test] 70 | public void RedBlackTreeRemoveTest() 71 | { 72 | var tree = new RedBlackTree(); 73 | tree.Insert(2); 74 | tree.Insert(6); 75 | tree.Insert(1); 76 | tree.Insert(3); 77 | Assert.IsTrue(tree.Remove(3), "RB tree should be able to remove existed element"); 78 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 79 | 80 | tree.Insert(11); 81 | tree.Insert(100); 82 | 83 | Assert.IsFalse(tree.Remove(-1), "RB tree shouldn't be able to remove not-existed element"); 84 | Assert.IsTrue(tree.Remove(1), "RB tree should be able to remove existed element"); 85 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 86 | Assert.AreEqual(4, tree.Root.Count, "RB tree should contain correct count of elements after removing"); 87 | 88 | Assert.IsTrue(tree.Remove(2), "RB tree should be able to remove existed element"); 89 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 90 | 91 | tree.Insert(60); 92 | tree.Insert(30); 93 | tree.Insert(20); 94 | Assert.IsTrue(tree.Remove(6), "RB tree should be able to remove existed element"); 95 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 96 | Assert.AreEqual(5, tree.Root.Count, "RB tree should contain correct count of elements after removing"); 97 | 98 | Assert.IsTrue(tree.Remove(60), "RB tree should be able to remove existed element"); 99 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 100 | 101 | tree.Insert(25); 102 | tree.Insert(28); 103 | Assert.IsTrue(tree.Remove(100), "RB tree should be able to remove existed element"); 104 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 105 | 106 | Assert.IsTrue(tree.Remove(25), "RB tree should be able to remove existed element"); 107 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 108 | 109 | Assert.IsTrue(tree.Remove(30), "RB tree should be able to remove existed element"); 110 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 111 | 112 | Assert.IsTrue(tree.Remove(11), "RB tree should be able to remove existed element"); 113 | Assert.IsTrue(tree.Verify(), "RB tree should be valid after element removing"); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /AlgorithmsTests/HelperTests/PrimeListTests.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Helpers; 2 | using NUnit.Framework; 3 | 4 | namespace AlgorithmsTests.HelperTests 5 | { 6 | class PrimeListTests 7 | { 8 | [Test] 9 | public void PrimeListTest() 10 | { 11 | Assert.AreEqual(2, PrimeList.GetNextPrime(0), "Next prime after 0 is 2"); 12 | Assert.AreEqual(2, PrimeList.GetNextPrime(1), "Next prime after 1 is 2"); 13 | Assert.AreEqual(3, PrimeList.GetNextPrime(2), "Next prime after 2 is 3"); 14 | Assert.AreEqual(5, PrimeList.GetNextPrime(3), "Next prime after 3 is 5"); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AlgorithmsTests/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("AlgorithmsTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AlgorithmsTests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 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("3ea5acef-6fff-4ea6-b1b5-fb5cbf96e02d")] 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 | -------------------------------------------------------------------------------- /AlgorithmsTests/SortAlgorithms/SorterTestsFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Algorithms.SortAlgorithms; 4 | using NUnit.Framework; 5 | 6 | namespace AlgorithmsTests.SortAlgorithms 7 | { 8 | [TestFixture] 9 | class SorterTestsFactory 10 | { 11 | Type[] sorterTypes; 12 | Type[] allTypes; 13 | public SorterTestsFactory() 14 | { 15 | Type sorterType = typeof(ISorter<>); 16 | Type sorterHelperType = typeof(ISorterTester<>); 17 | 18 | this.allTypes = AppDomain 19 | .CurrentDomain 20 | .GetAssemblies() 21 | .SelectMany(assembly => assembly.GetTypes()) 22 | .Where(type => !type.IsAbstract && !type.IsInterface) 23 | .ToArray(); 24 | this.sorterTypes = this.allTypes 25 | .Where(type => type.GetInterface("ISorter`1") != null) 26 | .ToArray(); 27 | } 28 | 29 | [Test] 30 | public void TestAllIntegerSorters() 31 | { 32 | this.TestAllSorters(); 33 | } 34 | 35 | [Test] 36 | public void TestAllDoubleSorters() 37 | { 38 | this.TestAllSorters(); 39 | } 40 | 41 | [Test] 42 | public void TestAllStringSorters() 43 | { 44 | this.TestAllSorters(); 45 | } 46 | 47 | [Test] 48 | public void TestAllCharSorters() 49 | { 50 | this.TestAllSorters(); 51 | } 52 | 53 | public void TestAllSorters() 54 | { 55 | Type sorterTesterType = typeof(ISorterTester); 56 | var sorterTesterTypes = this.allTypes 57 | .Where(type => sorterTesterType.IsAssignableFrom(type) && !type.IsGenericTypeDefinition) 58 | .ToArray(); 59 | 60 | Assert.IsTrue(sorterTesterTypes.Any(), "there is no sorter for this type of data"); 61 | var sorterHelper = Activator.CreateInstance(sorterTesterTypes[0]) as ISorterTester; 62 | 63 | foreach (Type sorterType in this.sorterTypes) 64 | { 65 | ISorter sorterImplementation = null; 66 | 67 | if (sorterType.IsGenericTypeDefinition) 68 | { 69 | Type[] typeArgs = { typeof(T) }; 70 | Type constructed = sorterType.MakeGenericType(typeArgs); 71 | sorterImplementation = Activator.CreateInstance(constructed) as ISorter; 72 | } 73 | else if (typeof(ISorter).IsAssignableFrom(sorterType)) 74 | { 75 | sorterImplementation = Activator.CreateInstance(sorterType) as ISorter; 76 | } 77 | 78 | if (sorterImplementation != null) 79 | { 80 | sorterHelper.TestSortedSequence(sorterImplementation); 81 | sorterHelper.TestReverseSortedSequence(sorterImplementation); 82 | sorterHelper.TestRandomSequence(sorterImplementation); 83 | SorterTestsHelper.TestSorterOnEmptyData(sorterImplementation); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /AlgorithmsTests/SortAlgorithms/SorterTestsHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Algorithms.SortAlgorithms; 3 | using NUnit.Framework; 4 | 5 | namespace AlgorithmsTests.SortAlgorithms 6 | { 7 | class SorterTestsHelper 8 | { 9 | public static void TestSorter(T[] input, T[] expectedOutput, ISorter sorterAlgorithm) 10 | { 11 | Assert.IsNotNull(input, "input is invalid"); 12 | Assert.IsNotNull(expectedOutput, "expectedOutput is invalid"); 13 | Assert.IsNotNull(sorterAlgorithm, "sorterAlgorithm is invalid"); 14 | 15 | T[] originalInput = new T[input.Length]; 16 | input.CopyTo(originalInput, 0); 17 | sorterAlgorithm.sort(input); 18 | 19 | CollectionAssert.AreEqual( 20 | input, 21 | expectedOutput, 22 | string.Format("Sorter [{0}] can't sort next sequence: [{1}]. Expected result: [{2}]. Actual result: [{3}]", 23 | sorterAlgorithm.GetType().Name, 24 | originalInput.Select(x => x.ToString()).Aggregate((x, y) => x + ", " + y), 25 | expectedOutput.Select(x => x.ToString()).Aggregate((x, y) => x + ", " + y), 26 | input.Select(x => x.ToString()).Aggregate((x, y) => x + ", " + y))); 27 | } 28 | 29 | public static void TestSorterOnEmptyData(ISorter sorterAlgorithm) 30 | { 31 | Assert.IsNotNull(sorterAlgorithm, "sorterAlgorithm is invalid"); 32 | var input = new T[0]; 33 | sorterAlgorithm.sort(input); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /AlgorithmsTests/SorterHelper/ISorterTester.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.SortAlgorithms; 2 | 3 | namespace AlgorithmsTests.SortAlgorithms 4 | { 5 | interface ISorterTester 6 | { 7 | void TestSortedSequence(ISorter sorter); 8 | void TestReverseSortedSequence(ISorter sorter); 9 | void TestRandomSequence(ISorter sorter); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /AlgorithmsTests/SorterHelper/SorterCharTester.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.SortAlgorithms; 2 | 3 | namespace AlgorithmsTests.SortAlgorithms 4 | { 5 | class SorterCharTester: ISorterTester 6 | { 7 | public void TestSortedSequence(ISorter sorter) 8 | { 9 | var input = new char[] { 'a', 'b', 'c', 'd', 'e' }; 10 | var expected = new char[] { 'a', 'b', 'c', 'd', 'e' }; 11 | SorterTestsHelper.TestSorter(input, expected, sorter); 12 | } 13 | 14 | public void TestReverseSortedSequence(ISorter sorter) 15 | { 16 | var input = new char[] { 'e', 'd', 'c', 'b', 'a' }; 17 | var expected = new char[] { 'a', 'b', 'c', 'd', 'e' }; 18 | SorterTestsHelper.TestSorter(input, expected, sorter); 19 | } 20 | 21 | public void TestRandomSequence(ISorter sorter) 22 | { 23 | var input = new char[] { 'b', 'd', 'c', 'e', 'a' }; 24 | var expected = new char[] { 'a', 'b', 'c', 'd', 'e' }; 25 | SorterTestsHelper.TestSorter(input, expected, sorter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AlgorithmsTests/SorterHelper/SorterDoubleTester.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Algorithms.SortAlgorithms; 3 | 4 | namespace AlgorithmsTests.SortAlgorithms 5 | { 6 | class SorterDoubleTester: ISorterTester 7 | { 8 | private const int testLength = 50; 9 | public void TestSortedSequence(ISorter sorter) 10 | { 11 | var baseSequense = Enumerable 12 | .Range(1, testLength) 13 | .Select(x => x + 0.5); 14 | var input = baseSequense.ToArray(); 15 | var expected = baseSequense.ToArray(); 16 | SorterTestsHelper.TestSorter(input, expected, sorter); 17 | } 18 | 19 | public void TestReverseSortedSequence(ISorter sorter) 20 | { 21 | var input = Enumerable 22 | .Range(-3, testLength) 23 | .Select(x => x + 0.5) 24 | .Reverse() 25 | .ToArray(); 26 | 27 | var expected = Enumerable 28 | .Range(-3, testLength) 29 | .Select(x => x + 0.5) 30 | .ToArray(); 31 | SorterTestsHelper.TestSorter(input, expected, sorter); 32 | } 33 | 34 | public void TestRandomSequence(ISorter sorter) 35 | { 36 | var input = new double[] { 4.5, 1.5, 2.5, 3.5, 5.5 }; 37 | var expected = Enumerable 38 | .Range(1, 5) 39 | .Select(x => x + 0.5) 40 | .ToArray(); 41 | SorterTestsHelper.TestSorter(input, expected, sorter); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /AlgorithmsTests/SorterHelper/SorterIntegerTester.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Algorithms.SortAlgorithms; 3 | 4 | namespace AlgorithmsTests.SortAlgorithms 5 | { 6 | class SorterIntegerTester : ISorterTester 7 | { 8 | private const int testLength = 50; 9 | public void TestSortedSequence(ISorter sorter) 10 | { 11 | var baseSequense = Enumerable.Range(1, testLength); 12 | var input = baseSequense.ToArray(); 13 | var expected = baseSequense.ToArray(); 14 | SorterTestsHelper.TestSorter(input, expected, sorter); 15 | } 16 | 17 | public void TestReverseSortedSequence(ISorter sorter) 18 | { 19 | var input = Enumerable.Range(-3, testLength).Reverse().ToArray(); 20 | var expected = Enumerable.Range(-3, testLength).ToArray(); 21 | SorterTestsHelper.TestSorter(input, expected, sorter); 22 | } 23 | 24 | public void TestRandomSequence(ISorter sorter) 25 | { 26 | var input = new int[] { 45, 11, 299, 30, 51, 0 }; 27 | var expected = new int[] { 0, 11, 30, 45, 51, 299 }; 28 | SorterTestsHelper.TestSorter(input, expected, sorter); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /AlgorithmsTests/SorterHelper/SorterStringTester.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.SortAlgorithms; 2 | 3 | namespace AlgorithmsTests.SortAlgorithms 4 | { 5 | class SorterStringTester : ISorterTester 6 | { 7 | public void TestSortedSequence(ISorter sorter) 8 | { 9 | var input = new string[] { "a", "b", "c", "d", "e" }; 10 | var expected = new string[] { "a", "b", "c", "d", "e" }; 11 | SorterTestsHelper.TestSorter(input, expected, sorter); 12 | } 13 | 14 | public void TestReverseSortedSequence(ISorter sorter) 15 | { 16 | var input = new string[] { "e", "d", "c", "b", "a" }; 17 | var expected = new string[] { "a", "b", "c", "d", "e" }; 18 | SorterTestsHelper.TestSorter(input, expected, sorter); 19 | } 20 | 21 | public void TestRandomSequence(ISorter sorter) 22 | { 23 | var input = new string[] { "e", "d", "c", "bd", "abc", "ab" }; 24 | var expected = new string[] { "ab", "abc", "bd", "c", "d", "e" }; 25 | SorterTestsHelper.TestSorter(input, expected, sorter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AlgorithmsTests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Evgenia Filatova 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sorting and data structure algorithms [![Build Status](https://travis-ci.org/Silvochka/algorithms.svg?branch=dev)](https://travis-ci.org/Silvochka/algorithms) [![Build status](https://ci.appveyor.com/api/projects/status/i9w52t621058hwln/branch/dev?svg=true)](https://ci.appveyor.com/project/Silvochka/algorithms/branch/dev) [![Coverage Status](https://coveralls.io/repos/github/Silvochka/algorithms/badge.svg?branch=dev&bust=1)](https://coveralls.io/github/Silvochka/algorithms?branch=dev) 2 | 3 | This repo is a C# library with implemented sorting alrogithms, structures and its algorithms. 4 | 5 | SortingAlgorithms: 6 | - Stable, generic: 7 | - [Bubble sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Stable/BubbleSorter.cs) 8 | - [Cocktail sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Stable/CocktailSorter.cs) 9 | - [Gnome sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Stable/GnomeSorter.cs) 10 | - [Insertion sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Stable/InsertionSorter.cs) 11 | - [Merge sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Stable/MergeSorter.cs) 12 | - [OddEven sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Stable/OddEvenSorter.cs) 13 | - Unstable, generic: 14 | - [Heap sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Unstable/HeapSorter.cs) 15 | - [Quick sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Unstable/QuickSorter.cs) 16 | - [Selection sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Unstable/SelectionSorter.cs) 17 | - [Shell sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/Unstable/ShellSorter.cs) 18 | - Non-comparison based algorithms: 19 | - [Bucket sort](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/NonComparison/BucketSorter.cs) - implemented for integer 20 | - [Couting sort (stable)](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/NonComparison/CountingStableSorter.cs) - implemented for integer 21 | - [Couting sort (unstable)](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/NonComparison/CountingSorter.cs) - implemented for integer 22 | - [LSD Radix](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/NonComparison/LSDRadixSorter.cs) - implemented for integer 23 | - [MSD Radix](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/SortAlgorithms/NonComparison/MSDRadixSorter.cs) - implemented for strings 24 | 25 | Data stuctures: 26 | - [Hash tables](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/HashTable/IHashTable.cs) 27 | - Implementations 28 | - [With linked list usage](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/HashTable/HashTableWithLinkedList.cs) 29 | - [With linear probing](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/HashTable/LinearHashTable.cs) 30 | - [With quadratic probing](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/HashTable/QuadraticHashTable.cs) 31 | - [With double hashing probing](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/HashTable/DoubleHashTable.cs) 32 | - Algorithms 33 | - Add 34 | - Contains 35 | - Remove 36 | - Clear 37 | - [Binary search tree](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs) 38 | - [Insert](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L33) 39 | - [Find](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L55) 40 | - [Remove](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L70) 41 | - [Traverse](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L99) 42 | - Infix ([recursive](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L691) and [iteration](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L714) implementation) 43 | - Prefix ([recursive](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L698) and [iteration](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L734) implementation) 44 | - Postfix ([recursive](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L705) and [iteration](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L756) implementation) 45 | - Breadth ([iteration](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L787) implementation) 46 | - [Verify](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L139) 47 | - [GetMin](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L153) 48 | - [GetMax](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L173) 49 | - [GetPredecessor](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L194) 50 | - [GetSuccessor](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L234) 51 | - [GetKElementInOrder](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L274) 52 | - [SplitByKey](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L290) 53 | - [Merge](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L351) (with tree where keys > than keys in this tree) 54 | - [RotateLeft](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L375) 55 | - [RotateRight](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L383) 56 | - [GetCommonRoot(key1, key2)](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L394) 57 | - [GetDistance(key1, key2)](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTree.cs#L439) 58 | - [Binary search tree node](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs) 59 | - [HasParent](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L66) 60 | - [IsTerminate](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L58) 61 | - [Count](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L74) 62 | - [Height](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L82) 63 | - [Degree](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L91) 64 | - [Depth](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L96) 65 | - [Level](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/BinarySearchTreeNode.cs#L109) 66 | - [AVL tree](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTree.cs) 67 | - [Insert](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTree.cs#L32) 68 | - [Verify](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTree.cs#L82) 69 | - [Remove](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTree.cs#L91) 70 | - [RebalanceIn](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTree.cs#L118) 71 | - [AVL tree node](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTreeNode.cs) 72 | - [Balance factor](https://github.com/Silvochka/algorithms/blob/dev/Algorithms/DataStructures/Tree/AVLTreeNode.cs#L18) 73 | 74 | ### Tests 75 | 76 | This library has generic tests for each sorter. New added sorter is testing automatically using Reflection. Currently it tests next types of array: 77 | - Integer 78 | - Double 79 | - String 80 | - Char 81 | 82 | Each type tested on next inputs: 83 | - Sorted sequense 84 | - Reverted sorted sequense 85 | - Random shuffled sequense 86 | - Empty array 87 | 88 | Each implemented data structures has tests which covering as much as possible. 89 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.1.{build} 2 | configuration: Debug 3 | environment: 4 | COVERALLS_REPO_TOKEN: 5 | secure: M6D0gHEqDI6J/zl93x+AVr6WVxzEviMR6xILmZ8sYqEy5GiumoMtgjljg+opDObB 6 | before_build: 7 | - nuget restore 8 | - nuget install NUnit.Runners -Version 2.6.4 -OutputDirectory tools 9 | - nuget install OpenCover -Version 4.6.519 -OutputDirectory tools 10 | - nuget install coveralls.net -Version 0.6.0 -OutputDirectory tools 11 | build: 12 | project: Algorithms.sln 13 | verbosity: minimal 14 | after_test: 15 | - .\tools\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -target:.\tools\NUnit.Runners.2.6.4\tools\nunit-console.exe -targetargs:"/nologo /noshadow .\AlgorithmsTests\bin\Debug\AlgorithmsTests.dll" -filter:"+[*]* -[*AlgorithmsTests]*" 16 | - .\tools\coveralls.net.0.6.0\tools\csmacnz.Coveralls.exe --opencover -i .\results.xml --------------------------------------------------------------------------------