C#: an ordered index with SortedSet
Answer range, minimum, maximum, and nearest-value queries on sorted keys.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var ages = new SortedSet<int> { 31, 24, 45, 29 };
Console.WriteLine("min " + ages.Min + " max " + ages.Max);
Console.WriteLine("range 25..40: " + string.Join(" ", ages.GetViewBetween(25, 40)));
int floor = ages.GetViewBetween(int.MinValue, 30).Max;
int ceiling = ages.GetViewBetween(30, int.MaxValue).Min;
Console.WriteLine("floor(30)=" + floor + " ceiling(30)=" + ceiling);
}
}min 24 max 45 range 25..40: 29 31 floor(30)=29 ceiling(30)=31
Explanation
A database index that keeps keys in order can answer range queries and nearest-value queries without scanning every row. SortedSet<T> is a collection of unique values stored in a balanced tree, so adding, removing, and finding take O(log n).
Min and Max return the smallest and largest elements. GetViewBetween returns a live view of the elements inside a range, without copying them. The nearest value at or below a key is the maximum of the view from the smallest possible value up to the key, and the nearest at or above is the minimum of the view from the key to the largest possible value.
Explore the dry run
using System;using System.Collections.Generic; class Program { static void Main() { var ages = new SortedSet<int> { 31, 24, 45, 29 }; Console.WriteLine("min " + ages.Min + " max " + ages.Max); Console.WriteLine("range 25..40: " + string.Join(" ", ages.GetViewBetween(25, 40))); int floor = ages.GetViewBetween(int.MinValue, 30).Max; int ceiling = ages.GetViewBetween(30, int.MaxValue).Min; Console.WriteLine("floor(30)=" + floor + " ceiling(30)=" + ceiling); }}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Values are kept sorted as they are added: 24, 29, 31, 45. | ages = {24, 29, 31, 45} | — | |
| The ends of the sorted order. | ages = {24, 29, 31, 45} | min 24 max 45 | |
| A view over the keys from 25 through 40. | ages = {24, 29, 31, 45} | min 24 max 45 range 25..40: 29 31 | |
| The largest key at or below 30 is 29; the smallest at or above is 31. | ages = {24, 29, 31, 45} | min 24 max 45 range 25..40: 29 31 floor(30)=29 ceiling(30)=31 |
Cost and common mistakes
Add, Remove, and Contains are O(log n); a range view is created in O(log n) and enumerated in O(k).
- Calling Max on an empty view throws or returns the default value. Check Count first.
- A SortedSet stores unique values only. Use SortedDictionary or SortedList to attach a row to each key.
Try it yourself
How would you list the ages greater than 30?
Reveal answer and reasoning
Use ages.GetViewBetween(31, int.MaxValue); it contains 31 and 45.