├── assets
├── TUM.png
├── bst.gif
├── dll.png
├── heap.gif
├── list.gif
├── sll.png
├── sqrt.png
├── ufds.gif
├── graphds.gif
├── graphs.gif
├── primes.png
├── sorting.gif
├── VisuAlgo.png
├── trees
│ ├── bst.png
│ ├── cbt.png
│ ├── fbt.png
│ ├── nbst.png
│ ├── ncbt.png
│ ├── nfbt.png
│ ├── avl
│ │ ├── bf.jpeg
│ │ ├── left.jpeg
│ │ ├── right.jpeg
│ │ ├── left-right.jpeg
│ │ └── right-left.jpeg
│ ├── bst-dark.png
│ ├── btorder.png
│ ├── cbt-dark.png
│ ├── fbt-dark.png
│ ├── nbst-dark.png
│ ├── ncbt-dark.png
│ ├── nfbt-dark.png
│ ├── btorder-dark.png
│ ├── red-black
│ │ ├── rb-case1.png
│ │ ├── rb-case1-dark.png
│ │ ├── rb-case2-after.png
│ │ ├── rb-case3-after.png
│ │ ├── rb-case4-after.png
│ │ ├── rb-case2-before.png
│ │ ├── rb-case3-before.png
│ │ ├── rb-case3-rotate.png
│ │ ├── rb-case4-before.png
│ │ ├── rb-case2-after-dark.png
│ │ ├── rb-case3-after-dark.png
│ │ ├── rb-case4-after-dark.png
│ │ ├── rb-case2-before-dark.png
│ │ ├── rb-case3-before-dark.png
│ │ ├── rb-case3-rotate-dark.png
│ │ └── rb-case4-before-dark.png
│ └── rotations
│ │ ├── left-left.png
│ │ ├── left-right.png
│ │ ├── right-left.png
│ │ ├── right-right.png
│ │ ├── left-left-dark.png
│ │ ├── left-right-dark.png
│ │ ├── right-left-dark.png
│ │ └── right-right-dark.png
├── heap_arr_dark.png
├── heap_arr_light.png
├── heap_tree_dark.png
├── heap_tree_light.png
├── logo
│ ├── rust-logo.png
│ └── csharp-logo.png
├── primes_compare.png
└── logo-algos.svg
├── rust
├── .vscode
│ └── settings.json
├── src
│ ├── main.rs
│ ├── primes
│ │ ├── mod.rs
│ │ ├── trial_division.rs
│ │ ├── sieve_of_eratosthenes.rs
│ │ └── dijkstra_primes.rs
│ ├── sorting
│ │ ├── mod.rs
│ │ ├── bubble_sort.rs
│ │ ├── heap_sort.rs
│ │ ├── selection_sort.rs
│ │ ├── quicksort.rs
│ │ ├── shell_sort.rs
│ │ ├── insertion_sort.rs
│ │ └── merge_sort.rs
│ ├── graphs
│ │ ├── mod.rs
│ │ ├── tarjan_state.rs
│ │ ├── kruskal.rs
│ │ ├── tarjan.rs
│ │ ├── dfs.rs
│ │ ├── bfs.rs
│ │ ├── prim.rs
│ │ ├── floyd_warshall.rs
│ │ ├── dijkstra.rs
│ │ ├── bellman_ford.rs
│ │ ├── kosaraju.rs
│ │ └── graph.rs
│ └── data_structures
│ │ ├── mod.rs
│ │ ├── disjoint_set.rs
│ │ ├── linked_list.rs
│ │ ├── heap.rs
│ │ ├── red_black_tree.rs
│ │ ├── binary_search_tree.rs
│ │ └── avl_tree.rs
├── Cargo.lock
├── target
│ ├── CACHEDIR.TAG
│ └── .rustc_info.json
└── Cargo.toml
├── csharp
├── RadixSort
│ ├── Program.cs
│ └── RadixSort.csproj
├── Graphs
│ ├── Graphs.csproj
│ └── Graph.cs
├── AVLTree
│ ├── AVLTree.csproj
│ └── AVLTree.cs
├── BinaryHeap
│ ├── BinaryHeap.csproj
│ └── Heap.cs
├── LinkedList
│ ├── LinkedList.csproj
│ └── SinglyLinkedList.cs
├── UnionFind
│ ├── UnionFind.csproj
│ └── UnionFindSet.cs
├── BinarySearchTree
│ ├── BinarySearchTree.csproj
│ └── BinarySearchTree.cs
├── RedBlackTree
│ ├── RedBlackTree.csproj
│ └── RedBlackTree.cs
├── TrialDivision
│ ├── TrialDivision.csproj
│ └── Program.cs
├── DijkstraPrimes
│ ├── DijkstraPrimes.csproj
│ └── Program.cs
├── SieveOfEratosthenes
│ ├── SieveOfEratosthenes.csproj
│ └── Program.cs
├── MergeSort
│ ├── MergeSort.csproj
│ └── Program.cs
├── QuickSort
│ ├── QuickSort.csproj
│ └── Program.cs
├── ShellSort
│ ├── ShellSort.csproj
│ └── Program.cs
├── BubbleSort
│ ├── BubbleSort.csproj
│ └── Program.cs
├── InsertionSort
│ ├── InsertionSort.csproj
│ └── Program.cs
├── SelectionSort
│ ├── SelectionSort.csproj
│ └── Program.cs
├── Prim
│ ├── Prim.csproj
│ └── GraphExtensions.cs
├── Dijkstra
│ ├── Dijkstra.csproj
│ └── GraphExtensions.cs
├── Kosaraju
│ ├── Kosaraju.csproj
│ └── GraphExtensions.cs
├── DepthFirstSearch
│ ├── DepthFirstSearch.csproj
│ └── GraphExtensions.cs
├── BreadthFirstSearch
│ ├── BreadthFirstSearch.csproj
│ └── GraphExtensions.cs
├── BellmanFord
│ ├── BellmanFord.csproj
│ └── GraphExtensions.cs
├── Kruskal
│ ├── Kruskal.csproj
│ └── GraphExtensions.cs
├── HeapSort
│ ├── HeapSort.csproj
│ └── Program.cs
└── Floyd–Warshall
│ ├── Floyd–Warshall.csproj
│ └── GraphExtensions.cs
└── .gitignore
/assets/TUM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/TUM.png
--------------------------------------------------------------------------------
/assets/bst.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/bst.gif
--------------------------------------------------------------------------------
/assets/dll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/dll.png
--------------------------------------------------------------------------------
/assets/heap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/heap.gif
--------------------------------------------------------------------------------
/assets/list.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/list.gif
--------------------------------------------------------------------------------
/assets/sll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/sll.png
--------------------------------------------------------------------------------
/assets/sqrt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/sqrt.png
--------------------------------------------------------------------------------
/assets/ufds.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/ufds.gif
--------------------------------------------------------------------------------
/rust/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "rust-analyzer.showUnlinkedFileNotification": false
3 | }
--------------------------------------------------------------------------------
/assets/graphds.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/graphds.gif
--------------------------------------------------------------------------------
/assets/graphs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/graphs.gif
--------------------------------------------------------------------------------
/assets/primes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/primes.png
--------------------------------------------------------------------------------
/assets/sorting.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/sorting.gif
--------------------------------------------------------------------------------
/assets/VisuAlgo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/VisuAlgo.png
--------------------------------------------------------------------------------
/assets/trees/bst.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/bst.png
--------------------------------------------------------------------------------
/assets/trees/cbt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/cbt.png
--------------------------------------------------------------------------------
/assets/trees/fbt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/fbt.png
--------------------------------------------------------------------------------
/assets/trees/nbst.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/nbst.png
--------------------------------------------------------------------------------
/assets/trees/ncbt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/ncbt.png
--------------------------------------------------------------------------------
/assets/trees/nfbt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/nfbt.png
--------------------------------------------------------------------------------
/assets/heap_arr_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/heap_arr_dark.png
--------------------------------------------------------------------------------
/assets/heap_arr_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/heap_arr_light.png
--------------------------------------------------------------------------------
/assets/heap_tree_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/heap_tree_dark.png
--------------------------------------------------------------------------------
/assets/heap_tree_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/heap_tree_light.png
--------------------------------------------------------------------------------
/assets/logo/rust-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/logo/rust-logo.png
--------------------------------------------------------------------------------
/assets/primes_compare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/primes_compare.png
--------------------------------------------------------------------------------
/assets/trees/avl/bf.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/avl/bf.jpeg
--------------------------------------------------------------------------------
/assets/trees/avl/left.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/avl/left.jpeg
--------------------------------------------------------------------------------
/assets/trees/bst-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/bst-dark.png
--------------------------------------------------------------------------------
/assets/trees/btorder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/btorder.png
--------------------------------------------------------------------------------
/assets/trees/cbt-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/cbt-dark.png
--------------------------------------------------------------------------------
/assets/trees/fbt-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/fbt-dark.png
--------------------------------------------------------------------------------
/assets/trees/nbst-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/nbst-dark.png
--------------------------------------------------------------------------------
/assets/trees/ncbt-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/ncbt-dark.png
--------------------------------------------------------------------------------
/assets/trees/nfbt-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/nfbt-dark.png
--------------------------------------------------------------------------------
/assets/logo/csharp-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/logo/csharp-logo.png
--------------------------------------------------------------------------------
/assets/trees/avl/right.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/avl/right.jpeg
--------------------------------------------------------------------------------
/rust/src/main.rs:
--------------------------------------------------------------------------------
1 | mod data_structures;
2 | mod graphs;
3 | mod primes;
4 | mod sorting;
5 |
6 | fn main() {
7 | }
8 |
--------------------------------------------------------------------------------
/assets/trees/btorder-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/btorder-dark.png
--------------------------------------------------------------------------------
/assets/trees/avl/left-right.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/avl/left-right.jpeg
--------------------------------------------------------------------------------
/assets/trees/avl/right-left.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/avl/right-left.jpeg
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case1.png
--------------------------------------------------------------------------------
/assets/trees/rotations/left-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/left-left.png
--------------------------------------------------------------------------------
/rust/src/primes/mod.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | mod dijkstra_primes;
3 | mod trial_division;
4 | mod sieve_of_eratosthenes;
5 |
--------------------------------------------------------------------------------
/assets/trees/rotations/left-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/left-right.png
--------------------------------------------------------------------------------
/assets/trees/rotations/right-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/right-left.png
--------------------------------------------------------------------------------
/assets/trees/rotations/right-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/right-right.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case1-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case1-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case2-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case2-after.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case3-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case3-after.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case4-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case4-after.png
--------------------------------------------------------------------------------
/assets/trees/rotations/left-left-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/left-left-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case2-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case2-before.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case3-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case3-before.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case3-rotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case3-rotate.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case4-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case4-before.png
--------------------------------------------------------------------------------
/assets/trees/rotations/left-right-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/left-right-dark.png
--------------------------------------------------------------------------------
/assets/trees/rotations/right-left-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/right-left-dark.png
--------------------------------------------------------------------------------
/assets/trees/rotations/right-right-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/rotations/right-right-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case2-after-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case2-after-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case3-after-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case3-after-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case4-after-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case4-after-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case2-before-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case2-before-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case3-before-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case3-before-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case3-rotate-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case3-rotate-dark.png
--------------------------------------------------------------------------------
/assets/trees/red-black/rb-case4-before-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnastasKosstow/algorithms/HEAD/assets/trees/red-black/rb-case4-before-dark.png
--------------------------------------------------------------------------------
/rust/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "rust"
7 | version = "0.1.0"
8 |
--------------------------------------------------------------------------------
/rust/src/sorting/mod.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | mod bubble_sort;
3 | mod selection_sort;
4 | mod insertion_sort;
5 | mod shell_sort;
6 | mod heap_sort;
7 | mod merge_sort;
8 | mod quicksort;
--------------------------------------------------------------------------------
/rust/target/CACHEDIR.TAG:
--------------------------------------------------------------------------------
1 | Signature: 8a477f597d28d172789f06886806bc55
2 | # This file is a cache directory tag created by cargo.
3 | # For information about cache directory tags see https://bford.info/cachedir/
4 |
--------------------------------------------------------------------------------
/csharp/RadixSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 7253, 3864, 573, 8511, 9619, 2608, 5455, 571, 1, 0 };
2 | arr = Sort(arr);
3 |
4 | int[] Sort(int[] sourceArray)
5 | {
6 | throw new NotImplementedException();
7 | }
8 |
--------------------------------------------------------------------------------
/rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rust"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 |
--------------------------------------------------------------------------------
/csharp/Graphs/Graphs.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/AVLTree/AVLTree.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/BinaryHeap/BinaryHeap.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/LinkedList/LinkedList.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/UnionFind/UnionFind.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/BinarySearchTree/BinarySearchTree.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/RedBlackTree/RedBlackTree.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/csharp/TrialDivision/TrialDivision.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/csharp/DijkstraPrimes/DijkstraPrimes.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/csharp/SieveOfEratosthenes/SieveOfEratosthenes.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/rust/src/graphs/mod.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | mod bfs;
3 | mod dfs;
4 | mod dijkstra;
5 | mod bellman_ford;
6 | mod floyd_warshall;
7 | mod kosaraju;
8 | mod kruskal;
9 | mod prim;
10 | mod tarjan_state;
11 | mod tarjan;
12 | mod graph;
13 |
14 | pub use graph::{Graph, GraphType, Node, NodeIndex, Edge};
--------------------------------------------------------------------------------
/csharp/MergeSort/MergeSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/QuickSort/QuickSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/RadixSort/RadixSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/ShellSort/ShellSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/BubbleSort/BubbleSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/InsertionSort/InsertionSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/SelectionSort/SelectionSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/csharp/Prim/Prim.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/csharp/Dijkstra/Dijkstra.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/csharp/Kosaraju/Kosaraju.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/csharp/DepthFirstSearch/DepthFirstSearch.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/csharp/BreadthFirstSearch/BreadthFirstSearch.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/csharp/BellmanFord/BellmanFord.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/csharp/Kruskal/Kruskal.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/csharp/HeapSort/HeapSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/csharp/Floyd–Warshall/Floyd–Warshall.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Floyd_Warshall
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/rust/src/data_structures/mod.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | mod avl_tree;
3 | mod red_black_tree;
4 | mod binary_search_tree;
5 | mod disjoint_set;
6 | mod linked_list;
7 | mod heap;
8 |
9 | pub use avl_tree::AvlTree;
10 | pub use avl_tree::TreeNode;
11 | pub use red_black_tree::RedBlackTree;
12 | pub use binary_search_tree::BinarySearchTree;
13 | pub use disjoint_set::DisjointSet;
14 | pub use linked_list::LinkedList;
15 | pub use heap::Heap;
16 | pub use heap::HeapType;
--------------------------------------------------------------------------------
/csharp/TrialDivision/Program.cs:
--------------------------------------------------------------------------------
1 | const int PRIMES_UP_TO = 100;
2 |
3 | var primes = new List();
4 |
5 | for (int number = 2; number <= PRIMES_UP_TO; number++)
6 | {
7 | bool isPrime = true;
8 | for (int primeIndex = 0; primeIndex < Math.Sqrt(primes.Count); primeIndex++)
9 | {
10 | if (primes.Any() && number % primes[primeIndex] == 0)
11 | {
12 | isPrime = false;
13 | break;
14 | }
15 | }
16 |
17 | if (isPrime)
18 | primes.Add(number);
19 | }
20 |
--------------------------------------------------------------------------------
/csharp/SieveOfEratosthenes/Program.cs:
--------------------------------------------------------------------------------
1 | const int PRIMES_UP_TO = 100;
2 |
3 | var sieve = Enumerable.Repeat(true, PRIMES_UP_TO).ToArray();
4 | sieve[0] = false;
5 | sieve[1] = false;
6 |
7 | for (int number = 0; number < Math.Sqrt(PRIMES_UP_TO); number++)
8 | {
9 | if (sieve[number] == true)
10 | {
11 | var multiple = number * number;
12 | while (multiple < PRIMES_UP_TO)
13 | {
14 | sieve[multiple] = false;
15 | multiple += number;
16 | }
17 | }
18 | }
19 |
20 | var primes = new List();
21 | for (int index = 0; index < sieve.Length; index++)
22 | {
23 | if (sieve[index])
24 | primes.Add(index);
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/rust/src/graphs/tarjan_state.rs:
--------------------------------------------------------------------------------
1 | use std::collections::{HashMap, HashSet};
2 |
3 | use super::NodeIndex;
4 |
5 | pub struct State {
6 | pub nodes_discovery_time: HashMap,
7 | pub nodes_low_link_value: HashMap,
8 | pub parent_node: HashMap,
9 | pub visited: HashSet,
10 | pub discovery_time: i32,
11 | }
12 |
13 | impl State {
14 | pub fn new() -> Self {
15 | State {
16 | nodes_discovery_time: HashMap::new(),
17 | nodes_low_link_value: HashMap::new(),
18 | parent_node: HashMap::new(),
19 | visited: HashSet::new(),
20 | discovery_time: 0
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/rust/src/sorting/bubble_sort.rs:
--------------------------------------------------------------------------------
1 | pub fn bubble_sort(arr: &mut [T]) {
2 | if arr.is_empty() {
3 | return;
4 | }
5 | for index in (0..arr.len()).rev() {
6 | for sort_index in 0..index {
7 | if arr[sort_index] > arr[sort_index + 1] {
8 | arr.swap(sort_index, sort_index + 1)
9 | }
10 | }
11 | }
12 | }
13 |
14 | #[cfg(test)]
15 | mod tests {
16 | use super::*;
17 |
18 | #[test]
19 | fn empty() {
20 | let mut empty_vec: Vec = Vec::new();
21 | bubble_sort(&mut empty_vec);
22 |
23 | assert!(empty_vec.is_empty());
24 | }
25 |
26 | #[test]
27 | fn sort() {
28 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
29 | bubble_sort(&mut arr);
30 |
31 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/rust/target/.rustc_info.json:
--------------------------------------------------------------------------------
1 | {"rustc_fingerprint":3823893406534814463,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.75.0 (82e1608df 2023-12-21)\nbinary: rustc\ncommit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112\ncommit-date: 2023-12-21\nhost: x86_64-pc-windows-msvc\nrelease: 1.75.0\nLLVM version: 17.0.6\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\kosstow\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\npacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n","stderr":""}},"successes":{}}
--------------------------------------------------------------------------------
/rust/src/sorting/heap_sort.rs:
--------------------------------------------------------------------------------
1 | use crate::data_structures::{Heap, HeapType};
2 |
3 | pub fn heap_sort(arr: &mut [T]) {
4 | if arr.is_empty() {
5 | return;
6 | }
7 |
8 | let mut heap: Heap = Heap::::new(HeapType::Min);
9 | let length = arr.len();
10 |
11 | for item in arr.iter() {
12 | heap.push(*item);
13 | }
14 |
15 | for index in 0..length {
16 | if let Some(item) = heap.pop() {
17 | arr[index] = item;
18 | }
19 | }
20 | }
21 |
22 | #[cfg(test)]
23 | mod tests {
24 | use super::*;
25 |
26 | #[test]
27 | fn empty() {
28 | let mut empty_vec: Vec = Vec::new();
29 | heap_sort(&mut empty_vec);
30 |
31 | assert!(empty_vec.is_empty());
32 | }
33 |
34 | #[test]
35 | fn sort() {
36 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
37 | heap_sort(&mut arr);
38 |
39 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/csharp/InsertionSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6 };
2 |
3 | // Start the loop from the second element, since the first element is considered sorted in Insertion sort
4 | for (int index = 1; index < arr.Length; index++)
5 | {
6 | // The current item to be placed in the correct position
7 | int currentItem = arr[index];
8 |
9 | // Find the position where the current item should be inserted
10 | // Start from the element before the current item and move backwards
11 | int insertionIndex = index - 1;
12 |
13 | // Move elements that are greater than the current item to one position ahead of their current position,
14 | // to make space for inserting the current item.
15 | while (insertionIndex >= 0 && arr[insertionIndex] > currentItem)
16 | {
17 | arr[insertionIndex + 1] = arr[insertionIndex];
18 | insertionIndex--;
19 | }
20 |
21 | // Insert the current item in its correct position.
22 | arr[insertionIndex + 1] = currentItem;
23 | }
24 |
--------------------------------------------------------------------------------
/csharp/SelectionSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6 };
2 |
3 | // Iterate over the array. Each iteration finds the minimum element in the unsorted part
4 | for (int index = 0; index < arr.Length - 1; index++)
5 | {
6 | // Assume the first element in the unsorted part is the minimum
7 | var currentMinValue = arr[index];
8 | var currentMinIndex = index;
9 |
10 | // Iterate over the unsorted part of the array
11 | for (int compareIndex = index + 1; compareIndex < arr.Length; compareIndex++)
12 | {
13 | // If a smaller element is found, update currentMinValue and currentMinIndex
14 | if (currentMinValue > arr[compareIndex])
15 | {
16 | currentMinValue = arr[compareIndex];
17 | currentMinIndex = compareIndex;
18 | }
19 | }
20 | // Swap the found minimum element with the first element in the unsorted part
21 | Swap(ref arr[index], ref arr[currentMinIndex]);
22 | }
23 |
24 | void Swap(ref int x1, ref int x2) => (x2, x1) = (x1, x2);
25 |
--------------------------------------------------------------------------------
/rust/src/sorting/selection_sort.rs:
--------------------------------------------------------------------------------
1 | pub fn selection_sort(arr: &mut [T]) {
2 | if arr.is_empty() {
3 | return;
4 | }
5 | let mut index: usize = 0;
6 | while index < arr.len() {
7 | let mut min_index: usize = index;
8 |
9 | for compare_index in index+1..arr.len() {
10 | if arr[min_index] > arr[compare_index] {
11 | min_index = compare_index;
12 | }
13 | }
14 |
15 | arr.swap(index, min_index);
16 | index += 1;
17 | }
18 | }
19 |
20 | #[cfg(test)]
21 | mod tests {
22 | use super::*;
23 |
24 | #[test]
25 | fn empty() {
26 | let mut empty_vec: Vec = Vec::new();
27 | selection_sort(&mut empty_vec);
28 |
29 | assert!(empty_vec.is_empty());
30 | }
31 |
32 | #[test]
33 | fn sort() {
34 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
35 | selection_sort(&mut arr);
36 |
37 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/rust/src/primes/trial_division.rs:
--------------------------------------------------------------------------------
1 | pub fn trieal_division(up_to: usize) -> Vec {
2 | if up_to < 2 {
3 | return vec![];
4 | }
5 |
6 | let mut primes: Vec = Vec::new();
7 |
8 | for number in 2..up_to {
9 | let mut is_prime = true;
10 | let sqrt_number = (number as f64).sqrt() as usize;
11 | for prime_index in 0..sqrt_number {
12 | if primes.len() > 0 && number % primes[prime_index] == 0 {
13 | is_prime = false;
14 | break;
15 | }
16 | }
17 |
18 | if is_prime {
19 | primes.push(number);
20 | }
21 | }
22 | primes
23 | }
24 |
25 |
26 | #[cfg(test)]
27 | mod tests {
28 | use super::*;
29 |
30 | #[test]
31 | fn test_trieal_division() {
32 | let primes: Vec = trieal_division(1000000);
33 | assert!(!primes.is_empty());
34 | assert_eq!(primes.len(), 78498);
35 | assert_eq!(primes.first().unwrap(), &2);
36 | assert_eq!(primes.last().unwrap(), &999983);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/csharp/HeapSort/Program.cs:
--------------------------------------------------------------------------------
1 | using BinaryHeap;
2 |
3 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6 };
4 |
5 | // Create a min heap. A min heap is used here because we want to sort the array in ascending order.
6 | // In a min heap, the smallest element is always at the root. Therefore, by continuously removing the root, we can obtain the elements in ascending order.
7 | // We can use already implemented heap structure from: DataStructures -> BinaryHeap
8 | var heap = new Heap(HeapType.Min);
9 |
10 | // Build the heap.
11 | // Insert all elements of the array into the heap.
12 | // The heap will rearrange these elements to maintain the min heap property, where the parent is smaller than its children.
13 | foreach (int item in arr)
14 | {
15 | heap.Push(item);
16 | }
17 |
18 | // Extract elements from the heap one by one and store them back into the array.
19 | // Since this is a min heap, each time we call Pop(), we get the smallest remaining element.
20 | // By doing this for each element, we are effectively sort the array.
21 | for (int index = 0; index < arr.Length; index++)
22 | {
23 | arr[index] = heap.Pop();
24 | }
25 |
--------------------------------------------------------------------------------
/rust/src/data_structures/disjoint_set.rs:
--------------------------------------------------------------------------------
1 | pub struct DisjointSet {
2 | parent: Vec,
3 | rank: Vec
4 | }
5 |
6 | impl DisjointSet {
7 | pub fn new(size: usize) -> Self {
8 | DisjointSet {
9 | parent: (0..size).collect(),
10 | rank: vec![0; size]
11 | }
12 | }
13 |
14 | pub fn find(&mut self, index: usize) -> usize {
15 | if self.parent[index] != index {
16 | self.parent[index] = self.find(self.parent[index]);
17 | }
18 | self.parent[index]
19 | }
20 |
21 | pub fn union(&mut self, x: usize, y: usize) {
22 | let x_root = self.find(x);
23 | let y_root = self.find(y);
24 |
25 | if x_root == y_root {
26 | return;
27 | }
28 |
29 | if self.rank[x_root] < self.rank[y_root] {
30 | self.parent[x_root] = y_root;
31 | }
32 | else if self.rank[x_root] > self.rank[y_root] {
33 | self.parent[y_root] = x_root;
34 | }
35 | else {
36 | self.parent[y_root] = x_root;
37 | self.rank[x_root] += 1;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/rust/src/primes/sieve_of_eratosthenes.rs:
--------------------------------------------------------------------------------
1 | pub fn sieve_of_eratosthenes(up_to: usize) -> Vec {
2 | if up_to < 2 {
3 | return vec![];
4 | }
5 |
6 | let mut sieve: Vec = vec![true; up_to];
7 | sieve[0] = false;
8 | sieve[1] = false;
9 |
10 | let sqrt_limit = (up_to as f64).sqrt() as usize;
11 | for number in 2..sqrt_limit + 1 {
12 | if sieve[number] == true {
13 | let mut multiple = number * number;
14 | while multiple < up_to {
15 | sieve[multiple] = false;
16 | multiple += number;
17 | }
18 | }
19 | }
20 | sieve.iter().enumerate()
21 | .filter_map(|(number, &is_prime)| if is_prime { Some(number) } else { None })
22 | .collect()
23 | }
24 |
25 |
26 | #[cfg(test)]
27 | mod tests {
28 | use super::*;
29 |
30 | #[test]
31 | fn test_sieve_of_eratosthenes() {
32 | let primes: Vec = sieve_of_eratosthenes(1000000);
33 | assert!(!primes.is_empty());
34 | assert_eq!(primes.len(), 78498);
35 | assert_eq!(primes.first().unwrap(), &2);
36 | assert_eq!(primes.last().unwrap(), &999983);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/csharp/BubbleSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6 };
2 |
3 | bool sorted;
4 |
5 | // Initialize the index for the last sorted element to the array's length
6 | // In bubbleSort after every iteration, the largest element in the unsorted part will move to its correct position at the end
7 | // So after each iteration we do not need to check - arr.Length - index
8 | int indexOfLastSortedElement = arr.Length;
9 | do
10 | {
11 | // Assume the array is sorted, change the value to false if a swap occurs
12 | sorted = true;
13 | for (int index = 1; index < indexOfLastSortedElement; index++)
14 | {
15 | // Compare each pair of elements
16 | // if they are out of order, swap
17 | if (arr[index - 1] > arr[index])
18 | {
19 | Swap(ref arr[index - 1], ref arr[index]);
20 |
21 | // Since a swap is made, mark the array as unsorted
22 | sorted = false;
23 | }
24 | }
25 | // Decrease the index of the last unsorted element by one
26 | // As the largest element in the unsorted part has moved to its correct position at the end
27 | indexOfLastSortedElement--;
28 |
29 | } while (!sorted); // Repeat until no swaps occurs and sorted variable stay as true
30 |
31 | void Swap(ref int x1, ref int x2) => (x2, x1) = (x1, x2);
32 |
--------------------------------------------------------------------------------
/rust/src/sorting/quicksort.rs:
--------------------------------------------------------------------------------
1 | pub fn quicksort(arr: &mut [T]) {
2 | if arr.is_empty() {
3 | return;
4 | }
5 | sort(arr, 0, arr.len() - 1);
6 | }
7 |
8 | fn sort(arr: &mut [T], left: usize, right: usize) {
9 | if left < right {
10 | let pivot_index = partition(arr, left, right);
11 | sort(arr, left, pivot_index);
12 | sort(arr, pivot_index + 1, right);
13 | }
14 | }
15 |
16 | fn partition(arr: &mut [T], left: usize, right: usize) -> usize {
17 | let pivot = right;
18 | let mut p_left = left;
19 | let mut p_right = right - 1;
20 |
21 | loop {
22 | while arr[p_left] < arr[pivot] {
23 | p_left += 1;
24 | }
25 |
26 | while arr[p_right] > arr[pivot] {
27 | p_right -= 1;
28 | }
29 |
30 | if p_left >= p_right {
31 | arr.swap(p_left, pivot);
32 | return p_right;
33 | }
34 | arr.swap(p_left, p_right);
35 | p_left += 1;
36 | p_right -= 1;
37 | }
38 | }
39 |
40 | #[cfg(test)]
41 | mod tests {
42 | use super::*;
43 |
44 | #[test]
45 | fn empty() {
46 | let mut empty_vec: Vec = Vec::new();
47 | quicksort(&mut empty_vec);
48 |
49 | assert!(empty_vec.is_empty());
50 | }
51 |
52 | #[test]
53 | fn sort() {
54 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
55 | quicksort(&mut arr);
56 |
57 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/csharp/ShellSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6, 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6, 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6, };
2 | int[] sequence = GenerateKnuthSequence(arr.Length);
3 |
4 | // Iterate over the Knuth sequence
5 | // and perform insertion sort for every step
6 | for (int stepIndex = 0; stepIndex < sequence.Length; stepIndex++)
7 | {
8 | int step = sequence[stepIndex];
9 |
10 | for (int index = step; index < arr.Length; index++)
11 | {
12 | var currentItem = arr[index];
13 | int compareIndex = index - step;
14 |
15 | // Shift elements that are step distance apart and greater than currentItem
16 | while (compareIndex >= 0 && currentItem < arr[compareIndex])
17 | {
18 | arr[compareIndex + step] = arr[compareIndex];
19 | compareIndex -= step;
20 | }
21 |
22 | // Place currentItem in its correct position
23 | arr[compareIndex + step] = currentItem;
24 | }
25 | }
26 |
27 | // Generate the Knuth sequence based on the array size
28 | // 1, 4, 13, 40, 121, ...
29 | static int[] GenerateKnuthSequence(int arraySize)
30 | {
31 | int gapSequenceLength = (int)Math.Floor(Math.Log(arraySize, 3)) - 1;
32 |
33 | int[] knuthSequence = new int[gapSequenceLength];
34 | int value = 1;
35 |
36 | for (int index = 0; index < gapSequenceLength; index++)
37 | {
38 | knuthSequence[index] = (value);
39 | value = 3 * value + 1; // Calculate the next gap size
40 | }
41 |
42 | Array.Reverse(knuthSequence); // Reverse the sequence as per Knuth's suggestion
43 | return knuthSequence;
44 | }
45 |
--------------------------------------------------------------------------------
/rust/src/sorting/shell_sort.rs:
--------------------------------------------------------------------------------
1 | pub fn shell_sort(arr: &mut [T]) {
2 | if arr.is_empty() {
3 | return;
4 | }
5 | let sequence: Vec = generate_knuth_sequence(arr.len());
6 |
7 | for seq_value in sequence.iter() {
8 | let seq_value = *seq_value as usize; // Dereference to get the i32 value
9 |
10 | for index in seq_value..arr.len() {
11 | let current_item: T = arr[index];
12 | let mut compare_index: usize = index;
13 |
14 | while compare_index >= seq_value && arr[compare_index - seq_value] > current_item {
15 | arr[compare_index] = arr[compare_index - seq_value];
16 | compare_index -= seq_value;
17 | }
18 | arr[compare_index] = current_item;
19 | }
20 | }
21 | }
22 |
23 | // Generate the Knuth sequence based on the array size
24 | // 1, 4, 13, 40, 121, ...
25 | fn generate_knuth_sequence(array_size: usize) -> Vec {
26 | let gap_sequence_length = (f64::log(array_size as f64, 3.0)).floor() as usize - 1;
27 |
28 | let mut knuth_sequence: Vec = Vec::with_capacity(gap_sequence_length);
29 | let mut value: i32 = 1;
30 | knuth_sequence.push(value);
31 |
32 | for _index in 0..gap_sequence_length {
33 | value = 3 * value + 1; // Calculate the next gap size
34 | knuth_sequence.push(value);
35 | }
36 |
37 | knuth_sequence.reverse(); // Reverse the sequence as per Knuth's suggestion
38 | knuth_sequence
39 | }
40 |
41 | #[cfg(test)]
42 | mod tests {
43 | use super::*;
44 |
45 | #[test]
46 | fn empty() {
47 | let mut empty_vec: Vec = Vec::new();
48 | shell_sort(&mut empty_vec);
49 |
50 | assert!(empty_vec.is_empty());
51 | }
52 |
53 | #[test]
54 | fn sort() {
55 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
56 | shell_sort(&mut arr);
57 |
58 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/csharp/DepthFirstSearch/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 |
3 | namespace DepthFirstSearch;
4 |
5 | /*
6 | for graph with nodes: A, B, C, D
7 | where: A -> B and C; B and C -> D
8 | A
9 | / \
10 | B C
11 | \ /
12 | D
13 |
14 | DFS traversal sequence: A -> C -> D -> B
15 | */
16 |
17 | public static class GraphExtensions
18 | {
19 | public static void DFS(this Graph graph, T startValue)
20 | {
21 | // Retrieve the start node from the graph using the provided value
22 | // If the start node is not found, handle the error appropriately
23 | var startNode = graph.GetNode(startValue);
24 | if (startNode == null)
25 | {
26 | // handle
27 | }
28 |
29 | // Initialize a stack to keep track of nodes
30 | // For DFS we use Stack - Last-In-First-Out (LIFO) data structure
31 | // stack is used to explore as far as possible along a branch before backtracking
32 | // ensuring a depth-first traversal of the graph
33 | var stack = new Stack>();
34 | var visited = new HashSet>();
35 |
36 | // Add the start node to the stack and mark it as visited
37 | stack.Push(startNode);
38 | visited.Add(startNode);
39 |
40 | // Continue searching as long as there are nodes left to visit
41 | while (stack.Count > 0)
42 | {
43 | var currentNode = stack.Pop();
44 | if (!graph.Edges.TryGetValue(currentNode, out var edges))
45 | continue;
46 |
47 | foreach (var edge in edges)
48 | {
49 | var adjacentNode = edge.Node;
50 |
51 | // If an adjacent node hasn't been visited
52 | // add it to the stack and mark it as visited
53 | if (!visited.Contains(adjacentNode))
54 | {
55 | visited.Add(adjacentNode);
56 | stack.Push(adjacentNode);
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/csharp/QuickSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6 };
2 | arr = Sort(arr, 0, arr.Length - 1);
3 |
4 | T[] Sort(T[] source, int low, int high) where T: IComparable
5 | {
6 | if (low < high)
7 | {
8 | // Partition the array segment and get the pivot's final position
9 | var pivot = Partition(source, low, high);
10 |
11 | // Recursively sort elements before the pivot
12 | Sort(source, low, pivot);
13 |
14 | // Recursively sort elements after the pivot
15 | Sort(source, pivot + 1, high);
16 | }
17 | return source;
18 | }
19 |
20 | int Partition(T[] array, int left, int right) where T : IComparable
21 | {
22 | // Selecting the leftmost element as the pivot for simplicity.
23 | // The pivot is a reference point to divide the array into two parts.
24 | var pivot = array[left];
25 | while (true)
26 | {
27 | // With two while loops, one from left to pivot and one from right to pivot
28 | // we search for elements that we can swap
29 | // starting from left if we find element that is greater than pivot,
30 | // and fro right if we find element that is less than pivot,
31 | // we swap the two elements from left and right
32 |
33 | // Find the first element from the left that is greater than pivot
34 | while (array[left].CompareTo(pivot) < 0)
35 | {
36 | left++;
37 | }
38 |
39 | // Find the first element from the right that is less than pivot
40 | while (array[right].CompareTo(pivot) > 0)
41 | {
42 | right--;
43 | }
44 |
45 | // If all elements are compared and swapped if necessary, the partition is complete
46 | if (left >= right)
47 | {
48 | return right;
49 | }
50 |
51 | var temp = array[left];
52 | array[left] = array[right];
53 | array[right] = temp;
54 |
55 | // Move to next elements in the array for comparison
56 | left++;
57 | right--;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/rust/src/graphs/kruskal.rs:
--------------------------------------------------------------------------------
1 | use crate::data_structures::DisjointSet;
2 | use crate::graphs::graph::{ Graph, Edge, NodeIndex };
3 |
4 | impl Graph {
5 | pub fn kruskal_mst(&self) -> Vec<(&NodeIndex, &Edge)> {
6 | if self.nodes.len() == 0 {
7 | return vec![];
8 | }
9 |
10 | let mut edges = self.edges
11 | .iter()
12 | .flat_map(|node_edge| {
13 | node_edge.1.iter().map(move |edge| (node_edge.0, edge))
14 | })
15 | .collect::>();
16 |
17 | edges.sort_by_key(|(_, edge)| edge.cost);
18 |
19 | let mut union_find = DisjointSet::new(self.nodes.len());
20 | let mut mst = Vec::new();
21 |
22 | for (node_ix, edge) in edges {
23 | let x_root = union_find.find(node_ix.ix);
24 | let y_root = union_find.find(edge.node_index.ix);
25 |
26 | if x_root != y_root {
27 | mst.push((node_ix, edge));
28 | union_find.union(x_root, y_root);
29 | }
30 | }
31 | mst
32 | }
33 | }
34 |
35 |
36 | #[cfg(test)]
37 | mod tests {
38 | use crate::graphs::graph::{ Graph, GraphType };
39 |
40 | #[test]
41 | fn kruskal_empty_graph() {
42 | let graph: Graph = Graph::new(GraphType::Undirected);
43 | let mst = graph.kruskal_mst();
44 | assert!(mst.is_empty());
45 | }
46 |
47 | #[test]
48 | fn kruskal_single_node() {
49 | let mut graph = Graph::new(GraphType::Undirected);
50 | graph.add_node(1);
51 | let mst = graph.kruskal_mst();
52 | assert!(mst.is_empty());
53 | }
54 |
55 | #[test]
56 | fn kruskal_disconnected_graph() {
57 | let mut graph = Graph::new(GraphType::Undirected);
58 | let n1 = graph.add_node(1);
59 | let n2 = graph.add_node(2);
60 | graph.add_edge(n1, n2, 1);
61 | graph.add_node(3); // Disconnected node
62 |
63 | let mst = graph.kruskal_mst();
64 | assert_eq!(mst.len(), 1);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/csharp/BreadthFirstSearch/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 | using System.Xml.Linq;
3 |
4 | namespace BreadthFirstSearch;
5 |
6 | /*
7 | for graph with nodes: A, B, C, D
8 | where: A -> B and C; B and C -> D
9 | A
10 | / \
11 | B C
12 | \ /
13 | D
14 |
15 | BFS traversal sequence: A -> B -> C -> D
16 | */
17 |
18 | public static class GraphExtensions
19 | {
20 | public static void BFS(this Graph graph, T startValue)
21 | {
22 | // Retrieve the start node from the graph using the provided value.
23 | // If the start node is not found, handle the error appropriately.
24 | var startNode = graph.GetNode(startValue);
25 | if (startNode == null)
26 | {
27 | // handle
28 | }
29 |
30 | // Initialize a queue to keep track of nodes
31 | // For BFS we use Queue - First-In-First-Out (FIFO) data structure
32 | // queue is used to ensure that nodes are explored in the order they are discovered
33 | // enabling level-by - level traversal of the graph
34 | var queue = new Queue>();
35 | var visited = new HashSet>();
36 |
37 | // Add the start node to the queue and mark it as visited
38 | queue.Enqueue(startNode);
39 | visited.Add(startNode);
40 |
41 | // Continue searching as long as there are nodes left to visit
42 | while (queue.Count > 0)
43 | {
44 | var currentNode = queue.Dequeue();
45 |
46 | if (!graph.Edges.TryGetValue(currentNode, out var edges))
47 | continue;
48 |
49 | foreach (var edge in edges)
50 | {
51 | var adjacentNode = edge.Node;
52 |
53 | // If an adjacent node hasn't been visited
54 | // add it to the queue and mark it as visited
55 | if (!visited.Contains(adjacentNode))
56 | {
57 | visited.Add(adjacentNode);
58 | queue.Enqueue(adjacentNode);
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/csharp/DijkstraPrimes/Program.cs:
--------------------------------------------------------------------------------
1 | const int PRIMES_UP_TO = 30;
2 |
3 |
4 | var primes = new List();
5 | var pool = new Pool();
6 |
7 | primes.Add(2);
8 | pool.Insert(2);
9 |
10 | for (int number = 3; number < PRIMES_UP_TO; number++)
11 | {
12 | var smallestMultiplier = pool.GetSmallestMultiplier();
13 | if (smallestMultiplier > 0)
14 | {
15 | if (number < smallestMultiplier)
16 | {
17 | primes.Add(number);
18 | pool.Insert(number);
19 | }
20 | else
21 | {
22 | pool.Update(number);
23 | }
24 | }
25 | }
26 |
27 | readonly struct Pool
28 | {
29 | private readonly List<(int Prime, int Multiple)> pairs;
30 |
31 | public Pool()
32 | {
33 | pairs = new();
34 | }
35 |
36 | public readonly void Insert(int value)
37 | =>
38 | this.pairs.Add((value, value * value));
39 |
40 | public readonly int GetSmallestMultiplier()
41 | =>
42 | this.pairs.Count > 0
43 | ? this.pairs[0].Multiple
44 | : 0;
45 |
46 | public void Update(int value)
47 | {
48 | int index = 0;
49 | for (; index < pairs.Count; index++)
50 | {
51 | if (pairs[index].Multiple == value)
52 | {
53 | pairs[index] = (pairs[index].Prime, pairs[index].Multiple + pairs[index].Prime);
54 | }
55 | else
56 | {
57 | break;
58 | }
59 | }
60 |
61 | if (this.pairs.Count > 1)
62 | {
63 | while (index >= 0)
64 | {
65 | index -= 1;
66 | int i = index;
67 | while (this.pairs[i].Multiple > this.pairs[i + 1].Multiple)
68 | {
69 | (this.pairs[i + 1], this.pairs[i]) = (this.pairs[i], this.pairs[i + 1]);
70 | i += 1;
71 | }
72 | if (index == 0)
73 | break;
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/csharp/Graphs/Graph.cs:
--------------------------------------------------------------------------------
1 | namespace Graphs;
2 |
3 | public enum GraphType
4 | {
5 | Directed,
6 | Undirected
7 | }
8 |
9 | public class Node
10 | {
11 | public T Value { get; }
12 |
13 | public Node(T value) => Value = value;
14 | }
15 |
16 | public class Edge
17 | {
18 | public int Cost { get; }
19 | public Node Node { get; }
20 |
21 | public Edge(int cost, Node node)
22 | {
23 | Cost = cost;
24 | Node = node;
25 | }
26 | }
27 |
28 | public class Graph
29 | {
30 | public ICollection> Nodes { get; }
31 | public IDictionary, ICollection>> Edges { get; }
32 | public GraphType GraphType { get; }
33 |
34 | public Graph() : this(GraphType.Undirected)
35 | {
36 | }
37 |
38 | public Graph(GraphType graphType)
39 | {
40 | Nodes = new List>();
41 | Edges = new Dictionary, ICollection>>();
42 | GraphType = graphType;
43 | }
44 |
45 | public void AddNode(T value)
46 | {
47 | var node = new Node(value);
48 | this.Nodes.Add(node);
49 | }
50 |
51 | public void AddEdge(Node fromNode, Node toNode, int cost)
52 | {
53 | if (fromNode == null || toNode == null)
54 | {
55 | // handle
56 | return;
57 | }
58 |
59 | Add(fromNode, toNode, cost);
60 |
61 | if (this.GraphType == GraphType.Undirected)
62 | {
63 | Add(toNode, fromNode, cost);
64 | }
65 |
66 | void Add(Node from, Node to, int cost)
67 | {
68 | if (!Edges.TryGetValue(from, out ICollection> value))
69 | {
70 | value = new List>();
71 | this.Edges.Add(from, value);
72 | }
73 |
74 | var edge = new Edge(cost, to);
75 | value.Add(edge);
76 | }
77 | }
78 |
79 | public Node GetNode(T value)
80 | {
81 | var node = this.Nodes.FirstOrDefault(x => x.Value.Equals(value));
82 | if (node.Value == null)
83 | {
84 | // handle
85 | }
86 |
87 | return node;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/rust/src/primes/dijkstra_primes.rs:
--------------------------------------------------------------------------------
1 | pub fn dijkstra_primes(up_to: usize) -> Vec {
2 | if up_to < 2 {
3 | return vec![];
4 | }
5 |
6 | let mut primes: Vec = Vec::new();
7 | let mut pool = Pool::new();
8 |
9 | primes.push(2);
10 | pool.insert(2);
11 |
12 | for number in 3..up_to {
13 | if let Some(multiplier) = pool.get_smallest_multiplier() {
14 | if number < multiplier {
15 | primes.push(number);
16 | pool.insert(number);
17 | } else {
18 | pool.update(number);
19 | }
20 | }
21 | }
22 |
23 | primes
24 | }
25 |
26 | struct Pool {
27 | pairs: Vec<(usize, usize)>
28 | }
29 |
30 | impl Pool {
31 | fn new() -> Self {
32 | Pool { pairs: vec![] }
33 | }
34 |
35 | fn insert(&mut self, v: usize) {
36 | self.pairs.push((v, v * v));
37 | }
38 |
39 | fn update(&mut self, v: usize) {
40 | let mut index = 0;
41 | for pair in self.pairs.iter_mut().take_while(|pair| pair.1 == v) {
42 | pair.1 += pair.0;
43 | index += 1;
44 | }
45 |
46 | if self.pairs.len() > 1 {
47 | index -= 1;
48 | loop {
49 | let mut i = index;
50 | while self.pairs[i].1 > self.pairs[i + 1].1 {
51 | self.pairs.swap(i, i + 1);
52 | i += 1;
53 | }
54 | if index == 0 {
55 | break;
56 | }
57 | index -= 1;
58 | }
59 | }
60 | }
61 |
62 | fn get_smallest_multiplier(&self) -> Option {
63 | if let Some(pair) = self.pairs.first() {
64 | return Some(pair.1);
65 | }
66 | None
67 | }
68 | }
69 |
70 |
71 | #[cfg(test)]
72 | mod tests {
73 | use super::*;
74 |
75 | #[test]
76 | fn test_dijkstra_primes() {
77 | let primes: Vec = dijkstra_primes(1000000);
78 | assert!(!primes.is_empty());
79 | assert_eq!(primes.len(), 78498);
80 | assert_eq!(primes.first().unwrap(), &2);
81 | assert_eq!(primes.last().unwrap(), &999983);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/csharp/UnionFind/UnionFindSet.cs:
--------------------------------------------------------------------------------
1 | namespace UnionFind;
2 |
3 | public class UnionFindSet
4 | {
5 | private int[] parent; // Stores the parent of each element. For a root element, parent[i] = i.
6 | private int[] rank; // Stores the approximate depth (or 'rank') of the tree for each root.
7 |
8 | public UnionFindSet(int size)
9 | {
10 | this.parent = Enumerable.Range(0, size).ToArray();
11 | this.rank = new int[size];
12 | }
13 |
14 | public int Find(int index)
15 | {
16 | // Path Compression: If 'index' is not the root (parent[index] != index),
17 | // recursively find the root and update the parent of 'index' for faster future lookups.
18 | if (parent[index] != index)
19 | {
20 | parent[index] = this.Find(parent[index]);
21 | }
22 |
23 | return parent[index];
24 | }
25 |
26 | public void Union(int x, int y)
27 | {
28 | // Find the roots of the sets that 'x' and 'y' belong to.
29 | var x_root = this.Find(x);
30 | var y_root = this.Find(y);
31 |
32 | // If both elements have the same root, they are already in the same set.
33 | if (x_root == y_root)
34 | {
35 | return;
36 | }
37 |
38 | // Union by Rank:
39 | /*
40 | * When performing a union of two sets, instead of arbitrarily choosing the root for merging,
41 | * the root with the smaller rank is attached to the root with the larger rank.
42 | * If both roots have the same rank, one is chosen as the new root and its rank is incremented by one.
43 | *
44 | * Attach the smaller tree to the larger tree's root to maintain balanced trees, preventing inefficient linear structures.
45 | * This approach significantly improves the efficiency of 'Find' operations by keeping tree heights minimal
46 | */
47 |
48 | if (this.rank[x_root] < this.rank[y_root])
49 | {
50 | this.parent[x_root] = y_root;
51 | }
52 | else if (this.rank[x_root] > this.rank[y_root])
53 | {
54 | this.parent[y_root] = x_root;
55 | }
56 | else
57 | {
58 | this.parent[y_root] = x_root;
59 | this.rank[x_root]++;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/csharp/Prim/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 |
3 | namespace Prim;
4 |
5 | public static class GraphExtensions
6 | {
7 | public static IEnumerable> PrimMst(this Graph graph)
8 | {
9 | if (graph.Nodes.Count == 0)
10 | {
11 | return Enumerable.Empty>();
12 | }
13 |
14 | var visited = new HashSet>();
15 |
16 | // PriorityQueue to store nodes along with their edge cost.
17 | // Nodes are processed based on minimum edge cost.
18 | var queue = new PriorityQueue<(Node, int), int>();
19 | var minimumSpanningTree = new List>();
20 |
21 | // Choose an arbitrary node as the starting point for Prim's algorithm.
22 | var root = graph.Nodes.First();
23 | queue.Enqueue((root, 0), 0);
24 |
25 | while (queue.Count > 0)
26 | {
27 | // Dequeue the node with the lowest edge cost.
28 | var queueItem = queue.Dequeue();
29 | var node = queueItem.Item1;
30 | var cost = queueItem.Item2;
31 |
32 | // Skip nodes that have already been visited to avoid cycles.
33 | if (visited.Contains(node))
34 | {
35 | continue;
36 | }
37 |
38 | // Add the node to the MST, along with its cost.
39 | minimumSpanningTree.Add(new NodeEdge()
40 | {
41 | Node = node,
42 | Cost = cost
43 | });
44 |
45 | visited.Add(node);
46 |
47 | if(graph.Edges.TryGetValue(node, out var edges))
48 | {
49 | foreach (var edge in edges)
50 | {
51 | // For each adjacent node that has not been visited, enqueue it with its cost.
52 | // The cost is the key for the priority queue to determine the processing order.
53 | if (!visited.Contains(edge.Node))
54 | {
55 | queue.Enqueue((edge.Node, edge.Cost), edge.Cost);
56 | }
57 | }
58 | }
59 | }
60 |
61 | return minimumSpanningTree;
62 | }
63 |
64 | public class NodeEdge
65 | {
66 | public Node Node { get; set; }
67 | public int Cost { get; set; }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/rust/src/sorting/insertion_sort.rs:
--------------------------------------------------------------------------------
1 | pub fn insertion_sort(arr: &mut [T]) {
2 | if arr.is_empty() {
3 | return;
4 | }
5 | for index in 1..arr.len() {
6 | let current_item: T = arr[index];
7 | let mut insertion_index: usize = index;
8 |
9 | while insertion_index > 0 && arr[insertion_index - 1] > current_item {
10 | arr[insertion_index] = arr[insertion_index - 1];
11 | insertion_index -= 1;
12 | }
13 | arr[insertion_index] = current_item;
14 | }
15 | }
16 |
17 | // alternatively we can use 'rotate_right' function from rust std
18 | /*
19 | the main idea is only to find the index at which we need to put 'current_item'
20 | and let 'rotate_right' to do all the swaps
21 |
22 | we find the correct position for 'current_item' without making any swaps
23 | and what 'rotate_right(1)' do is:
24 | shift every item one position right and the rightmost items goes to first position
25 |
26 | for example:
27 |
28 | arr = [1, 2, 3]
29 | index = 2
30 | insertion_index = 0
31 |
32 | arr[insertion_index..=index].rotate_right(1);
33 | arr = [3, 1, 2]
34 |
35 | */
36 | pub fn insertion_sort_with_rotate_right(arr: &mut [T]) {
37 | if arr.is_empty() {
38 | return;
39 | }
40 | for index in 1..arr.len() {
41 | let current_item: T = arr[index];
42 | let mut insertion_index: usize = index;
43 |
44 | while insertion_index > 0 && arr[insertion_index - 1] > current_item {
45 | insertion_index -= 1;
46 | }
47 | arr[insertion_index..=index].rotate_right(1);
48 | }
49 | }
50 |
51 | #[cfg(test)]
52 | mod tests {
53 | use super::*;
54 |
55 | #[test]
56 | fn empty() {
57 | let mut empty_vec: Vec = Vec::new();
58 | insertion_sort(&mut empty_vec);
59 |
60 | assert!(empty_vec.is_empty());
61 | }
62 |
63 | #[test]
64 | fn sort() {
65 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
66 | insertion_sort(&mut arr);
67 |
68 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
69 | }
70 |
71 | #[test]
72 | fn sort_with_rotate_right() {
73 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
74 | insertion_sort_with_rotate_right(&mut arr);
75 |
76 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/rust/src/graphs/tarjan.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use crate::graphs::graph::{ Graph, NodeIndex };
4 |
5 | use super::{tarjan_state::State, Node};
6 |
7 | /*
8 | NOT READY!
9 | */
10 |
11 | impl Graph {
12 | pub fn find_low_link_values(&self) -> HashMap {
13 | if self.length == 0 {
14 | return HashMap::new();
15 | }
16 |
17 | let mut state = State::new();
18 | let root: &Node = self.nodes.first().unwrap();
19 |
20 | self.tarjan_dfs(root.index, &mut state);
21 | state.nodes_low_link_value
22 | }
23 |
24 | fn tarjan_dfs(&self, node_index: NodeIndex, state: &mut State) {
25 | state.discovery_time += 1;
26 | state.visited.insert(node_index);
27 | state.nodes_discovery_time.insert(node_index, state.discovery_time);
28 | state.nodes_low_link_value.insert(node_index, state.discovery_time);
29 |
30 | let edges = match self.edges.get(&node_index) {
31 | Some(edges) => edges,
32 | None => return
33 | };
34 |
35 | for edge in edges {
36 | if !state.visited.contains(&edge.node_index) {
37 | state.parent_node.insert(edge.node_index, node_index);
38 | self.tarjan_dfs(edge.node_index, state);
39 |
40 | state.nodes_low_link_value.insert(
41 | node_index,
42 | std::cmp::min(
43 | state.nodes_low_link_value[&node_index],
44 | state.nodes_low_link_value[&edge.node_index],
45 | ),
46 | );
47 | } else if Some(&node_index) != state.parent_node.get(&edge.node_index) {
48 | state.nodes_low_link_value.insert(
49 | node_index,
50 | std::cmp::min(
51 | state.nodes_low_link_value[&node_index],
52 | state.nodes_discovery_time[&edge.node_index],
53 | ),
54 | );
55 | }
56 | }
57 | }
58 | }
59 |
60 |
61 | #[cfg(test)]
62 | mod tests {
63 | use crate::graphs::graph::{ Graph, GraphType };
64 |
65 | #[test]
66 | fn empty_graph() {
67 | let graph: Graph = Graph::new(GraphType::Undirected);
68 | let llv = graph.find_low_link_values();
69 | assert!(llv.is_empty());
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/rust/src/graphs/dfs.rs:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | for graph with nodes: A, B, C, D
4 | where: A -> B and C; B and C -> D
5 | A
6 | / \
7 | B C
8 | \ /
9 | D
10 |
11 | DFS traversal sequence: A -> C -> D -> B
12 | */
13 |
14 | use std::collections::HashSet;
15 |
16 | use crate::graphs::graph::{ Graph, Node, NodeIndex };
17 |
18 | impl Graph {
19 | pub fn dfs(&self, root_node: &Node) -> Vec {
20 |
21 | let mut result: Vec = Vec::new();
22 | let mut stack: Vec<&NodeIndex> = vec![];
23 | stack.push(&root_node.index);
24 |
25 | let mut visited: HashSet<&NodeIndex> = HashSet::new();
26 |
27 | while let Some(node_index) = stack.pop() {
28 | if visited.contains(node_index) {
29 | continue;
30 | }
31 | visited.insert(node_index);
32 | result.push(self.nodes[node_index.ix].value);
33 |
34 | let edges = match self.edges.get(node_index) {
35 | Some(edges) => edges,
36 | None => continue
37 | };
38 |
39 | for edge in edges {
40 | if !visited.contains(&edge.node_index) {
41 | stack.push(&edge.node_index);
42 | }
43 | }
44 | }
45 | result
46 | }
47 | }
48 |
49 |
50 | #[cfg(test)]
51 | mod tests {
52 | use crate::graphs::GraphType;
53 |
54 | use super::*;
55 |
56 | fn create_test_graph() -> Graph {
57 | let mut graph = Graph::new(GraphType::Directed);
58 | let a = graph.add_node('A');
59 | let b = graph.add_node('B');
60 | let c = graph.add_node('C');
61 | let d = graph.add_node('D');
62 |
63 | graph.add_edge(a, b, 1);
64 | graph.add_edge(a, c, 1);
65 | graph.add_edge(b, d, 1);
66 | graph.add_edge(c, d, 1);
67 |
68 | graph
69 | }
70 |
71 | #[test]
72 | fn dfs_simple_graph() {
73 | let graph = create_test_graph();
74 | let root = graph.get_node(NodeIndex { ix: 0 }).unwrap();
75 |
76 | let traversal = graph.dfs(root);
77 | assert_eq!(traversal, vec!['A', 'C', 'D', 'B']);
78 | }
79 |
80 | #[test]
81 | fn dfs_empty_graph() {
82 | let graph: Graph = Graph::new(GraphType::Directed);
83 |
84 | if let Some(root) = graph.nodes.get(0) {
85 | let traversal = graph.dfs(root);
86 | assert!(traversal.is_empty());
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/rust/src/sorting/merge_sort.rs:
--------------------------------------------------------------------------------
1 | pub fn merge_sort(arr: &mut [T]) {
2 | if arr.is_empty() {
3 | return;
4 | }
5 | sort(arr);
6 | }
7 |
8 | fn sort(arr: &mut [T]) {
9 | if arr.len() == 1 {
10 | return; // If the array has only one element, it's already sorted
11 | }
12 |
13 | // Finding the middle index of the array to split it into two halves
14 | let middle_index: usize = arr.len() / 2;
15 | let (left_array, right_array) = arr.split_at_mut(middle_index);
16 |
17 | sort(left_array);
18 | sort(right_array);
19 |
20 | let merged = merge(left_array, right_array);
21 | for (index, item) in merged.iter().enumerate() {
22 | arr[index] = item.clone();
23 | }
24 | }
25 |
26 | fn merge(left_array: &[T], right_array: &[T]) -> Vec {
27 | let mut left_array_index: usize = 0;
28 | let mut right_array_index: usize = 0;
29 | let mut merged_vector: Vec = Vec::with_capacity(left_array.len() + right_array.len());
30 |
31 | // Merging the two arrays until one of them is fully traversed
32 | while left_array_index < left_array.len() && right_array_index < right_array.len() {
33 | if left_array[left_array_index] <= right_array[right_array_index] {
34 | merged_vector.push(left_array[left_array_index]);
35 | left_array_index += 1;
36 | } else {
37 | merged_vector.push(right_array[right_array_index]);
38 | right_array_index += 1;
39 | }
40 | }
41 |
42 | // Adding remaining elements from the left array (if any)
43 | while left_array_index < left_array.len() {
44 | merged_vector.push(left_array[left_array_index]);
45 | left_array_index += 1;
46 | }
47 |
48 | // Adding remaining elements from the right array (if any)
49 | while right_array_index < right_array.len() {
50 | merged_vector.push(right_array[right_array_index]);
51 | right_array_index += 1;
52 | }
53 |
54 | merged_vector
55 | }
56 |
57 | #[cfg(test)]
58 | mod tests {
59 | use super::*;
60 |
61 | #[test]
62 | fn empty() {
63 | let mut empty_vec: Vec = Vec::new();
64 | merge_sort(&mut empty_vec);
65 |
66 | assert!(empty_vec.is_empty());
67 | }
68 |
69 | #[test]
70 | fn sort() {
71 | let mut arr: Vec = vec![4, -3, 7, 0, 10, -6, 7, 1];
72 | merge_sort(&mut arr);
73 |
74 | assert_eq!(arr, vec![-6, -3, 0, 1, 4, 7, 7, 10]);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/rust/src/graphs/bfs.rs:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | for graph with nodes: A, B, C, D
4 | where: A -> B and C; B and C -> D
5 | A
6 | / \
7 | B C
8 | \ /
9 | D
10 |
11 | BFS traversal sequence: A -> B -> C -> D
12 | */
13 |
14 | use std::collections::VecDeque;
15 |
16 | use crate::graphs::graph::{ Graph, Node, NodeIndex };
17 |
18 | impl Graph {
19 | pub fn bfs(&self, root_node: &Node) -> Vec {
20 |
21 | let mut result: Vec = Vec::new();
22 | let mut queue: VecDeque = VecDeque::new();
23 | queue.push_back(root_node.index);
24 |
25 | let mut visited: Vec = Vec::new();
26 |
27 | while let Some(node_index) = queue.pop_front() {
28 | if visited.contains(&node_index) {
29 | continue;
30 | }
31 |
32 | visited.push(node_index);
33 | result.push(self.nodes[node_index.ix].value);
34 |
35 | let edges = match self.edges.get(&node_index) {
36 | Some(edges) => edges,
37 | None => continue
38 | };
39 |
40 | for edge in edges {
41 | if !visited.contains(&edge.node_index) && !queue.contains(&edge.node_index) {
42 | queue.push_back(edge.node_index);
43 | }
44 | }
45 | }
46 | result
47 | }
48 | }
49 |
50 |
51 | #[cfg(test)]
52 | mod tests {
53 | use crate::graphs::GraphType;
54 |
55 | use super::*;
56 |
57 | fn create_test_graph() -> Graph {
58 | let mut graph = Graph::new(GraphType::Directed);
59 | let a = graph.add_node('A');
60 | let b = graph.add_node('B');
61 | let c = graph.add_node('C');
62 | let d = graph.add_node('D');
63 |
64 | graph.add_edge(a, b, 1);
65 | graph.add_edge(a, c, 1);
66 | graph.add_edge(b, d, 1);
67 | graph.add_edge(c, d, 1);
68 |
69 | graph
70 | }
71 |
72 | #[test]
73 | fn bfs_simple_graph() {
74 | let graph = create_test_graph();
75 | let root = graph.get_node(NodeIndex { ix: 0 }).unwrap();
76 |
77 | let traversal = graph.bfs(root);
78 | assert_eq!(traversal, vec!['A', 'B', 'C', 'D']);
79 | }
80 |
81 | #[test]
82 | fn bfs_empty_graph() {
83 | let graph: Graph = Graph::new(GraphType::Directed);
84 |
85 | if let Some(root) = graph.nodes.get(0) {
86 | let traversal = graph.bfs(root);
87 | assert!(traversal.is_empty());
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/rust/src/graphs/prim.rs:
--------------------------------------------------------------------------------
1 | use std::cmp::Reverse;
2 | use std::collections::{ BinaryHeap, HashSet };
3 |
4 | use crate::graphs::graph::{ Graph, NodeIndex };
5 |
6 | impl Graph {
7 | pub fn prim_mst(&self) -> Vec<(&NodeIndex, isize)> {
8 | if self.nodes.len() == 0 {
9 | return vec![];
10 | }
11 |
12 | let mut heap = BinaryHeap::new();
13 | let mut visited = HashSet::new();
14 | let mut mst = Vec::new();
15 |
16 | let root = self.nodes.first().unwrap();
17 | heap.push(Reverse((0, &root.index)));
18 |
19 | while let Some(Reverse((cost, node_ix))) = heap.pop() {
20 | if visited.contains(node_ix) {
21 | continue;
22 | }
23 |
24 | visited.insert(node_ix);
25 | mst.push((node_ix, cost));
26 |
27 | if let Some(edges) = self.edges.get(node_ix) {
28 | for edge in edges {
29 | let next = &edge.node_index;
30 | if !visited.contains(next) {
31 | heap.push(Reverse((edge.cost, next)));
32 | }
33 | }
34 | }
35 | }
36 | mst
37 | }
38 | }
39 |
40 |
41 | #[cfg(test)]
42 | mod tests {
43 | use crate::graphs::GraphType;
44 |
45 | use super::*;
46 |
47 | #[test]
48 | fn prim_single_node() {
49 | let mut graph = Graph::new(GraphType::Undirected);
50 | graph.add_node(1);
51 | let mst = graph.prim_mst();
52 | assert_eq!(mst.len(), 1);
53 | }
54 |
55 | #[test]
56 | fn prim_disconnected_graph() {
57 | let mut graph = Graph::new(GraphType::Undirected);
58 | let n1 = graph.add_node(1);
59 | let n2 = graph.add_node(2);
60 | graph.add_edge(n1, n2, 1);
61 |
62 | graph.add_node(3); // Disconnected node
63 |
64 | let mst = graph.prim_mst();
65 | assert_eq!(mst.len(), 2);
66 | }
67 |
68 | #[test]
69 | fn prim_single_mst() {
70 | let mut graph = Graph::new(GraphType::Undirected);
71 | let n1 = graph.add_node(1);
72 | let n2 = graph.add_node(2);
73 | let n3 = graph.add_node(3);
74 | let n4 = graph.add_node(4);
75 | graph.add_edge(n1, n2, 1);
76 | graph.add_edge(n1, n3, 3);
77 | graph.add_edge(n2, n4, 10);
78 | graph.add_edge(n3, n4, 5);
79 |
80 | let mst = graph.prim_mst();
81 | let total_cost: isize = mst.iter()
82 | .map(|x| x.1)
83 | .sum();
84 |
85 | assert_eq!(total_cost, 9);
86 | }
87 | }
--------------------------------------------------------------------------------
/csharp/LinkedList/SinglyLinkedList.cs:
--------------------------------------------------------------------------------
1 | namespace LinkedList;
2 |
3 | public class SinglyLinkedList
4 | {
5 | private class Node
6 | {
7 | public T Data;
8 | public Node Next;
9 |
10 | public Node(T data)
11 | {
12 | this.Data = data;
13 | this.Next = null;
14 | }
15 | }
16 |
17 | private Node head;
18 | private Node tail;
19 | private int length;
20 |
21 | public int Length
22 | {
23 | get { return this.length; }
24 | private set { length = value; }
25 | }
26 |
27 | public SinglyLinkedList()
28 | {
29 | head = null;
30 | tail = null;
31 | length = 0;
32 | }
33 |
34 | public bool IsEmpty()
35 | {
36 | return length == 0;
37 | }
38 |
39 | public void Add(T data)
40 | {
41 | var node = new Node(data);
42 |
43 | if (IsEmpty())
44 | {
45 | head = tail = node;
46 | }
47 | else
48 | {
49 | tail.Next = node;
50 | tail = node;
51 | }
52 |
53 | length++;
54 | }
55 |
56 | public T Get(int index)
57 | {
58 | if (IsEmpty() || index < 0 || index >= length)
59 | {
60 | throw new IndexOutOfRangeException("Index out of range.");
61 | }
62 |
63 | var current = head;
64 | for (int i = 0; i < index; i++)
65 | {
66 | current = current.Next;
67 | }
68 |
69 | return current.Data;
70 | }
71 |
72 | public void Delete(int index)
73 | {
74 | if (IsEmpty() || index < 0 || index >= length)
75 | {
76 | throw new IndexOutOfRangeException("Index out of range.");
77 | }
78 |
79 | if (index == 0)
80 | {
81 | head = head.Next;
82 | if (length == 1)
83 | {
84 | tail = null;
85 | }
86 | }
87 | else
88 | {
89 | var current = head;
90 | for (int i = 0; i < index - 1; i++)
91 | {
92 | current = current.Next;
93 | }
94 |
95 | current.Next = current.Next.Next;
96 | if (index == length - 1) // If the last element is being deleted
97 | {
98 | tail = current;
99 | }
100 | }
101 |
102 | length--;
103 | }
104 |
105 | public void Clear()
106 | {
107 | head = null;
108 | tail = null;
109 | length = 0;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/rust/src/graphs/floyd_warshall.rs:
--------------------------------------------------------------------------------
1 | use crate::graphs::graph::Graph;
2 |
3 | impl Graph {
4 | pub fn floyd_warshall_shortest_path(&self) -> Vec> {
5 |
6 | let node_count = self.nodes.len();
7 | let mut distances = vec![vec![isize::MAX; node_count]; node_count];
8 |
9 | for (source_index, node) in self.nodes.iter().enumerate() {
10 | distances[source_index][source_index] = 0; // Distance to self is 0
11 |
12 | if let Some(edges) = self.edges.get(&node.index) {
13 | for edge in edges {
14 | distances[source_index][edge.node_index.ix] = edge.cost;
15 | }
16 | }
17 | }
18 |
19 | for intermediate_vertex in 0..node_count {
20 | for source_vertex in 0..node_count {
21 | for destination_vertex in 0..node_count {
22 | let new_distance = std::cmp::min(
23 | distances[source_vertex][destination_vertex],
24 | distances[source_vertex][intermediate_vertex].saturating_add(distances[intermediate_vertex][destination_vertex]),
25 | );
26 |
27 | distances[source_vertex][destination_vertex] = new_distance;
28 | }
29 | }
30 | }
31 | distances
32 | }
33 | }
34 |
35 |
36 | #[cfg(test)]
37 | mod tests {
38 | use super::*;
39 | use crate::graphs::GraphType;
40 |
41 | #[test]
42 | fn empty_graph() {
43 | let graph: Graph<&str> = Graph::new(GraphType::Undirected);
44 |
45 | let result = graph.floyd_warshall_shortest_path();
46 | assert_eq!(result, Vec::>::new());
47 | }
48 |
49 | #[test]
50 | fn single_path() {
51 | let mut graph: Graph<&str> = Graph::new(GraphType::Directed);
52 | let a = graph.add_node("A");
53 | let b = graph.add_node("B");
54 | graph.add_edge(a, b, 1);
55 |
56 | let result = graph.floyd_warshall_shortest_path();
57 | assert_eq!(result, vec![vec![0, 1], vec![isize::MAX, 0]]);
58 | }
59 |
60 | #[test]
61 | fn multiple_paths() {
62 | let mut graph: Graph<&str> = Graph::new(GraphType::Directed);
63 | let a = graph.add_node("A");
64 | let b = graph.add_node("B");
65 | let c = graph.add_node("C");
66 | graph.add_edge(a, b, 3);
67 | graph.add_edge(b, c, 2);
68 |
69 | let result = graph.floyd_warshall_shortest_path();
70 | assert_eq!(result, vec![vec![0, 3, 5], vec![isize::MAX, 0, 2], vec![isize::MAX, isize::MAX, 0]]);
71 | }
72 | }
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/csharp/MergeSort/Program.cs:
--------------------------------------------------------------------------------
1 | int[] arr = new[] { 1, 7, 3, 2, 9, 5, 4, 2, 7, 3, 8, 6 };
2 | arr = Sort(arr);
3 |
4 | int[] Sort(int[] sourceArray)
5 | {
6 | // Base case: if the array has only one element, it's already sorted
7 | if (sourceArray.Length == 1)
8 | {
9 | return sourceArray;
10 | }
11 |
12 | // Finding the middle index of the array to split it into two halves
13 | int middleIndex = sourceArray.Length / 2;
14 |
15 | // Create two sub-arrays from the original array and copy values
16 | // for example: if sourceArray is { 1, 2, 3, 4 } after Array.Copy operations leftArray is { 1, 2 } and rightArray is { 4, 3 }
17 | var leftArray = new int[middleIndex];
18 | var rightArray = new int[sourceArray.Length - middleIndex];
19 |
20 | Array.Copy(sourceArray, 0, leftArray, 0, middleIndex);
21 | Array.Copy(sourceArray, middleIndex, rightArray, 0, sourceArray.Length - middleIndex);
22 |
23 | // Use recursion to sort the left and right sub-arrays
24 | leftArray = Sort(leftArray);
25 | rightArray = Sort(rightArray);
26 |
27 | // After the two sub-arrays are sorted, Merge() method will merge/combine sub-arrays into one array
28 | return Merge(leftArray, rightArray);
29 | }
30 |
31 | int[] Merge(int[] leftArray, int[] rightArray)
32 | {
33 | int leftArrayIndex = 0;
34 | int rightArrayIndex = 0;
35 | int mergedArrayIndex = 0;
36 |
37 | var mergedArray = new int[leftArray.Length + rightArray.Length];
38 |
39 | // Merging the two arrays until one of them is fully traversed
40 | while (leftArrayIndex < leftArray.Length && rightArrayIndex < rightArray.Length)
41 | {
42 | // Comparing elements of the two arrays and adding the smaller one to the merged array
43 | if (leftArray[leftArrayIndex] <= rightArray[rightArrayIndex])
44 | {
45 | mergedArray[mergedArrayIndex] = leftArray[leftArrayIndex];
46 | leftArrayIndex++;
47 | }
48 | else
49 | {
50 | mergedArray[mergedArrayIndex] = rightArray[rightArrayIndex];
51 | rightArrayIndex++;
52 | }
53 | mergedArrayIndex++;
54 | }
55 |
56 | // Adding remaining elements from the left array (if any)
57 | while (leftArrayIndex < leftArray.Length)
58 | {
59 | mergedArray[mergedArrayIndex] = leftArray[leftArrayIndex];
60 | leftArrayIndex++;
61 | mergedArrayIndex++;
62 | }
63 |
64 | // Adding remaining elements from the right array (if any)
65 | while (rightArrayIndex < rightArray.Length)
66 | {
67 | mergedArray[mergedArrayIndex] = rightArray[rightArrayIndex];
68 | rightArrayIndex++;
69 | mergedArrayIndex++;
70 | }
71 |
72 | return mergedArray;
73 | }
74 |
--------------------------------------------------------------------------------
/csharp/BinaryHeap/Heap.cs:
--------------------------------------------------------------------------------
1 | namespace BinaryHeap;
2 |
3 | public enum HeapType
4 | {
5 | Min,
6 | Max
7 | }
8 |
9 | public class Heap where T : IComparable
10 | {
11 | private List heap;
12 | private HeapType heapType;
13 |
14 | public Heap() : this(HeapType.Max)
15 | {
16 | }
17 |
18 | public Heap(HeapType heapType)
19 | {
20 | heap = new List();
21 | this.heapType = heapType;
22 | }
23 |
24 | public bool IsEmpty()
25 | {
26 | return this.heap.Count == 0;
27 | }
28 |
29 | public void Push(T item)
30 | {
31 | var oldLength = heap.Count;
32 | heap.Add(item);
33 | SiftUp(oldLength);
34 | }
35 |
36 | public T Pop()
37 | {
38 | if (this.IsEmpty())
39 | {
40 | return default;
41 | }
42 |
43 | var max = heap[0];
44 | var last = heap[heap.Count - 1];
45 | heap.RemoveAt(heap.Count - 1);
46 |
47 | if (heap.Count > 0)
48 | {
49 | heap[0] = last;
50 | SiftDown(0);
51 | }
52 | return max;
53 | }
54 |
55 | private void SiftUp(int index)
56 | {
57 | if (index == 0)
58 | {
59 | return;
60 | }
61 |
62 | int parentIndex = (index - 1) / 2;
63 | Func shouldSwap = (heapType == HeapType.Max) ?
64 | new Func((a, b) => a.CompareTo(b) > 0) :
65 | new Func((a, b) => a.CompareTo(b) < 0);
66 |
67 | if (shouldSwap(heap[index], heap[parentIndex]))
68 | {
69 | (heap[index], heap[parentIndex]) = (heap[parentIndex], heap[index]);
70 | SiftUp(parentIndex);
71 | }
72 | }
73 |
74 | private void SiftDown(int index)
75 | {
76 | int leftChildIndex = index * 2 + 1;
77 | int rightChildIndex = index * 2 + 2;
78 |
79 | if (leftChildIndex >= heap.Count)
80 | {
81 | return;
82 | }
83 |
84 | Func comparison = (heapType == HeapType.Max) ?
85 | new Func((a, b) => a.CompareTo(b) > 0) :
86 | new Func((a, b) => a.CompareTo(b) < 0);
87 |
88 | int childIndex = leftChildIndex;
89 | if (rightChildIndex < heap.Count && comparison(heap[rightChildIndex], heap[leftChildIndex]))
90 | {
91 | childIndex = rightChildIndex;
92 | }
93 |
94 | if (comparison(heap[childIndex], heap[index]))
95 | {
96 | (heap[index], heap[childIndex]) = (heap[childIndex], heap[index]);
97 | SiftDown(childIndex);
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/csharp/BellmanFord/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 |
3 | namespace BellmanFord;
4 |
5 | public static class GraphExtensions
6 | {
7 | public static int BellmanFordShortestPath(this Graph graph, Node from, Node to)
8 | {
9 | // Initialize a dictionary to store the shortest distance from the 'from' node to every other node.
10 | // Initially, the distance to the 'from' node is 0 and infinity (int.MaxValue) to all other nodes.
11 | // 'from' node is 0 because we start from this node
12 | var distances = graph.Nodes.ToDictionary(key => key, value =>
13 | {
14 | return value == from ? 0 : int.MaxValue;
15 | });
16 |
17 | // This flag helps to stop the algorithm early if no updates are made in a full iteration over all nodes.
18 | bool updated = true;
19 |
20 | // Relax edges up to 'n-1' times (where 'n' is the number of nodes).
21 | // This is because the shortest path in a graph without cycles will have at most 'n-1' edges.
22 | for (int node = 0; node < graph.Nodes.Count - 1; node++)
23 | {
24 | if (!updated) {
25 | break;
26 | }
27 | updated = false;
28 |
29 | // Iterate over all edges and update distances if a shorter path is found.
30 | // This process is called 'relaxation'.
31 | foreach (var node_edges in graph.Edges)
32 | {
33 | var currentNode = node_edges.Key;
34 | var cost = distances[currentNode];
35 |
36 | // Update the distance if the sum of the current node's distance and the edge cost is smaller.
37 | foreach (var edge in node_edges.Value)
38 | {
39 | if (cost + edge.Cost < distances[edge.Node])
40 | {
41 | distances[edge.Node] = cost + edge.Cost;
42 | updated = true;
43 | }
44 | }
45 | }
46 | }
47 |
48 | // Check for negative weight cycles which can be detected if we can relax any edge further.
49 | // If a further relaxation is possible, it means there's a negative cycle.
50 | foreach (var node_edges in graph.Edges)
51 | {
52 | var currentNode = node_edges.Key;
53 | var cost = distances[currentNode];
54 |
55 | foreach (var edge in node_edges.Value)
56 | {
57 | if (cost + edge.Cost < distances[edge.Node])
58 | {
59 | // If a negative cycle exists, the shortest path problem has no solution.
60 | // handle case
61 | return 0;
62 | }
63 | }
64 | }
65 |
66 | // After processing all nodes, retrieve the shortest path distance to the 'to' node
67 | // If this distance is still int.MaxValue, it means there's no path from 'from' node to 'to' node
68 | distances.TryGetValue(to, out int shortestPath);
69 | return shortestPath;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/csharp/Kruskal/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 | using UnionFind;
3 |
4 | namespace Kruskal;
5 |
6 | public static class GraphExtensions
7 | {
8 | public static IEnumerable> KruskalMst(this Graph graph)
9 | {
10 | if (graph.Nodes.Count == 0)
11 | {
12 | return Enumerable.Empty>();
13 | }
14 |
15 | // Map each node to a unique integer index for use in the union-find data structure
16 | var nodeIndexMap = new Dictionary, int>();
17 | int index = 0;
18 | foreach (var node in graph.Nodes)
19 | {
20 | nodeIndexMap[node] = index++;
21 | }
22 |
23 | // Convert the graph's edges into a flat list and sort them by cost
24 | // Sorting the edges is a key step in Kruskal's algorithm, which processes edges in ascending order of cost
25 | var nodeEdges = graph.Edges
26 | .SelectMany(node => node.Value
27 | .Select(edge => new NodeEdge()
28 | {
29 | Cost = edge.Cost,
30 | From = node.Key,
31 | To = edge.Node
32 | }))
33 | .OrderBy(nodeEdge => nodeEdge.Cost);
34 |
35 | // The Union-Find structure quickly tells us if two nodes are in the same subset by checking if they have the same root.
36 | // If they do, it means they are already connected, and adding an edge between them would form a cycle.
37 | var unionFind = new UnionFindSet(graph.Nodes.Count);
38 |
39 | // Result
40 | var minimumSpanningTree = new List>();
41 |
42 | foreach (var nodeEdge in nodeEdges)
43 | {
44 | // Determines if the nodes at either end of the current edge (nodeEdge.From and nodeEdge.To) are in different subsets (trees).
45 | // If they are in different subsets, it means that adding this edge will not create a cycle.
46 | // If they are in the same subset, adding the edge would complete a cycle, which we must avoid.
47 | var nodeX = unionFind.Find(nodeIndexMap[nodeEdge.From]);
48 | var nodeY = unionFind.Find(nodeIndexMap[nodeEdge.To]);
49 |
50 | // Ensures that the current edge connects two different subsets
51 | // If nodeX and nodeY are different, the nodes are in different subsets, and adding the edge is safe
52 | // WHY?
53 | // When it's confirmed that adding the edge won't create a cycle,
54 | // the Union operation merges the two subsets into a single subset.
55 | // This step is essential for progressively building the MST, as it connects different parts of the graph.
56 | if (nodeX != nodeY)
57 | {
58 | unionFind.Union(nodeX, nodeY);
59 | minimumSpanningTree.Add(nodeEdge);
60 | }
61 | }
62 |
63 | return minimumSpanningTree;
64 | }
65 |
66 | public class NodeEdge
67 | {
68 | public Node From { get; set; }
69 | public Node To { get; set; }
70 | public int Cost { get; set; }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/rust/src/graphs/dijkstra.rs:
--------------------------------------------------------------------------------
1 | use std::collections::{ BinaryHeap, HashMap, HashSet };
2 | use std::cmp::Reverse;
3 |
4 | use crate::graphs::graph::{ Graph, Edge, Node };
5 |
6 | use super::NodeIndex;
7 |
8 | impl Graph {
9 | pub fn dijkstra_shortest_path(&self, from_node: &Node, to_node: &Node) -> Option {
10 | if self.nodes.len() == 0 {
11 | return Some(0);
12 | }
13 |
14 | let mut distances = self.nodes.iter()
15 | .map(|node| {
16 | return if node == from_node { (&node.index, 0) } else { (&node.index, isize::MAX) };
17 | })
18 | .collect::>();
19 |
20 | let mut visited: HashSet<&NodeIndex> = HashSet::new();
21 | let mut heap: BinaryHeap> = BinaryHeap::new();
22 | heap.push(Reverse((0, &from_node.index)));
23 |
24 | while let Some(Reverse((cost, node_ix))) = heap.pop() {
25 | if &cost > distances.get(&node_ix).unwrap_or(&isize::MAX) {
26 | continue;
27 | }
28 |
29 | let edges: &Vec = match self.edges.get(&node_ix) {
30 | Some(edges) => edges,
31 | None => continue
32 | };
33 |
34 | for edge in edges {
35 | if cost + edge.cost < *distances.get(&edge.node_index).unwrap_or(&isize::MAX) {
36 |
37 | distances.insert(&edge.node_index, cost + edge.cost);
38 | if !visited.contains(&edge.node_index) {
39 | heap.push(Reverse((cost + edge.cost, &edge.node_index)));
40 | }
41 | }
42 | }
43 | visited.insert(&node_ix);
44 | }
45 |
46 | distances.get(&to_node.index)
47 | .copied()
48 | .filter(|&distance| distance != isize::MAX)
49 |
50 | }
51 | }
52 |
53 |
54 | #[cfg(test)]
55 | mod tests {
56 | use crate::graphs::GraphType;
57 |
58 | use super::*;
59 |
60 | #[test]
61 | fn find_path() {
62 | let mut graph = Graph::new(GraphType::Directed);
63 | let n1 = graph.add_node(1);
64 | let n2 = graph.add_node(2);
65 | let n3 = graph.add_node(3);
66 |
67 | graph.add_edge(n1, n2, 1);
68 | graph.add_edge(n2, n3, 1);
69 |
70 | let node1 = graph.get_node(n1).unwrap();
71 | let node3 = graph.get_node(n3).unwrap();
72 |
73 | assert_eq!(graph.dijkstra_shortest_path(node1, node3), Some(2));
74 | }
75 |
76 | #[test]
77 | fn no_path_exists() {
78 | let mut graph = Graph::new(GraphType::Directed);
79 | let n1 = graph.add_node(1);
80 | let n2 = graph.add_node(2);
81 |
82 | let node1 = graph.get_node(n1).unwrap();
83 | let node2 = graph.get_node(n2).unwrap();
84 |
85 | assert_eq!(graph.dijkstra_shortest_path(node1, node2), None);
86 | }
87 |
88 | #[test]
89 | fn path_to_self() {
90 | let mut graph = Graph::new(GraphType::Directed);
91 | let n1 = graph.add_node(1);
92 |
93 | let node1 = graph.get_node(n1).unwrap();
94 |
95 | assert_eq!(graph.dijkstra_shortest_path(node1, node1), Some(0));
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/csharp/BinarySearchTree/BinarySearchTree.cs:
--------------------------------------------------------------------------------
1 | namespace BinarySearchTree;
2 |
3 | public class TreeNode where T : IComparable
4 | {
5 | public T Value;
6 | public TreeNode Left;
7 | public TreeNode Right;
8 |
9 | public TreeNode(T value)
10 | {
11 | Value = value;
12 | Left = null;
13 | Right = null;
14 | }
15 | }
16 |
17 | public class BinarySearchTree where T : IComparable
18 | {
19 | public TreeNode Root;
20 | public uint Length { get; private set; }
21 |
22 | public BinarySearchTree()
23 | {
24 | Root = null;
25 | Length = 0;
26 | }
27 |
28 | public void Insert(T value)
29 | {
30 | if (Root != null)
31 | {
32 | InsertValue(Root, value);
33 | }
34 | else
35 | {
36 | Root = new TreeNode(value);
37 | }
38 | Length++;
39 | }
40 |
41 | private void InsertValue(TreeNode node, T value)
42 | {
43 | if (value.CompareTo(node.Value) < 0)
44 | {
45 | if (node.Left != null)
46 | InsertValue(node.Left, value);
47 | else
48 | node.Left = new TreeNode(value);
49 | }
50 | else
51 | {
52 | if (node.Right != null)
53 | InsertValue(node.Right, value);
54 | else
55 | node.Right = new TreeNode(value);
56 | }
57 | }
58 |
59 | public void Delete(T value)
60 | {
61 | Root = DeleteNode(Root, value);
62 | Length--;
63 | }
64 |
65 | private TreeNode DeleteNode(TreeNode node, T value)
66 | {
67 | if (node == null)
68 | return null;
69 |
70 | int compare = value.CompareTo(node.Value);
71 | if (compare < 0)
72 | node.Left = DeleteNode(node.Left, value);
73 | else if (compare > 0)
74 | node.Right = DeleteNode(node.Right, value);
75 | else
76 | {
77 | if (node.Left == null)
78 | return node.Right;
79 | else if (node.Right == null)
80 | return node.Left;
81 |
82 | TreeNode minNode = FindMin(node.Right);
83 | node.Value = minNode.Value;
84 | node.Right = DeleteNode(node.Right, minNode.Value);
85 | }
86 | return node;
87 | }
88 |
89 | private TreeNode FindMin(TreeNode node)
90 | {
91 | TreeNode current = node;
92 | while (current.Left != null)
93 | {
94 | current = current.Left;
95 | }
96 | return current;
97 | }
98 |
99 | public List GetAll()
100 | {
101 | var all = new List();
102 | InOrderTraversal(Root, all);
103 | return all;
104 | }
105 |
106 | private void InOrderTraversal(TreeNode node, List all)
107 | {
108 | if (node == null) return;
109 |
110 | InOrderTraversal(node.Left, all);
111 | all.Add(node.Value);
112 | InOrderTraversal(node.Right, all);
113 | }
114 |
115 | public void Clear()
116 | {
117 | Root = null;
118 | Length = 0;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/rust/src/graphs/bellman_ford.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use crate::graphs::graph::{ Graph, Node };
4 |
5 | impl Graph {
6 | pub fn bellman_ford_shortest_path(&self, from_node: &Node, to_node: &Node) -> Option {
7 | if self.nodes.len() == 0 {
8 | return Some(0);
9 | }
10 |
11 | let mut distances = self.nodes
12 | .iter()
13 | .map(|node| (node.index, isize::MAX))
14 | .collect::>();
15 |
16 | distances.insert(from_node.index, 0);
17 |
18 | let mut updated = true;
19 | for _ in 0..self.nodes.len() - 1 {
20 | if !updated {
21 | break;
22 | }
23 | updated = false;
24 |
25 | for node_edges in self.edges.iter() {
26 | let node_index = node_edges.0;
27 | let cost = *distances.get(node_index).unwrap_or(&isize::MAX);
28 |
29 | for edge in node_edges.1.iter() {
30 | if cost + edge.cost < *distances.get(&edge.node_index).unwrap_or(&isize::MAX) {
31 | distances.insert(edge.node_index, cost + edge.cost);
32 | updated = true;
33 | }
34 | }
35 | }
36 | }
37 |
38 | for node_edges in self.edges.iter() {
39 | let cost = *distances.get(node_edges.0).unwrap_or(&isize::MAX);
40 |
41 | for edge in node_edges.1.iter() {
42 | if cost + edge.cost < *distances.get(&edge.node_index).unwrap_or(&isize::MAX) {
43 | return None;
44 | }
45 | }
46 | }
47 |
48 | distances.get(&to_node.index)
49 | .copied()
50 | .filter(|&distance| distance != isize::MAX)
51 | }
52 | }
53 |
54 |
55 | #[cfg(test)]
56 | mod tests {
57 | use crate::graphs::GraphType;
58 |
59 | use super::*;
60 |
61 | #[test]
62 | fn find_path() {
63 | let mut graph = Graph::new(GraphType::Directed);
64 | let n1 = graph.add_node("А");
65 | let n2 = graph.add_node("B");
66 | let n3 = graph.add_node("C");
67 |
68 | graph.add_edge(n1, n2, 5);
69 | graph.add_edge(n1, n3, 4);
70 | graph.add_edge(n2, n3, -2);
71 |
72 | let node1 = graph.get_node(n1).unwrap();
73 | let node3 = graph.get_node(n3).unwrap();
74 |
75 | assert_eq!(graph.bellman_ford_shortest_path(node1, node3), Some(3));
76 | }
77 |
78 | #[test]
79 | fn negative_cycle() {
80 | let mut graph = Graph::new(GraphType::Directed);
81 | let n1 = graph.add_node(1);
82 | let n2 = graph.add_node(2);
83 |
84 | graph.add_edge(n1, n1, -1);
85 |
86 | let node1 = graph.get_node(n1).unwrap();
87 | let node2 = graph.get_node(n2).unwrap();
88 |
89 | assert_eq!(graph.bellman_ford_shortest_path(node1, node2), None);
90 | }
91 |
92 | #[test]
93 | fn test_path_to_self() {
94 | let mut graph = Graph::new(GraphType::Directed);
95 | let n1 = graph.add_node(1);
96 |
97 | let node1 = graph.get_node(n1).unwrap();
98 |
99 | assert_eq!(graph.bellman_ford_shortest_path(node1, node1), Some(0));
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/csharp/Dijkstra/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 |
3 | namespace Dijkstra;
4 |
5 | public static class GraphExtensions
6 | {
7 | public static int DijkstraShortestPath(this Graph graph, Node from, Node to)
8 | {
9 | // Initialize a dictionary to store the shortest distance from the 'from' node to every other node.
10 | // Initially, the distance to the 'from' node is 0 and infinity (int.MaxValue) to all other nodes.
11 | // 'from' node is 0 because we start from this node
12 | var distances = graph.Nodes.ToDictionary(key => key, value =>
13 | {
14 | return value == from ? 0 : int.MaxValue;
15 | });
16 |
17 | // HashSet to keep track of visited nodes to avoid reprocessing.
18 | var visited = new HashSet>();
19 |
20 | // PriorityQueue to select the node with the minimum distance for processing next.
21 | // It stores pairs of (Node, Distance) and sorts them by Distance.
22 | var queue = new PriorityQueue<(Node, int), int>();
23 | queue.Enqueue((from, 0), 0);
24 |
25 | while (queue.Count > 0)
26 | {
27 | // Dequeue the node with the smallest known distance.
28 | // On first step this is 'from' node with 0
29 | var dequeueItem = queue.Dequeue();
30 | var node = dequeueItem.Item1;
31 | var cost = dequeueItem.Item2;
32 |
33 | // Check if the current node has adjacent nodes.
34 | if (graph.Edges.TryGetValue(node, out var edges))
35 | {
36 | // For each adjacent node, calculate the distance through the current node.
37 | foreach (var edge in edges)
38 | {
39 | // This line checks if the current path to the adjacent node (edge.Node) is shorter than any previously found paths
40 | // The 'distances.TryGetValue(edge.Node, out int value)' attempts to get the current shortest known distance to the adjacent node
41 | // The 'cost > value' part checks if the current total cost to reach 'edge.Node'
42 | // via the current node is greater than this known shortest distance ('value')
43 | // If it is, this means that the current path is not shorter than the already known path to 'edge.Node',and we skip
44 | if (!distances.TryGetValue(edge.Node, out int value) || cost > value)
45 | continue;
46 |
47 | // If the path through the current node is shorter, update the distance of the adjacent node.
48 | if ((cost + edge.Cost) < distances[edge.Node])
49 | {
50 | var newCost = cost + edge.Cost;
51 | distances[edge.Node] = newCost;
52 |
53 | // If the adjacent node is unvisited, add it to the queue for further processing.
54 | if (!visited.Contains(edge.Node))
55 | {
56 | queue.Enqueue((edge.Node, newCost), newCost);
57 | }
58 | }
59 | }
60 | // Mark the current node as visited
61 | visited.Add(node);
62 | }
63 | }
64 |
65 | // After processing all nodes, retrieve the shortest path distance to the 'to' node
66 | // If this distance is still int.MaxValue, it means there's no path from 'from' node to 'to' node
67 | distances.TryGetValue(to, out int shortestPath);
68 | if (shortestPath == int.MaxValue)
69 | {
70 | // handle the case where no path exists
71 | }
72 | return shortestPath;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/rust/src/graphs/kosaraju.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashSet;
2 |
3 | use crate::graphs::graph::{ Graph, NodeIndex };
4 |
5 | impl Graph {
6 | pub fn kosaraju_scc(&self) -> Vec> {
7 | if self.nodes.len() == 0 {
8 | return vec![];
9 | }
10 |
11 | let mut visited: HashSet = HashSet::new();
12 | let mut stack: Vec = Vec::new();
13 |
14 | for node in self.nodes.iter() {
15 | if !visited.contains(&node.index) {
16 | self.initial_dfs(&node.index, &mut visited, &mut stack);
17 | }
18 | }
19 |
20 | visited.clear();
21 | let mut components: Vec> = Vec::new();
22 |
23 | while let Some(node_index) = stack.pop() {
24 | if !visited.contains(&node_index) {
25 | let mut component = Vec::new();
26 | self.dfs_scc(&node_index, &mut visited, &mut component);
27 | components.push(component);
28 | }
29 | }
30 |
31 | components
32 | }
33 |
34 | fn initial_dfs(&self, node_index: &NodeIndex, visited: &mut HashSet, stack: &mut Vec) {
35 | if visited.contains(&node_index) {
36 | return;
37 | }
38 |
39 | visited.insert(*node_index);
40 |
41 | if let Some(edges) = self.edges.get(&node_index) {
42 | for edge in edges {
43 | self.initial_dfs(&edge.node_index, visited, stack);
44 | }
45 | }
46 |
47 | stack.push(*node_index);
48 | }
49 |
50 | fn dfs_scc(&self, node_index: &NodeIndex, visited: &mut HashSet, component: &mut Vec) {
51 | if visited.contains(&node_index) {
52 | return;
53 | }
54 |
55 | visited.insert(*node_index);
56 |
57 | if let Some(edges) = self.edges.get(&node_index) {
58 | for edge in edges {
59 | self.dfs_scc(&edge.node_index, visited, component);
60 | }
61 | }
62 |
63 | component.push(*node_index);
64 | }
65 | }
66 |
67 |
68 | #[cfg(test)]
69 | mod tests {
70 | use crate::graphs::graph::{Graph, GraphType, Node, NodeIndex, Edge};
71 |
72 | fn create_test_graph(edges: Vec<(usize, usize)>) -> Graph {
73 | let mut graph = Graph::new(GraphType::Directed);
74 |
75 | for (from, to) in edges {
76 | graph.nodes.push(Node {
77 | value: from as i32,
78 | index: NodeIndex { ix: from },
79 | });
80 | graph.edges.entry(NodeIndex { ix: from })
81 | .or_insert_with(Vec::new)
82 | .push(Edge {
83 | cost: 1,
84 | node_index: NodeIndex { ix: to },
85 | });
86 | }
87 |
88 | graph
89 | }
90 |
91 | #[test]
92 | fn empty_graph() {
93 | let graph: Graph = Graph::new(GraphType::Undirected);
94 | let scc = graph.kosaraju_scc();
95 | assert!(scc.is_empty());
96 | }
97 |
98 | #[test]
99 | fn multiple_sccs() {
100 | let graph = create_test_graph(vec![(0, 1), (1, 2), (2, 0), (3, 4)]);
101 | let scc = graph.kosaraju_scc();
102 | assert_eq!(scc.len(), 2);
103 | }
104 |
105 | #[test]
106 | fn single_node_graph() {
107 | let graph = create_test_graph(vec![(0, 0)]);
108 | let scc = graph.kosaraju_scc();
109 | assert_eq!(scc.len(), 1);
110 | }
111 |
112 | #[test]
113 | fn disconnected_graph() {
114 | let graph = create_test_graph(vec![(0, 1), (2, 3)]);
115 | let scc = graph.kosaraju_scc();
116 | assert_eq!(scc.len(), 2);
117 | }
118 |
119 | #[test]
120 | fn cycle_graph() {
121 | let graph = create_test_graph(vec![(0, 1), (1, 2), (2, 0)]);
122 | let scc = graph.kosaraju_scc();
123 | assert_eq!(scc.len(), 1);
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/csharp/Floyd–Warshall/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 |
3 | namespace Floyd_Warshall;
4 |
5 | public static class GraphExtensions
6 | {
7 | public static int FloydWarshallShortestPath(this Graph graph, Node from, Node to)
8 | {
9 | var vertices = graph.Nodes.Count;
10 |
11 | // Create a map of each node to an integer index. This mapping is crucial for
12 | // using a 2D array to represent the distances between each pair of nodes.
13 | var nodesIndexes = GetNodesIndexes(graph);
14 |
15 | // Initialize a 2D array to store the shortest distances between each pair of vertices.
16 | // This array will be updated throughout the algorithm to reflect the shortest known distances.
17 | var distances = new int[vertices, vertices];
18 |
19 | // Initialize the distances array.
20 | // The distance from a node to itself is 0; for all other nodes, it is initially set to 'int.MaxValue'.
21 | // This represents that initially, the shortest distance to these nodes is unknown (infinite).
22 | for (var row = 0; row < distances.GetLength(0); row++)
23 | {
24 | for (var column = 0; column < distances.GetLength(1); column++)
25 | {
26 | if (row == column)
27 | distances[row, column] = 0;
28 | else
29 | distances[row, column] = int.MaxValue;
30 | }
31 | }
32 |
33 | // Populate the distances array with the direct distances between nodes as per the graph's edges.
34 | // Sets up the base cases for the algorithm, representing the initial known distances.
35 | foreach (var nodeEdges in graph.Edges)
36 | {
37 | var source = nodesIndexes[nodeEdges.Key];
38 | foreach (var edge in nodeEdges.Value)
39 | {
40 | var destination = nodesIndexes[edge.Node];
41 | distances[source, destination] = edge.Cost;
42 | }
43 | }
44 |
45 | // Three nested loops iterate over all triplets of vertices (source, intermediate, destination).
46 | // We check if the path from source to destination via an intermediate vertex is shorter than the current known path.
47 | for (int intermediateVertex = 0; intermediateVertex < vertices; intermediateVertex++)
48 | {
49 | for (int sourceVertex = 0; sourceVertex < vertices; sourceVertex++)
50 | {
51 | for (int destinationVertex = 0; destinationVertex < vertices; destinationVertex++)
52 | {
53 | // Skip if the path from source to intermediate or intermediate to destination is infinite.
54 | // This means that there is no path between nodes.
55 | if (distances[sourceVertex, intermediateVertex] == int.MaxValue ||
56 | distances[intermediateVertex, destinationVertex] == int.MaxValue)
57 | {
58 | continue;
59 | }
60 |
61 | // Update the distance if a shorter path is found via the intermediate vertex.
62 | if (distances[sourceVertex, intermediateVertex] + distances[intermediateVertex, destinationVertex] < distances[sourceVertex, destinationVertex])
63 | distances[sourceVertex, destinationVertex] = distances[sourceVertex, intermediateVertex] + distances[intermediateVertex, destinationVertex];
64 | }
65 | }
66 | }
67 |
68 | return distances[nodesIndexes[from], nodesIndexes[to]];
69 | }
70 |
71 | private static IDictionary, int> GetNodesIndexes(Graph graph)
72 | {
73 | var nodesIndex = new Dictionary, int>();
74 | int index = 0;
75 |
76 | // Creating a node-index mapping is necessary to translate the graph's node references to array indices.
77 | // This mapping simplifies the algorithm's operations on the distances array.
78 | foreach (var node in graph.Nodes)
79 | {
80 | nodesIndex[node] = index++;
81 | }
82 | return nodesIndex;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/csharp/Kosaraju/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Graphs;
2 |
3 | namespace Kosaraju;
4 |
5 | public static class GraphExtensions
6 | {
7 | public static List>> KosarajuSCCs(this Graph graph)
8 | {
9 | // Initialize a list to store the strongly connected components.
10 | var SCCs = new List>>();
11 |
12 | if (graph.Nodes.Count == 0)
13 | {
14 | return SCCs;
15 | }
16 |
17 | var reverseGraph = new Graph(graph.GraphType);
18 |
19 | var visited = new HashSet>();
20 | var stack = new Stack>();
21 |
22 | // Perform the first DFS on the original graph.
23 | // The purpose of this DFS is to fill the stack with nodes in the order of their finishing times.
24 | // This is important for the second DFS phase, where nodes are processed in this order to identify SCCs.
25 | foreach (var node in graph.Nodes)
26 | {
27 | if (visited.Contains(node))
28 | {
29 | continue;
30 | }
31 | Dfs(node, stack, visited);
32 | }
33 |
34 | Stack> Dfs(Node node, Stack> stack, HashSet> visited)
35 | {
36 | if (visited.Contains(node))
37 | {
38 | return stack;
39 | }
40 |
41 | visited.Add(node);
42 |
43 | var hasEdges = graph.Edges.TryGetValue(node, out var edges);
44 | if (hasEdges && edges.Count > 0)
45 | {
46 | foreach (var edge in edges)
47 | {
48 | Dfs(edge.Node, stack, visited);
49 | }
50 | }
51 |
52 | stack.Push(node);
53 | return stack;
54 | }
55 |
56 | // Construct a mapping of incoming edges for each node.
57 | // This map will be used in the second DFS, where we need to traverse the graph in the 'reverse' direction without explicitly creating a reversed graph.
58 | var incomingEdges = new Dictionary, List>>();
59 | foreach (var node in graph.Nodes)
60 | {
61 | if (graph.Edges.TryGetValue(node, out var edges))
62 | {
63 | foreach (var edge in edges)
64 | {
65 | if (!incomingEdges.ContainsKey(edge.Node))
66 | incomingEdges[edge.Node] = new List>();
67 | incomingEdges[edge.Node].Add(node);
68 | }
69 | }
70 | }
71 |
72 | // Reset the visited set for the second DFS.
73 | visited.Clear();
74 |
75 | // Perform the second DFS using the stack filled during the first DFS. This DFS is done in the reverse
76 | // order of node completion from the first DFS. It uses the incoming edges map to traverse the graph in reverse.
77 | // This step is crucial for identifying SCCs, as nodes in an SCC will be reachable from each other in this reverse traversal.
78 | while (stack.Count != 0)
79 | {
80 | var node = stack.Pop();
81 | if (!visited.Contains(node))
82 | {
83 | var component = new List>();
84 | ReverseDfs(node, component, incomingEdges);
85 |
86 | SCCs.Add(component);
87 | }
88 | }
89 |
90 | // The ReverseDfs method recursively explores nodes using the incoming edges map.
91 | // Nodes are added to the current component if they are reachable in this reversed context.
92 | // This effectively groups nodes of the same SCC together.
93 | void ReverseDfs(Node node, List> component, Dictionary, List>> edges)
94 | {
95 | if (visited.Contains(node)) return;
96 |
97 | visited.Add(node);
98 | component.Add(node);
99 |
100 | if (edges.TryGetValue(node, out var predecessors))
101 | {
102 | foreach (var pred in predecessors)
103 | {
104 | ReverseDfs(pred, component, edges);
105 | }
106 | }
107 | }
108 |
109 | return SCCs;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/rust/src/data_structures/linked_list.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | use std::ptr::NonNull;
3 |
4 | #[derive(Eq, PartialEq, Clone, Copy)]
5 | pub struct Node {
6 | pub value: N,
7 | pub next: Option>>,
8 | prev: Option>>
9 | }
10 |
11 | pub struct LinkedList {
12 | pub head: Option>>,
13 | pub tail: Option>>,
14 | pub length: usize,
15 | }
16 |
17 | impl LinkedList {
18 | pub fn new() -> Self {
19 | LinkedList {
20 | head: None,
21 | tail: None,
22 | length: 0
23 | }
24 | }
25 |
26 | pub fn is_empty(&self) -> bool {
27 | self.length == 0
28 | }
29 |
30 | pub fn add(&mut self, value: N) {
31 | let node: Node = Node {
32 | value,
33 | next: None,
34 | prev: self.tail
35 | };
36 |
37 | unsafe {
38 | self.add_node(node);
39 | }
40 | self.length += 1;
41 | }
42 |
43 | unsafe fn add_node(&mut self, node: Node) {
44 | let node_box = Box::new(node);
45 | let node_ptr = NonNull::new(Box::into_raw(node_box));
46 |
47 | match self.tail {
48 | Some(tail) => {
49 | (*tail.as_ptr()).next = node_ptr;
50 | self.tail = node_ptr;
51 | },
52 | None => {
53 | self.head = node_ptr;
54 | self.tail = node_ptr;
55 | }
56 | }
57 | }
58 |
59 | pub fn get_all(&self) -> Vec {
60 | let node: Option>> = self.head;
61 |
62 | let result: Vec;
63 | unsafe {
64 | match self.get_all_nodes_values(node) {
65 | Some(v) => result = v,
66 | None => result = vec![]
67 | };
68 | }
69 | result
70 | }
71 |
72 | unsafe fn get_all_nodes_values(&self, mut node: Option>>) -> Option> {
73 | let mut vec: Vec = vec![];
74 | loop {
75 | match node {
76 | Some(n) => {
77 | let current_node = &(*n.as_ptr());
78 | vec.push(current_node.value.clone());
79 | node = current_node.next;
80 | },
81 | None => break
82 | }
83 | }
84 | Some(vec)
85 | }
86 |
87 | pub fn delete(&mut self, value: N) {
88 | if self.is_empty() {
89 | return;
90 | }
91 |
92 | let node: Option>> = self.head;
93 | unsafe {
94 | self.delete_node(value, node);
95 | }
96 | }
97 |
98 | unsafe fn delete_node(&mut self, value: N, mut node: Option>>) {
99 | while let Some(current_node) = node {
100 | if current_node.as_ref().value == value {
101 | let old_ptr = Box::from_raw(current_node.as_ptr());
102 |
103 | if let Some(mut prev) = old_ptr.prev {
104 | prev.as_mut().next = old_ptr.next;
105 | }
106 |
107 | if let Some(mut next) = old_ptr.next {
108 | next.as_mut().prev = old_ptr.prev;
109 | }
110 |
111 | self.length -= 1;
112 | break;
113 | }
114 | node = (*current_node.as_ptr()).next;
115 | }
116 | }
117 |
118 | pub fn clear(&mut self) {
119 | unsafe {
120 | self.clear_all_nodes();
121 | }
122 |
123 | self.head = None;
124 | self.tail = None;
125 | self.length = 0;
126 | }
127 |
128 | unsafe fn clear_all_nodes(&mut self) {
129 | while let Some(node) = self.head {
130 | let boxed_node = Box::from_raw(node.as_ptr());
131 | self.head = boxed_node.next;
132 | }
133 | }
134 | }
135 |
136 | impl Drop for LinkedList {
137 | fn drop(&mut self) {
138 | while let Some(node) = self.head {
139 | unsafe {
140 | let boxed_node = Box::from_raw(node.as_ptr());
141 | self.head = boxed_node.next;
142 | }
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/rust/src/data_structures/heap.rs:
--------------------------------------------------------------------------------
1 | #[derive(PartialEq)]
2 | pub enum HeapType {
3 | Min,
4 | Max
5 | }
6 |
7 | pub struct Heap {
8 | data: Vec,
9 | heap_type: HeapType
10 | }
11 |
12 | impl