Click here to Skip to main content
15,885,366 members
Articles / Programming Languages / Visual Basic

.NET Deque

Rate me:
Please Sign up or sign in to vote.
4.10/5 (4 votes)
8 Nov 2007CPOL4 min read 40.5K   213   16   7
A .NET implementation of a Deque object.

Screenshot - DequeScreen.jpg

Introduction

Recently, I was working on a project that uses a buffer queue to send data across the network (yes, this would be my Winsock control). I needed to grab the next item in the queue, modify it, and then stick it back on the top of the queue.

As you all know, you can't do this with a Queue object, though you can do it with a Stack - but then, you can't preserve the FIFO method of the Queue. So, I resorted to using a Collection, and doing it manually.

While streamlining my control, I decided to combine the Stack and Queue together so it would be simple to do (not to mention read, when looking back through the code). I just couldn't seem to find anything on how to do this (quick Google searches).

I decided to combine the names and call it a Quack, but that's when my searches kicked in and I found out it was called a Deque (pronounced "deck"). I decided to check for any .NET implementations, but all I saw were C++ references. I already had mine made, so I decided to share it here.

This is a rather simple implementation of a Deque, and really quite simple to make yourself - however, the point of the article is to allow you to find the information in order to use it - whether you want to make your own implementation or not.

I have it implementing ICollection, IEnumerable, and ICloneable - just like the Stack and Queue objects. Everything is stored in a private, internal, generic LinkedList(Of Object).

** Update ** I have updated this to a more complete version of a Deque, as well as using a LinkedList for better performance. The operations now available were taken from the Deque entry at Wikipedia here[^], and include the following: PushBack, PushFront, PopBack, PopFront, PeekBack, and PeekFront.

Let's get on to the implementation and the use of it, shall we?

Stacks

Stacks use a last-in, first-out (LIFO) procedure. With stacks, you use the Push method to put an item onto the stack, and the Pop method to take an item off the stack.

Let's look at an example of this.

Suppose I put the numbers 1, 2, 3, and 4 into a stack - in that order, it might be visualized like this:

4
3
2
1

The I take one off using Pop. This would result in the 4 being taken off, and the stack looking like this:

3
2
1

Queues

A queue uses a first-in, first-out (FIFO) procedure. Here, you use the methods Enqueue and Dequeue to put an item into the queue, and take an item out of the queue, respectively.

Let's look at an example using the exact same procedure of adding 1, 2, 3, and 4 to the queue, in the same order. Here is how the queue would look:

1
2
3
4

Then, after taking an item off using Dequeue, I retrieve the 1, leaving me with a queue that looks like:

2
3
4

Building the class

As I'm using a LinkedList to store the items, we can refer to the Front and Back as the First and Last, respectively. The three methods Push, Pop, and Peek, all have two implementations, one for the front and one for the back.

VB
Public Sub PushBack(ByVal obj As Object)
    llList.AddLast(obj)
End Sub

Public Function PopBack(Of dataType)() As dataType
    Dim objRet As dataType = PeekBack(Of dataType)()
    llList.RemoveLast()
    Return objRet
End Function

Public Function PeekBack(Of dataType)() As dataType
    If llList.Count = 0 Then Return Nothing
    Return DirectCast(llList.Last().Value, dataType)
End Function

Notice how easy it is to add and remove to the end of the LinkedList. Adding and removing from the front is just as easy as using the AddFirst, RemoveFirst, and First methods of the LinkedList.

The biggest difficulty in creating this class was getting it to properly implement the three interfaces: ICollection, IEnumerable, and ICloneable. Fortunately though, the List was able to provide the abilities of those function. See the source code for more details.

Using the Code

Really, this is as simple to use as the Stack and Queue classes; if you know how to use them, you can use this.

But for those that don't know how to use them, here is a quick example of how to use this class. The state of the Deque after any given line is shown in the comments, with the top of the list being on the left.

