Foundations of Data Structures and Algorithms in C#
CSharp-DataStructures-Algorithms-Fundamentals is a focused, foundational repository written in C# that helps developers understand and implement the most essential data structures and algorithms through simple, self-contained examples. It was developed as a response to the scarcity of educational DSA content in C#, particularly when compared to the abundance of materials available in JavaScript, Python, or Java. This project mirrors the pedagogical structure of popular repositories in those languages, with a particular focus on readability and conceptual clarity rather than optimality or cleverness. What's Inside This repository covers a range of fundamental topics in data structures and algorithms, including: Arrays: Basic operations and manipulation techniques. Linked Lists: Implementation and traversal methods. Stacks and Queues: Understanding LIFO and FIFO structures. Trees: Binary trees, traversal algorithms, and more. Graphs: Representation and traversal techniques. Recursion: Solving problems through recursive approaches. Sorting Algorithms: Implementations of Bubble Sort, Insertion Sort, Merge Sort, Quick Sort, and more. Searching Algorithms: Linear and Binary Search methods. Hash Tables: Understanding hashing and collision resolution. Frequency Counters: Techniques for counting occurrences efficiently. Sliding Window: Optimizing problems involving subsets of data. Divide and Conquer: Breaking problems into subproblems for efficient solutions. Greedy Algorithms: Making optimal choices at each step. Dynamic Programming: Solving complex problems by breaking them down into simpler subproblems. Graph Algorithms: Including Dijkstra's algorithm for shortest paths. Each topic is presented with clear, concise examples to aid understanding. Motivation and Purpose The repository was created to address two key issues: The lack of beginner-friendly C# materials on DSA While countless tutorials and repositories exist for languages like JavaScript or Python, comparable resources in C# are rare. This project adapts proven learning structures to C#, offering a consistent and readable path through classic problems. To promote conceptual understanding over clever implementations Rather than diving into complex or optimal code, the examples here emphasize digestibility — making it easier for learners to grasp the logic behind each structure or algorithm before worrying about performance tuning. Target Audience Developers with little or no formal education in data structures and algorithms Bootcamp or self-taught programmers transitioning to more technical interviews C# developers seeking a clean, minimal reference for foundational concepts Interviewees needing a conceptual refresher on common DSA patterns in C# Mentors and educators looking for teachable, idiomatic examples Selected Examples The repository includes a variety of topics such as pointers, recursion, sorting, searching, and graph traversal. Below are three representative samples. 1. Count Unique Values (Multiple Pointers Pattern) namespace CSharp_DataStructures_Algorithms_Fundamentals { using System; public static partial class MultiplePointers { public static int CountUniqueValues(int[] arr) { if (arr.Length == 0) return 0; // Pointer for tracking unique values int i = 0; for (int j = 1; j
CSharp-DataStructures-Algorithms-Fundamentals is a focused, foundational repository written in C# that helps developers understand and implement the most essential data structures and algorithms through simple, self-contained examples.
It was developed as a response to the scarcity of educational DSA content in C#, particularly when compared to the abundance of materials available in JavaScript, Python, or Java. This project mirrors the pedagogical structure of popular repositories in those languages, with a particular focus on readability and conceptual clarity rather than optimality or cleverness.
What's Inside
This repository covers a range of fundamental topics in data structures and algorithms, including:
- Arrays: Basic operations and manipulation techniques.
- Linked Lists: Implementation and traversal methods.
- Stacks and Queues: Understanding LIFO and FIFO structures.
- Trees: Binary trees, traversal algorithms, and more.
- Graphs: Representation and traversal techniques.
- Recursion: Solving problems through recursive approaches.
- Sorting Algorithms: Implementations of Bubble Sort, Insertion Sort, Merge Sort, Quick Sort, and more.
- Searching Algorithms: Linear and Binary Search methods.
- Hash Tables: Understanding hashing and collision resolution.
- Frequency Counters: Techniques for counting occurrences efficiently.
- Sliding Window: Optimizing problems involving subsets of data.
- Divide and Conquer: Breaking problems into subproblems for efficient solutions.
- Greedy Algorithms: Making optimal choices at each step.
- Dynamic Programming: Solving complex problems by breaking them down into simpler subproblems.
- Graph Algorithms: Including Dijkstra's algorithm for shortest paths.
Each topic is presented with clear, concise examples to aid understanding.
Motivation and Purpose
The repository was created to address two key issues:
The lack of beginner-friendly C# materials on DSA
While countless tutorials and repositories exist for languages like JavaScript or Python, comparable resources in C# are rare. This project adapts proven learning structures to C#, offering a consistent and readable path through classic problems.To promote conceptual understanding over clever implementations
Rather than diving into complex or optimal code, the examples here emphasize digestibility — making it easier for learners to grasp the logic behind each structure or algorithm before worrying about performance tuning.
Target Audience
- Developers with little or no formal education in data structures and algorithms
- Bootcamp or self-taught programmers transitioning to more technical interviews
- C# developers seeking a clean, minimal reference for foundational concepts
- Interviewees needing a conceptual refresher on common DSA patterns in C#
- Mentors and educators looking for teachable, idiomatic examples
Selected Examples
The repository includes a variety of topics such as pointers, recursion, sorting, searching, and graph traversal. Below are three representative samples.
1. Count Unique Values (Multiple Pointers Pattern)
namespace CSharp_DataStructures_Algorithms_Fundamentals
{
using System;
public static partial class MultiplePointers
{
public static int CountUniqueValues(int[] arr)
{
if (arr.Length == 0) return 0;
// Pointer for tracking unique values
int i = 0;
for (int j = 1; j < arr.Length; j++)
{
// When two pointers point to different elements
if (arr[i] != arr[j])
{
i++; // Increment the pointer for unique values
arr[i] = arr[j]; // Assign current value to next unique slot
}
}
return i + 1; // Total unique values
}
}
}
Use Case: Counts the number of unique values in a sorted array.
Concepts Reinforced: Two-pointer technique, array traversal, in-place updates.
2. QuickSort (Divide and Conquer)
public static void QuickSort(int[] arr, int left, int right)
{
if (left < right)
{
// Find the pivot index
int pivotIndex = Pivot(arr, left, right);
// Sort left and right halves
QuickSort(arr, left, pivotIndex - 1);
QuickSort(arr, pivotIndex + 1, right);
}
}
// Example breakdown:
// QuickSort([4,6,9,1,2,5,3])
// Pivot = 4 → partitions array
// [3,2,1,4,6,9,5] → 4 is now in place
// Recurse on each side
/*
QuickSort(arr, left=0, right=6)
Pivot: 4, PivotIndex: 3
Array: { 3, 2, 1, 4, 9, 5, 6 }
├── QuickSort(arr, left=0, right=2)
│ Pivot: 3, PivotIndex: 2
│ Array: { 1, 2, 3, 4, 9, 5, 6 }
│
│ ├── QuickSort(arr, left=0, right=1)
│ │ Pivot: 1, PivotIndex: 0
│ │ Array: { 1, 2, 3, 4, 9, 5, 6 }
│ │ ├── QuickSort(arr, left=0, right=-1) → Return
│ │ └── QuickSort(arr, left=1, right=1) → Return
│
│ └── QuickSort(arr, left=3, right=2) → Return
│
└── QuickSort(arr, left=4, right=6)
Pivot: 9, PivotIndex: 6
Array: { 1, 2, 3, 4, 6, 5, 9 }
├── QuickSort(arr, left=4, right=5)
│ Pivot: 6, PivotIndex: 5
│ Array: { 1, 2, 3, 4, 5, 6, 9 }
│ ├── QuickSort(arr, left=4, right=4) → Return
│ └── QuickSort(arr, left=6, right=5) → Return
└── QuickSort(arr, left=7, right=6) → Return
*/
Use Case: In-place sorting of arrays via partitioning.
Concepts Reinforced: Recursion, divide-and-conquer strategy, pivot logic.
3. Dijkstra’s Algorithm (Graph Traversal with Priority Queue)
public List<string> Dijkstra(string start, string finish)
{
var nodes = new PriorityQueue<string>();
var distances = new Dictionary<string, int>();
var previous = new Dictionary<string, string?>();
var path = new List<string>();
foreach (var vertex in adjacencyList.Keys)
{
if (vertex == start)
{
distances[vertex] = 0;
nodes.Enqueue(vertex, 0);
}
else
{
distances[vertex] = int.MaxValue;
nodes.Enqueue(vertex, int.MaxValue);
}
previous[vertex] = null;
}
while (nodes.Count > 0)
{
var dequeuedNode = nodes.Dequeue();
var smallest = dequeuedNode.Item1;
if (smallest == finish)
{
while (previous[smallest] != null)
{
path.Add(smallest);
smallest = previous[smallest];
}
break;
}
if (distances[smallest] != int.MaxValue)
{
foreach (var edge in adjacencyList[smallest])
{
int candidate = distances[smallest] + edge.Weight;
if (candidate < distances[edge.Node])
{
distances[edge.Node] = candidate;
previous[edge.Node] = smallest;
nodes.Enqueue(edge.Node, candidate);
}
}
}
}
path.Add(start);
path.Reverse();
return path;
}
// Example: Dijkstra("A", "F")
// Shortest path: A → C → D → F
// Total cost: 5
/*
Initialization:
A distance = 0, other nodes = ∞
Priority queue: [A(0), B(∞), C(∞), D(∞), E(∞), F(∞)]
Step 1: Process A
A → B (4), A → C (2)
B updated to 4, C updated to 2
Priority queue: [C(2), B(4), D(∞), E(∞), F(∞)]
Step 2: Process C
C → D (2 + 2 = 4)
D updated to 4
Priority queue: [D(4), B(4), E(∞), F(∞)]
Step 3: Process B
B → E (4 + 3 = 7)
E updated to 7
Priority queue: [D(4), E(7), F(∞)]
Step 4: Process D
D → E (4 + 3 = 7) (no change)
D → F (4 + 1 = 5)
F updated to 5
Priority queue: [F(5), E(7)]
Step 5: Process F
F is the target, stop.
Path Reconstruction:
F → D → C → A
Reverse: A → C → D → F
Final Output
["A", "C", "D", "F"]
This is the shortest path from A to F, with a total cost of 5.
*/
Use Case: Computes the shortest path between two nodes in a weighted graph.
Concepts Reinforced: Graph traversal, priority queues, dictionaries, and path reconstruction.
Project Philosophy
This repository serves as a bridge between learning and implementation — it doesn’t aim to provide complete academic coverage of each topic, but instead prioritizes conceptual clarity and accessible code.
Each algorithm is written with readability in mind. More advanced topics such as recursion or graph traversal are broken down with commentary and examples, ensuring learners not only see the implementation but also understand the underlying mechanics.
Explore the Repository
If this collection supports your own study or helps you mentor others, consider:
⭐ Starring the GitHub repo