Deque

One of the coolest data structures in the standard C++ library is the "deque". It keeps items close together like an array, which improves cache efficiency and like a linked list, it doesn’t need to perform a copy of all its items when it is enlarged beyond its current capacity. Despite this, it can be accessed by index like an array. It also supports fast removal or insertion of items both at the beginning and at the end of it and is thus usable as a stack or a queue.

Sadly, the deque data structure is missing in the .NET collection classes.

I discovered some deque implementations on the web, but those all seemed to be simple wrappers around .NET’s LinkedList<> class and not actual implementations of the deque data structure. So I decided to amend this situation:

UML diagram of my Deque class

Usage isn’t much different from a List<T> – here are some snippets:

Deque<string> strings = new Deque<string>();

// Adding to the end of a deque is fast. Even if the deque's block size is
// exceeded, unlike a List<> it doesn't need to copy its contents, so even
// in this case the spike is manageable.
for(int index = 0; index < 1024; ++index) {
  strings.AddLast("World");
}

// Adding to the beginning of a deque is also fast. The items do not have to
// be copied around in memory.
for(int index = 0; index < 1024; ++index) {
  strings.AddFirst("Hello");
}

// The deque can be very efficiently processed from one end to the other
while(strings.Count > 0) {
  Console.Write(strings.First);
  strings.RemoveFirst();
}

The deque is slightly slower than a List<> at some operations (accessing items by index, adding items with enough capacity remaining, removing items close to the middle) but eliminates most of the weak points of the List<> compared to the LinkedList<> class.

Features

  • Fully implements the IList<> and IList interfaces
  • Unit-tested code with 100% test coverage
  • Efficient implementation and lightning-fast enumerators

Benchmarks

Update: I’ve written some benchmarks that test my Deque versus .NET’s List<> and LinkedList<> classes. Here are the results (each measured with 250,000 items)

AddLast()

This is one operation all of the data structures can do easily:

AddFirst()

This is one requires the List<T> to shift its whole contents but can be done natively by the Deque<T> and LinkedList<T>:

AddRandom()

This one is tricky: it inserts new items at random places. The List<T> needs to shift all contents after the insertion point. The Deque<T> will shift either the contents before the insertion point or after the insertion point (depending on which involves fewer items). The LinkedList<T> doesn’t need to shift at all, but reaching the index is tricky – my benchmark checks whether it’s shorter to follow links from the beginning of the list, from the end of the list or from a point where the last insertion took place.

The Deque class is part of the Nuclex.Support library from the Nuclex Framework. You can find the most recent release of the code on the framework’s CodePlex site: http://nuclexframework.codeplex.com/