VB
Dim q As New Deque
Dim objRet As Object
q.PushBack(1) ' 1
q.PushBack(2) ' 1, 2
q.PushBack(3) ' 1, 2, 3
q.PushBack(4) ' 1, 2, 3, 4
objRet = q.PopFront() ' 2, 3, 4
q.PushFront(-1) ' -1, 2, 3, 4
q.PushFront(9) ' 9, -1, 2, 3, 4
objRet = q.PopFront() ' -1, 2, 3, 4
objRet = q.PopBack() ' -1, 2, 3
objRet = q.PopFront() ' 2, 3
objRet = q.PopBack() ' 2
objRet = q.PopFront() '

Points of Interest

The example project "animated" various examples. This was very simply done using the Sleep method to hold the display for a bit, not to mention sort of fun to build. It graphically shows how a stack/queue/deque works.

Summary

I just made this as part of another project, and hope that others can benefit from my playing around with the code.

Have fun with your own coding projects!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralHi I Enhanced for better generic format usinf (OF T) for frame work 2.0 or greater ... Nice Code Tridex ... Pin
tridex2-Jan-08 4:08
tridex2-Jan-08 4:08 
Option Strict On
''' <summary>
''' Represents both a last-in, first-out (LIFO) and a first-in, first-out (FIFO) non-generic collection of objects.
''' </summary>
''' <remarks>
''' While the System.Collections.Stack and the System.Collections.Queue
''' have seemingly different ways of operating, they can be combined easily
''' by just manipulating the way in which an item in inserted into the list.
'''
''' This allows the removal from the list to remain the same, whether you
''' are treating this class like a Stack or a Queue. The also allows the
''' Peek() method to work for both at the same time.
'''
''' Helping tidbit - Deque is pronounced like "deck."
''' </remarks>
Public Class Deque(Of T) Mad | :mad:

Implements ICollection, IEnumerable(Of T), IEnumerable, ICloneable

#Region " Private Members "

''' <summary>
''' Stores the list of items within this instance.
''' </summary>
Private llList As LinkedList(Of T)

#End Region

#Region " Constructor "

''' <summary>
''' Initializes a new instance of the Deque class that is empty and has the default initial capacity.
''' </summary>
Public Sub New()

llList = New LinkedList(Of T)

End Sub

''' <summary>
''' Initializes a new instance of the Deque class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
''' </summary>
''' <param name="col">The collection whose elements are copied to the new Deque.</param>
Public Sub New(ByVal col As ICollection)

llList = New LinkedList(Of T)(CType(col, IEnumerable(Of T)))

End Sub

#End Region

#Region " Interface Method Implementations "

''' <summary>
''' Copies the entire Deque to a compatible one-dimensional array, starting at the specified index of the target array.
''' </summary>
''' <param name="array">The one-dimensional Array that is the destination of the elements copied from Deque. The Array must have zero-based indexing.</param>
''' <param name="index">The zero-based index in array at which copying begins.</param>
Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer) Implements System.Collections.ICollection.CopyTo
If array.Rank > 1 Then Throw New ArgumentException("Array must have only a single dimension.", "array")
llList.CopyTo(CType(array, T()), index)
End Sub

''' <summary>
''' Gets the number of elements actually contained in the Deque.
''' </summary>
''' <value>The number of elements actually contained in the Deque.</value>
Public ReadOnly Property Count() As Integer Implements System.Collections.ICollection.Count
Get
Return llList.Count
End Get
End Property

''' <summary>
''' Gets a value indicating whether access to the ICollection is synchronized (thread safe).
''' </summary>
''' <value>true if access to the ICollection is synchronized (thread safe); otherwise, false. In the default implementation of List, this property always returns false.</value>
Public ReadOnly Property IsSynchronized() As Boolean Implements System.Collections.ICollection.IsSynchronized
Get
Return CType(llList, ICollection).IsSynchronized
End Get
End Property

''' <summary>
''' Gets an object that can be used to synchronize access to the ICollection.
''' </summary>
''' <value>An object that can be used to synchronize access to the ICollection. In the default implementation of List, this property always returns the current instance.</value>
Public ReadOnly Property SyncRoot() As Object Implements System.Collections.ICollection.SyncRoot
Get
Return CType(llList, ICollection).SyncRoot
End Get
End Property

''' <summary>
''' Returns an enumerator that iterates through the Queue.
''' </summary>
Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator

