33

I am almost certain this should be a duplicate but I searched for some time and could not find the answer. What should I use in C# to replace C++ vector and deque efficiently. That is I need a structure that supports direct indexing effieciently and also supports delete from one or both ends(depending on vector or deque case) again in an efficient manner.

In java I usually use ArrayList at least for vector but for C# I found this source that states: ArrayList resizes dynamically. As elements are added, it grows in capacity to accommodate them. It is most often used in older C# programs.. So what is the new way to do this? And again what do I do for the deque case?

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176

6 Answers6

24

There's no built-in Deque container, but there are several implementations available.

Here's a good one from Stephen Cleary. This provides O(1) operations to index and also to insert at the beginning and append at the end.

The C# equivalent to Vector is List<T>. Indexed access is O(1), but insertion or removal is O(N) (other than Inserting at the end, which is O(1)).

Brian
  • 25,523
  • 18
  • 82
  • 173
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • How effiecient is the indexing operation in `List`? I thought it will simply iterate through the list – Ivaylo Strandjev Mar 24 '13 at 13:45
  • 4
    @IvayloStrandjev it's not a doubly linked list, it's a vector. – wRAR Mar 24 '13 at 13:47
  • @Ivaylo: No, it's not a linked-list, it's a wrapper around an array and so the indexing just uses the index to access the underlying array directly, so it's an O(1) operation. (Almost the same as a C++ vector) – Matthew Watson Mar 24 '13 at 13:47
  • @MatthewWatson please clarify O(N) or O(1) your comment seems to contradict itself – Ivaylo Strandjev Mar 24 '13 at 13:48
  • It was a typo, I meant O(1) - sorry! (Fixed) – Matthew Watson Mar 24 '13 at 13:49
  • 1
    Insertion is O(N) when the item is inserted in the middle, O(1) if at end (generally) – BlackBear Mar 24 '13 at 13:55
  • @BlackBear: Thanks, added that to my answer. – Matthew Watson Mar 24 '13 at 13:57
  • Just FYI the doubly-linked list in C# is the LinkedList class: http://msdn.microsoft.com/en-us/library/he2s3bh7.aspx The OP is of course correct about List being an array wrapper. – Kevin Anderson Mar 24 '13 at 16:18
  • 1
    Is it really necessary to reference 15 other packages just to write a basic Deque? – Jake Jan 03 '18 at 03:45
  • @BlackBear, Actually, it's O(1) for any constant distance from the end, since O(C) = O(1). It's also O(1) if the size of the list is constrained to be less than some constant, no matter how large ... O(googleplex) = O(1). Which shows that big-O can be quite misleading. – Jim Balter Sep 02 '23 at 07:24
11

For a C# vector, a good candidate is System.Collection.Generic.List as others mentioned.
The closest to the deque in C++ would be System.Collection.Generic.LinkedList which is a doubly linked list.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
Dale Wick
  • 135
  • 1
  • 2
1

Consider System.Collections.Generic.List and other from System.Collection.Generic they serve the same purpose as their C++ equivalents.
Additionally, there might be more containers for you. Look here.

bash.d
  • 13,029
  • 3
  • 29
  • 42
0

Though you cannot do an index operation, linkedlist is probably one of the closest in implementing dequeue first and dequeue last in constant time.

https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1.removefirst?view=netframework-4.8

re3el
  • 735
  • 2
  • 12
  • 28
-1

Deque is not in C#, but we can archive functionality by Vector and List, Below is a sample program to archive Deque by List.

using System;
using System.Collections.Generic;

public class GFG{
    
// Function to generate the array by
// inserting array elements one by one
// followed by reversing the array
static void generateArray(int []arr, int n)
{
    
    // Doubly ended Queue
    List<int> ans = new List<int>();
 
    // Start adding functionality at both end
    // Iterate over the array 
    // Even no at the front and odd no at the rear
    for(int i = 0; i < n; i++) 
    {
        
        // Push array elements
        // alternately to the front
        // and back
        if (arr[i]%2==0)
            ans.Insert(0,arr[i]);
        else
            ans.Add(arr[i]);
    }

    printDeque(ans);
    // Output 8 6 4 2 6 5 1 3
    
    // Start removing functionality at both end
    // Let i want to remove first(8) and last(3) element from Deque

    ans.RemoveAt(0);
    printDeque(ans);
    // Output 6 4 2 6 5 1 3 
    ans.RemoveAt(ans.Count-1);
    printDeque(ans);
    // Output 6 4 2 6 5 1
    
    
    
}
static void printDeque(List<int> q){
    // Print the elements
    // of the Deque
    foreach(int x in q)
    {
        Console.Write(x + " ");
    }
    Console.WriteLine();
}
    
// Driver Code
public static void Main(String[] args)
{
    
    int []arr = {5, 6, 1, 2, 3, 4,6, 8 };
    int n = arr.Length;
    generateArray(arr, n);
}
}
  • 1
    This is a pretty bad solution as the Insert into a List is much slower than a deque needs to be. You may consider an implementation where you had two Lists. To iterate through this entire deque implementation you would first iterate backward over one list then forwards over the other. This allows you to quickly add and remove from both ends of the deque by simply adding and removing from the list. Libraries for this exist as described in the accepted answer. – Benji Altman Nov 04 '21 at 17:53
  • The question says "deque **efficiently**", which this doesn't do. – Jim Balter Sep 02 '23 at 07:17
-1

For me, these simple extension methods were enough.

using System.Linq;
using System.Collections.Generic;
-----
-----


        public static T consume<T>(this List<T> list, int index) {
            if (list.Count < index) return default(T);
            var item = list[index];
            list.RemoveAt(index);
            return item;
        }
        public static T pop<T>(this List<T> list) {
            return list.consume(list.Count - 1);
        }
        public static T dequeue<T>(this List<T> list) {
            return list.consume(0);
        }
        public static void push<T>(this List<T> list, T item) {
            list.Add(item);
        }
        public static void enqueue<T>(this List<T> list, T item) {
            list.Add(item);
        }
Sheikh Abdul Wahid
  • 2,623
  • 2
  • 25
  • 24