A documentation-first C# library implementing foundational linear, tree, and graph structures.
The library is designed to emphasise:
-
Clear and deliberate documentation.
-
Foundational design principles:
- architectural boundaries
- clear separation of responsibilities between layers
- appropriate encapsulation
-
Explicit consideration of design tradeoffs.
-
Explicit consideration of time and space complexity.
To support this, the library deliberately includes non-standard implementations of certain structures, and each source file includes an in-depth documentation block.
Each source file documentation block includes the following sections:
- Role
- Invariants
- Methods (if the class includes any)
- Design Discussion
The library divides into three areas:
- (A) Linear structures
- (B) Tree structures
- (C) Graph structures
Each area is structured as one or more conceptual flows.
(A) Linear structures:
- (A.i)
SimpleNode<T>=>SinglyLinkedList<T>=>Queue<T>andStack<T> - (A.ii)
ComplexNode<T>=>DoublyLinkedList<T>=>Deque<T> - (A.iii)
ArrayDeque<T>
(B) Tree structures:
- (B.i)
GeneralTreeNode<T>=>GeneralTree<T>=>ComposedBinaryTree<T> - (B.ii)
BinaryTreeNode<T>=>BinaryTree<T>=>BinarySearchTree<T>andMinHeap<T> - (B.iii)
ArrayMinHeap<T>
(C) Graph structures:
- (C.i)
GraphNode<T>=>Graph<T>
The library was developed in the order presented here. Whilst each flow can be considered independently, the source files are most naturally read sequentially. Design tradeoffs in earlier flows often inform later implementation decisions.
-
To check equality of
Tobjectsxandy,EqualityComparer<T>.Default.Equals(x, y)is used. -
To check identity of node references,
==is used.
-
Each node class is a minimal, low-level container. It contains no methods and is entirely managed by a certain higher-level class. A node consists of a Value and pointers to other nodes of the same kind (pointers vary in arity and directionality, depending on the node type).
-
Each node class instance belongs to at most one instance of the relevant higher-level class. Removed nodes become unowned and cannot be added to another instance of the higher-level class.
-
Compiler warnings concerning nullability have been disabled. Logic guarantees that whenever an expression is required to be non-null, it is.
-
In production, the null-forgiving operator
!is recommended. This is avoided here to reduce noise. -
Variables declared as non-nullable but initialised later are set with
null!to avoid definite assignment errors (CS0165). -
varis avoided to keep types explicit.