Return llList.GetEnumerator()

End Function

Public Function GetEnumerator1() As System.Collections.Generic.IEnumerator(Of T) Implements System.Collections.Generic.IEnumerable(Of T).GetEnumerator

Return llList.GetEnumerator()

End Function

''' <summary>
''' Creates a shallow copy of the Queue.
''' </summary>
Public Function Clone() As Object Implements System.ICloneable.Clone

Return New Deque(Of T)(llList)

End Function

#End Region

#Region " Methods common to both Queues and Stacks "

''' <summary>
''' Removes all elements from the Deque.
''' </summary>
Public Sub Clear()

llList.Clear()

End Sub

''' <summary>
''' Determines whether an element is in the Deque.
''' </summary>
''' <param name="obj">The object to locate in the Deque. The value can be a null reference (Nothing in Visual Basic) for reference types.</param>
Public Function Contains(ByVal obj As T) As Boolean

Return llList.Contains(obj)

End Function

''' <summary>
''' Copies the elements of the Deque to a new array.
''' </summary>
''' <returns>An array containing copies of the elements of the Deque.</returns>
Public Function ToArray() As T()
Dim retObj(llList.Count - 1) As T
Dim i As Integer = 0
For Each obj As T In llList
retObj(i) = obj
i += 1
Next
Return retObj
End Function

''' <summary>
''' Returns a String that represents the current Object.
''' </summary>
''' <returns>A String that represents the current Object.</returns>
Public Overrides Function ToString() As String
Return llList.ToString()
End Function

#End Region

#Region " Deque Methods "

''' <summary>
''' Adds an object to the end of the Deque.
''' </summary>
''' <param name="obj">The object to add. The value can be a null reference.</param>
Public Sub PushBack(ByVal obj As T)
llList.AddLast(obj)
End Sub

''' <summary>
''' Adds an object to the front of the Deque.
''' </summary>
''' <param name="obj">The object to add. The value can be a null reference.</param>
Public Sub PushFront(ByVal obj As T)

llList.AddFirst(obj)

End Sub

''' <summary>
''' Returns and removes the object from the end of the Deque.
''' </summary>
Public Function PopBack(Of dataType)() As T
Dim objRet As T = PeekBack(Of T)()
llList.RemoveLast()
Return objRet
End Function

''' <summary>
''' Returns and removes the object from the front of the Deque.
''' </summary>
Public Function PopFront(Of dataType)() As T
Dim objRet As T = PeekFront(Of T)()
llList.RemoveFirst()
Return objRet
End Function

''' <summary>
''' Returns an object from the back of the Deque without removing it.
''' </summary>
Public Function PeekBack(Of dataType)() As T
If llList.Count = 0 Then Return Nothing
Return DirectCast(llList.Last().Value, T)
End Function

''' <summary>
''' Return an object from the front of the Deque without removing it.
''' </summary>
Public Function PeekFront(Of dataType)() As T
If llList.Count = 0 Then Return Nothing
Return DirectCast(llList.First().Value, T)
End Function

#End Region


End Class
GeneralComments Pin
ttobler13-Nov-07 5:06
ttobler13-Nov-07 5:06 
GeneralRe: Comments Pin
Chris Kolkman13-Nov-07 5:20
Chris Kolkman13-Nov-07 5:20 
GeneralRe: Comments Pin
Chris Kolkman13-Nov-07 6:02
Chris Kolkman13-Nov-07 6:02 
GeneralRe: Comments Pin
ttobler13-Nov-07 7:18
ttobler13-Nov-07 7:18 
GeneralAnother thought... Pin
rcardare8-Nov-07 12:58
rcardare8-Nov-07 12:58 
GeneralRe: Another thought... Pin
Chris Kolkman9-Nov-07 2:43
Chris Kolkman9-Nov-07 2:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.