{"id":51272885,"url":"https://github.com/arcsymer/algorithms","last_synced_at":"2026-06-29T19:30:30.942Z","repository":{"id":366635408,"uuid":"1277053041","full_name":"arcsymer/algorithms","owner":"arcsymer","description":"Idiomatic C#/.NET 10 algorithms \u0026 data-structures library built from scratch — 11 structures, 16 algorithms, 129 tests, 7 Codility-style katas","archived":false,"fork":false,"pushed_at":"2026-06-22T16:28:49.000Z","size":39,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T18:18:39.578Z","etag":null,"topics":["algorithms","csharp","data-structures","dotnet","interview-prep","portfolio"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arcsymer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-22T14:37:37.000Z","updated_at":"2026-06-22T16:29:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/arcsymer/algorithms","commit_stats":null,"previous_names":["arcsymer/algorithms"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/arcsymer/algorithms","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcsymer%2Falgorithms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcsymer%2Falgorithms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcsymer%2Falgorithms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcsymer%2Falgorithms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arcsymer","download_url":"https://codeload.github.com/arcsymer/algorithms/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcsymer%2Falgorithms/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34941025,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","csharp","data-structures","dotnet","interview-prep","portfolio"],"created_at":"2026-06-29T19:30:27.630Z","updated_at":"2026-06-29T19:30:30.931Z","avatar_url":"https://github.com/arcsymer.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AlgoLib — Algorithms \u0026 Data Structures in C#\n\n\u003e A C# (.NET 10) library of classic data structures and algorithms, built from scratch with no external algorithmic dependencies.\n\n[![CI](https://img.shields.io/github/actions/workflow/status/arcsymer/algorithms/ci.yml?branch=main\u0026label=CI\u0026logo=github)](https://github.com/arcsymer/algorithms/actions/workflows/ci.yml)\n[![Tests](https://img.shields.io/badge/tests-265%20passing-brightgreen)](https://github.com/arcsymer/algorithms/actions)\n[![Coverage](https://img.shields.io/badge/line%20coverage-%7E94%25-brightgreen)](https://github.com/arcsymer/algorithms/actions)\n[![.NET](https://img.shields.io/badge/.NET-10.0-512BD4?logo=dotnet)](https://dotnet.microsoft.com/)\n\n---\n\n## What \u0026 Why\n\nAlgoLib implements 14 data structures and 23 algorithms in C# with generics, null-safety, and xUnit tests. I wrote it to keep my CS fundamentals sharp at interview depth (Codility/LeetCode tier), without hiding the complexity behind BCL wrappers.\n\nA few decisions worth noting:\n- Separate chaining for HashMap: simple, cache-friendly chains; load factor 0.75 triggers doubling.\n- Circular buffer for Queue/Deque: amortized O(1) at both ends without node allocation.\n- Floyd's heapify in the MinHeap constructor: O(n) build instead of O(n log n) repeated inserts.\n- Kahn's BFS for topological sort: cleaner cycle detection than DFS coloring.\n- Median-of-three pivot in QuickSort: avoids O(n²) on already-sorted inputs.\n- LRU Cache uses sentinel-head doubly-linked list + Dictionary: both Get and Put are strictly O(1).\n- Fenwick Tree (BIT) stores 1-indexed internally, exposes 0-indexed API: O(log n) update and prefix query, vs O(1) query of static prefix sums when the array changes between queries.\n- QuickSelect uses a random pivot (seeded for reproducibility) to defeat adversarial sorted-input worst cases.\n- Bellman-Ford relaxes V-1 times then runs a V-th pass to detect negative cycles; early exit when no update occurs in a pass.\n- Segment Tree (lazy propagation) defers range-add updates with a lazy array; pushes pending delta only when a node is actually visited, achieving O(log n) per range update and range query.\n- Rabin-Karp uses a rolling polynomial hash (base 131, mod 10^9+7) to slide the window in O(1) per step; falls back to character comparison only on hash match to handle collisions.\n- Z-function computes the Z-array in O(n) by maintaining a \"Z-box\" [l, r) — the rightmost interval where z[l] is known — reusing previous values without re-scanning.\n- Floyd-Warshall runs the standard DP relaxation in-place; the O(V³) loop is safe because dist[i][k] and dist[k][j] are fixed for the current k iteration.\n\n---\n\n## Contents\n\n### Data Structures (14)\n\n| Name | File |\n|---|---|\n| DynamicArray | `src/AlgoLib/DataStructures/DynamicArray.cs` |\n| SinglyLinkedList | `src/AlgoLib/DataStructures/SinglyLinkedList.cs` |\n| DoublyLinkedList | `src/AlgoLib/DataStructures/DoublyLinkedList.cs` |\n| Stack | `src/AlgoLib/DataStructures/Stack.cs` |\n| Queue | `src/AlgoLib/DataStructures/Queue.cs` |\n| Deque | `src/AlgoLib/DataStructures/Deque.cs` |\n| BinarySearchTree | `src/AlgoLib/DataStructures/BinarySearchTree.cs` |\n| MinHeap | `src/AlgoLib/DataStructures/MinHeap.cs` |\n| HashMap | `src/AlgoLib/DataStructures/HashMap.cs` |\n| UnionFind | `src/AlgoLib/DataStructures/UnionFind.cs` |\n| Trie | `src/AlgoLib/DataStructures/Trie.cs` |\n| **FenwickTree** (BIT) | `src/AlgoLib/DataStructures/FenwickTree.cs` |\n| **LruCache** | `src/AlgoLib/DataStructures/LruCache.cs` |\n| **SegmentTree** (lazy propagation) | `src/AlgoLib/DataStructures/SegmentTree.cs` |\n\n### Algorithms (23)\n\n| Name | File |\n|---|---|\n| QuickSort, MergeSort, HeapSort, CountingSort | `src/AlgoLib/Sorting/SortingAlgorithms.cs` |\n| BinarySearch, LowerBound, UpperBound, CountOccurrences | `src/AlgoLib/Searching/BinarySearch.cs` |\n| **QuickSelect** (KthSmallest / KthLargest) | `src/AlgoLib/Searching/QuickSelect.cs` |\n| BFS, DFS, Dijkstra, Topological Sort, **Bellman-Ford** | `src/AlgoLib/Graphs/GraphAlgorithms.cs` |\n| **Floyd-Warshall** (all-pairs shortest paths) | `src/AlgoLib/Graphs/FloydWarshall.cs` |\n| KMP Search | `src/AlgoLib/Strings/KmpSearch.cs` |\n| **Rabin-Karp** (rolling-hash search) | `src/AlgoLib/Strings/RabinKarp.cs` |\n| **Z-Function** (Z-array + pattern search + period) | `src/AlgoLib/Strings/ZFunction.cs` |\n| Two Pointers, Sliding Window, Prefix Sums, Kadane | `src/AlgoLib/Strings/ArrayTechniques.cs` |\n\n---\n\n## Complexity Reference Table\n\n### Data Structures\n\n| Structure | Operation | Time (avg) | Time (worst) | Space |\n|---|---|---|---|---|\n| **DynamicArray** | Get/Set by index | O(1) | O(1) | O(n) |\n| | Add (append) | O(1) amortized | O(n) grow | |\n| | Insert at index | O(n) | O(n) | |\n| | RemoveAt | O(n) | O(n) | |\n| | IndexOf | O(n) | O(n) | |\n| **SinglyLinkedList** | AddFirst / AddLast | O(1) | O(1) | O(n) |\n| | RemoveFirst | O(1) | O(1) | |\n| | RemoveLast | O(n) | O(n) | |\n| | Find | O(n) | O(n) | |\n| **DoublyLinkedList** | AddFirst / AddLast | O(1) | O(1) | O(n) |\n| | RemoveFirst / RemoveLast | O(1) | O(1) | |\n| | Remove(node) | O(1) | O(1) | |\n| | Find | O(n) | O(n) | |\n| **Stack** | Push / Pop / Peek | O(1) amortized | O(n) grow | O(n) |\n| **Queue** | Enqueue / Dequeue / Peek | O(1) amortized | O(n) grow | O(n) |\n| **Deque** | AddFront/Back, RemoveFront/Back | O(1) amortized | O(n) grow | O(n) |\n| **BinarySearchTree** | Insert / Contains / Remove | O(log n) | O(n) unbalanced | O(n) |\n| | Min / Max | O(log n) | O(n) | |\n| | InOrder traversal | O(n) | O(n) | |\n| **MinHeap** | Push | O(log n) | O(log n) | O(n) |\n| | Pop (extract min) | O(log n) | O(log n) | |\n| | Peek | O(1) | O(1) | |\n| | Build from n elements | O(n) | O(n) | |\n| **HashMap** | Put / Get / Remove | O(1) avg | O(n) worst | O(n) |\n| | ContainsKey | O(1) avg | O(n) worst | |\n| **UnionFind** | Find / Union / Connected | O(α(n)) | O(α(n)) | O(n) |\n| **Trie** | Insert / Search / StartsWith / Delete | O(L) | O(L) | O(α·N·L) |\n| **FenwickTree** | Update (point add) | O(log n) | O(log n) | O(n) |\n| | PrefixSum / RangeSum | O(log n) | O(log n) | |\n| | Build from array | O(n log n) | O(n log n) | |\n| **LruCache** | Get | O(1) | O(1) | O(capacity) |\n| | Put (with eviction) | O(1) | O(1) | |\n| **SegmentTree** | RangeAdd (lazy) | O(log n) | O(log n) | O(n) |\n| | RangeSum | O(log n) | O(log n) | |\n| | PointGet | O(log n) | O(log n) | |\n| | Build from array | O(n) | O(n) | |\n\nα(n) = inverse Ackermann — effectively O(1) in practice.  \nL = length of string key.\n\n---\n\n### Algorithms\n\n| Algorithm | Time | Space | Notes |\n|---|---|---|---|\n| **QuickSort** | O(n log n) avg | O(log n) | Median-of-three pivot; O(n²) worst case |\n| **MergeSort** | O(n log n) | O(n) | Stable; consistent in all cases |\n| **HeapSort** | O(n log n) | O(1) | In-place; not stable |\n| **CountingSort** | O(n + k) | O(n + k) | k = max value; integers only |\n| **BinarySearch** | O(log n) | O(1) | Sorted input required |\n| **LowerBound** | O(log n) | O(1) | First index ≥ target |\n| **UpperBound** | O(log n) | O(1) | First index \u003e target |\n| **CountOccurrences** | O(log n) | O(1) | Uses LowerBound + UpperBound |\n| **BFS** | O(V + E) | O(V) | Shortest path in unweighted graph |\n| **DFS** | O(V + E) | O(V) | Cycle detection, connectivity |\n| **Dijkstra** | O((V+E) log V) | O(V) | Non-negative weights; binary heap |\n| **Bellman-Ford** | O(V × E) | O(V) | Negative weights OK; detects negative cycles |\n| **Floyd-Warshall** | O(V³) | O(V²) | All-pairs shortest paths; detects negative cycles |\n| **Topological Sort** | O(V + E) | O(V) | Kahn's BFS algorithm; detects cycles |\n| **QuickSelect** | O(n) avg, O(n²) worst | O(n) copy + O(log n) stack | k-th smallest/largest; random pivot |\n| **KMP Search** | O(n + m) | O(m) | n = text, m = pattern length |\n| **Rabin-Karp** | O(n + m) avg, O(nm) worst | O(1) | Rolling polynomial hash; collision-safe |\n| **Z-Function** | O(n) build, O(n+m) search | O(n) | Z-box technique; also computes string period |\n| **Two Pointers** | O(n) | O(1) | Sorted array pair/range queries |\n| **Sliding Window** | O(n) | O(1) | Fixed or variable window; sum/length |\n| **Prefix Sums** | O(n) build, O(1) query | O(n) | Range sum in O(1) after preprocessing |\n| **Kadane** | O(n) | O(1) | Maximum subarray sum with index tracking |\n\n---\n\n## Katas (Codility-style)\n\nSeven worked problems, each with an annotated solution and complexity breakdown.\n\n| # | Problem | Key Technique | Time | Link |\n|---|---|---|---|---|\n| 01 | Two Sum | Hash Map | O(n) | [katas/01-two-sum.md](katas/01-two-sum.md) |\n| 02 | Maximum Subarray | Kadane's Algorithm | O(n) | [katas/02-max-subarray.md](katas/02-max-subarray.md) |\n| 03 | Search in Rotated Sorted Array | Modified Binary Search | O(log n) | [katas/03-binary-search-rotated.md](katas/03-binary-search-rotated.md) |\n| 04 | Number of Islands | BFS flood fill | O(R × C) | [katas/04-number-of-islands.md](katas/04-number-of-islands.md) |\n| 05 | Longest Substring Without Repeating | Sliding Window + Hash Map | O(n) | [katas/05-longest-substring-no-repeat.md](katas/05-longest-substring-no-repeat.md) |\n| 06 | Course Schedule | Kahn's Topological Sort | O(V + E) | [katas/06-course-schedule.md](katas/06-course-schedule.md) |\n| 07 | Word Dictionary | Trie (Prefix Tree) | O(L) per op | [katas/07-word-search-trie.md](katas/07-word-search-trie.md) |\n\n---\n\n## Build \u0026 Test\n\nRequires [.NET 10 SDK](https://dotnet.microsoft.com/download).\n\nThe SDK version is pinned via `global.json` (`10.0.300`, `rollForward: latestFeature`).\n\n```bash\n# Clone\ngit clone https://github.com/arcsymer/algorithms.git\ncd algorithms\n\n# Build the whole solution (Release, no warnings)\ndotnet build AlgoLib.slnx -c Release\n\n# Run all tests\ndotnet test -c Release\n\n# Run with line/branch coverage (coverlet.collector already in test project)\ndotnet test -c Release --collect:\"XPlat Code Coverage\" --results-directory TestResults\n```\n\nActual test output (Release):\n\n```\nBuild succeeded.\n    0 Warning(s)\n    0 Error(s)\n\nPassed!  - Failed: 0, Passed: 265, Skipped: 0, Total: 265, Duration: 274 ms - AlgoLib.Tests.dll (net10.0)\n```\n\n**265 tests** pass across 22 test files (xUnit `[Fact]` + `[Theory]`/`[InlineData]`), mirroring the `src/` structure.\n\nCoverage (Cobertura, via coverlet): **line ~94% / branch ~90%** (estimated).\n\n---\n\n## Demo\n\nA runnable console showcase (`src/AlgoLib.Demo`) prints results for the key structures and algorithms — sortings, BFS/DFS/topological sort, Dijkstra/Bellman-Ford/Floyd-Warshall, KMP/Rabin-Karp/Z-function, LRU cache, Trie, heap, union-find, BST, Fenwick/segment trees.\n\n```bash\ndotnet run --project src/AlgoLib.Demo -c Release\n```\n\nCaptured output: [`_Docs/screenshots/algorithms/demo.txt`](../_Docs/screenshots/algorithms/demo.txt).\n\n## NuGet package\n\nThe library ships package metadata and can be packed into a `.nupkg`:\n\n```bash\ndotnet pack src/AlgoLib/AlgoLib.csproj -c Release\n# -\u003e src/AlgoLib/bin/Release/AlgoLib.1.0.0.nupkg (+ AlgoLib.1.0.0.snupkg symbols)\n```\n\n`PackageId=AlgoLib`, `Version=1.0.0`, MIT-licensed, zero runtime dependencies, ships XML docs.\n\n---\n\n## Performance\n\nMeasured with a Stopwatch harness (`bench/Program.cs`) in Release mode on .NET 10.\nEach figure is the median of 5 runs; GC.Collect() called before each trial.\nHardware: Windows 11, Intel/AMD desktop (your mileage may vary by ±15%).\n\n### Sorting — n = 1 000 000 random ints\n\n| Algorithm | Median |\n|---|---|\n| QuickSort (median-of-three) | 98 ms |\n| MergeSort | 118 ms |\n| HeapSort | 130 ms |\n\nQuickSort is fastest in practice due to cache-locality of the in-place partition.\nHeapSort is slowest despite identical O(n log n) complexity — heap accesses jump around in memory.\n\n### QuickSelect — n = 1 000 000, k = N/2 (median)\n\n| Algorithm | Median |\n|---|---|\n| QuickSelect | 9 ms |\n\n~11× faster than full QuickSort for a single order-statistic query.\n\n### HashMap — n = 100 000\n\n| Operation | Median |\n|---|---|\n| Put (including 2 rehashes) | 6 ms |\n| Get (all hits, pre-filled) | 0 ms (\u003c 1 ms) |\n\n### LRU Cache — capacity = 1 000, ops = 100 000\n\n| Operation | Median |\n|---|---|\n| Put (evict-heavy: 99k evictions) | 2 ms |\n| Get (all hits, warm cache) | 1 ms |\n\n### Fenwick Tree — n = 1 000 000\n\n| Operation | Median |\n|---|---|\n| Build from array (n × Update) | 19 ms |\n| RangeSum query × 100 000 | \u003c 1 ms |\n| Update (point add) × 100 000 | 2 ms |\n\nFor comparison, `BuildPrefixSums` + `RangeSum` (O(1) query, no updates): \u003c 1 ms for 100 000 queries — identical throughput, but the static version cannot handle mid-stream updates.\n\n### Dijkstra vs Bellman-Ford — V = 500, sparse directed graph\n\n| Algorithm | Median |\n|---|---|\n| Dijkstra O((V+E) log V) | 10 µs |\n| Bellman-Ford O(V×E) | 19 µs |\n\nOn small sparse graphs the difference is modest; on dense graphs or large V Bellman-Ford degrades faster.\nUse Dijkstra when weights are non-negative; Bellman-Ford when negative weights or cycle detection are needed.\n\n---\n\n## Using AlgoLib as a Library\n\nReference the project directly (no NuGet package yet):\n\n```xml\n\u003c!-- In your .csproj --\u003e\n\u003cItemGroup\u003e\n  \u003cProjectReference Include=\"path/to/algorithms/src/AlgoLib/AlgoLib.csproj\" /\u003e\n\u003c/ItemGroup\u003e\n```\n\nExample usage:\n\n```csharp\nusing AlgoLib.DataStructures;\nusing AlgoLib.Sorting;\nusing AlgoLib.Searching;\nusing AlgoLib.Graphs;\nusing AlgoLib.Strings;\n\n// Generic MinHeap\nvar heap = new MinHeap\u003cint\u003e();\nheap.Push(5); heap.Push(1); heap.Push(3);\nConsole.WriteLine(heap.Pop()); // 1\n\n// In-place QuickSort (median-of-three pivot)\nint[] arr = { 9, 3, 7, 1, 5 };\nSortingAlgorithms.QuickSort(arr);\n// arr is now [1, 3, 5, 7, 9]\n\n// QuickSelect: 3rd smallest in O(n) average (original array untouched)\nint kth = QuickSelect.KthSmallest(new[] { 9, 3, 7, 1, 5 }, 3); // 5\n\n// LRU Cache (O(1) get/put)\nvar lru = new LruCache\u003cint, string\u003e(capacity: 2);\nlru.Put(1, \"one\"); lru.Put(2, \"two\");\nlru.Get(1);        // makes 1 MRU\nlru.Put(3, \"three\"); // evicts key 2 (LRU)\nConsole.WriteLine(lru.TryGet(2, out _)); // False — evicted\n\n// Fenwick Tree: point-update + range-sum in O(log n)\nvar bit = new FenwickTree(new long[] { 1, 3, 5, 7, 9 });\nConsole.WriteLine(bit.RangeSum(1, 3)); // 3+5+7 = 15\nbit.Update(2, +10);                    // arr[2] += 10 → now 15\nConsole.WriteLine(bit.RangeSum(1, 3)); // 3+15+7 = 25\n\n// Dijkstra shortest paths\nvar g = new WeightedGraph(5);\ng.AddEdge(0, 1, 4); g.AddEdge(0, 2, 1);\ng.AddEdge(2, 1, 2); g.AddEdge(1, 3, 1);\ndouble[] dist = GraphAlgorithms.Dijkstra(g, source: 0);\n// dist[3] == 4  (path: 0→2→1→3)\n\n// Bellman-Ford: handles negative weights\nvar g2 = new WeightedGraph(3);\ng2.AddEdge(0, 1, 4); g2.AddEdge(1, 2, -3);\ndouble[] bfDist = GraphAlgorithms.BellmanFord(g2, source: 0);\n// bfDist[2] == 1.0  (4 + (-3))\n\n// Trie\nvar trie = new Trie();\ntrie.Insert(\"hello\"); trie.Insert(\"world\");\nConsole.WriteLine(trie.StartsWith(\"hel\")); // True\nConsole.WriteLine(trie.Search(\"hell\"));    // False\n\n// Segment Tree: range add + range sum in O(log n)\nvar seg = new SegmentTree(new long[] { 1, 2, 3, 4, 5 });\nseg.RangeAdd(1, 3, 10);                       // arr[1..3] += 10 → [1,12,13,14,5]\nConsole.WriteLine(seg.RangeSum(1, 3));         // 39\nConsole.WriteLine(seg.PointGet(2));            // 13\n\n// Rabin-Karp rolling-hash search\nvar rkMatches = RabinKarp.Search(\"abababab\", \"abab\"); // [0, 2, 4]\n\n// Z-Function pattern search\nvar zMatches = ZFunction.Search(\"abababab\", \"abab\");  // [0, 2, 4]\nint period = ZFunction.ShortestPeriod(\"ababab\");      // 2\n\n// Floyd-Warshall all-pairs shortest paths\nvar g3 = new WeightedGraph(3);\ng3.AddEdge(0, 1, 1); g3.AddEdge(1, 2, 2); g3.AddEdge(0, 2, 4);\ndouble[][] allDist = FloydWarshall.Compute(g3);\n// allDist[0][2] == 3.0 (via 0→1→2, not direct 4)\nvar path = FloydWarshall.GetPath(g3, allDist, 0, 2); // [0, 1, 2]\n```\n\n---\n\n## Project Structure\n\n```\nalgorithms/\n├── src/AlgoLib/\n│   ├── DataStructures/   DynamicArray, SinglyLinkedList, DoublyLinkedList,\n│   │                     Stack, Queue, Deque, BinarySearchTree, MinHeap,\n│   │                     HashMap, UnionFind, Trie,\n│   │                     FenwickTree, LruCache, SegmentTree\n│   ├── Sorting/          SortingAlgorithms (QuickSort, MergeSort, HeapSort, CountingSort)\n│   ├── Searching/        BinarySearch (+ LowerBound, UpperBound, CountOccurrences),\n│   │                     QuickSelect (KthSmallest, KthLargest)\n│   ├── Graphs/           Graph, WeightedGraph,\n│   │                     GraphAlgorithms (BFS, DFS, Dijkstra, TopoSort, BellmanFord),\n│   │                     FloydWarshall (all-pairs shortest paths + path reconstruction)\n│   └── Strings/          KmpSearch, RabinKarp, ZFunction,\n│                         ArrayTechniques (TwoPointers, SlidingWindow, PrefixSums, Kadane)\n├── src/AlgoLib.Demo/     Runnable console showcase of the whole library\n├── tests/AlgoLib.Tests/  xUnit tests mirroring src structure (265 tests)\n├── bench/                Stopwatch micro-benchmark harness (median of N runs)\n├── katas/                7 Codility-style problem walkthroughs\n└── .github/workflows/    CI pipeline (dotnet build + test on push/PR)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcsymer%2Falgorithms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farcsymer%2Falgorithms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcsymer%2Falgorithms/lists"}