├── .travis.yml ├── deploy.sh ├── .gitignore ├── cs-algorithms ├── UnionFind │ ├── IUnionFind.cs │ ├── QuickFind.cs │ ├── QuickUnion.cs │ ├── WeightedQuickUnion.cs │ ├── WeightedQuickUnionWithPathCompression.cs │ └── Percolation.cs ├── DataStructures │ ├── Queue │ │ ├── IQueue.cs │ │ ├── QueueArray.cs │ │ ├── QueueLinkedList.cs │ │ ├── MinPQ.cs │ │ ├── MaxPQ.cs │ │ └── IndexMinPQ.cs │ ├── Stack │ │ ├── IStack.cs │ │ ├── StackArray.cs │ │ └── StackLinkedList.cs │ ├── HashMap │ │ ├── IHashMap.cs │ │ ├── HashMapWithSeparateChaining.cs │ │ └── HashMapWithLinearProbing.cs │ ├── TreeMap │ │ ├── ITreeMap.cs │ │ ├── LeftLeaningRedBlackTree.cs │ │ └── BinarySearchTree.cs │ ├── HashSet │ │ ├── HashSetWithLinearProbing.cs │ │ └── HashSetWithSeparateChaining.cs │ ├── SearchTries │ │ ├── ISearchTries.cs │ │ ├── RWayTries.cs │ │ └── TernarySearchTries.cs │ └── Graphs │ │ ├── Graph.cs │ │ ├── DiGraph.cs │ │ ├── Edge.cs │ │ ├── WeightedGraph.cs │ │ └── WeightedDiGraph.cs ├── Shuffling │ └── KnuthShuffle.cs ├── cs-algorithms.csproj ├── Strings │ ├── Search │ │ ├── LongestCommonPattern.cs │ │ ├── BoyerMoore.cs │ │ ├── KnuthMorrisPratt.cs │ │ ├── LongestRepeatedPattern.cs │ │ └── RabinKarp.cs │ └── Sort │ │ ├── LSD.cs │ │ ├── ThreeWaysQuickSort.cs │ │ └── MSD.cs ├── Search │ └── BinarySearch.cs ├── Sorting │ ├── SelectionSort.cs │ ├── InsertionSort.cs │ ├── ShellSort.cs │ ├── ThreeWayQuickSort.cs │ ├── QuickSort.cs │ ├── HeapSort.cs │ └── MergeSort.cs ├── Utils │ ├── ObjectUtil.cs │ └── SortUtil.cs ├── Graphs │ ├── MaxFlow │ │ ├── FlowNetwork.cs │ │ ├── FlowEdge.cs │ │ └── FordFulkerson.cs │ ├── MST │ │ ├── Kruskal.cs │ │ ├── LazyPrim.cs │ │ └── EagerPrim.cs │ ├── Connectivity │ │ ├── StronglyConnectedComponents.cs │ │ └── ConnectedComponents.cs │ ├── TopologicalSort │ │ └── DepthFirstPostOrder.cs │ ├── Cycles │ │ └── DirectedCycles.cs │ ├── Search │ │ ├── DepthFirstSearch.cs │ │ └── BreadthFirstSearch.cs │ └── ShortestPaths │ │ ├── TopologicalSortShortestPath.cs │ │ ├── Dijkstra.cs │ │ └── BellmanFord.cs └── Selection │ └── QuickSelect.cs ├── cs-algorithms-unit-tests ├── Search │ └── BinarySearchUnitTest.cs ├── Sorting │ ├── InsertionSortUnitTest.cs │ ├── SelectionSortUnitTest.cs │ ├── MergeSortUnitTest.cs │ ├── ShellSortUnitTest.cs │ ├── QuickSortUnitTest.cs │ ├── ThreeWayQuickSortUnitTest.cs │ └── HeapSortUnitTest.cs ├── Selection │ └── QuickSelectUnitTest.cs ├── UnionFind │ ├── PercolationUnitTest.cs │ ├── QuickFindUnitTest.cs │ ├── QuickUnionUnitTest.cs │ ├── WeightedQuickUnionUnitTest.cs │ └── WeightedQuickUnionWithPathCompressionUnitTest.cs ├── DataStrutures │ ├── Stack │ │ ├── StackArrayUnitTest.cs │ │ └── StackLinkedListUnitTest.cs │ ├── Queue │ │ ├── QueueArrayUnitTest.cs │ │ ├── QueueLinkedListUnitTest.cs │ │ ├── MinPQUnitTest.cs │ │ ├── MaxPQUnitTest.cs │ │ └── IndexMinPQUnitTest.cs │ ├── TreeMap │ │ ├── BinarySearchTreeUnitTest.cs │ │ └── LeftLeaningRedBlackTreeUnitTest.cs │ ├── HashMap │ │ ├── HashMapWithLinearProbingUnitTest.cs │ │ └── HashMapWithSeparateChainingUnitTest.cs │ └── SearchTries │ │ ├── RWayTriesUnitTest.cs │ │ └── TernarySearchTriesUnitTest.cs ├── Graphs │ ├── Cycles │ │ └── DirectedCycleUnitTest.cs │ ├── MST │ │ ├── KruskalUnitTest.cs │ │ ├── LazyPrimUnitTest.cs │ │ └── EagerPrimUnitTest.cs │ ├── TopologicalSort │ │ └── DepthFirstPostOrderUnitTest.cs │ ├── MaxFlow │ │ └── FordFulkersonUnitTest.cs │ ├── Connectivity │ │ ├── StronglyConnectedComponentsUnitTest.cs │ │ └── ConnectedComponentsUnitTest.cs │ ├── Search │ │ ├── DepthFirstSearchUnitTest.cs │ │ └── BreadthFirstSearchUnitTest.cs │ ├── ShortestPaths │ │ ├── DijkstraUnitTest.cs │ │ ├── BellmanFordUnitTest.cs │ │ └── TopologicalSortShortestPathUnitTest.cs │ └── GraphGenerator.cs ├── Strings │ ├── Sort │ │ ├── LSDUnitTest.cs │ │ ├── MSDUnitTest.cs │ │ └── ThreeWaysQuickSortUnitTest.cs │ └── Search │ │ ├── LongestRepeatedPatternUnitTest.cs │ │ ├── LongestCommonPatternUnitTest.cs │ │ ├── RabinKarpUnitTest.cs │ │ ├── BoyerMooreUnitTest.cs │ │ └── KnuthMorrisPrattUnitTest.cs └── cs-algorithms-unit-tests.csproj ├── .vscode ├── tasks.json └── launch.json ├── LICENSE ├── README.md └── cs-algorithms.sln /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | dist: trusty 3 | sudo: required 4 | mono: none 5 | dotnet: 1.0.3 6 | script: 7 | - cd cs-algorithms-unit-tests && dotnet restore && dotnet build && dotnet test 8 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | dotnet pack cs-algorithms/cs-algorithms.csproj /p:PackageVersion=1.0.1 --configuration release --include-source --output ../build 2 | nuget push build/cs-algorithms.1.0.1.nupkg -Source https://www.nuget.org/api/v2/package -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | bin/ 3 | **/obj/ 4 | **/bin/ 5 | packages/ 6 | .idea/ 7 | *.iml 8 | build/ 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | 18 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 19 | hs_err_pid* 20 | -------------------------------------------------------------------------------- /cs-algorithms/UnionFind/IUnionFind.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Algorithms.UnionFind 7 | { 8 | public interface IUnionFind 9 | { 10 | void Union(int i, int j); 11 | bool IsConnected(int i, int j); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Queue/IQueue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Queue 4 | { 5 | public interface IQueue : IEnumerable 6 | { 7 | T Dequeue(); 8 | void Enqueue(T item); 9 | int Count { get; } 10 | bool IsEmpty { get; } 11 | } 12 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Stack/IStack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace DataStructures.Stack 5 | { 6 | public interface IStack : IEnumerable 7 | { 8 | T Pop(); 9 | void Push(T item); 10 | int Count { get; } 11 | bool IsEmpty { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Search/BinarySearchUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Search; 2 | using Xunit; 3 | 4 | namespace AlgorithmsUnitTest.Search 5 | { 6 | public class BinarySearchUnitTest 7 | { 8 | [Fact] 9 | public void TestSearch() 10 | { 11 | var a = new[] {1, 2, 4, 5, 7, 9}; 12 | Assert.Equal(BinarySearch.IndexOf(a, 4), 2); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [ 10 | "${workspaceRoot}/cs-algorithms.csproj" 11 | ], 12 | "isBuildCommand": true, 13 | "problemMatcher": "$msCompile" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/HashMap/IHashMap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.HashMap 4 | { 5 | public interface IHashMap 6 | { 7 | V this[K key] { get; set; } 8 | bool ContainsKey(K key); 9 | int Count { get; } 10 | bool IsEmpty { get; } 11 | void Delete(K key); 12 | IEnumerable Keys { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/InsertionSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Sorting; 2 | using Xunit; 3 | 4 | namespace AlgorithmsUnitTest.Sorting 5 | { 6 | public class InsertionSortUnitTest 7 | { 8 | [Fact] 9 | public void testSort() 10 | { 11 | var a = new[] {5, 4, 3, 2, 6, 1, 0}; 12 | InsertionSort.Sort(a); 13 | Assert.Equal(new[]{0, 1, 2, 3, 4, 5, 6}, a); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/SelectionSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Sorting; 2 | using Xunit; 3 | 4 | namespace AlgorithmsUnitTest.Sorting 5 | { 6 | public class SelectionSortUnitTest 7 | { 8 | [Fact] 9 | public void testSort() 10 | { 11 | var a = new[] {5, 4, 3, 2, 6, 1, 0}; 12 | SelectionSort.Sort(a); 13 | Assert.Equal(new[]{0, 1, 2, 3, 4, 5, 6}, a); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/TreeMap/ITreeMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.DataStructures.TreeMap 5 | { 6 | public interface ITreeMap where K : IComparable 7 | { 8 | V this[K key] { get; set; } 9 | int Count { get; } 10 | bool IsEmpty { get; } 11 | bool ContainsKey(K key); 12 | K MinKey(); 13 | IEnumerable Keys { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/HashSet/HashSetWithLinearProbing.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.HashMap; 2 | 3 | namespace Algorithms.DataStructures.HashSet 4 | { 5 | public class HashSetWithLinearProbing : HashMapWithLinearProbing 6 | { 7 | public void Add(T item) 8 | { 9 | this[item] = item; 10 | } 11 | 12 | public bool Contains(T item) 13 | { 14 | return ContainsKey(item); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/HashSet/HashSetWithSeparateChaining.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.HashMap; 2 | 3 | namespace Algorithms.DataStructures.HashSet 4 | { 5 | public class HashSetWithSeparateChaining : HashMapWithSeparateChaining 6 | { 7 | public void Add(T item) 8 | { 9 | this[item] = item; 10 | } 11 | 12 | public bool Contains(T item) 13 | { 14 | return ContainsKey(item); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /cs-algorithms/Shuffling/KnuthShuffle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using Algorithms.Utils; 4 | 5 | namespace Algorithms.Shuffling 6 | { 7 | public class KnuthShuffle 8 | { 9 | 10 | public static void Shuffle(T[] a) 11 | { 12 | var random = new Random(); 13 | for (var i = 1; i < a.Length; ++i) 14 | { 15 | var j = random.Next(i + 1); 16 | SortUtil.Exchange(a, i, j); 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /cs-algorithms/cs-algorithms.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard1.4 4 | 5 | 6 | 7 | 8 | 9 | 10 | 1.1.2 11 | 12 | 13 | 1.1.2 14 | 15 | 16 | -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Selection/QuickSelectUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Numerics; 3 | using SimuKit.Algorithms.Selection; 4 | using Xunit; 5 | 6 | namespace AlgorithmsUnitTest.Selection 7 | { 8 | public class QuickSelectUnitTest 9 | { 10 | 11 | [Fact] 12 | public void testSelectK() 13 | { 14 | var a = new[] 15 | { 16 | 1, 3, 5, 2, 4, 6, 0 17 | }; 18 | 19 | Assert.Equal(3, QuickSelect.Select(a, 3, (a1, b) => a1 - b)); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/SearchTries/ISearchTries.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace Algorithms.DataStructures.SearchTries 6 | { 7 | public interface ISearchTries 8 | { 9 | T this[string key] { get; set; } 10 | 11 | int Count { get; } 12 | bool IsEmpty { get; } 13 | 14 | void Delete(String key); 15 | bool ContainsKey(String key); 16 | 17 | IEnumerable Keys { get; } 18 | IEnumerable KeysWithPrefix(string prefix); 19 | } 20 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/UnionFind/PercolationUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.UnionFind; 3 | using Xunit; 4 | 5 | namespace AlgorithmsUnitTest.UnionFind 6 | { 7 | public class PercolationUnitTest 8 | { 9 | protected Random mRandom = new Random(); 10 | 11 | [Fact] 12 | public void RunPercolation() 13 | { 14 | var p = new Percolation(100, 100); 15 | const int iterations = 10; 16 | var percolationThreshold = p.RunMonteCarlo(mRandom, iterations); 17 | Console.WriteLine("Percolation Threshold: {0}", percolationThreshold); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Stack/StackArrayUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using DataStructures.Stack; 3 | 4 | namespace AlgorithmsUnitTest.DataStrutures.Stack 5 | { 6 | public class StackArrayUnitTest 7 | { 8 | [Fact] 9 | public void TestStack() 10 | { 11 | var stack = new StackArray(); 12 | stack.Push(10); 13 | stack.Push(20); 14 | Assert.Equal(2, stack.Count); 15 | Assert.False(stack.IsEmpty); 16 | Assert.Equal(20, stack.Pop()); 17 | Assert.Equal(10, stack.Pop()); 18 | Assert.True(stack.IsEmpty); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Stack/StackLinkedListUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using DataStructures.Stack; 3 | 4 | namespace AlgorithmsUnitTest.DataStrutures.Stack 5 | { 6 | public class StackLinkedListUnitTest 7 | { 8 | [Fact] 9 | public void TestStack() 10 | { 11 | var stack = new StackLinkedList(); 12 | stack.Push(10); 13 | stack.Push(20); 14 | Assert.Equal(2, stack.Count); 15 | Assert.False(stack.IsEmpty); 16 | Assert.Equal(20, stack.Pop()); 17 | Assert.Equal(10, stack.Pop()); 18 | Assert.True(stack.IsEmpty); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/MergeSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Shuffling; 2 | using Algorithms.Sorting; 3 | using Xunit; 4 | 5 | namespace AlgorithmsUnitTest.Sorting 6 | { 7 | public class MergeSortUnitTest 8 | { 9 | [Fact] 10 | public void testSort() 11 | { 12 | var a = new int[100]; 13 | var b = new int[100]; 14 | for (var i = 0; i < a.Length; ++i) 15 | { 16 | a[i] = i; 17 | b[i] = i; 18 | } 19 | KnuthShuffle.Shuffle(a); 20 | Assert.NotEqual(b, a); 21 | MergeSort.Sort(a); 22 | Assert.Equal(b, a); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/ShellSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Shuffling; 2 | using Algorithms.Sorting; 3 | using Xunit; 4 | 5 | namespace AlgorithmsUnitTest.Sorting 6 | { 7 | public class ShellSortUnitTest 8 | { 9 | [Fact] 10 | public void testSort() 11 | { 12 | var a = new int[100]; 13 | var b = new int[100]; 14 | for (var i = 0; i < a.Length; ++i) 15 | { 16 | a[i] = i; 17 | b[i] = i; 18 | } 19 | KnuthShuffle.Shuffle(a); 20 | Assert.NotEqual(b, a); 21 | ShellSort.Sort(a); 22 | Assert.Equal(b, a); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Queue/QueueArrayUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Queue; 2 | using Xunit; 3 | 4 | namespace AlgorithmsUnitTest.DataStrutures.Queue 5 | { 6 | public class QueueArrayUnitTest 7 | { 8 | [Fact] 9 | public void TestQueue() 10 | { 11 | var queue = new QueueArray(); 12 | queue.Enqueue(10); 13 | Assert.Equal(1, queue.Count); 14 | queue.Enqueue(20); 15 | Assert.Equal(2, queue.Count); 16 | Assert.False(queue.IsEmpty); 17 | Assert.Equal(10, queue.Dequeue()); 18 | Assert.Equal(20, queue.Dequeue()); 19 | Assert.True(queue.IsEmpty); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Queue/QueueLinkedListUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Queue; 2 | using Xunit; 3 | 4 | namespace AlgorithmsUnitTest.DataStrutures.Queue 5 | { 6 | public class QueueLinkedListUnitTest 7 | { 8 | [Fact] 9 | public void TestQueue() 10 | { 11 | var queue = new QueueLinkedList(); 12 | queue.Enqueue(10); 13 | Assert.Equal(1, queue.Count); 14 | queue.Enqueue(20); 15 | Assert.Equal(2, queue.Count); 16 | Assert.False(queue.IsEmpty); 17 | Assert.Equal(10, queue.Dequeue()); 18 | Assert.Equal(20, queue.Dequeue()); 19 | Assert.True(queue.IsEmpty); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/Cycles/DirectedCycleUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.Cycles; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.Cycles 7 | { 8 | public class DirectedCycleUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | 12 | public DirectedCycleUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void Test() 19 | { 20 | var G1 = GraphGenerator.dag(); 21 | var dc = new DirectedCycles(G1); 22 | console.WriteLine("dag has cycles: " + dc.HasCycle); 23 | 24 | 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/MST/KruskalUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.MST; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.MST 7 | { 8 | public class KruskalUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public KruskalUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | var g = GraphGenerator.edgeWeightedGraph(); 20 | var mst = new Kruskal(g); 21 | foreach(var e in mst.MST){ 22 | console.WriteLine(e.ToString()); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/MST/LazyPrimUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.MST; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.MST 7 | { 8 | public class LazyPrimUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public LazyPrimUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | var g = GraphGenerator.edgeWeightedGraph(); 20 | var mst = new LazyPrim(g); 21 | foreach(var e in mst.MST){ 22 | console.WriteLine(e.ToString()); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/MST/EagerPrimUnitTest.cs: -------------------------------------------------------------------------------- 1 | 2 | using Algorithms.DataStructures.Graphs; 3 | using Algorithms.Graphs.MST; 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace AlgorithmsUnitTest.Graphs.MST 8 | { 9 | public class EagerPrimUnitTest 10 | { 11 | private ITestOutputHelper console; 12 | public EagerPrimUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void Test() 19 | { 20 | var g = GraphGenerator.edgeWeightedGraph(); 21 | var mst = new EagerPrim(g); 22 | foreach(var e in mst.MST){ 23 | console.WriteLine(e.ToString()); 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /cs-algorithms/Strings/Search/LongestCommonPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Sorting; 3 | 4 | namespace Algorithms.Strings.Search 5 | { 6 | public class LongestCommonPattern 7 | { 8 | 9 | 10 | public static String LongestCommonString(String s, String pat) 11 | { 12 | int J = 0; 13 | for (var i = 0; i < s.Length; ++i) 14 | { 15 | for (var j = 0; j < pat.Length; ++j) 16 | { 17 | 18 | if (i+j >= s.Length || s[i + j] != pat[j]) 19 | { 20 | J = Math.Max(J, j); 21 | break; 22 | } 23 | } 24 | } 25 | return pat.Substring(0, J); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/TopologicalSort/DepthFirstPostOrderUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.TopologicalSort; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.TopologicalSort 7 | { 8 | public class DepthFirstPostOrderUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | 12 | public DepthFirstPostOrderUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void Test() 19 | { 20 | DiGraph dag = GraphGenerator.dag(); 21 | 22 | var dfo = new DepthFirstPostOrder(dag); 23 | console.WriteLine(dfo.PostOrderToString()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/QuickSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Shuffling; 2 | using Algorithms.Sorting; 3 | using Xunit; 4 | 5 | namespace AlgorithmsUnitTest.Sorting 6 | { 7 | public class QuickSortUnitTest 8 | { 9 | [Fact] 10 | public void testSort() 11 | { 12 | var a = new int[100]; 13 | var b = new int[100]; 14 | for (var i = 0; i < a.Length; ++i) 15 | { 16 | a[i] = i; 17 | b[i] = i; 18 | } 19 | KnuthShuffle.Shuffle(a); 20 | Assert.NotEqual(b, a); 21 | QuickSort.Sort(a); 22 | for (var i = 0; i < a.Length; ++i) 23 | { 24 | Assert.Equal(b[i], a[i]); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Queue/MinPQUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Queue; 2 | using Xunit; 3 | 4 | namespace AlgorithmsUnitTest.DataStrutures.Queue 5 | { 6 | public class MinPQUnitTest 7 | { 8 | [Fact] 9 | public void TestMinPQ() 10 | { 11 | MinPQ pq = new MinPQ(); 12 | 13 | for (var i = 0; i < 100; ++i) 14 | { 15 | pq.Enqueue(99-i); 16 | } 17 | Assert.Equal(100, pq.Count); 18 | Assert.False(pq.IsEmpty); 19 | for (var i = 0; i < 100; ++i) 20 | { 21 | Assert.Equal(i, pq.DelMin()); 22 | Assert.Equal(99-i, pq.Count); 23 | } 24 | Assert.True(pq.IsEmpty); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /cs-algorithms/Search/BinarySearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using Algorithms.Utils; 4 | 5 | namespace Algorithms.Search 6 | { 7 | public class BinarySearch 8 | { 9 | public static int IndexOf(T[] a, T v) where T: IComparable 10 | { 11 | var lo = 0; 12 | var hi = a.Length - 1; 13 | int comparison(T a1, T a2) => a1.CompareTo(a2); 14 | 15 | while (lo <= hi) 16 | { 17 | int mid = lo + (hi - lo) / 2; 18 | if (SortUtil.IsLessThan(a[mid], v, comparison)) lo = mid+1; 19 | else if (SortUtil.IsGreaterThan(a[mid], v, comparison)) hi = mid - 1; 20 | else return mid; 21 | } 22 | return -1; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/ThreeWayQuickSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Shuffling; 3 | using Algorithms.Sorting; 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace AlgorithmsUnitTest.Sorting 8 | { 9 | public class ThreeWayQuickSortUnitTest 10 | { 11 | 12 | [Fact] 13 | public void testSort() 14 | { 15 | var a = new int[100]; 16 | var b = new int[100]; 17 | for (var i = 0; i < a.Length; ++i) 18 | { 19 | a[i] = i; 20 | b[i] = i; 21 | } 22 | KnuthShuffle.Shuffle(a); 23 | Assert.NotEqual(b, a); 24 | ThreeWayQuickSort.Sort(a); 25 | 26 | for (var i = 0; i < a.Length; ++i) 27 | { 28 | Assert.Equal(b[i], a[i]); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/MaxFlow/FordFulkersonUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.DataStructures.Graphs; 3 | using Algorithms.Graphs.MaxFlow; 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace AlgorithmsUnitTest.Graphs.MaxFlow 8 | { 9 | public class FordFulkersonUnitTest 10 | { 11 | private ITestOutputHelper console; 12 | 13 | public FordFulkersonUnitTest(ITestOutputHelper console) 14 | { 15 | this.console = console; 16 | } 17 | 18 | [Fact] 19 | public void Test() 20 | { 21 | FlowNetwork network = GraphGenerator.flowNetwork(); 22 | 23 | FordFulkerson fordFulkerson = new FordFulkerson(network, 0, 7); 24 | console.WriteLine("max-flow: " + fordFulkerson.Value); 25 | Console.WriteLine("max-flow: " + fordFulkerson.Value); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Graphs/Graph.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Graphs 4 | { 5 | public class Graph 6 | { 7 | private int vertexCount; 8 | private List[] adjList; 9 | public Graph(int V) 10 | { 11 | vertexCount = V; 12 | adjList = new List[V]; 13 | for (var v = 0; v < V; ++v) 14 | { 15 | adjList[v] = new List(); 16 | } 17 | } 18 | 19 | public int V() 20 | { 21 | return vertexCount; 22 | } 23 | 24 | public List adj(int v) 25 | { 26 | return adjList[v]; 27 | } 28 | 29 | public void addEdge(int w, int v) 30 | { 31 | adjList[v].Add(w); 32 | adjList[w].Add(v); 33 | } 34 | 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Sort/LSDUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Sort; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Sort 7 | { 8 | public class LSDUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public LSDUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | 20 | var words= "bed bug dad yes zoo now for tip ilk dim tag jot sob nob sky hut men egg few jay owl joy rap gig wee was wad fee tap tar dug jam all bad yet".Split(' '); 21 | LSD.Sort(words); 22 | 23 | for (var i = 1; i < words.Length; ++i) 24 | { 25 | Assert.True(words[i-1].CompareTo(words[i]) <= 0); 26 | } 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Sort/MSDUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Sort; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Sort 7 | { 8 | public class MSDUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public MSDUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | 20 | var words= "bed bug dad yes zoo now for tip ilk dim tag jot sob nob sky hut men egg few jay owl joy rap gig wee was wad fee tap tar dug jam all bad yet".Split(' '); 21 | MSD.Sort(words); 22 | 23 | for (var i = 1; i < words.Length; ++i) 24 | { 25 | Assert.True(words[i-1].CompareTo(words[i]) <= 0); 26 | } 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/Connectivity/StronglyConnectedComponentsUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.Connectivity; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.Connectivity 7 | { 8 | public class StronglyConnectedComponentsUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public StronglyConnectedComponentsUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | var g = GraphGenerator.dag4StronglyConnectedComponents(); 20 | 21 | var scc = new StronglyConnectedComponents(g); 22 | 23 | for(var v = 0; v < g.V(); ++v){ 24 | console.WriteLine(v + "\t:" + scc.componentId(v)); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/Connectivity/ConnectedComponentsUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.Connectivity; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.Connectivity 7 | { 8 | public class ConnectedComponentsUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public ConnectedComponentsUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | var g = GraphGenerator.graph4ConnectedComponents(); 20 | var cc = new ConnectedComponents(g); 21 | console.WriteLine("count: {0}", cc.Count); 22 | for(var v = 0; v < g.V(); ++v) { 23 | console.WriteLine(v + "\t:" + cc.componentId(v)); 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/SelectionSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | 4 | namespace Algorithms.Sorting 5 | { 6 | public class SelectionSort 7 | { 8 | public static void Sort(T[] a, int lo, int hi, Comparison comparator) 9 | { 10 | for (var i = lo; i < hi; ++i) 11 | { 12 | var max = a[i]; 13 | var J = i; 14 | for (var j = i + 1; j <= hi; ++j) 15 | { 16 | if (SortUtil.IsLessThan(a[j], a[J], comparator)) 17 | { 18 | J = j; 19 | } 20 | } 21 | SortUtil.Exchange(a, i, J); 22 | } 23 | } 24 | 25 | public static void Sort(T[] a) where T : IComparable 26 | { 27 | Sort(a, 0, a.Length-1, (a1, a2) => a1.CompareTo(a2)); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /cs-algorithms/Utils/ObjectUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.Utils 4 | { 5 | public class ObjectUtil 6 | { 7 | public static bool IsNullOrDefault(T argument) 8 | { 9 | // deal with normal scenarios 10 | if (argument == null) return true; 11 | if (object.Equals(argument, default(T))) return true; 12 | 13 | // deal with non-null nullables 14 | Type methodType = typeof(T); 15 | if (Nullable.GetUnderlyingType(methodType) != null) return false; 16 | 17 | // deal with boxed value types 18 | Type argumentType = argument.GetType(); 19 | if (argumentType != methodType) 20 | { 21 | object obj = Activator.CreateInstance(argument.GetType()); 22 | return obj.Equals(argument); 23 | } 24 | 25 | return false; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/InsertionSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | 4 | namespace Algorithms.Sorting 5 | { 6 | public class InsertionSort 7 | { 8 | public static void Sort(T[] a, int lo, int hi, Comparison compare) 9 | { 10 | for (var i = lo + 1; i <= hi; ++i) 11 | { 12 | for (var j = i-1; j >= lo; --j) 13 | { 14 | if (SortUtil.IsLessThan(a[j+1], a[j], compare)) 15 | { 16 | SortUtil.Exchange(a, j, j + 1); 17 | } 18 | else 19 | { 20 | break; 21 | } 22 | } 23 | } 24 | } 25 | 26 | public static void Sort(T[] a) where T : IComparable 27 | { 28 | Sort(a, 0, a.Length-1, (a1, a2) => a1.CompareTo(a2)); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Sort/ThreeWaysQuickSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Sort; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Sort 7 | { 8 | public class ThreeWaysQuickSortUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public ThreeWaysQuickSortUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void Test() 18 | { 19 | 20 | var words= "bed bug dad yes zoo now for tip ilk dim tag jot sob nob sky hut men egg few jay owl joy rap gig wee was wad fee tap tar dug jam all bad yet".Split(' '); 21 | ThreeWaysQuickSort.Sort(words); 22 | 23 | for (var i = 1; i < words.Length; ++i) 24 | { 25 | Assert.True(words[i-1].CompareTo(words[i]) <= 0); 26 | } 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/cs-algorithms-unit-tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp1.1 4 | 5 | 6 | 7 | 1.1.2 8 | 9 | 10 | 1.1.2 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {238151a2-dcda-4bef-8052-73e7b2e95ce4} 19 | cs-algorithms 20 | 21 | 22 | -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/Search/DepthFirstSearchUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.Search 7 | { 8 | public class DepthFirstSearchUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public DepthFirstSearchUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void TestSearch() 18 | { 19 | var g = GraphGenerator.graph(); 20 | 21 | var s = 0; 22 | var dfs = new DepthFirstSearch(g, s); 23 | 24 | for(var v=0; v < g.V(); ++v) { 25 | if (!dfs.CanReach(v)) continue; 26 | console.WriteLine(s + " is connected to " + v); 27 | console.WriteLine("path: " + dfs.PathToString(v)); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/MaxFlow/FlowNetwork.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.Graphs.MaxFlow 4 | { 5 | public class FlowNetwork 6 | { 7 | private int vertexCount; 8 | private List[] adjList; 9 | 10 | public FlowNetwork(int V) 11 | { 12 | vertexCount = V; 13 | adjList = new List[V]; 14 | for (var v = 0; v < V; v++) 15 | { 16 | adjList[v] = new List(); 17 | } 18 | } 19 | 20 | public void addEdge(FlowEdge e) 21 | { 22 | var v = e.from(); 23 | var w = e.to(); 24 | adjList[v].Add(e); 25 | adjList[w].Add(e); 26 | } 27 | 28 | public List adj(int v) 29 | { 30 | return adjList[v]; 31 | } 32 | 33 | public int V() 34 | { 35 | return vertexCount; 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/Search/BreadthFirstSearchUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Graphs.Search 7 | { 8 | public class BreadthFirstSearchUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public BreadthFirstSearchUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void TestSearch() 18 | { 19 | var g = GraphGenerator.graph(); 20 | 21 | var s = 0; 22 | var dfs = new BreadthFirstSearch(g, s); 23 | 24 | for(var v=0; v < g.V(); ++v) { 25 | if (!dfs.CanReach(v)) continue; 26 | console.WriteLine(s + " is connected to " + v); 27 | console.WriteLine("path: " + dfs.PathToString(v)); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /cs-algorithms/UnionFind/QuickFind.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Algorithms.UnionFind 7 | { 8 | public class QuickFind : IUnionFind 9 | { 10 | protected int[] mID; 11 | public QuickFind(int n) 12 | { 13 | mID = new int[n]; 14 | for (var i = 0; i < n; ++i) 15 | { 16 | mID[i] = i; 17 | } 18 | } 19 | 20 | public void Union(int i, int j) 21 | { 22 | var p = mID[i]; 23 | var q = mID[j]; 24 | if (p == q) return; 25 | for (var k = 0; k < mID.Length; ++k) 26 | { 27 | if (mID[k] == q) 28 | { 29 | mID[k] = p; 30 | } 31 | } 32 | } 33 | 34 | public bool IsConnected(int i, int j) 35 | { 36 | return mID[i] == mID[j]; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cs-algorithms/UnionFind/QuickUnion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Algorithms.UnionFind 7 | { 8 | public class QuickUnion : IUnionFind 9 | { 10 | protected int[] mParentID = null; 11 | public QuickUnion(int n) 12 | { 13 | mParentID = new int[n]; 14 | for (var i = 0; i < n; ++i) 15 | { 16 | mParentID[i] = i; 17 | } 18 | } 19 | 20 | public void Union(int i, int j) 21 | { 22 | var p = GetRoot(i); 23 | var q = GetRoot(j); 24 | mParentID[p] = q; 25 | } 26 | 27 | protected int GetRoot(int i) 28 | { 29 | while (mParentID[i] != i) 30 | { 31 | i = mParentID[i]; 32 | } 33 | return i; 34 | } 35 | 36 | public bool IsConnected(int i, int j) 37 | { 38 | return GetRoot(i) == GetRoot(j); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cs-algorithms/Strings/Sort/LSD.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.Strings.Sort 2 | { 3 | public class LSD 4 | { 5 | public static void Sort(string[] a) 6 | { 7 | var N = a.Length; 8 | var M = a[0].Length; 9 | 10 | var R = 256; 11 | 12 | var aux = new string[N]; 13 | 14 | for (var d = M-1; d >= 0; --d) 15 | { 16 | var counts = new int[R + 1]; 17 | 18 | for (var i = 0; i < N; ++i) 19 | { 20 | counts[a[i][d]+1]++; 21 | } 22 | 23 | for (var r = 0; r < R; ++r) 24 | { 25 | counts[r + 1] += counts[r]; 26 | } 27 | 28 | for (var i = 0; i < N; ++i) 29 | { 30 | aux[counts[a[i][d]]++] = a[i]; 31 | } 32 | 33 | for (var i = 0; i < N; ++i) 34 | { 35 | a[i] = aux[i]; 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /cs-algorithms/Utils/SortUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | 5 | namespace Algorithms.Utils 6 | { 7 | public class SortUtil 8 | { 9 | public static bool IsLessThan(T p0, T p1, Comparison compareTo) 10 | { 11 | return compareTo(p0, p1) < 0; 12 | } 13 | 14 | public static bool IsGreaterThan(T p0, T p1, Comparison compareTo) 15 | { 16 | return compareTo(p0, p1) > 0; 17 | } 18 | 19 | public static void Exchange(T[] a, int i, int j) 20 | { 21 | var temp = a[i]; 22 | a[i] = a[j]; 23 | a[j] = temp; 24 | } 25 | 26 | public static bool IsLessThan(T p0, T p1) where T : IComparable 27 | { 28 | return IsLessThan(p0, p1, (a1, a2) => a1.CompareTo(a2)); 29 | } 30 | 31 | public static bool IsGreaterThan(T p0, T p1) where T : IComparable 32 | { 33 | return IsGreaterThan(p0, p1, (a1, a2) => a1.CompareTo(a2)); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/UnionFind/QuickFindUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.UnionFind; 2 | using Xunit; 3 | using Xunit.Abstractions; 4 | 5 | namespace AlgorithmsUnitTest.UnionFind 6 | { 7 | public class QuickFindUnitTest 8 | { 9 | private readonly ITestOutputHelper logger; 10 | public QuickFindUnitTest(ITestOutputHelper console) 11 | { 12 | this.logger = console; 13 | } 14 | 15 | [Fact] 16 | public void test_union_find() 17 | { 18 | var uf = new QuickFind(10); 19 | uf.Union(1, 3); 20 | uf.Union(2, 3); 21 | uf.Union(5, 6); 22 | uf.Union(4, 5); 23 | 24 | Assert.True(uf.IsConnected(1, 3)); 25 | Assert.True(uf.IsConnected(2, 3)); 26 | Assert.True(uf.IsConnected(1, 2)); 27 | Assert.True(uf.IsConnected(4, 5)); 28 | Assert.True(uf.IsConnected(4, 6)); 29 | Assert.False(uf.IsConnected(1, 6)); 30 | Assert.False(uf.IsConnected(3, 4)); 31 | 32 | this.logger.WriteLine("Connected: {1, 2, 3}"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Queue/MaxPQUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Queue; 2 | using Xunit; 3 | using Xunit.Abstractions; 4 | 5 | namespace AlgorithmsUnitTest.DataStrutures.Queue 6 | { 7 | public class MaxPQUnitTest 8 | { 9 | private ITestOutputHelper console; 10 | public MaxPQUnitTest(ITestOutputHelper console) 11 | { 12 | this.console = console; 13 | } 14 | [Fact] 15 | public void TestMaxPQ() 16 | { 17 | var pq = new MaxPQ(); 18 | 19 | for (var i = 0; i < 100; ++i) 20 | { 21 | pq.Enqueue(i); 22 | } 23 | Assert.Equal(100, pq.Count); 24 | Assert.False(pq.IsEmpty); 25 | for (var i = 0; i < 100; ++i) 26 | { 27 | Assert.Equal(99-i, pq.DelMax()); 28 | Assert.Equal(99-i, pq.Count); 29 | } 30 | Assert.True(pq.IsEmpty); 31 | 32 | foreach (var v in pq) 33 | { 34 | console.WriteLine("{0}", v); 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/UnionFind/QuickUnionUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.UnionFind; 2 | using Xunit; 3 | using Xunit.Abstractions; 4 | 5 | namespace AlgorithmsUnitTest.UnionFind 6 | { 7 | public class QuickUnionUnitTest 8 | { 9 | private readonly ITestOutputHelper logger; 10 | public QuickUnionUnitTest(ITestOutputHelper console) 11 | { 12 | this.logger = console; 13 | } 14 | 15 | [Fact] 16 | public void test_union_find() 17 | { 18 | var uf = new QuickUnion(10); 19 | uf.Union(1, 3); 20 | uf.Union(2, 3); 21 | uf.Union(5, 6); 22 | uf.Union(4, 5); 23 | 24 | Assert.True(uf.IsConnected(1, 3)); 25 | Assert.True(uf.IsConnected(2, 3)); 26 | Assert.True(uf.IsConnected(1, 2)); 27 | Assert.True(uf.IsConnected(4, 5)); 28 | Assert.True(uf.IsConnected(4, 6)); 29 | Assert.False(uf.IsConnected(1, 6)); 30 | Assert.False(uf.IsConnected(3, 4)); 31 | 32 | this.logger.WriteLine("Connected: {1, 2, 3}"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/MST/Kruskal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Algorithms.DataStructures.Graphs; 3 | using Algorithms.DataStructures.Queue; 4 | using Algorithms.UnionFind; 5 | 6 | namespace Algorithms.Graphs.MST 7 | { 8 | public class Kruskal 9 | { 10 | private List mst; 11 | public Kruskal(WeightedGraph G) 12 | { 13 | var V = G.V(); 14 | var uf =new QuickUnion(V); 15 | 16 | var pq =new MinPQ(); 17 | 18 | mst =new List(); 19 | foreach(Edge e in G.edges()) 20 | { 21 | pq.Enqueue(e); 22 | } 23 | 24 | while (!pq.IsEmpty && mst.Count < V - 1) 25 | { 26 | var e = pq.DelMin(); 27 | var v = e.either(); 28 | var w = e.other(v); 29 | 30 | if (!uf.IsConnected(v, w)) 31 | { 32 | uf.Union(v, w); 33 | mst.Add(e); 34 | } 35 | } 36 | 37 | 38 | } 39 | 40 | public List MST => mst; 41 | } 42 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Chen Caishun 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 | -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Sorting/HeapSortUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.Shuffling; 2 | using Algorithms.Sorting; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Sorting 7 | { 8 | public class HeapSortUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public HeapSortUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void testSort() 18 | { 19 | var a = new int[100]; 20 | var b = new int[100]; 21 | for (var i = 0; i < a.Length; ++i) 22 | { 23 | a[i] = i; 24 | b[i] = i; 25 | } 26 | KnuthShuffle.Shuffle(a); 27 | Assert.NotEqual(b, a); 28 | HeapSort.Sort(a); 29 | for (var i = 0; i < a.Length; ++i) 30 | { 31 | console.WriteLine("{0}", a[i]); 32 | } 33 | for (var i = 0; i < a.Length; ++i) 34 | { 35 | Assert.Equal(b[i], a[i]); 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/UnionFind/WeightedQuickUnionUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.UnionFind; 2 | using Xunit; 3 | using Xunit.Abstractions; 4 | 5 | namespace AlgorithmsUnitTest.UnionFind 6 | { 7 | public class WeightedQuickUnionUnitTest 8 | { 9 | private readonly ITestOutputHelper logger; 10 | public WeightedQuickUnionUnitTest(ITestOutputHelper console) 11 | { 12 | this.logger = console; 13 | } 14 | 15 | [Fact] 16 | public void test_union_find() 17 | { 18 | var uf = new QuickUnion(10); 19 | uf.Union(1, 3); 20 | uf.Union(2, 3); 21 | uf.Union(5, 6); 22 | uf.Union(4, 5); 23 | 24 | Assert.True(uf.IsConnected(1, 3)); 25 | Assert.True(uf.IsConnected(2, 3)); 26 | Assert.True(uf.IsConnected(1, 2)); 27 | Assert.True(uf.IsConnected(4, 5)); 28 | Assert.True(uf.IsConnected(4, 6)); 29 | Assert.False(uf.IsConnected(1, 6)); 30 | Assert.False(uf.IsConnected(3, 4)); 31 | 32 | this.logger.WriteLine("Connected: {1, 2, 3}"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/UnionFind/WeightedQuickUnionWithPathCompressionUnitTest.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.UnionFind; 2 | using Xunit; 3 | using Xunit.Abstractions; 4 | 5 | namespace AlgorithmsUnitTest.UnionFind 6 | { 7 | public class WeightedQuickUnionWithPathCompressionUnitTest 8 | { 9 | private readonly ITestOutputHelper logger; 10 | public WeightedQuickUnionWithPathCompressionUnitTest(ITestOutputHelper console) 11 | { 12 | this.logger = console; 13 | } 14 | 15 | [Fact] 16 | public void test_union_find() 17 | { 18 | var uf = new QuickUnion(10); 19 | uf.Union(1, 3); 20 | uf.Union(2, 3); 21 | uf.Union(5, 6); 22 | uf.Union(4, 5); 23 | 24 | Assert.True(uf.IsConnected(1, 3)); 25 | Assert.True(uf.IsConnected(2, 3)); 26 | Assert.True(uf.IsConnected(1, 2)); 27 | Assert.True(uf.IsConnected(4, 5)); 28 | Assert.True(uf.IsConnected(4, 6)); 29 | Assert.False(uf.IsConnected(1, 6)); 30 | Assert.False(uf.IsConnected(3, 4)); 31 | 32 | this.logger.WriteLine("Connected: {1, 2, 3}"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /cs-algorithms/Strings/Search/BoyerMoore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.Strings.Search 4 | { 5 | public class BoyerMoore 6 | { 7 | private int[] right; 8 | private const int R = 256; 9 | private int M; 10 | private string pat; 11 | public BoyerMoore(string pat) 12 | { 13 | this.pat = pat; 14 | right = new int[R]; 15 | for (int i = 0; i < pat.Length; ++i) 16 | { 17 | right[pat[i]] = i; 18 | } 19 | M = pat.Length; 20 | } 21 | 22 | public int Search(string text) 23 | { 24 | int skip; 25 | for (int i = 0; i < text.Length - M; i+=skip) 26 | { 27 | skip = 0; 28 | for (var j = M - 1; j >= 0; j--) 29 | { 30 | if (text[i + j] != pat[j]) 31 | { 32 | skip = Math.Max(1, j - right[text[i + j]]); 33 | break; 34 | } 35 | } 36 | if (skip == 0) return i; 37 | } 38 | return -1; 39 | } 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /cs-algorithms/Strings/Search/KnuthMorrisPratt.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.Strings.Search 2 | { 3 | public class KnuthMorrisPratt 4 | { 5 | private const int R = 256; 6 | private int M; 7 | private int[][] dfs; 8 | public KnuthMorrisPratt(string pat) 9 | { 10 | M = pat.Length; 11 | dfs = new int[R][]; 12 | for (var i = 0; i < R; ++i) 13 | { 14 | dfs[i] = new int[M]; 15 | } 16 | dfs[pat[0]][0] = 1; 17 | int X = 0; 18 | for (var i = 1; i < M; ++i) 19 | { 20 | for (var r = 0; r < R; ++r) 21 | { 22 | dfs[r][i] = dfs[r][X]; 23 | } 24 | dfs[pat[i]][i] = i + 1; 25 | X = dfs[pat[i]][X]; 26 | } 27 | } 28 | 29 | public int Search(string text) 30 | { 31 | int N = text.Length; 32 | int X = 0; 33 | for (var i = 0; i < N; ++i) 34 | { 35 | X = dfs[text[i]][X]; 36 | if (X == M) return i-M+1; 37 | } 38 | return -1; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Graphs/DiGraph.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Graphs 4 | { 5 | public class DiGraph 6 | { 7 | private int vertexCount; 8 | private List[] adjList; 9 | public DiGraph(int V) 10 | { 11 | vertexCount = V; 12 | adjList = new List[V]; 13 | for (var v = 0; v < V; ++v) 14 | { 15 | adjList[v] = new List(); 16 | } 17 | } 18 | 19 | public int V() 20 | { 21 | return vertexCount; 22 | } 23 | 24 | public List adj(int v) 25 | { 26 | return adjList[v]; 27 | } 28 | 29 | public void addEdge(int v, int w) 30 | { 31 | adjList[v].Add(w); 32 | } 33 | 34 | public DiGraph reverse() 35 | { 36 | var g = new DiGraph(vertexCount); 37 | for (var v = 0; v < vertexCount; ++v) 38 | { 39 | foreach (var w in adjList[v]) 40 | { 41 | g.addEdge(w, v); 42 | } 43 | } 44 | 45 | return g; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Graphs/Edge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.Graphs 4 | { 5 | public class Edge : IComparable 6 | { 7 | private int v; 8 | private int w; 9 | private double weight; 10 | private IComparable _comparableImplementation; 11 | 12 | public Edge(int v, int w, double weight) 13 | { 14 | this.v = v; 15 | this.w = w; 16 | this.weight = weight; 17 | 18 | } 19 | 20 | public int either() 21 | { 22 | return v; 23 | } 24 | 25 | public int other(int v) 26 | { 27 | return this.v == v ? w : this.v; 28 | } 29 | 30 | public int from() 31 | { 32 | return v; 33 | } 34 | 35 | public int to() 36 | { 37 | return w; 38 | } 39 | 40 | public double Weight => weight; 41 | 42 | 43 | public int CompareTo(Edge that) 44 | { 45 | return weight.CompareTo(that.Weight); 46 | } 47 | 48 | public override String ToString() 49 | { 50 | return v + " =(" + weight + ")=> " + w; 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/TreeMap/BinarySearchTreeUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.PortableExecutable; 2 | using Algorithms.DataStructures.TreeMap; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.DataStrutures.TreeMap 7 | { 8 | public class BinarySearchTreeUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public BinarySearchTreeUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void TestTreeMap() 18 | { 19 | var map = new BinarySearchTree(); 20 | Assert.True(map.IsEmpty); 21 | map[1] = 1; 22 | Assert.Equal(1, map[1]); 23 | map[2] = 2; 24 | Assert.Equal(2, map[2]); 25 | Assert.Equal(2, map.Count); 26 | 27 | map.Delete(2); 28 | Assert.Equal(1, map.Count); 29 | Assert.True(map.ContainsKey(1)); 30 | Assert.False(map.ContainsKey(2)); 31 | Assert.False(map.IsEmpty); 32 | 33 | foreach(int key in map.Keys) 34 | { 35 | console.WriteLine("{0}", key); 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /cs-algorithms/Strings/Sort/ThreeWaysQuickSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | 4 | namespace Algorithms.Strings.Sort 5 | { 6 | public class ThreeWaysQuickSort 7 | { 8 | public static void Sort(string[] a) 9 | { 10 | Sort(a, 0, a.Length-1, 0); 11 | } 12 | 13 | private static void Sort(string[] a, int lo, int hi, int d) 14 | { 15 | if (lo >= hi) 16 | { 17 | return; 18 | } 19 | 20 | var c = charAt(a[lo], d); 21 | 22 | int i = lo, lt = lo, gt = hi; 23 | while (i <= gt) 24 | { 25 | var cmp = c.CompareTo(charAt(a[i], d)); 26 | if(cmp > 0) SortUtil.Exchange(a, i++, lt++); 27 | else if (cmp < 0) SortUtil.Exchange(a, i, gt--); 28 | else i++; 29 | } 30 | 31 | Sort(a, lo, lt-1, d); 32 | if(c >= 0) Sort(a, lt, gt, d+1); 33 | Sort(a, gt+1, hi, d); 34 | } 35 | 36 | private static int charAt(string a, int d) 37 | { 38 | if (a.Length <= d) 39 | { 40 | return -1; 41 | } 42 | return a[d]; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/MaxFlow/FlowEdge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.Graphs.MaxFlow 4 | { 5 | public class FlowEdge 6 | { 7 | private int v; 8 | private int w; 9 | private double capacity; 10 | private double flow; 11 | 12 | public FlowEdge(int v, int w, double capacity) 13 | { 14 | this.v = v; 15 | this.w = w; 16 | this.capacity = capacity; 17 | } 18 | 19 | public int from() 20 | { 21 | return v; 22 | } 23 | 24 | public int to() 25 | { 26 | return w; 27 | } 28 | 29 | public int either() 30 | { 31 | return v; 32 | } 33 | 34 | public int other(int x) 35 | { 36 | return x == v ? w : v; 37 | } 38 | 39 | public double residualCapacityTo(int x) 40 | { 41 | if (x == v) return flow; 42 | if (x == w) return capacity - flow; 43 | throw new NotImplementedException(); 44 | } 45 | 46 | public void addResidualFlowTo(int x, double delta) 47 | { 48 | if (x == v) flow -= delta; 49 | else if (x == w) flow += delta; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Graphs/WeightedGraph.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Graphs 4 | { 5 | public class WeightedGraph 6 | { 7 | private int vertexCount; 8 | private List[] adjList; 9 | 10 | public WeightedGraph(int V) 11 | { 12 | vertexCount = V; 13 | adjList = new List[V]; 14 | for (var v = 0; v < V; ++v) 15 | { 16 | adjList[v] =new List(); 17 | } 18 | } 19 | 20 | public void addEdge(Edge e) 21 | { 22 | var v = e.either(); 23 | var w = e.other(v); 24 | 25 | adjList[v].Add(e); 26 | adjList[w].Add(e); 27 | } 28 | 29 | public List adj(int v) 30 | { 31 | return adjList[v]; 32 | } 33 | 34 | public int V() 35 | { 36 | return vertexCount; 37 | } 38 | 39 | public List edges() 40 | { 41 | var result = new List(); 42 | for (var v = 0; v < vertexCount; ++v) 43 | { 44 | result.AddRange(adjList[v]); 45 | } 46 | return result; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/ShellSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | 4 | namespace Algorithms.Sorting 5 | { 6 | public class ShellSort 7 | { 8 | public static void Sort(T[] a, Comparison compare) 9 | { 10 | var n = a.Length; 11 | var h = 1; 12 | while (h < n / 3) 13 | { 14 | h = 3 * h + 1; 15 | } 16 | 17 | var step = h; 18 | while (step > 0) 19 | { 20 | for (var i = step; i < n; i++) 21 | { 22 | for (var j = i; j >= step; j -= step) 23 | { 24 | if (SortUtil.IsLessThan(a[j], a[j - step], compare)) 25 | { 26 | SortUtil.Exchange(a, j, j - step); 27 | } 28 | else 29 | { 30 | break; 31 | } 32 | } 33 | } 34 | step--; 35 | } 36 | } 37 | 38 | public static void Sort(T[] ints) where T : IComparable 39 | { 40 | Sort(ints, (a1, a2) => a1.CompareTo(a2)); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /cs-algorithms/Strings/Search/LongestRepeatedPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Sorting; 3 | 4 | namespace Algorithms.Strings.Search 5 | { 6 | public class LongestRepeatedPattern 7 | { 8 | public static String Find(String text) 9 | { 10 | int N = text.Length; 11 | String[] a = new String[N]; 12 | for (var i = 0; i < N; ++i) 13 | { 14 | a[i] = text.Substring(i, N-i); 15 | } 16 | 17 | QuickSort.Sort(a); 18 | 19 | String result = ""; 20 | for (int i = 0; i < a.Length-1; ++i) 21 | { 22 | var j = lcp(a[i], a[i + 1]); 23 | if (result.Length < j) 24 | { 25 | result = a[i].Substring(0, j); 26 | } 27 | } 28 | return result; 29 | } 30 | 31 | private static int lcp(String s1, String s2) 32 | { 33 | int k = Math.Min(s1.Length, s2.Length); 34 | var i = 0; 35 | for (i = 0; i < k; ++i) 36 | { 37 | if (s1[i] != s2[i]) 38 | { 39 | break; 40 | } 41 | } 42 | return i; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (console)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceRoot}/bin/Debug/netcoreapp1.1/cs-algorithms.dll", 14 | "args": [], 15 | "cwd": "${workspaceRoot}", 16 | // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window 17 | "console": "internalConsole", 18 | "stopAtEntry": false, 19 | "internalConsoleOptions": "openOnSessionStart" 20 | }, 21 | { 22 | "name": ".NET Core Attach", 23 | "type": "coreclr", 24 | "request": "attach", 25 | "processId": "${command:pickProcess}" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/HashMap/HashMapWithLinearProbingUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.PortableExecutable; 2 | using Algorithms.DataStructures.HashMap; 3 | using Algorithms.DataStructures.TreeMap; 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace AlgorithmsUnitTest.DataStrutures.TreeMap 8 | { 9 | public class HashMapWithLinearProbingUnitTest 10 | { 11 | private ITestOutputHelper console; 12 | public HashMapWithLinearProbingUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void TestHashMap() 19 | { 20 | var map = new HashMapWithLinearProbing(); 21 | Assert.True(map.IsEmpty); 22 | map[1] = 1; 23 | Assert.Equal(1, map[1]); 24 | map[2] = 2; 25 | Assert.Equal(2, map[2]); 26 | Assert.Equal(2, map.Count); 27 | 28 | map.Delete(2); 29 | Assert.Equal(1, map.Count); 30 | Assert.True(map.ContainsKey(1)); 31 | Assert.False(map.ContainsKey(2)); 32 | Assert.False(map.IsEmpty); 33 | 34 | foreach(var key in map.Keys) 35 | { 36 | console.WriteLine("{0}", key); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/HashMap/HashMapWithSeparateChainingUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.PortableExecutable; 2 | using Algorithms.DataStructures.HashMap; 3 | using Algorithms.DataStructures.TreeMap; 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace AlgorithmsUnitTest.DataStrutures.TreeMap 8 | { 9 | public class HashMapWithSeparateChainingUnitTest 10 | { 11 | private ITestOutputHelper console; 12 | public HashMapWithSeparateChainingUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void TestHashMap() 19 | { 20 | var map = new HashMapWithSeparateChaining(); 21 | Assert.True(map.IsEmpty); 22 | map[1] = 1; 23 | Assert.Equal(1, map[1]); 24 | map[2] = 2; 25 | Assert.Equal(2, map[2]); 26 | Assert.Equal(2, map.Count); 27 | 28 | map.Delete(2); 29 | Assert.Equal(1, map.Count); 30 | Assert.True(map.ContainsKey(1)); 31 | Assert.False(map.ContainsKey(2)); 32 | Assert.False(map.IsEmpty); 33 | 34 | foreach(var key in map.Keys) 35 | { 36 | console.WriteLine("{0}", key); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/Queue/IndexMinPQUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Algorithms.DataStructures.Queue; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.DataStrutures.Queue 7 | { 8 | public class IndexMinPQUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | 12 | public IndexMinPQUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void Test() 19 | { 20 | var pq = new IndexMinPQ(10); 21 | 22 | pq.Enqueue(1, 20); 23 | pq.Enqueue(2, 15); 24 | 25 | Assert.Equal(15, pq.MinKey()); 26 | 27 | pq.Enqueue(1, 10); 28 | 29 | Assert.Equal(10, pq.MinKey()); 30 | 31 | pq.Enqueue(3, 11); 32 | 33 | Assert.Equal(1, pq.DelMin()); 34 | 35 | Assert.Equal(11, pq.MinKey()); 36 | 37 | Assert.Equal(2, pq.Count); 38 | 39 | Assert.False(pq.IsEmpty); 40 | 41 | pq.Enqueue(2, 10); 42 | 43 | Assert.Equal(10, pq.MinKey()); 44 | Assert.Equal(2, pq.DelMin()); 45 | 46 | foreach (var v in pq) 47 | { 48 | console.WriteLine("key: {0}", v); 49 | } 50 | 51 | 52 | 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/Connectivity/StronglyConnectedComponents.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.TopologicalSort; 3 | 4 | namespace Algorithms.Graphs.Connectivity 5 | { 6 | public class StronglyConnectedComponents 7 | { 8 | private bool[] marked; 9 | private int[] id; 10 | private int count; 11 | public StronglyConnectedComponents(DiGraph G) 12 | { 13 | count = 0; 14 | var V = G.V(); 15 | marked = new bool[V]; 16 | id = new int[V]; 17 | 18 | var ts = new DepthFirstPostOrder(G.reverse()); 19 | foreach (var v in ts.PostOrder()) 20 | { 21 | if (!marked[v]) 22 | { 23 | dfs(G, v); 24 | count++; 25 | } 26 | } 27 | } 28 | 29 | private void dfs(DiGraph G, int v) 30 | { 31 | marked[v] = true; 32 | id[v] = count; 33 | foreach (var w in G.adj(v)) 34 | { 35 | if (!marked[w]) 36 | { 37 | dfs(G, w); 38 | } 39 | } 40 | } 41 | 42 | public int componentId(int v) 43 | { 44 | return id[v]; 45 | } 46 | 47 | public int Count => count; 48 | } 49 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/Connectivity/ConnectedComponents.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Algorithms.DataStructures.Graphs; 3 | 4 | namespace Algorithms.Graphs.Connectivity 5 | { 6 | public class ConnectedComponents 7 | { 8 | private bool[] marked; 9 | private int[] id; 10 | private int count = 0; 11 | 12 | public ConnectedComponents(Graph G) 13 | { 14 | count = 0; 15 | var V = G.V(); 16 | marked = new bool[V]; 17 | id = new int[V]; 18 | 19 | for (var v = 0; v < V; ++v) 20 | { 21 | id[v] = -1; 22 | } 23 | 24 | for (var v = 0; v < V; ++v) 25 | { 26 | if (!marked[v]) 27 | { 28 | dfs(G, v); 29 | count++; 30 | } 31 | 32 | } 33 | } 34 | 35 | private void dfs(Graph G, int v) 36 | { 37 | marked[v] = true; 38 | id[v] = count; 39 | foreach (var w in G.adj(v)) 40 | { 41 | if (!marked[w]) 42 | { 43 | dfs(G, w); 44 | } 45 | } 46 | } 47 | 48 | public int componentId(int v) 49 | { 50 | return id[v]; 51 | } 52 | 53 | public int Count => count; 54 | } 55 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/ThreeWayQuickSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | 4 | namespace Algorithms.Sorting 5 | { 6 | public class ThreeWayQuickSort 7 | { 8 | public static void Sort(T[] a) where T : IComparable 9 | { 10 | Sort(a, 0, a.Length-1, (a1, a2) => a1.CompareTo(a2)); 11 | } 12 | 13 | public static void Sort(T[] a, int lo, int hi, Comparison compare) 14 | { 15 | if (lo >= hi) 16 | { 17 | return; 18 | } 19 | 20 | if (hi - lo < 7) 21 | { 22 | InsertionSort.Sort(a, lo, hi, compare); 23 | return; 24 | } 25 | 26 | 27 | int i = lo, lt = lo, gt = hi; 28 | var v = a[lo]; 29 | while (i <= gt) 30 | { 31 | if (SortUtil.IsLessThan(a[i], v, compare)) 32 | { 33 | SortUtil.Exchange(a, i++, lt++); 34 | } 35 | else if (SortUtil.IsLessThan(v, a[i], compare)) 36 | { 37 | SortUtil.Exchange(a, i, gt--); 38 | } 39 | else 40 | { 41 | i++; 42 | } 43 | } 44 | 45 | Sort(a, lo, lt-1, compare); 46 | Sort(a, gt+1, hi, compare); 47 | 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/TreeMap/LeftLeaningRedBlackTreeUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.PortableExecutable; 2 | using Algorithms.DataStructures.TreeMap; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.DataStrutures.TreeMap 7 | { 8 | public class LeftLeaningRedBlackTreeUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | public LeftLeaningRedBlackTreeUnitTest(ITestOutputHelper console) 12 | { 13 | this.console = console; 14 | } 15 | 16 | [Fact] 17 | public void TestTreeMap() 18 | { 19 | var map = new LeftLeaningRedBlackTree(); 20 | map[1] = 1; 21 | Assert.Equal(1, map[1]); 22 | map[2] = 2; 23 | Assert.Equal(2, map[2]); 24 | Assert.Equal(2, map.Count); 25 | 26 | map.Delete(2); 27 | Assert.Equal(1, map.Count); 28 | Assert.True(map.ContainsKey(1)); 29 | Assert.False(map.ContainsKey(2)); 30 | 31 | for (var i = 3; i < 100; ++i) 32 | { 33 | map[i] = i; 34 | } 35 | 36 | Assert.True(map.ContainsKey(1)); 37 | for (var i = 3; i < 100; ++i) 38 | { 39 | Assert.True(map.ContainsKey(i)); 40 | } 41 | 42 | Assert.Equal(98, map.Count); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /cs-algorithms/Strings/Search/RabinKarp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | 4 | namespace Algorithms.Strings.Search 5 | { 6 | public class RabinKarp 7 | { 8 | private const int R = 256; 9 | private int Q = 179426549; 10 | private int patHash; 11 | private int M; 12 | private int RM; 13 | public RabinKarp(string pat) 14 | { 15 | var N = pat.Length; 16 | RM = 1; 17 | for (var i = 1; i < N; ++i) 18 | { 19 | RM = (RM * R) % Q; 20 | } 21 | patHash = Hash(pat, pat.Length); 22 | M = pat.Length; 23 | } 24 | 25 | private int Hash(String text, int k) 26 | { 27 | int h = 0; 28 | for (var i = 0; i < k; ++i) 29 | { 30 | h = (h * R + text[i]) % Q; 31 | } 32 | return h; 33 | } 34 | 35 | public int Search(string text) 36 | { 37 | int N = text.Length; 38 | var h = Hash(text, M); 39 | if (h == patHash) return 0; 40 | for (var i = 1; i < N - M; ++i) 41 | { 42 | h = (h + Q - RM * text[i - 1] % Q) % Q; 43 | h = (h * R + text[i + M - 1]) % Q; 44 | 45 | if (h == patHash) return i; 46 | } 47 | return -1; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /cs-algorithms/UnionFind/WeightedQuickUnion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Algorithms.UnionFind 7 | { 8 | public class WeightedQuickUnion : IUnionFind 9 | { 10 | protected int[] mParent = null; 11 | protected int[] mSize = null; 12 | public WeightedQuickUnion(int n) 13 | { 14 | mParent = new int[n]; 15 | mSize = new int[n]; 16 | for (var i = 0; i < n; ++i) 17 | { 18 | mParent[i] = i; 19 | mSize[i] = 1; 20 | } 21 | } 22 | 23 | protected int GetRoot(int i) 24 | { 25 | while (mParent[i] != i) 26 | { 27 | i = mParent[i]; 28 | } 29 | return i; 30 | } 31 | 32 | public void Union(int p, int q) 33 | { 34 | var i = GetRoot(p); 35 | var j = GetRoot(q); 36 | if (mSize[i] < mSize[j]) 37 | { 38 | mParent[i] = j; 39 | mSize[j] += mSize[i]; 40 | } 41 | else 42 | { 43 | mParent[j] = i; 44 | mSize[i] += mSize[j]; 45 | } 46 | } 47 | 48 | public bool IsConnected(int i, int j) 49 | { 50 | return GetRoot(i) == GetRoot(j); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /cs-algorithms/Strings/Sort/MSD.cs: -------------------------------------------------------------------------------- 1 | namespace Algorithms.Strings.Sort 2 | { 3 | public class MSD 4 | { 5 | public static void Sort(string[] a) 6 | { 7 | string[] aux = new string[a.Length]; 8 | Sort(a, aux, 0, a.Length-1, 0); 9 | } 10 | 11 | private static void Sort(string[] a, string[] aux, int lo, int hi, int d) 12 | { 13 | if (lo >= hi) return; 14 | 15 | var R = 256; 16 | var count = new int[R + 2]; 17 | 18 | for (var i = lo; i <= hi; ++i) 19 | { 20 | count[charAt(a[i], d) + 2]++; 21 | } 22 | 23 | for (var r = 0; r < R + 1; ++r) 24 | { 25 | count[r + 1] += count[r]; 26 | } 27 | 28 | for (var i = lo; i <= hi; ++i) 29 | { 30 | aux[count[charAt(a[i], d) + 1]++] = a[i]; 31 | } 32 | 33 | for (var i = lo; i <= hi; ++i) 34 | { 35 | a[i] = aux[i-lo]; 36 | } 37 | 38 | for (var r = 0; r < R+1; ++r) 39 | { 40 | Sort(a, aux, lo + count[r], lo + count[r+1]-1, d+1); 41 | } 42 | } 43 | 44 | private static int charAt(string a, int d) 45 | { 46 | if (a.Length <= d) 47 | { 48 | return -1; 49 | } 50 | return a[d]; 51 | } 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /cs-algorithms/Selection/QuickSelect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Algorithms.Utils; 6 | 7 | namespace SimuKit.Algorithms.Selection 8 | { 9 | public class QuickSelect 10 | { 11 | public static T Select(T[] a, int k, Comparison compareTo = null) 12 | { 13 | int lo = 0; 14 | int hi = a.Length - 1; 15 | while (lo < hi) 16 | { 17 | int j = Partition(a, lo, hi, compareTo); 18 | if (j < k) lo = j + 1; 19 | else if (j > k) hi = j - 1; 20 | else return a[k]; 21 | } 22 | 23 | return a[k]; 24 | } 25 | 26 | public static int Partition(T[] a, int lo, int hi, Comparison compareTo) 27 | { 28 | int i = lo; 29 | int j = hi + 1; 30 | while (true) 31 | { 32 | while (SortUtil.IsLessThan(a[++i], a[lo], compareTo)) 33 | { 34 | if (i == hi) break; 35 | } 36 | while(SortUtil.IsLessThan(a[lo], a[--j], compareTo)) 37 | { 38 | if(j==lo) break; 39 | } 40 | 41 | if(i >= j) break; 42 | 43 | SortUtil.Exchange(a, i, j); 44 | } 45 | 46 | SortUtil.Exchange(a, lo, j); 47 | return j; 48 | 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Graphs/WeightedDiGraph.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Algorithms.DataStructures.Graphs 4 | { 5 | public class WeightedDiGraph 6 | { 7 | private int vertexCount; 8 | private List[] adjList; 9 | 10 | public WeightedDiGraph(int V) 11 | { 12 | vertexCount = V; 13 | adjList = new List[V]; 14 | for (var v = 0; v < V; ++v) 15 | { 16 | adjList[v] =new List(); 17 | } 18 | } 19 | 20 | public void addEdge(Edge e) 21 | { 22 | var v = e.from(); 23 | 24 | adjList[v].Add(e); 25 | } 26 | 27 | public List adj(int v) 28 | { 29 | return adjList[v]; 30 | } 31 | 32 | public int V() 33 | { 34 | return vertexCount; 35 | } 36 | 37 | public List edges() 38 | { 39 | var result = new List(); 40 | for (var v = 0; v < vertexCount; ++v) 41 | { 42 | result.AddRange(adjList[v]); 43 | } 44 | return result; 45 | } 46 | 47 | public DiGraph ToDiGraph() 48 | { 49 | DiGraph g = new DiGraph(vertexCount); 50 | 51 | foreach(var e in edges()) 52 | { 53 | g.addEdge(e.from(), e.to()); 54 | } 55 | 56 | return g; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/MST/LazyPrim.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Algorithms.DataStructures.Graphs; 3 | using Algorithms.DataStructures.Queue; 4 | 5 | namespace Algorithms.Graphs.MST 6 | { 7 | public class LazyPrim 8 | { 9 | private bool[] marked; 10 | private List mst; 11 | private MinPQ pq; 12 | 13 | public LazyPrim(WeightedGraph G) 14 | { 15 | var V = G.V(); 16 | marked = new bool[V]; 17 | pq = new MinPQ(); 18 | 19 | var s = 0; 20 | foreach (var e in G.adj(s)) 21 | { 22 | pq.Enqueue(e); 23 | } 24 | 25 | mst = new List(); 26 | 27 | while (!pq.IsEmpty && mst.Count < V - 1) 28 | { 29 | var e = pq.DelMin(); 30 | var v = e.either(); 31 | var w = e.other(v); 32 | 33 | if (marked[v] && marked[w]) continue; 34 | 35 | mst.Add(e); 36 | 37 | if(!marked[v]) visit(G, v); 38 | if (!marked[w]) visit(G, w); 39 | } 40 | } 41 | 42 | private void visit(WeightedGraph G, int v) 43 | { 44 | marked[v] = true; 45 | foreach (var e in G.adj(v)) 46 | { 47 | var w = e.other(v); 48 | if (!marked[w]) 49 | { 50 | pq.Enqueue(e); 51 | } 52 | } 53 | } 54 | 55 | public List MST => mst; 56 | } 57 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/MST/EagerPrim.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Algorithms.DataStructures.Graphs; 5 | using Algorithms.DataStructures.Queue; 6 | 7 | namespace Algorithms.Graphs.MST 8 | { 9 | public class EagerPrim 10 | { 11 | private IndexMinPQ pq; 12 | private List path; 13 | private bool[] marked; 14 | 15 | public EagerPrim(WeightedGraph G) 16 | { 17 | int V = G.V(); 18 | pq = new IndexMinPQ(V); 19 | 20 | marked = new bool[V]; 21 | 22 | Visit(G, 0); 23 | 24 | path = new List(); 25 | 26 | while (!pq.IsEmpty) 27 | { 28 | var e = pq.MinKey(); 29 | var v = pq.DelMin(); 30 | path.Add(e); 31 | if(!marked[v]) Visit(G, v); 32 | } 33 | } 34 | 35 | private void Visit(WeightedGraph G, int v) 36 | { 37 | marked[v] = true; 38 | foreach (var e in G.adj(v)) 39 | { 40 | int w = e.other(v); 41 | if (!marked[w]) 42 | { 43 | if (!pq.Contains(w)) 44 | { 45 | pq.Insert(w, e); 46 | } 47 | else 48 | { 49 | pq.DecreaseKey(w, e); 50 | } 51 | } 52 | } 53 | } 54 | 55 | public List MST => path; 56 | } 57 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/QuickSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | 4 | namespace Algorithms.Sorting 5 | { 6 | public class QuickSort 7 | { 8 | public static void Sort(T[] a) where T : IComparable 9 | { 10 | Sort(a, 0, a.Length - 1, (a1, a2) => a1.CompareTo(a2)); 11 | } 12 | 13 | public static void Sort(T[] a, int lo, int hi, Comparison compare) 14 | { 15 | if (lo >= hi) 16 | { 17 | return; 18 | } 19 | 20 | if (hi - lo <= 7) 21 | { 22 | InsertionSort.Sort(a, lo, hi, compare); 23 | return; 24 | } 25 | 26 | var j = Partition(a, lo, hi, compare); 27 | Sort(a, lo, j-1, compare); 28 | Sort(a, j+1, hi, compare); 29 | } 30 | 31 | public static int Partition(T[] a, int lo, int hi, Comparison compare) 32 | { 33 | var v = a[lo]; 34 | int i = lo, j = hi+1; 35 | while (true) 36 | { 37 | while (SortUtil.IsLessThan(a[++i], v, compare)) 38 | { 39 | if (i >= hi) break; 40 | } 41 | while (SortUtil.IsLessThan(v, a[--j], compare)) 42 | { 43 | if (j <= lo) break; 44 | } 45 | 46 | if (i >= j) 47 | { 48 | break; 49 | } 50 | 51 | SortUtil.Exchange(a, i, j); 52 | } 53 | SortUtil.Exchange(a, lo, j); 54 | return j; 55 | } 56 | 57 | } 58 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/HeapSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices.ComTypes; 3 | using Algorithms.Utils; 4 | 5 | namespace Algorithms.Sorting 6 | { 7 | public class HeapSort 8 | { 9 | public static void Sort(T[] a) where T : IComparable 10 | { 11 | Sort(a, (a1, a2) => a1.CompareTo(a2)); 12 | } 13 | 14 | public static void Sort(T[] a, Comparison comparison) 15 | { 16 | var N = a.Length; 17 | for (var i = N / 2; i >= 1; --i) 18 | { 19 | Sink(a, i, N, comparison); 20 | } 21 | while (N > 0) 22 | { 23 | SortUtil.Exchange(a, Index(1), Index(N)); 24 | Sink(a, 1, --N, comparison); 25 | } 26 | } 27 | 28 | private static void Sink(T[] a, int k, int N, Comparison comparison) 29 | { 30 | while (k * 2 <= N) 31 | { 32 | var child = 2 * k; 33 | if (child < N && SortUtil.IsGreaterThan(a[Index(child + 1)], a[Index(child)], comparison)) 34 | { 35 | child++; 36 | } 37 | if (SortUtil.IsGreaterThan(a[Index(child)], a[Index(k)], comparison)) 38 | { 39 | SortUtil.Exchange(a, Index(child), Index(k)); 40 | k = child; 41 | } 42 | else 43 | { 44 | break; 45 | } 46 | } 47 | } 48 | 49 | private static int Index(int j) 50 | { 51 | return j - 1; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /cs-algorithms/UnionFind/WeightedQuickUnionWithPathCompression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Algorithms.UnionFind 7 | { 8 | public class WeightedQuickUnionWithPathCompression : IUnionFind 9 | { 10 | protected int[] mParent = null; 11 | protected int[] mSize = null; 12 | public WeightedQuickUnionWithPathCompression(int n) 13 | { 14 | mParent = new int[n]; 15 | mSize = new int[n]; 16 | for (int i = 0; i < n; ++i) 17 | { 18 | mParent[i] = i; 19 | mSize[i] = 1; 20 | } 21 | } 22 | 23 | public int GetSize(int i) 24 | { 25 | int r = GetRoot(i); 26 | return mSize[r]; 27 | } 28 | 29 | protected int GetRoot(int i) 30 | { 31 | while (mParent[i] != i) 32 | { 33 | mParent[i] = mParent[mParent[i]]; 34 | i = mParent[i]; 35 | } 36 | return i; 37 | } 38 | 39 | public void Union(int p, int q) 40 | { 41 | int i = GetRoot(p); 42 | int j = GetRoot(q); 43 | if (mSize[i] < mSize[j]) 44 | { 45 | mParent[i] = j; 46 | mSize[j] += mSize[i]; 47 | } 48 | else 49 | { 50 | mParent[j] = i; 51 | mSize[i] += mSize[j]; 52 | } 53 | } 54 | 55 | public bool IsConnected(int i, int j) 56 | { 57 | return GetRoot(i) == GetRoot(j); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/SearchTries/RWayTriesUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.PortableExecutable; 2 | using Algorithms.DataStructures.HashMap; 3 | using Algorithms.DataStructures.SearchTries; 4 | using Algorithms.DataStructures.TreeMap; 5 | using Xunit; 6 | using Xunit.Abstractions; 7 | 8 | namespace AlgorithmsUnitTest.DataStrutures.TreeMap 9 | { 10 | public class RWayTriesUnitTest 11 | { 12 | private ITestOutputHelper console; 13 | public RWayTriesUnitTest(ITestOutputHelper console) 14 | { 15 | this.console = console; 16 | } 17 | 18 | [Fact] 19 | public void TestSearchTries() 20 | { 21 | var map = new RWayTries(); 22 | Assert.True(map.IsEmpty); 23 | map["one"] = 1; 24 | Assert.Equal(1, map["one"]); 25 | map["two"] = 2; 26 | Assert.Equal(2, map["two"]); 27 | Assert.Equal(2, map.Count); 28 | 29 | 30 | map.Delete("two"); 31 | Assert.Equal(1, map.Count); 32 | Assert.True(map.ContainsKey("one")); 33 | Assert.False(map.ContainsKey("two")); 34 | Assert.False(map.IsEmpty); 35 | 36 | 37 | foreach(var key in map.Keys) 38 | { 39 | console.WriteLine("{0}", key); 40 | } 41 | 42 | map["test"] = 3; 43 | map["te"] = 4; 44 | map["team"] = 4; 45 | map["dream"] = 2; 46 | 47 | int count = 0; 48 | foreach (var key in map.KeysWithPrefix("te")) 49 | { 50 | count++; 51 | console.WriteLine("{0}", key); 52 | } 53 | Assert.Equal(3, count); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/TopologicalSort/DepthFirstPostOrder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Algorithms.DataStructures.Graphs; 5 | using DataStructures.Stack; 6 | 7 | namespace Algorithms.Graphs.TopologicalSort 8 | { 9 | public class DepthFirstPostOrder 10 | { 11 | private bool[] marked; 12 | private StackLinkedList reversePostOrder; 13 | 14 | public DepthFirstPostOrder(DiGraph G) 15 | { 16 | var V = G.V(); 17 | 18 | marked = new bool[V]; 19 | reversePostOrder = new StackLinkedList(); 20 | for (var v = 0; v < V; ++v) 21 | { 22 | if (marked[v]) continue; 23 | dfs(G, v); 24 | } 25 | } 26 | 27 | private void dfs(DiGraph G, int v) 28 | { 29 | marked[v] = true; 30 | foreach (var w in G.adj(v)) 31 | { 32 | if (marked[w]) continue; 33 | dfs(G, w); 34 | } 35 | reversePostOrder.Push(v); 36 | } 37 | 38 | public IEnumerable PostOrder() 39 | { 40 | return reversePostOrder; 41 | } 42 | 43 | public String PostOrderToString() 44 | { 45 | StringBuilder sb = new StringBuilder(); 46 | var first = true; 47 | foreach (var x in PostOrder()) 48 | { 49 | if (first) 50 | { 51 | first = false; 52 | } 53 | else 54 | { 55 | sb.Append(" => "); 56 | } 57 | sb.Append(x); 58 | } 59 | return sb.ToString(); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/ShortestPaths/DijkstraUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Algorithms.DataStructures.Graphs; 5 | using Algorithms.Graphs.ShortestPaths; 6 | using Xunit; 7 | using Xunit.Abstractions; 8 | 9 | namespace AlgorithmsUnitTest.Graphs.ShortestPaths 10 | { 11 | public class DijkstraUnitTest 12 | { 13 | private ITestOutputHelper console; 14 | 15 | public DijkstraUnitTest(ITestOutputHelper console) 16 | { 17 | this.console = console; 18 | } 19 | 20 | [Fact] 21 | public void Test() 22 | { 23 | WeightedDiGraph G = GraphGenerator.directedEdgeWeightedGraph(); 24 | Dijkstra dijkstra = new Dijkstra(G, 0); 25 | for(var v=1; v < G.V(); ++v) 26 | { 27 | if (!dijkstra.HasPathTo(v)) 28 | { 29 | Console.WriteLine("Path not found for {0}", v); 30 | continue; 31 | } 32 | IEnumerable path = dijkstra.PathTo(v); 33 | 34 | console.WriteLine(ToString(path)); 35 | Console.WriteLine(ToString(path)); 36 | } 37 | } 38 | 39 | private String ToString(IEnumerable path) 40 | { 41 | StringBuilder sb = new StringBuilder(); 42 | bool first = true; 43 | foreach (var e in path) 44 | { 45 | if (first) 46 | { 47 | first = false; 48 | sb.Append(e.from()); 49 | } 50 | sb.Append("=(").Append(e.Weight).Append(")=>").Append(e.to()); 51 | } 52 | return sb.ToString(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/DataStrutures/SearchTries/TernarySearchTriesUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.PortableExecutable; 2 | using Algorithms.DataStructures.HashMap; 3 | using Algorithms.DataStructures.SearchTries; 4 | using Algorithms.DataStructures.TreeMap; 5 | using Xunit; 6 | using Xunit.Abstractions; 7 | 8 | namespace AlgorithmsUnitTest.DataStrutures.TreeMap 9 | { 10 | public class TernarySearchTriesUnitTest 11 | { 12 | private ITestOutputHelper console; 13 | public TernarySearchTriesUnitTest(ITestOutputHelper console) 14 | { 15 | this.console = console; 16 | } 17 | 18 | [Fact] 19 | public void TestSearchTries() 20 | { 21 | var map = new TernarySearchTries(); 22 | Assert.True(map.IsEmpty); 23 | map["one"] = 1; 24 | Assert.Equal(1, map["one"]); 25 | map["two"] = 2; 26 | Assert.Equal(2, map["two"]); 27 | Assert.Equal(2, map.Count); 28 | 29 | 30 | 31 | map.Delete("two"); 32 | Assert.Equal(1, map.Count); 33 | Assert.True(map.ContainsKey("one")); 34 | Assert.False(map.ContainsKey("two")); 35 | Assert.False(map.IsEmpty); 36 | 37 | 38 | 39 | foreach(var key in map.Keys) 40 | { 41 | console.WriteLine("{0}", key); 42 | } 43 | 44 | 45 | map["test"] = 3; 46 | map["te"] = 4; 47 | map["team"] = 4; 48 | map["dream"] = 2; 49 | 50 | int count = 0; 51 | foreach (var key in map.KeysWithPrefix("te")) 52 | { 53 | count++; 54 | console.WriteLine("{0}", key); 55 | } 56 | Assert.Equal(3, count); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/Cycles/DirectedCycles.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Algorithms.DataStructures.Graphs; 3 | using Algorithms.Graphs.Search; 4 | using DataStructures.Stack; 5 | 6 | namespace Algorithms.Graphs.Cycles 7 | { 8 | public class DirectedCycles 9 | { 10 | private bool[] marked; 11 | private bool[] onStack; 12 | private int[] edgeTo; 13 | private StackLinkedList circle; 14 | 15 | public DirectedCycles(DiGraph G) 16 | { 17 | 18 | var V = G.V(); 19 | marked = new bool[V]; 20 | edgeTo = new int[V]; 21 | onStack = new bool[V]; 22 | 23 | } 24 | 25 | private void dfs(DiGraph G, int v) 26 | { 27 | marked[v] = true; 28 | onStack[v] = true; 29 | foreach (var w in G.adj(v)) 30 | { 31 | if (!marked[w]) 32 | { 33 | edgeTo[w] = v; 34 | dfs(G, w); 35 | } else if (onStack[w]) 36 | { 37 | if (circle == null) 38 | { 39 | return; 40 | } 41 | else 42 | { 43 | circle = new StackLinkedList(); 44 | for (var x = w; x != v; x = edgeTo[x]) { 45 | circle.Push(x); 46 | } 47 | 48 | circle.Push(v); 49 | circle.Push(w); 50 | 51 | } 52 | } 53 | } 54 | onStack[v] = false; 55 | } 56 | 57 | 58 | public bool HasCycle => circle != null; 59 | public IEnumerable Cycle => circle; 60 | 61 | } 62 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/ShortestPaths/BellmanFordUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Algorithms.DataStructures.Graphs; 5 | using Algorithms.Graphs.ShortestPaths; 6 | using Xunit; 7 | using Xunit.Abstractions; 8 | 9 | namespace AlgorithmsUnitTest.Graphs.ShortestPaths 10 | { 11 | public class BellmanFordUnitTest 12 | { 13 | private ITestOutputHelper console; 14 | 15 | public BellmanFordUnitTest(ITestOutputHelper console) 16 | { 17 | this.console = console; 18 | } 19 | 20 | [Fact] 21 | public void Test() 22 | { 23 | WeightedDiGraph G = GraphGenerator.directedEdgeWeightedGraph(); 24 | BellmanFulkerson BellmanFulkerson = new BellmanFulkerson(G, 0); 25 | for(var v=1; v < G.V(); ++v) 26 | { 27 | if (!BellmanFulkerson.HasPathTo(v)) 28 | { 29 | Console.WriteLine("Path not found for {0}", v); 30 | continue; 31 | } 32 | IEnumerable path = BellmanFulkerson.PathTo(v); 33 | 34 | console.WriteLine(ToString(path)); 35 | Console.WriteLine(ToString(path)); 36 | } 37 | } 38 | 39 | private String ToString(IEnumerable path) 40 | { 41 | StringBuilder sb = new StringBuilder(); 42 | bool first = true; 43 | foreach (var e in path) 44 | { 45 | if (first) 46 | { 47 | first = false; 48 | sb.Append(e.from()); 49 | } 50 | sb.Append("=(").Append(e.Weight).Append(")=>").Append(e.to()); 51 | } 52 | return sb.ToString(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /cs-algorithms/Sorting/MergeSort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Utils; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Algorithms.Sorting 6 | { 7 | public class MergeSort 8 | { 9 | public static void Sort(T[] a) where T : IComparable 10 | { 11 | Sort(a, 0, a.Length-1, (a1, a2) => a1.CompareTo(a2)); 12 | } 13 | 14 | public static void Sort(T[] a, int lo, int hi, Comparison compare) 15 | { 16 | var aux = new T[a.Length]; 17 | Sort(a, aux, lo, hi, compare); 18 | } 19 | 20 | private static void Sort(T[] a, T[] aux, int lo, int hi, Comparison compare) 21 | { 22 | if (lo >= hi) return; 23 | 24 | if (hi - lo <= 7) 25 | { 26 | InsertionSort.Sort(a, lo, hi, compare); 27 | return; 28 | } 29 | 30 | var mid = (hi - lo) / 2 + lo; 31 | Sort(a, aux, lo, mid, compare); 32 | Sort(a, aux, mid, hi, compare); 33 | Merge(a, aux, lo, mid, hi, compare); 34 | } 35 | 36 | private static void Merge(T[] a, T[] aux, int lo, int mid, int hi, Comparison compare) 37 | { 38 | int i, j; 39 | for (i = lo; i <= hi; ++i) 40 | { 41 | aux[i] = a[i]; 42 | } 43 | 44 | i = lo; 45 | j = mid; 46 | for(var k=lo; k <= hi; ++k) 47 | { 48 | if (i >= mid) a[k] = aux[j++]; 49 | else if (j >= hi) a[k] = aux[i++]; 50 | else if (SortUtil.IsLessThan(aux[i], aux[j], compare)) 51 | { 52 | a[k] = aux[i++]; 53 | } 54 | else 55 | { 56 | a[k] = aux[j++]; 57 | } 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/ShortestPaths/TopologicalSortShortestPathUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Algorithms.DataStructures.Graphs; 5 | using Algorithms.Graphs.ShortestPaths; 6 | using Xunit; 7 | using Xunit.Abstractions; 8 | 9 | namespace AlgorithmsUnitTest.Graphs.ShortestPaths 10 | { 11 | public class TopologicalSortShortestPathUnitTest 12 | { 13 | private ITestOutputHelper console; 14 | 15 | public TopologicalSortShortestPathUnitTest(ITestOutputHelper console) 16 | { 17 | this.console = console; 18 | } 19 | 20 | [Fact] 21 | public void Test() 22 | { 23 | var G = GraphGenerator.directedEdgeWeightedGraph(); 24 | var TopologicalSortShortestPath = new TopologicalSortShortestPath(G, 0); 25 | for(var v=1; v < G.V(); ++v) 26 | { 27 | if (!TopologicalSortShortestPath.HasPathTo(v)) 28 | { 29 | Console.WriteLine("Path not found for {0}", v); 30 | continue; 31 | } 32 | IEnumerable path = TopologicalSortShortestPath.PathTo(v); 33 | 34 | console.WriteLine(ToString(path)); 35 | Console.WriteLine(ToString(path)); 36 | } 37 | } 38 | 39 | private String ToString(IEnumerable path) 40 | { 41 | StringBuilder sb = new StringBuilder(); 42 | bool first = true; 43 | foreach (var e in path) 44 | { 45 | if (first) 46 | { 47 | first = false; 48 | sb.Append(e.from()); 49 | } 50 | sb.Append("=(").Append(e.Weight).Append(")=>").Append(e.to()); 51 | } 52 | return sb.ToString(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Stack/StackArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace DataStructures.Stack 6 | { 7 | public class StackArray : IStack 8 | { 9 | private T[] s = new T[10]; 10 | private int N = 0; 11 | 12 | public T Pop() 13 | { 14 | if (N == 0) return default(T); 15 | T item = s[--N]; 16 | if (N == s.Length / 4) Resize(s.Length / 2); 17 | return item; 18 | } 19 | 20 | private void Resize(int len) 21 | { 22 | T[] temp = new T[len]; 23 | for (var i = 0; i < Math.Min(len, s.Length); ++i) 24 | { 25 | temp[i] = s[i]; 26 | } 27 | s = temp; 28 | 29 | } 30 | 31 | public void Push(T item) 32 | { 33 | s[N++] = item; 34 | if(N == s.Length) Resize(s.Length * 2); 35 | } 36 | 37 | public int Count => N; 38 | public bool IsEmpty => N == 0; 39 | public IEnumerator GetEnumerator() 40 | { 41 | return new StackEnumerator(s, N); 42 | } 43 | 44 | IEnumerator IEnumerable.GetEnumerator() 45 | { 46 | return GetEnumerator(); 47 | } 48 | 49 | private class StackEnumerator : IEnumerator 50 | { 51 | private int current; 52 | private T[] s; 53 | private int N; 54 | private T value; 55 | 56 | public StackEnumerator(T[] s, int N) 57 | { 58 | this.s = s; 59 | this.N = N; 60 | current = N; 61 | } 62 | 63 | public bool MoveNext() 64 | { 65 | if (current == -1) return false; 66 | value = s[current--]; 67 | return true; 68 | } 69 | 70 | public void Reset() 71 | { 72 | current = N-1; 73 | } 74 | 75 | public T Current => value; 76 | 77 | object IEnumerator.Current 78 | { 79 | get { return Current; } 80 | } 81 | 82 | public void Dispose() 83 | { 84 | 85 | } 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Search/LongestRepeatedPatternUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Search 7 | { 8 | public class LongestRepeatedPatternUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | 12 | public LongestRepeatedPatternUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void Test() 19 | { 20 | String text = "o fare thee well, poor devil of a Sub-Sub, whose commen- \n" + "tator I am. Thou belongest to that hopeless, sallow tribe \n" 21 | + "which no wine of this world will ever warm ; and for whom \n" + "even Pale Sherry would be too rosy-strong ; but with whom \n" 22 | + "one sometimes loves to sit, and feel poor-devilish, too ; and \n" 23 | + "grow convivial upon tears ; and say to them bluntly with full \n" + "eyes and empty glasses, and in not altogether unpleasant \n" 24 | + "sadness Give it up, Sub-Subs ! For by how much the more \n" + "pains ye take to please the world, by so much the more shall \n" 25 | + "ye forever go thankless ! Would that I could clear out \n" + "Hampton Court and the Tuileries for ye ! But gulp down \n" 26 | + "your tears and hie aloft to the royal-mast with your hearts ; \n" + "for your friends who have gone before are clearing out the \n" 27 | + "seven-storied heavens, and making refugees of long-pampered \n" + "Gabriel, Michael, and Raphael, against your coming. Here \n" 28 | + "ye strike but splintered hearts together there, ye shall \n" + "strike unsplinterable glasses! "; 29 | 30 | console.WriteLine(LongestRepeatedPattern.Find(text)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Search/LongestCommonPatternUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Search 7 | { 8 | public class LongestCommonPatternUnitTest 9 | { 10 | private ITestOutputHelper console; 11 | 12 | public LongestCommonPatternUnitTest(ITestOutputHelper console) 13 | { 14 | this.console = console; 15 | } 16 | 17 | [Fact] 18 | public void Test() 19 | { 20 | String text = "o fare thee well, poor devil of a Sub-Sub, whose commen- \n" + "tator I am. Thou belongest to that hopeless, sallow tribe \n" 21 | + "which no wine of this world will ever warm ; and for whom \n" + "even Pale Sherry would be too rosy-strong ; but with whom \n" 22 | + "one sometimes loves to sit, and feel poor-devilish, too ; and \n" 23 | + "grow convivial upon tears ; and say to them bluntly with full \n" + "eyes and empty glasses, and in not altogether unpleasant \n" 24 | + "sadness Give it up, Sub-Subs ! For by how much the more \n" + "pains ye take to please the world, by so much the more shall \n" 25 | + "ye forever go thankless ! Would that I could clear out \n" + "Hampton Court and the Tuileries for ye ! But gulp down \n" 26 | + "your tears and hie aloft to the royal-mast with your hearts ; \n" + "for your friends who have gone before are clearing out the \n" 27 | + "seven-storied heavens, and making refugees of long-pampered \n" + "Gabriel, Michael, and Raphael, against your coming. Here \n" 28 | + "ye strike but splintered hearts together there, ye shall \n" + "strike unsplinterable glasses! "; 29 | 30 | console.WriteLine(LongestCommonPattern.LongestCommonString(text, "ye strike but splintered hit")); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/Search/DepthFirstSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Algorithms.DataStructures.Graphs; 5 | using DataStructures.Stack; 6 | 7 | namespace Algorithms.Graphs.Search 8 | { 9 | public class DepthFirstSearch 10 | { 11 | private bool[] marked; 12 | private int[] edgeTo; 13 | private int s; 14 | private int V; 15 | public DepthFirstSearch(Graph G, int s) 16 | { 17 | this.s = s; 18 | this.V = G.V(); 19 | 20 | marked = new bool[V]; 21 | edgeTo = new int[V]; 22 | 23 | dfs(G, s); 24 | 25 | } 26 | 27 | private void dfs(Graph G, int v) 28 | { 29 | marked[v] = true; 30 | foreach (var w in G.adj(v)) 31 | { 32 | if (marked[w]) continue; 33 | edgeTo[w] = v; 34 | dfs(G, w); 35 | } 36 | } 37 | 38 | public bool CanReach(int v) 39 | { 40 | return marked[v]; 41 | } 42 | 43 | public IEnumerable Path(int v) 44 | { 45 | if (!marked[v]) return new List(); 46 | 47 | var path = new StackLinkedList(); 48 | 49 | for (var x = v; x != s; x = edgeTo[x]) 50 | { 51 | path.Push(x); 52 | } 53 | path.Push(s); 54 | return path; 55 | } 56 | 57 | public String PathToString(int v) 58 | { 59 | StringBuilder sb = new StringBuilder(); 60 | var first = true; 61 | foreach (var x in Path(v)) 62 | { 63 | if (first) 64 | { 65 | first = false; 66 | } 67 | else 68 | { 69 | sb.Append(" => "); 70 | } 71 | sb.Append(x); 72 | } 73 | return sb.ToString(); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/ShortestPaths/TopologicalSortShortestPath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Algorithms.DataStructures.Graphs; 4 | using Algorithms.DataStructures.Queue; 5 | using Algorithms.Graphs.TopologicalSort; 6 | using DataStructures.Stack; 7 | 8 | namespace Algorithms.Graphs.ShortestPaths 9 | { 10 | public class TopologicalSortShortestPath 11 | { 12 | private int s; 13 | private bool[] marked; 14 | private Edge[] edgeTo; 15 | private double[] cost; 16 | public TopologicalSortShortestPath(WeightedDiGraph G, int s) 17 | { 18 | this.s = s; 19 | int V = G.V(); 20 | marked = new bool[V]; 21 | edgeTo = new Edge[V]; 22 | cost = new double[V]; 23 | 24 | for (var i = 0; i < V; ++i) 25 | { 26 | cost[i] = Double.MaxValue; 27 | } 28 | 29 | cost[s] = 0; 30 | 31 | DepthFirstPostOrder dfo = new DepthFirstPostOrder(G.ToDiGraph()); 32 | 33 | foreach (var v in dfo.PostOrder()) 34 | { 35 | foreach (var e in G.adj(v)) 36 | { 37 | Relax(G, e); 38 | } 39 | } 40 | 41 | } 42 | 43 | private void Relax(WeightedDiGraph G, Edge e) 44 | { 45 | int v = e.from(); 46 | int w = e.to(); 47 | if (cost[w] > cost[v] + e.Weight) 48 | { 49 | cost[w] = cost[v] + e.Weight; 50 | edgeTo[w] = e; 51 | marked[w] = true; 52 | } 53 | } 54 | 55 | public bool HasPathTo(int v) 56 | { 57 | return marked[v]; 58 | } 59 | 60 | public IEnumerable PathTo(int v) 61 | { 62 | var path = new StackLinkedList(); 63 | for (var x = v; x != s; x = edgeTo[x].from()) 64 | { 65 | path.Push(edgeTo[x]); 66 | } 67 | return path; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/MaxFlow/FordFulkerson.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.DataStructures.Queue; 3 | 4 | namespace Algorithms.Graphs.MaxFlow 5 | { 6 | public class FordFulkerson 7 | { 8 | private int s; 9 | private int t; 10 | private FlowEdge[] edgeTo; 11 | private bool[] marked; 12 | private double value; 13 | 14 | public FordFulkerson(FlowNetwork G, int s, int t) 15 | { 16 | 17 | 18 | this.s = s; 19 | this.t = t; 20 | value = 0; 21 | 22 | while (HasAugmentedPath(G)) 23 | { 24 | var bottle = double.MaxValue; 25 | for (var x = t; x != s; x = edgeTo[x].other(x)) 26 | { 27 | bottle = Math.Min(bottle, edgeTo[x].residualCapacityTo(x)); 28 | } 29 | 30 | for (var x = t; x != s; x = edgeTo[x].other(x)) 31 | { 32 | edgeTo[x].addResidualFlowTo(x, bottle); 33 | } 34 | 35 | value += bottle; 36 | 37 | } 38 | } 39 | 40 | private bool HasAugmentedPath(FlowNetwork G) 41 | { 42 | var V = G.V(); 43 | edgeTo = new FlowEdge[V]; 44 | marked = new bool[V]; 45 | var queue =new QueueLinkedList(); 46 | queue.Enqueue(s); 47 | 48 | while (!queue.IsEmpty) 49 | { 50 | var x = queue.Dequeue(); 51 | marked[x] = true; 52 | foreach (var e in G.adj(x)) 53 | { 54 | var w = e.other(x); 55 | 56 | if (!marked[w] && e.residualCapacityTo(w) > 0) 57 | { 58 | queue.Enqueue(w); 59 | edgeTo[w] = e; 60 | 61 | if (w == t) 62 | { 63 | return true; 64 | } 65 | } 66 | } 67 | } 68 | 69 | return false; 70 | } 71 | 72 | public double Value => value; 73 | } 74 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/Search/BreadthFirstSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Algorithms.DataStructures.Graphs; 5 | using Algorithms.DataStructures.Queue; 6 | using DataStructures.Stack; 7 | 8 | namespace Algorithms.Graphs.Search 9 | { 10 | public class BreadthFirstSearch 11 | { 12 | private bool[] marked; 13 | private int[] edgeTo; 14 | private int s; 15 | 16 | public BreadthFirstSearch(Graph G, int s) 17 | { 18 | var V = G.V(); 19 | this.s = s; 20 | 21 | var queue = new QueueLinkedList(); 22 | queue.Enqueue(s); 23 | 24 | marked = new bool[V]; 25 | edgeTo = new int[V]; 26 | 27 | marked[s] = true; 28 | 29 | while (!queue.IsEmpty) 30 | { 31 | var v = queue.Dequeue(); 32 | 33 | foreach (var w in G.adj(v)) 34 | { 35 | if (marked[w]) continue; 36 | edgeTo[w] = v; 37 | marked[w] = true; 38 | queue.Enqueue(w); 39 | } 40 | } 41 | } 42 | 43 | public bool CanReach(int v){ 44 | return marked[v]; 45 | } 46 | 47 | public IEnumerable Path(int v) 48 | { 49 | var path = new StackLinkedList(); 50 | for (var x = v; x != s; x = edgeTo[x]) 51 | { 52 | path.Push(x); 53 | } 54 | path.Push(s); 55 | return path; 56 | } 57 | 58 | public String PathToString(int v) 59 | { 60 | var sb = new StringBuilder(); 61 | var first = true; 62 | foreach (var x in Path(v)) 63 | { 64 | if (first) 65 | { 66 | first = false; 67 | } 68 | else 69 | { 70 | sb.Append(" => "); 71 | } 72 | sb.Append(x); 73 | } 74 | return sb.ToString(); 75 | } 76 | } 77 | 78 | 79 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Search/RabinKarpUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Search 7 | { 8 | public class RabinKarpUnitTest 9 | { 10 | 11 | private ITestOutputHelper console; 12 | 13 | public RabinKarpUnitTest(ITestOutputHelper console) 14 | { 15 | this.console = console; 16 | } 17 | 18 | [Fact] 19 | public void Test() 20 | { 21 | String text = "o fare thee well, poor devil of a Sub-Sub, whose commen- \n" + "tator I am. Thou belongest to that hopeless, sallow tribe \n" 22 | + "which no wine of this world will ever warm ; and for whom \n" + "even Pale Sherry would be too rosy-strong ; but with whom \n" 23 | + "one sometimes loves to sit, and feel poor-devilish, too ; and \n" 24 | + "grow convivial upon tears ; and say to them bluntly with full \n" + "eyes and empty glasses, and in not altogether unpleasant \n" 25 | + "sadness Give it up, Sub-Subs ! For by how much the more \n" + "pains ye take to please the world, by so much the more shall \n" 26 | + "ye forever go thankless ! Would that I could clear out \n" + "Hampton Court and the Tuileries for ye ! But gulp down \n" 27 | + "your tears and hie aloft to the royal-mast with your hearts ; \n" + "for your friends who have gone before are clearing out the \n" 28 | + "seven-storied heavens, and making refugees of long-pampered \n" + "Gabriel, Michael, and Raphael, against your coming. Here \n" 29 | + "ye strike but splintered hearts together there, ye shall \n" + "strike unsplinterable glasses! "; 30 | 31 | RabinKarp bm = new RabinKarp("the"); 32 | print("found at " + bm.Search(text)); 33 | Assert.NotEqual(-1, bm.Search(text)); 34 | } 35 | 36 | private void print(String content) 37 | { 38 | Console.WriteLine(content); 39 | console.WriteLine(content); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Search/BoyerMooreUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Search 7 | { 8 | public class BoyerMooreUnitTest 9 | { 10 | 11 | private ITestOutputHelper console; 12 | 13 | public BoyerMooreUnitTest(ITestOutputHelper console) 14 | { 15 | this.console = console; 16 | } 17 | 18 | [Fact] 19 | public void Test() 20 | { 21 | String text = "o fare thee well, poor devil of a Sub-Sub, whose commen- \n" + "tator I am. Thou belongest to that hopeless, sallow tribe \n" 22 | + "which no wine of this world will ever warm ; and for whom \n" + "even Pale Sherry would be too rosy-strong ; but with whom \n" 23 | + "one sometimes loves to sit, and feel poor-devilish, too ; and \n" 24 | + "grow convivial upon tears ; and say to them bluntly with full \n" + "eyes and empty glasses, and in not altogether unpleasant \n" 25 | + "sadness Give it up, Sub-Subs ! For by how much the more \n" + "pains ye take to please the world, by so much the more shall \n" 26 | + "ye forever go thankless ! Would that I could clear out \n" + "Hampton Court and the Tuileries for ye ! But gulp down \n" 27 | + "your tears and hie aloft to the royal-mast with your hearts ; \n" + "for your friends who have gone before are clearing out the \n" 28 | + "seven-storied heavens, and making refugees of long-pampered \n" + "Gabriel, Michael, and Raphael, against your coming. Here \n" 29 | + "ye strike but splintered hearts together there, ye shall \n" + "strike unsplinterable glasses! "; 30 | 31 | BoyerMoore bm = new BoyerMoore("the"); 32 | print("found at " + bm.Search(text)); 33 | Assert.NotEqual(-1, bm.Search(text)); 34 | } 35 | 36 | private void print(String content) 37 | { 38 | Console.WriteLine(content); 39 | console.WriteLine(content); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Strings/Search/KnuthMorrisPrattUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Algorithms.Strings.Search; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace AlgorithmsUnitTest.Strings.Search 7 | { 8 | public class KnuthMorrisPrattUnitTest 9 | { 10 | 11 | private ITestOutputHelper console; 12 | 13 | public KnuthMorrisPrattUnitTest(ITestOutputHelper console) 14 | { 15 | this.console = console; 16 | } 17 | 18 | [Fact] 19 | public void Test() 20 | { 21 | String text = "o fare thee well, poor devil of a Sub-Sub, whose commen- \n" + "tator I am. Thou belongest to that hopeless, sallow tribe \n" 22 | + "which no wine of this world will ever warm ; and for whom \n" + "even Pale Sherry would be too rosy-strong ; but with whom \n" 23 | + "one sometimes loves to sit, and feel poor-devilish, too ; and \n" 24 | + "grow convivial upon tears ; and say to them bluntly with full \n" + "eyes and empty glasses, and in not altogether unpleasant \n" 25 | + "sadness Give it up, Sub-Subs ! For by how much the more \n" + "pains ye take to please the world, by so much the more shall \n" 26 | + "ye forever go thankless ! Would that I could clear out \n" + "Hampton Court and the Tuileries for ye ! But gulp down \n" 27 | + "your tears and hie aloft to the royal-mast with your hearts ; \n" + "for your friends who have gone before are clearing out the \n" 28 | + "seven-storied heavens, and making refugees of long-pampered \n" + "Gabriel, Michael, and Raphael, against your coming. Here \n" 29 | + "ye strike but splintered hearts together there, ye shall \n" + "strike unsplinterable glasses! "; 30 | 31 | KnuthMorrisPratt bm = new KnuthMorrisPratt("the"); 32 | print("found at " + bm.Search(text)); 33 | Assert.NotEqual(-1, bm.Search(text)); 34 | } 35 | 36 | private void print(String content) 37 | { 38 | Console.WriteLine(content); 39 | console.WriteLine(content); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Stack/StackLinkedList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Xml; 4 | 5 | namespace DataStructures.Stack 6 | { 7 | public class StackNode 8 | { 9 | internal T item; 10 | internal StackNode Next; 11 | } 12 | 13 | public class StackLinkedList : IStack 14 | { 15 | private StackNode first; 16 | private int N = 0; 17 | 18 | public T Pop() 19 | { 20 | if (first == null) return default(T); 21 | var oldFirst = first; 22 | first = oldFirst.Next; 23 | N--; 24 | return oldFirst.item; 25 | } 26 | 27 | public void Push(T item) 28 | { 29 | var oldFirst = first; 30 | first = new StackNode 31 | { 32 | item = item, 33 | Next = oldFirst 34 | }; 35 | N++; 36 | } 37 | 38 | public int Count => N; 39 | 40 | public bool IsEmpty => Count == 0; 41 | public IEnumerator GetEnumerator() 42 | { 43 | return new StackEnumerator(first); 44 | } 45 | 46 | IEnumerator IEnumerable.GetEnumerator() 47 | { 48 | return GetEnumerator(); 49 | } 50 | 51 | private class StackEnumerator : IEnumerator 52 | { 53 | private T value; 54 | private StackNode current; 55 | private StackNode first; 56 | 57 | public StackEnumerator(StackNode first) 58 | { 59 | this.first = first; 60 | this.current = first; 61 | } 62 | 63 | 64 | public bool MoveNext() 65 | { 66 | if (current == null) return false; 67 | value = current.item; 68 | current = current.Next; 69 | return true; 70 | } 71 | 72 | public void Reset() 73 | { 74 | current = first; 75 | } 76 | 77 | public T Current => value; 78 | 79 | object IEnumerator.Current 80 | { 81 | get { return Current; } 82 | } 83 | 84 | public void Dispose() 85 | { 86 | 87 | } 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/ShortestPaths/Dijkstra.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Xml; 5 | using Algorithms.DataStructures.Graphs; 6 | using Algorithms.DataStructures.Queue; 7 | using DataStructures.Stack; 8 | 9 | namespace Algorithms.Graphs.ShortestPaths 10 | { 11 | public class Dijkstra 12 | { 13 | private int s; 14 | private bool[] marked; 15 | private Edge[] edgeTo; 16 | private double[] cost; 17 | private IndexMinPQ pq; 18 | 19 | public Dijkstra(WeightedDiGraph G, int s) 20 | { 21 | this.s = s; 22 | int V = G.V(); 23 | marked = new bool[V]; 24 | edgeTo = new Edge[V]; 25 | cost = new double[V]; 26 | 27 | for (var i = 0; i < V; ++i) 28 | { 29 | cost[i] = Double.MaxValue; 30 | } 31 | 32 | cost[s] = 0; 33 | 34 | pq = new IndexMinPQ(V); 35 | 36 | 37 | pq.Insert(s, 0); 38 | 39 | while (!pq.IsEmpty) 40 | { 41 | var v = pq.DelMin(); 42 | marked[v] = true; 43 | foreach (var e in G.adj(v)) 44 | { 45 | Relax(G, e); 46 | } 47 | } 48 | 49 | 50 | 51 | } 52 | 53 | private void Relax(WeightedDiGraph G, Edge e) 54 | { 55 | int v = e.from(); 56 | int w = e.to(); 57 | if (cost[w] > cost[v] + e.Weight) 58 | { 59 | cost[w] = cost[v] + e.Weight; 60 | edgeTo[w] = e; 61 | if (!pq.Contains(w)) 62 | { 63 | pq.Insert(w, cost[w]); 64 | } 65 | else 66 | { 67 | pq.DecreaseKey(w, cost[w]); 68 | } 69 | } 70 | } 71 | 72 | public bool HasPathTo(int v) 73 | { 74 | return marked[v]; 75 | } 76 | 77 | public IEnumerable PathTo(int v) 78 | { 79 | var path = new StackLinkedList(); 80 | for (var x = v; x != s; x = edgeTo[x].from()) 81 | { 82 | path.Push(edgeTo[x]); 83 | } 84 | return path; 85 | } 86 | 87 | } 88 | } -------------------------------------------------------------------------------- /cs-algorithms/Graphs/ShortestPaths/BellmanFord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Algorithms.DataStructures.Graphs; 4 | using DataStructures.Stack; 5 | 6 | namespace Algorithms.Graphs.ShortestPaths 7 | { 8 | public class BellmanFulkerson 9 | { 10 | private double[] cost; 11 | private Edge[] edgeTo; 12 | private int s; 13 | private bool negativeCycles; 14 | 15 | public BellmanFulkerson(WeightedDiGraph G, int s) 16 | { 17 | this.s = s; 18 | var V = G.V(); 19 | cost = new double[V]; 20 | for (var v = 0; v < V; ++v) 21 | { 22 | cost[v] = Double.MaxValue; 23 | } 24 | 25 | edgeTo = new Edge[V]; 26 | cost[s] = 0; 27 | 28 | for (var j = 0; j < V; ++j) 29 | { 30 | for (var v = 0; v < V; ++v) 31 | { 32 | foreach (var e in G.adj(v)) 33 | { 34 | Relax(G, e); 35 | } 36 | } 37 | } 38 | 39 | negativeCycles = false; 40 | for (var v = 0; v < V; ++v) 41 | { 42 | foreach (var e in G.adj(v)) 43 | { 44 | if (Relax(G, e)) 45 | { 46 | negativeCycles = true; 47 | } 48 | } 49 | } 50 | } 51 | 52 | private bool Relax(WeightedDiGraph G, Edge e) 53 | { 54 | var v = e.from(); 55 | var w = e.to(); 56 | if (cost[w] > cost[v] + e.Weight) 57 | { 58 | cost[w] = cost[v] + e.Weight; 59 | edgeTo[w] = e; 60 | 61 | return true; 62 | } 63 | return false; 64 | } 65 | 66 | public bool HasPathTo(int v) 67 | { 68 | return cost[v] < Double.MaxValue; 69 | } 70 | 71 | public bool HashNegativeCycles() 72 | { 73 | return negativeCycles; 74 | } 75 | 76 | public IEnumerable PathTo(int v) 77 | { 78 | var path = new StackLinkedList(); 79 | for (var x = v; x != this.s; x = edgeTo[x].other(x)) 80 | { 81 | path.Push(edgeTo[x]); 82 | } 83 | 84 | return path; 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/TreeMap/LeftLeaningRedBlackTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.DataStructures.TreeMap 4 | { 5 | public class LeftLeaningRedBlackTree : BinarySearchTree where K : IComparable 6 | { 7 | protected override Node Put(Node x, K key, V value) 8 | { 9 | if (x == null) 10 | { 11 | return new Node 12 | { 13 | key = key, 14 | value = value, 15 | count = 1, 16 | isRed = true 17 | }; 18 | } 19 | 20 | var cmp = key.CompareTo(x.key); 21 | 22 | if (cmp < 0) 23 | { 24 | x.left = Put(x.left, key, value); 25 | } else if (cmp > 0) 26 | { 27 | x.right = Put(x.right, key, value); 28 | } 29 | else 30 | { 31 | x.value = value; 32 | } 33 | 34 | if (isRed(x.right) && !isRed(x.left)) x = rotateLeft(x); 35 | if (isRed(x.left) && isRed(x.left.left)) x = rotateRight(x); 36 | if (isRed(x.left) && isRed(x.right)) flipColor(x); 37 | 38 | 39 | x.count = 1 + _Count(x.left) + _Count(x.right); 40 | 41 | return x; 42 | 43 | } 44 | 45 | private bool isRed(Node x) 46 | { 47 | if (x == null) return false; 48 | return x.isRed; 49 | } 50 | 51 | private void flipColor(Node x) 52 | { 53 | if (x.left != null) x.left.isRed = false; 54 | if (x.right != null) x.right.isRed = false; 55 | x.isRed = true; 56 | 57 | } 58 | 59 | private Node rotateLeft(Node x) 60 | { 61 | var m = x.right; 62 | x.right = m.left; 63 | m.left = x; 64 | m.isRed = x.isRed; 65 | x.isRed = true; 66 | 67 | x.count = 1 + _Count(x.left) + _Count(x.right); 68 | 69 | return m; 70 | } 71 | 72 | private Node rotateRight(Node x) 73 | { 74 | var m = x.left; 75 | x.left = m.right; 76 | m.right = x; 77 | 78 | m.isRed = x.isRed; 79 | x.isRed = true; 80 | 81 | x.count = 1 + _Count(x.left) + _Count(x.right); 82 | 83 | return m; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cs-algorithms 2 | Package cs-algorithms provides C# implementation of algorithms for data structures and manipulation, as well as graph and string processing. The project is written with .NET Core and is cross-platform for development. 3 | 4 | [![Build Status](https://travis-ci.org/cschen1205/cs-algorithms.svg?branch=master)](https://travis-ci.org/cschen1205/cs-algorithms) 5 | 6 | # Install 7 | 8 | Run the following command using nuget: 9 | 10 | Install-Package cs-algorithms 11 | 12 | # Features 13 | 14 | * Data Structure 15 | 16 | - Stack 17 | 18 | + Linked List 19 | + Array 20 | 21 | - Queue 22 | 23 | + Linked List 24 | + Array 25 | 26 | - HashSet 27 | - HashMap 28 | 29 | + Separate Chaining 30 | + Linear Probing 31 | 32 | - Binary Search Tree 33 | - Red Black Tree 34 | - Priority Queue 35 | 36 | + MinPQ 37 | + MaxPQ 38 | + IndexMinPQ 39 | 40 | - Graph 41 | 42 | + Simple graph 43 | + Edge weighted graph 44 | + Directed graph (digraph) 45 | + Directed edge weight graph 46 | 47 | - Search Tries (Symbol table with string-based keys) 48 | 49 | + R-way search tries 50 | + Ternary search tries 51 | 52 | * Algorithms 53 | 54 | - Sorting 55 | 56 | + Selection Sort 57 | + Insertion Sort 58 | + Shell Sort 59 | + Merge Sort 60 | + Quick Sort 61 | + 3-Ways Quick Sort 62 | + Heap Sort 63 | 64 | - Selection 65 | 66 | + Binary Search 67 | 68 | - Shuffling 69 | 70 | + Knuth 71 | 72 | - Union Find 73 | 74 | + Quick Find 75 | + Weighted Quick Union with path compression 76 | 77 | * Graph Algorithms 78 | 79 | - Search 80 | 81 | + Depth First Search 82 | + Breadth First Search 83 | 84 | - Connectivity 85 | 86 | + Connected Components 87 | + Strongly Connected Components 88 | 89 | - Topological Sorting 90 | 91 | + Depth First Reverse Post Order 92 | 93 | - Directed Cycle Detection 94 | 95 | - Minimum Spanning Tree 96 | 97 | + Kruskal 98 | + Prim (Lazy) 99 | + Prim (Eager) 100 | 101 | - Shortest Path 102 | 103 | + Dijkstra 104 | + Topological Sort (for directed acyclic graph, namely dag) 105 | + Bellman-Ford (for graph with negative weight as well) 106 | 107 | - MaxFlow MinCut 108 | 109 | + Ford-Fulkerson 110 | 111 | * Strings 112 | 113 | - Longest Repeated Substring 114 | - String Sorting 115 | 116 | + LSD (Least Significant Digit first radix sorting) 117 | + MSD (Most Significant Digit first radix sorting) 118 | + 3-Ways String Quick Sort 119 | 120 | - String Search 121 | 122 | + Rabin Karp 123 | + Boyer Moore 124 | + Knuth Morris Pratt 125 | -------------------------------------------------------------------------------- /cs-algorithms/UnionFind/Percolation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Algorithms.UnionFind 4 | { 5 | public class Percolation 6 | { 7 | private readonly int mWidth; 8 | private readonly int mHeight; 9 | private readonly int[] top; 10 | private readonly int[] bottom; 11 | 12 | public Percolation(int width, int height) 13 | { 14 | mWidth = width; 15 | mHeight = height; 16 | 17 | top = new int[mWidth]; 18 | bottom = new int[mWidth]; 19 | 20 | for (var i = 0; i < mWidth; ++i) 21 | { 22 | top[i] = i; 23 | } 24 | 25 | for (var i = 0; i < mWidth; ++i) 26 | { 27 | bottom[i] = (mHeight - 1) * mWidth + i; 28 | } 29 | } 30 | 31 | public double RunMonteCarlo(Random rand, int iterations) 32 | { 33 | double percolationThreshold = 0; 34 | for (var i = 0; i < iterations; ++i) 35 | { 36 | percolationThreshold += ComputePercolationThreshold(rand); 37 | } 38 | return percolationThreshold / iterations; 39 | } 40 | 41 | public double ComputePercolationThreshold(Random rand) 42 | { 43 | var n = mWidth * mHeight; 44 | 45 | var uf = new WeightedQuickUnionWithPathCompression(n); 46 | 47 | var connected_top_site = -1; 48 | var connected_bottom_site = -1; 49 | while (!IsPercolated(uf, out connected_top_site, out connected_bottom_site)) 50 | { 51 | var i = rand.Next(n); 52 | var j = i; 53 | while (i == j || uf.IsConnected(i, j)) 54 | { 55 | j = rand.Next(n); 56 | } 57 | uf.Union(i, j); 58 | } 59 | 60 | var componentSize = uf.GetSize(connected_top_site); 61 | 62 | var percolationThreshold = (double)componentSize / n; 63 | 64 | return percolationThreshold; 65 | } 66 | 67 | 68 | private bool IsPercolated(IUnionFind uf, out int selected_top_cell, out int selected_bottom_cell) 69 | { 70 | selected_top_cell = -1; 71 | selected_bottom_cell = -1; 72 | 73 | foreach (var top_cell in top) 74 | { 75 | foreach (var bottom_cell in bottom) 76 | { 77 | if (!uf.IsConnected(top_cell, bottom_cell)) continue; 78 | selected_top_cell = top_cell; 79 | selected_bottom_cell = bottom_cell; 80 | return true; 81 | } 82 | } 83 | return false; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Queue/QueueArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Net.Http.Headers; 5 | 6 | namespace Algorithms.DataStructures.Queue 7 | { 8 | public class QueueArray : IQueue 9 | { 10 | private T[] s = new T[20]; 11 | private int head = 0; 12 | private int tail = 0; 13 | 14 | public T Dequeue() 15 | { 16 | if (IsEmpty) 17 | { 18 | return default(T); 19 | } 20 | var item = s[head++]; 21 | if (Count < s.Length / 4) Resize(s.Length / 4); 22 | return item; 23 | } 24 | 25 | private void Resize(int len) 26 | { 27 | var temp = new T[len]; 28 | for (var i = head; i < tail; ++i) 29 | { 30 | temp[i - head] = s[i]; 31 | } 32 | tail = tail - head; 33 | head = 0; 34 | s = temp; 35 | } 36 | 37 | public void Enqueue(T item) 38 | { 39 | s[tail++] = item; 40 | if(tail == s.Length) Resize(s.Length * 2); 41 | } 42 | 43 | public int Count => tail - head; 44 | public bool IsEmpty => tail - head == 0; 45 | 46 | public IEnumerator GetEnumerator() 47 | { 48 | return new QueueEnumerator(s, head, tail); 49 | } 50 | 51 | IEnumerator IEnumerable.GetEnumerator() 52 | { 53 | return GetEnumerator(); 54 | } 55 | 56 | private class QueueEnumerator : IEnumerator 57 | { 58 | private int current; 59 | private T[] s; 60 | private int head; 61 | private int tail; 62 | private T value; 63 | 64 | public QueueEnumerator(T[] s, int head, int tail) 65 | { 66 | current = head; 67 | this.head = head; 68 | this.tail = tail; 69 | this.s = s; 70 | } 71 | 72 | public bool MoveNext() 73 | { 74 | if (current == tail) return false; 75 | value = s[current]; 76 | current++; 77 | return true; 78 | } 79 | 80 | public void Reset() 81 | { 82 | current = head; 83 | } 84 | 85 | public T Current => value; 86 | 87 | object IEnumerator.Current 88 | { 89 | get { return Current; } 90 | } 91 | 92 | public void Dispose() 93 | { 94 | 95 | } 96 | } 97 | } 98 | 99 | 100 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Queue/QueueLinkedList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace Algorithms.DataStructures.Queue 6 | { 7 | internal class QueueNode 8 | { 9 | internal T item; 10 | internal QueueNode Next; 11 | } 12 | 13 | public class QueueLinkedList : IQueue 14 | { 15 | private QueueNode head; 16 | private QueueNode tail; 17 | private int N = 0; 18 | 19 | public T Dequeue() 20 | { 21 | QueueNode oldHead = head; 22 | if (oldHead == null) 23 | { 24 | return default(T); 25 | } 26 | head = oldHead.Next; 27 | N--; 28 | if (head == null) 29 | { 30 | tail = null; 31 | } 32 | return oldHead.item; 33 | } 34 | 35 | public void Enqueue(T item) 36 | { 37 | var oldTail = tail; 38 | tail = new QueueNode 39 | { 40 | item = item 41 | }; 42 | if (oldTail != null) 43 | { 44 | oldTail.Next = tail; 45 | } 46 | if (head == null) 47 | { 48 | head = tail; 49 | } 50 | N++; 51 | } 52 | 53 | public int Count => N; 54 | public bool IsEmpty => N == 0; 55 | public IEnumerator GetEnumerator() 56 | { 57 | return new QueueEnumerator(head); 58 | } 59 | 60 | IEnumerator IEnumerable.GetEnumerator() 61 | { 62 | return GetEnumerator(); 63 | } 64 | 65 | private class QueueEnumerator : IEnumerator 66 | { 67 | private QueueNode head; 68 | private QueueNode current; 69 | private T value; 70 | public QueueEnumerator(QueueNode head) 71 | { 72 | this.head = head; 73 | this.current = head; 74 | } 75 | public bool MoveNext() 76 | { 77 | if (current == null) return false; 78 | value = current.item; 79 | current = current.Next; 80 | return true; 81 | } 82 | 83 | public void Reset() 84 | { 85 | current = head; 86 | } 87 | 88 | public T Current => value; 89 | 90 | object IEnumerator.Current 91 | { 92 | get { return Current; } 93 | } 94 | 95 | public void Dispose() 96 | { 97 | 98 | } 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /cs-algorithms.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cs-algorithms", "cs-algorithms\cs-algorithms.csproj", "{238151A2-DCDA-4BEF-8052-73E7B2E95CE4}" 7 | EndProject 8 | Project("{2AD4B6A7-11A8-4CB6-B83D-91F491E938AE}") = "cs-algorithms-unit-tests", "cs-algorithms-unit-tests\cs-algorithms-unit-tests.csproj", "{B48EB8B6-1C8F-4822-A00F-591394C1E9C8}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Debug|x64.ActiveCfg = Debug|x64 26 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Debug|x64.Build.0 = Debug|x64 27 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Debug|x86.ActiveCfg = Debug|x86 28 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Debug|x86.Build.0 = Debug|x86 29 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Release|x64.ActiveCfg = Release|x64 32 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Release|x64.Build.0 = Release|x64 33 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Release|x86.ActiveCfg = Release|x86 34 | {238151A2-DCDA-4BEF-8052-73E7B2E95CE4}.Release|x86.Build.0 = Release|x86 35 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Debug|x64.ActiveCfg = Debug|x64 38 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Debug|x64.Build.0 = Debug|x64 39 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Debug|x86.ActiveCfg = Debug|x86 40 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Debug|x86.Build.0 = Debug|x86 41 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Release|x64.ActiveCfg = Release|x64 44 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Release|x64.Build.0 = Release|x64 45 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Release|x86.ActiveCfg = Release|x86 46 | {B48EB8B6-1C8F-4822-A00F-591394C1E9C8}.Release|x86.Build.0 = Release|x86 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/HashMap/HashMapWithSeparateChaining.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.DataStructures.HashMap 5 | { 6 | public class Node 7 | { 8 | internal K key; 9 | internal V value; 10 | internal Node next; 11 | } 12 | 13 | public class HashMapWithSeparateChaining : IHashMap 14 | { 15 | private const int M = 97; 16 | private Node[] s; 17 | private int N = 0; 18 | 19 | public HashMapWithSeparateChaining() 20 | { 21 | s = new Node[M]; 22 | 23 | } 24 | 25 | public V this[K key] 26 | { 27 | get 28 | { 29 | var hash = Hash(key); 30 | for (var x = s[hash]; x != null; x = x.next) 31 | { 32 | if (x.key .Equals( key)) 33 | { 34 | return x.value; 35 | } 36 | } 37 | return default(V); 38 | } 39 | set 40 | { 41 | var hash = Hash(key); 42 | for (var x = s[hash]; x != null; x = x.next) 43 | { 44 | if (!x.key.Equals(key)) continue; 45 | x.value = value; 46 | return; 47 | } 48 | 49 | var old = s[hash]; 50 | s[hash] = new Node 51 | { 52 | key = key, 53 | value = value, 54 | next = old 55 | }; 56 | N++; 57 | 58 | 59 | } 60 | } 61 | 62 | private int Hash(K key) 63 | { 64 | return (key.GetHashCode() & 0x7fffffff) % M; 65 | } 66 | 67 | public bool ContainsKey(K key) 68 | { 69 | var hash = Hash(key); 70 | return !this[key].Equals(default(V)); 71 | } 72 | 73 | public int Count => N; 74 | public bool IsEmpty => N == 0; 75 | public void Delete(K key) 76 | { 77 | var hash = Hash(key); 78 | Node prev = null; 79 | for (var x = s[hash]; x != null; x = x.next) 80 | { 81 | if (x.key.Equals(key)) 82 | { 83 | if (prev == null) 84 | { 85 | s[hash] = x.next; 86 | } 87 | else 88 | { 89 | prev.next = x.next; 90 | } 91 | 92 | N--; 93 | break; 94 | } 95 | prev = x; 96 | } 97 | } 98 | 99 | public IEnumerable Keys 100 | { 101 | get 102 | { 103 | var keys = new List(); 104 | for (var h = 0; h < M; ++h) 105 | { 106 | for (var x = s[h]; x != null; x = x.next) 107 | { 108 | keys.Add(x.key); 109 | } 110 | } 111 | return keys; 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/HashMap/HashMapWithLinearProbing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Algorithms.DataStructures.HashMap 5 | { 6 | public class HashMapWithLinearProbing : IHashMap 7 | { 8 | private int N; 9 | private Node[] s; 10 | 11 | public HashMapWithLinearProbing() 12 | { 13 | s = new Node[97]; 14 | } 15 | 16 | public HashMapWithLinearProbing(int len) 17 | { 18 | s = new Node[len]; 19 | } 20 | 21 | private int Hash(K key) 22 | { 23 | return (key.GetHashCode() & 0x7fffffff) % s.Length; 24 | } 25 | 26 | public V this[K key] 27 | { 28 | get 29 | { 30 | var hash = Hash(key); 31 | for (var x = s[hash]; x != null; x = s[(++hash) % s.Length]) 32 | { 33 | if (x.key.Equals(key)) 34 | { 35 | return x.value; 36 | } 37 | } 38 | return default(V); 39 | } 40 | set 41 | { 42 | var hash = Hash(key); 43 | for (var x = s[hash]; x != null; x = s[(++hash) % s.Length]) 44 | { 45 | if (x.key.Equals(key)) 46 | { 47 | x.value = value; 48 | return; 49 | } 50 | } 51 | s[hash % s.Length] = new Node 52 | { 53 | key = key, 54 | value = value 55 | }; 56 | N++; 57 | if (s[(hash + 1) % s.Length] != null) 58 | { 59 | Resize(s.Length * 2); 60 | } 61 | } 62 | } 63 | 64 | private void Resize(int len) 65 | { 66 | var temp = new HashMapWithLinearProbing(len); 67 | for (var h = 0; h < s.Length; ++h) 68 | { 69 | temp[s[h].key] = s[h].value; 70 | } 71 | s = temp.s; 72 | } 73 | 74 | public bool ContainsKey(K key) 75 | { 76 | return !this[key].Equals(default(V)); 77 | } 78 | 79 | public int Count => N; 80 | public bool IsEmpty => N == 0; 81 | public void Delete(K key) 82 | { 83 | var hash = Hash(key); 84 | for (var x = s[hash]; x != null; x = s[(++hash) % s.Length]) 85 | { 86 | if (x.key.Equals(key)) 87 | { 88 | s[hash % s.Length] = null; 89 | N--; 90 | if (N == s.Length / 4) 91 | { 92 | Resize(s.Length / 2); 93 | } 94 | break; 95 | } 96 | } 97 | } 98 | 99 | public IEnumerable Keys 100 | { 101 | get 102 | { 103 | var keys = new List(); 104 | for (var h = 0; h < s.Length; ++h) 105 | { 106 | if (s[h] == null) continue; 107 | keys.Add(s[h].key); 108 | } 109 | return keys; 110 | } 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/SearchTries/RWayTries.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using Algorithms.DataStructures.Queue; 7 | using Algorithms.Utils; 8 | 9 | namespace Algorithms.DataStructures.SearchTries 10 | { 11 | public class RWayTries : ISearchTries 12 | { 13 | private const int R = 256; 14 | private int N = 0; 15 | 16 | private class Node 17 | { 18 | internal T value; 19 | internal Node[] children = new Node[R]; 20 | } 21 | 22 | private Node root; 23 | 24 | public T this[string key] 25 | { 26 | get 27 | { 28 | var x = Get(root, key, 0); 29 | if (x != null) 30 | { 31 | return x.value; 32 | } 33 | return default(T); 34 | } 35 | set 36 | { 37 | root = Put(root, key, value, 0); 38 | 39 | } 40 | } 41 | 42 | private Node Put(Node x, string key, T value, int d) 43 | { 44 | if (x == null) 45 | { 46 | x = new Node(); 47 | } 48 | 49 | if (key.Length == d) 50 | { 51 | if (ObjectUtil.IsNullOrDefault(x.value)) 52 | { 53 | N++; 54 | } 55 | 56 | x.value = value; 57 | return x; 58 | } 59 | 60 | char v = key[d]; 61 | x.children[v] = Put(x.children[v], key, value, d + 1); 62 | return x; 63 | } 64 | 65 | public void Delete(String key) 66 | { 67 | Node x = Get(root, key, 0); 68 | if (x != null) 69 | { 70 | N--; 71 | x.value = default(T); 72 | } 73 | } 74 | 75 | public bool ContainsKey(String key) 76 | { 77 | Node x = Get(root, key, 0); 78 | if (x == null) return false; 79 | return !ObjectUtil.IsNullOrDefault(x.value); 80 | } 81 | 82 | public IEnumerable Keys { 83 | get 84 | { 85 | var queue = new QueueLinkedList(); 86 | 87 | Collect(root, "", queue); 88 | 89 | return queue; 90 | } 91 | } 92 | 93 | public IEnumerable KeysWithPrefix(string prefix) 94 | { 95 | 96 | Node x = Get(root, prefix, 0); 97 | QueueLinkedList queue = new QueueLinkedList(); 98 | if (x != null) 99 | { 100 | Collect(x, prefix, queue); 101 | } 102 | return queue; 103 | } 104 | 105 | private void Collect(Node x, String prefix, IQueue queue) 106 | { 107 | if (x == null) return; 108 | if (!ObjectUtil.IsNullOrDefault(x.value)) 109 | { 110 | queue.Enqueue(prefix); 111 | } 112 | for (int r = 0; r < R; ++r) 113 | { 114 | Collect(x.children[r], prefix + ((char)r), queue); 115 | } 116 | } 117 | 118 | private Node Get(Node x, string key, int d) 119 | { 120 | if (x == null) return null; 121 | if (key.Length == d) return x; 122 | char v = key[d]; 123 | return Get(x.children[v], key, d + 1); 124 | } 125 | 126 | public int Count => N; 127 | public bool IsEmpty => N == 0; 128 | 129 | 130 | } 131 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/SearchTries/TernarySearchTries.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Algorithms.DataStructures.Queue; 4 | using Algorithms.Utils; 5 | 6 | namespace Algorithms.DataStructures.SearchTries 7 | { 8 | public class TernarySearchTries : ISearchTries 9 | { 10 | private class Node 11 | { 12 | internal char key; 13 | internal T value; 14 | internal Node left; 15 | internal Node mid; 16 | internal Node right; 17 | } 18 | 19 | private Node root; 20 | private int N; 21 | 22 | public T this[string key] 23 | { 24 | get 25 | { 26 | Node x = Get(root, key, 0); 27 | if (x != null) 28 | { 29 | return x.value; 30 | } 31 | return default(T); 32 | } 33 | set { root = Put(root, key, value, 0); } 34 | } 35 | 36 | private Node Put(Node x, string key, T value, int d) 37 | { 38 | if (x == null) 39 | { 40 | x = new Node 41 | { 42 | key = key[d] 43 | }; 44 | } 45 | 46 | int cmp = key[d].CompareTo(x.key); 47 | if (cmp < 0) 48 | { 49 | x.left = Put(x.left, key, value, d); 50 | } else if (cmp > 0) 51 | { 52 | x.right = Put(x.right, key, value, d); 53 | } 54 | else 55 | { 56 | if (d >= key.Length-1) 57 | { 58 | if (ObjectUtil.IsNullOrDefault(x.value)) 59 | { 60 | N++; 61 | } 62 | x.value = value; 63 | } 64 | else 65 | { 66 | x.mid = Put(x.mid, key, value, d + 1); 67 | } 68 | } 69 | return x; 70 | } 71 | 72 | private Node Get(Node x, string key, int d) 73 | { 74 | if (x == null) 75 | { 76 | return null; 77 | } 78 | 79 | int cmp = key[d].CompareTo(x.key); 80 | 81 | if (cmp < 0) return Get(x.left, key, d); 82 | if (cmp > 0) return Get(x.right, key, d); 83 | if (key.Length - 1 == d) 84 | { 85 | return x; 86 | } 87 | return Get(x.mid, key, d + 1); 88 | } 89 | 90 | public int Count => N; 91 | public bool IsEmpty => N == 0; 92 | 93 | public void Delete(string key) 94 | { 95 | Node x = Get(root, key, 0); 96 | if (x != null) 97 | { 98 | if (!ObjectUtil.IsNullOrDefault(x.value)) 99 | { 100 | N--; 101 | } 102 | x.value = default(T); 103 | } 104 | } 105 | 106 | public bool ContainsKey(string key) 107 | { 108 | Node x = Get(root, key, 0); 109 | if(x !=null) 110 | { 111 | return !ObjectUtil.IsNullOrDefault(x.value); 112 | } 113 | return false; 114 | } 115 | 116 | public IEnumerable Keys 117 | { 118 | get 119 | { 120 | var queue = new QueueLinkedList(); 121 | 122 | Collect(root, "", queue); 123 | 124 | return queue; 125 | } 126 | } 127 | 128 | private void Collect(Node x, string prefix, IQueue queue) 129 | { 130 | if (x == null) 131 | { 132 | return; 133 | } 134 | if (!ObjectUtil.IsNullOrDefault(x.value)) 135 | { 136 | queue.Enqueue(prefix); 137 | } 138 | Collect(x.left, prefix, queue); 139 | Collect(x.mid, prefix + x.key, queue); 140 | Collect(x.right, prefix, queue); 141 | } 142 | 143 | public IEnumerable KeysWithPrefix(string prefix) 144 | { 145 | IQueue queue = new QueueLinkedList(); 146 | 147 | Node x = Get(root, prefix, 0); 148 | if (x != null) 149 | { 150 | Collect(x, prefix, queue); 151 | } 152 | return queue; 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/TreeMap/BinarySearchTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using Algorithms.DataStructures.Queue; 5 | 6 | namespace Algorithms.DataStructures.TreeMap 7 | { 8 | public class Node where K : IComparable 9 | { 10 | internal K key; 11 | internal V value; 12 | internal Node left; 13 | internal Node right; 14 | internal int count = 0; 15 | internal bool isRed = false; 16 | } 17 | 18 | public class BinarySearchTree : ITreeMap where K : IComparable 19 | { 20 | 21 | private Node root; 22 | 23 | public void Put(K key, V value) 24 | { 25 | root = Put(root, key, value); 26 | } 27 | 28 | protected virtual Node Put(Node x, K key, V value) 29 | { 30 | if (x == null) 31 | { 32 | return new Node 33 | { 34 | key = key, 35 | value = value, 36 | count = 1 37 | }; 38 | } 39 | 40 | var cmp = key.CompareTo(x.key); 41 | 42 | if (cmp < 0) 43 | { 44 | x.left = Put(x.left, key, value); 45 | } else if (cmp > 0) 46 | { 47 | x.right = Put(x.right, key, value); 48 | } 49 | else 50 | { 51 | x.value = value; 52 | } 53 | 54 | x.count = 1 + _Count(x.left) + _Count(x.right); 55 | 56 | return x; 57 | 58 | } 59 | 60 | public V Get(K key) 61 | { 62 | var x = Get(root, key); 63 | return x != null ? x.value : default(V); 64 | } 65 | 66 | private static Node Get(Node x, K key) 67 | { 68 | if (x == null) return null; 69 | var cmp = key.CompareTo(x.key); 70 | if (cmp < 0) return Get(x.left, key); 71 | if (cmp > 0) return Get(x.right, key); 72 | 73 | return x; 74 | } 75 | 76 | protected int _Count(Node x) 77 | { 78 | return x == null ? 0 : x.count; 79 | } 80 | 81 | 82 | public void Delete(K key) 83 | { 84 | root = Delete(root, key); 85 | } 86 | 87 | private Node Delete(Node x, K key) 88 | { 89 | if (x == null) return null; 90 | 91 | var cmp = key.CompareTo(x.key); 92 | if (cmp < 0) x.left = Delete(x.left, key); 93 | else if (cmp > 0) x.right = Delete(x.right, key); 94 | else 95 | { 96 | if (x.left == null) return x.right; 97 | if (x.right == null) return x.left; 98 | 99 | var m = Min(x.right); 100 | m.right = DelMin(x.right); 101 | m.left = x.left; 102 | 103 | x = m; 104 | } 105 | 106 | x.count = 1 + _Count(x.left) + _Count(x.right); 107 | 108 | return x; 109 | } 110 | 111 | private Node DelMin(Node x) 112 | { 113 | if (x.left == null) 114 | { 115 | return x; 116 | } 117 | x.left = DelMin(x.left); 118 | 119 | x.count = 1 + _Count(x.left) + _Count(x.right); 120 | return x; 121 | } 122 | 123 | private Node Min(Node x) 124 | { 125 | if (x.left == null) 126 | { 127 | return x; 128 | } 129 | return Min(x.left); 130 | } 131 | 132 | 133 | public V this[K key] 134 | { 135 | get => Get(key); 136 | set => Put(key, value); 137 | } 138 | 139 | public int Count => _Count(root); 140 | public bool IsEmpty => _Count(root) == 0; 141 | 142 | public bool ContainsKey(K key) 143 | { 144 | var x = Get(root, key); 145 | return x != null; 146 | 147 | } 148 | 149 | public K MinKey() 150 | { 151 | var x = Min(root); 152 | if (x == null) return default(K); 153 | return x.key; 154 | } 155 | 156 | public IEnumerable Keys 157 | { 158 | get 159 | { 160 | IQueue queue = new QueueLinkedList(); 161 | Collect(root, queue); 162 | return queue; 163 | } 164 | } 165 | 166 | private void Collect(Node x, IQueue queue) 167 | { 168 | if (x == null) return; 169 | Collect(x.left, queue); 170 | queue.Enqueue(x.key); 171 | Collect(x.right,queue); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Queue/MinPQ.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices.ComTypes; 5 | using Algorithms.Utils; 6 | 7 | namespace Algorithms.DataStructures.Queue 8 | { 9 | public class MinPQ : IQueue 10 | where T : IComparable 11 | { 12 | private T[] s = new T[20]; 13 | private int N = 0; 14 | 15 | public T Dequeue() 16 | { 17 | return DelMin(); 18 | } 19 | 20 | public T DelMin() 21 | { 22 | if (IsEmpty) 23 | { 24 | return default(T); 25 | } 26 | 27 | var item = s[1]; 28 | SortUtil.Exchange(s, 1, N--); 29 | Sink(1); 30 | if(N < s.Length / 4) Resize(s.Length / 2); 31 | return item; 32 | } 33 | 34 | private void Sink(int k) 35 | { 36 | while (2 * k < N) 37 | { 38 | int child = k * 2; 39 | if (child < N && SortUtil.IsLessThan(s[child + 1], s[child])) 40 | { 41 | child++; 42 | } 43 | if (SortUtil.IsLessThan(s[child], s[k])) 44 | { 45 | SortUtil.Exchange(s, child, k); 46 | k = child; 47 | } 48 | else 49 | { 50 | break; 51 | } 52 | } 53 | } 54 | 55 | 56 | public void Enqueue(T item) 57 | { 58 | if (N == s.Length - 1) Resize(s.Length * 2); 59 | s[++N] = item; 60 | Swim(N); 61 | } 62 | 63 | private void Resize(int len) 64 | { 65 | var temp = new T[len]; 66 | for (var i = 0; i < Math.Min(len, s.Length); ++i) 67 | { 68 | temp[i] = s[i]; 69 | } 70 | s = temp; 71 | } 72 | 73 | private void Swim(int k) 74 | { 75 | while (k > 1) 76 | { 77 | var parent = k / 2; 78 | if (SortUtil.IsLessThan(s[k], s[parent])) 79 | { 80 | SortUtil.Exchange(s, k, parent); 81 | k = parent; 82 | } 83 | else 84 | { 85 | break; 86 | } 87 | } 88 | } 89 | 90 | public int Count => N; 91 | public bool IsEmpty => N == 0; 92 | 93 | public IEnumerator GetEnumerator() 94 | { 95 | return new QueueEnumerator(s, N); 96 | } 97 | 98 | IEnumerator IEnumerable.GetEnumerator() 99 | { 100 | return GetEnumerator(); 101 | } 102 | 103 | private class QueueEnumerator : IEnumerator 104 | { 105 | private T[] values; 106 | private int current = 0; 107 | private T value; 108 | 109 | public QueueEnumerator(T[] s, int N) 110 | { 111 | s = (T[]) s.Clone(); 112 | this.values = new T[N]; 113 | int k = 0; 114 | while (N > 0) 115 | { 116 | values[k++] = s[1]; 117 | SortUtil.Exchange(s, 1, N--); 118 | Sink(s, 1, N); 119 | } 120 | } 121 | 122 | private void Sink(T[] s, int k, int N) 123 | { 124 | while (k * 2 <= N) 125 | { 126 | int child = k * 2; 127 | if (child < N && SortUtil.IsLessThan(s[child + 1], s[child])) 128 | { 129 | child++; 130 | } 131 | if (SortUtil.IsLessThan(s[child], s[k])) 132 | { 133 | SortUtil.Exchange(s, k, child); 134 | k = child; 135 | } 136 | else 137 | { 138 | break; 139 | } 140 | } 141 | } 142 | 143 | public bool MoveNext() 144 | { 145 | if (current == values.Length) 146 | { 147 | return false; 148 | } 149 | value = values[current]; 150 | 151 | current++; 152 | return true; 153 | } 154 | 155 | public void Reset() 156 | { 157 | current = 0; 158 | } 159 | 160 | public T Current => value; 161 | 162 | object IEnumerator.Current 163 | { 164 | get { return Current; } 165 | } 166 | 167 | public void Dispose() 168 | { 169 | 170 | } 171 | } 172 | } 173 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Queue/MaxPQ.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices.ComTypes; 5 | using Algorithms.Utils; 6 | 7 | namespace Algorithms.DataStructures.Queue 8 | { 9 | public class MaxPQ : IQueue 10 | where T : IComparable 11 | { 12 | private T[] s = new T[20]; 13 | private int N = 0; 14 | 15 | public T Dequeue() 16 | { 17 | return DelMax(); 18 | } 19 | 20 | public T DelMax() 21 | { 22 | if (IsEmpty) 23 | { 24 | return default(T); 25 | } 26 | 27 | var item = s[1]; 28 | SortUtil.Exchange(s, 1, N--); 29 | Sink(1); 30 | if(N < s.Length / 4) Resize(s.Length / 2); 31 | return item; 32 | } 33 | 34 | private void Sink(int k) 35 | { 36 | while (2 * k < N) 37 | { 38 | int child = k * 2; 39 | if (child < N && SortUtil.IsGreaterThan(s[child + 1], s[child])) 40 | { 41 | child++; 42 | } 43 | if (SortUtil.IsGreaterThan(s[child], s[k])) 44 | { 45 | SortUtil.Exchange(s, child, k); 46 | k = child; 47 | } 48 | else 49 | { 50 | break; 51 | } 52 | } 53 | } 54 | 55 | 56 | public void Enqueue(T item) 57 | { 58 | if (N == s.Length - 1) Resize(s.Length * 2); 59 | s[++N] = item; 60 | Swim(N); 61 | } 62 | 63 | private void Resize(int len) 64 | { 65 | var temp = new T[len]; 66 | for (var i = 0; i < Math.Min(len, s.Length); ++i) 67 | { 68 | temp[i] = s[i]; 69 | } 70 | s = temp; 71 | } 72 | 73 | private void Swim(int k) 74 | { 75 | while (k > 1) 76 | { 77 | var parent = k / 2; 78 | if (SortUtil.IsGreaterThan(s[k], s[parent])) 79 | { 80 | SortUtil.Exchange(s, k, parent); 81 | k = parent; 82 | } 83 | else 84 | { 85 | break; 86 | } 87 | } 88 | } 89 | 90 | public int Count => N; 91 | public bool IsEmpty => N == 0; 92 | public IEnumerator GetEnumerator() 93 | { 94 | return new QueueEnumerator(s, N); 95 | } 96 | 97 | IEnumerator IEnumerable.GetEnumerator() 98 | { 99 | return GetEnumerator(); 100 | } 101 | 102 | private class QueueEnumerator : IEnumerator 103 | { 104 | private T[] values; 105 | private int current = 0; 106 | private T value; 107 | 108 | public QueueEnumerator(T[] s, int N) 109 | { 110 | s = (T[]) s.Clone(); 111 | this.values = new T[N]; 112 | int k = 0; 113 | while (N > 0) 114 | { 115 | values[k++] = s[1]; 116 | SortUtil.Exchange(s, 1, N--); 117 | Sink(s, 1, N); 118 | } 119 | } 120 | 121 | private void Sink(T[] s, int k, int N) 122 | { 123 | while (k * 2 <= N) 124 | { 125 | int child = k * 2; 126 | if (child < N && SortUtil.IsGreaterThan(s[child + 1], s[child])) 127 | { 128 | child++; 129 | } 130 | if (SortUtil.IsGreaterThan(s[child], s[k])) 131 | { 132 | SortUtil.Exchange(s, k, child); 133 | k = child; 134 | } 135 | else 136 | { 137 | break; 138 | } 139 | } 140 | } 141 | 142 | public bool MoveNext() 143 | { 144 | if (current == values.Length) 145 | { 146 | return false; 147 | } 148 | value = values[current]; 149 | 150 | current++; 151 | return true; 152 | } 153 | 154 | public void Reset() 155 | { 156 | current = 0; 157 | } 158 | 159 | public T Current => value; 160 | 161 | object IEnumerator.Current 162 | { 163 | get { return Current; } 164 | } 165 | 166 | public void Dispose() 167 | { 168 | 169 | } 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /cs-algorithms-unit-tests/Graphs/GraphGenerator.cs: -------------------------------------------------------------------------------- 1 | using Algorithms.DataStructures.Graphs; 2 | using Algorithms.Graphs.MaxFlow; 3 | 4 | namespace AlgorithmsUnitTest.Graphs 5 | { 6 | public class GraphGenerator 7 | { 8 | public static Graph graph(){ 9 | var g = new Graph(6); 10 | g.addEdge(0, 5); 11 | g.addEdge(2, 4); 12 | g.addEdge(2, 3); 13 | g.addEdge(1, 2); 14 | g.addEdge(0, 1); 15 | g.addEdge(3, 4); 16 | g.addEdge(3, 5); 17 | g.addEdge(0, 2); 18 | 19 | return g; 20 | } 21 | 22 | //directed acyclic graph 23 | public static DiGraph dag(){ 24 | var dag = new DiGraph(7); 25 | 26 | dag.addEdge(0, 5); 27 | dag.addEdge(0, 2); 28 | dag.addEdge(0, 1); 29 | dag.addEdge(3, 6); 30 | dag.addEdge(3, 5); 31 | dag.addEdge(3, 4); 32 | dag.addEdge(5, 4); 33 | dag.addEdge(6, 4); 34 | dag.addEdge(6, 0); 35 | dag.addEdge(3, 2); 36 | dag.addEdge(1, 4); 37 | 38 | 39 | 40 | 41 | 42 | 43 | return dag; 44 | } 45 | 46 | public static Graph graph4ConnectedComponents() { 47 | var g = new Graph(13); 48 | g.addEdge(0, 5); 49 | g.addEdge(4, 3); 50 | g.addEdge(0, 1); 51 | g.addEdge(9, 12); 52 | g.addEdge(6, 4); 53 | g.addEdge(5, 4); 54 | g.addEdge(0, 2); 55 | g.addEdge(11, 12); 56 | g.addEdge(9,10); 57 | g.addEdge(0, 6); 58 | g.addEdge(7, 8); 59 | g.addEdge(9, 11); 60 | g.addEdge(5, 3); 61 | return g; 62 | } 63 | 64 | public static DiGraph dag4StronglyConnectedComponents(){ 65 | var graph = new DiGraph(13); 66 | graph.addEdge(4, 2); 67 | graph.addEdge(2, 3); 68 | graph.addEdge(3, 2); 69 | graph.addEdge(6, 0); 70 | graph.addEdge(0, 1); 71 | graph.addEdge(2, 0); 72 | graph.addEdge(11, 12); 73 | graph.addEdge(12, 9); 74 | graph.addEdge(9, 10); 75 | graph.addEdge(9, 11); 76 | graph.addEdge(8, 9); 77 | graph.addEdge(10, 12); 78 | graph.addEdge(11, 4); 79 | graph.addEdge(4, 3); 80 | graph.addEdge(3, 5); 81 | graph.addEdge(7, 8); 82 | graph.addEdge(8, 7); 83 | graph.addEdge(5, 4); 84 | graph.addEdge(0, 5); 85 | graph.addEdge(6, 4); 86 | graph.addEdge(6, 9); 87 | graph.addEdge(7, 6); 88 | 89 | return graph; 90 | } 91 | 92 | public static WeightedGraph edgeWeightedGraph(){ 93 | var g = new WeightedGraph(8); 94 | g.addEdge(new Edge(0, 7, 0.16)); 95 | g.addEdge(new Edge(2, 3, 0.17)); 96 | g.addEdge(new Edge(1, 7, 0.19)); 97 | g.addEdge(new Edge(0, 2, 0.26)); 98 | g.addEdge(new Edge(5, 7, 0.28)); 99 | g.addEdge(new Edge(1, 3, 0.29)); 100 | g.addEdge(new Edge(1, 5, 0.32)); 101 | g.addEdge(new Edge(2, 7, 0.34)); 102 | g.addEdge(new Edge(4, 5, 0.35)); 103 | g.addEdge(new Edge(1, 2, 0.36)); 104 | g.addEdge(new Edge(4, 7, 0.37)); 105 | g.addEdge(new Edge(0, 4, 0.38)); 106 | g.addEdge(new Edge(6, 2, 0.4)); 107 | g.addEdge(new Edge(3, 6, 0.52)); 108 | g.addEdge(new Edge(6, 0, 0.58)); 109 | g.addEdge(new Edge(6, 4, 0.93)); 110 | 111 | return g; 112 | } 113 | 114 | 115 | public static WeightedDiGraph directedEdgeWeightedGraph() 116 | { 117 | var g = new WeightedDiGraph(8); 118 | 119 | g.addEdge(new Edge(0, 1, 5.0)); 120 | g.addEdge(new Edge(0, 4, 9.0)); 121 | g.addEdge(new Edge(0, 7, 8.0)); 122 | g.addEdge(new Edge(1, 2, 12.0)); 123 | g.addEdge(new Edge(1, 3, 15.0)); 124 | g.addEdge(new Edge(1, 7, 4.0)); 125 | g.addEdge(new Edge(2, 3, 3.0)); 126 | g.addEdge(new Edge(2, 6, 11.0)); 127 | g.addEdge(new Edge(3, 6, 9.0)); 128 | g.addEdge(new Edge(4, 5, 5.0)); 129 | g.addEdge(new Edge(4, 6, 20.0)); 130 | g.addEdge(new Edge(4, 7, 5.0)); 131 | g.addEdge(new Edge(5, 2, 1.0)); 132 | g.addEdge(new Edge(5, 6, 13.0)); 133 | g.addEdge(new Edge(7, 5, 6.0)); 134 | g.addEdge(new Edge(7, 2, 7.0)); 135 | return g; 136 | 137 | } 138 | 139 | public static FlowNetwork flowNetwork() { 140 | FlowNetwork g = new FlowNetwork(8); 141 | g.addEdge(new FlowEdge(0, 1, 10)); 142 | g.addEdge(new FlowEdge(0, 2, 5)); 143 | g.addEdge(new FlowEdge(0, 3, 15)); 144 | g.addEdge(new FlowEdge(1, 4, 9)); 145 | g.addEdge(new FlowEdge(1, 5, 15)); 146 | g.addEdge(new FlowEdge(1, 2, 4)); 147 | g.addEdge(new FlowEdge(2, 5, 8)); 148 | g.addEdge(new FlowEdge(2, 3, 4)); 149 | g.addEdge(new FlowEdge(3, 6, 16)); 150 | g.addEdge(new FlowEdge(4, 5, 15)); 151 | g.addEdge(new FlowEdge(4, 7, 10)); 152 | g.addEdge(new FlowEdge(5, 7, 10)); 153 | g.addEdge(new FlowEdge(5, 6, 15)); 154 | g.addEdge(new FlowEdge(6, 2, 6)); 155 | g.addEdge(new FlowEdge(6, 7, 10)); 156 | 157 | return g; 158 | } 159 | } 160 | 161 | 162 | } -------------------------------------------------------------------------------- /cs-algorithms/DataStructures/Queue/IndexMinPQ.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using Algorithms.Sorting; 5 | using Algorithms.Utils; 6 | 7 | namespace Algorithms.DataStructures.Queue 8 | { 9 | public class IndexMinPQ : IEnumerable where T : IComparable 10 | { 11 | private T[] keys; 12 | private int[] pq; 13 | private int[] qp; 14 | private int N = 0; 15 | 16 | public IndexMinPQ(int N) 17 | { 18 | keys = new T[N+1]; 19 | pq = new int[N + 1]; 20 | qp = new int[N + 1]; 21 | for (var i = 0; i <= N; ++i) 22 | { 23 | qp[i] = -1; 24 | } 25 | } 26 | 27 | public IndexMinPQ(T[] keys, int[] pq, int[] qp, int N) 28 | { 29 | this.keys = (T[]) keys.Clone(); 30 | this.pq = (int[]) pq.Clone(); 31 | this.qp = (int[]) qp.Clone(); 32 | this.N = N; 33 | } 34 | 35 | public IEnumerator GetEnumerator() 36 | { 37 | return new IndexMinPQEnumerator(keys, pq, qp, N); 38 | } 39 | 40 | IEnumerator IEnumerable.GetEnumerator() 41 | { 42 | return GetEnumerator(); 43 | } 44 | 45 | public T MinKey() 46 | { 47 | return keys[pq[1]]; 48 | } 49 | 50 | public int DelMin() 51 | { 52 | var item = pq[1]; 53 | SortUtil.Exchange(pq, 1, N); 54 | qp[pq[1]] = 1; 55 | qp[pq[N]] = N; 56 | N--; 57 | Sink(1); 58 | return item; 59 | } 60 | 61 | public void Enqueue(int index, T item) 62 | { 63 | var p = qp[index]; 64 | if (p == -1) 65 | { 66 | Insert(index, item); 67 | } 68 | else 69 | { 70 | if (SortUtil.IsLessThan(keys[index], item)) 71 | { 72 | keys[index] = item; 73 | Sink(p); 74 | } 75 | else 76 | { 77 | keys[index] = item; 78 | Swim(p); 79 | } 80 | } 81 | } 82 | 83 | public void DecreaseKey(int index, T item) 84 | { 85 | int p = qp[index]; 86 | if (SortUtil.IsGreaterThan(keys[index], item)) 87 | { 88 | keys[index] = item; 89 | Swim(p); 90 | } 91 | } 92 | 93 | public bool Contains(int index) 94 | { 95 | return qp[index] != -1; 96 | } 97 | 98 | private void Sink(int k) 99 | { 100 | while (k * 2 <= N) 101 | { 102 | int child = 2 * k; 103 | if (child < N && SortUtil.IsLessThan(keys[pq[child + 1]], keys[pq[child]])) 104 | { 105 | child++; 106 | } 107 | if (SortUtil.IsLessThan(keys[pq[child]], keys[pq[k]])) 108 | { 109 | SortUtil.Exchange(pq, child, k); 110 | qp[pq[child]] = child; 111 | qp[pq[k]] = k; 112 | k = child; 113 | } 114 | else 115 | { 116 | break; 117 | } 118 | } 119 | } 120 | 121 | public void Insert(int index, T item) 122 | { 123 | keys[index] = item; 124 | pq[++N] = index; 125 | qp[index] = pq[N]; 126 | Swim(N); 127 | } 128 | 129 | private void Swim(int k) 130 | { 131 | while (k > 1) 132 | { 133 | var parent = k / 2; 134 | if (SortUtil.IsLessThan(keys[pq[k]], keys[pq[parent]])) 135 | { 136 | SortUtil.Exchange(pq, k, parent); 137 | 138 | qp[pq[k]] = k; 139 | qp[pq[parent]] = parent; 140 | 141 | k = parent; 142 | } 143 | else 144 | { 145 | break; 146 | } 147 | } 148 | } 149 | 150 | public int Count => N; 151 | public bool IsEmpty => N == 0; 152 | 153 | private class IndexMinPQEnumerator : IEnumerator 154 | { 155 | private T[] keys; 156 | private int[] pq; 157 | private int[] qp; 158 | private int N; 159 | private T value; 160 | 161 | private IndexMinPQ current; 162 | 163 | 164 | public IndexMinPQEnumerator(T[] keys, int[] pq, int[] qp, int N) 165 | { 166 | this.keys = keys; 167 | this.pq = pq; 168 | this.qp = qp; 169 | this.N = N; 170 | current = new IndexMinPQ(keys,pq, qp, N); 171 | } 172 | 173 | public bool MoveNext() 174 | { 175 | if (current.IsEmpty) return false; 176 | value = current.MinKey(); 177 | current.DelMin(); 178 | return true; 179 | } 180 | 181 | public void Reset() 182 | { 183 | current = new IndexMinPQ(keys, pq, qp, N); 184 | } 185 | 186 | public T Current => value; 187 | 188 | object IEnumerator.Current 189 | { 190 | get { return Current; } 191 | } 192 | 193 | public void Dispose() 194 | { 195 | 196 | } 197 | } 198 | } 199 | } --------------------------------------------------------------------------------