using System;
using System.Collections;
using System.Collections.Generic;
namespace Developpez.Dotnet.Collections
{
///
/// Représente une collection de type file (premier entré, premier sorti, FIFO),
/// où chaque élément n'est présent qu'une fois.
///
/// Type des éléments de la collection
/// Si un élément déjà présent est ajouté à nouveau, il est replacé à la fin de la pile
public class QueueSet : ICollection
{
private readonly LinkedList _items;
private readonly Dictionary> _nodes;
private readonly IEqualityComparer _comparer;
///
/// Crée une nouvelle instance de QueueSet<T> avec le comparateur d'égalité par défaut
///
public QueueSet()
: this(null)
{
}
///
/// Crée une nouvelle instance de QueueSet<T> avec le comparateur d'égalité spécifié
///
/// Comparateur à utiliser pour tester l'égalité des éléments
public QueueSet(IEqualityComparer comparer)
{
_comparer = comparer ?? EqualityComparer.Default;
_items = new LinkedList();
_nodes = new Dictionary>(_comparer);
}
///
/// Ajoute une élément à la fin de la file. Si l'élément est déjà présent, il est replacé à la fin de la file
///
/// Élément à ajouter
/// true si l'élément a été ajouté, false s'il était déjà présent
/// Cette méthode est proche d'une opération en O(1) si la capacité interne est suffisante.
/// Si la capacité doit être augmentée, cette méthode devient une opération en O(n).
public bool Enqueue(T item)
{
LinkedListNode node;
if (_nodes.TryGetValue(item, out node))
{
if (node.Next != null) // i.e. not already at the end of the queue
{
_items.Remove(node);
node = _items.AddLast(item);
_nodes[item] = node;
}
return false;
}
node = _items.AddLast(item);
_nodes[item] = node;
return true;
}
///
/// Supprime et retourne l'élément se trouvant en tête de la file
///
/// L'élément qui se trouvait en tête de la file
/// Cette méthode est proche d'une opération en O(1)
public T Dequeue()
{
var node = _items.First;
if (node == null)
throw new InvalidOperationException("The queue was empty");
T item = node.Value;
_items.RemoveFirst();
_nodes.Remove(item);
return item;
}
///
/// Retourne l'élément se trouvant en tête de la file, sans le supprimer
///
/// L'élément se trouvant en tête de la file
/// Cette méthode est une opération en O(1).
public T Peek()
{
var node = _items.First;
if (node == null)
throw new InvalidOperationException("The queue was empty");
return node.Value;
}
#region Implementation of IEnumerable
///
/// Renvoie un énumérateur pour parcourir les éléments de la collection
///
/// Un énumérateur pour parcourir les éléments de la collection
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
///
/// Renvoie un énumérateur pour parcourir les éléments de la collection
///
/// Un énumérateur pour parcourir les éléments de la collection
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region Implementation of ICollection
///
/// Ajoute un élément à la collection
///
/// Élément à ajouter
void ICollection.Add(T item)
{
Enqueue(item);
}
///
/// Supprime un élément de la collection
///
/// Élément à supprimer
/// true si l'élément a été supprimé, false s'il n'appartenait pas à la collection
bool ICollection.Remove(T item)
{
LinkedListNode node;
if (_nodes.TryGetValue(item, out node))
{
_items.Remove(node);
_nodes.Remove(item);
return true;
}
return false;
}
///
/// Supprime tous les éléments de la collection
///
/// Cette méthode est une opération en O(n).
public void Clear()
{
_items.Clear();
_nodes.Clear();
}
///
/// Indique si l'élément est présent dans la collection
///
/// Élément recherché
/// true si l'élément est présent dans la collection, sinon false
/// Cette méthode est proche d'une opération en O(1).
public bool Contains(T item)
{
return _nodes.ContainsKey(item);
}
///
/// Copie les éléments de la collection vers le tableau spécifié
///
/// Tableau vers lequel les éléments sont copiés
/// Position dans le tableau à laquelle la copie commence
/// Cette méthode est une opération en O(n).
public void CopyTo(T[] array, int arrayIndex)
{
_items.CopyTo(array, arrayIndex);
}
///
/// Renvoie le nombre d'éléments dans la collection
///
/// Obtenir la valeur de cette propriété est une opération en O(1).
public int Count
{
get { return _items.Count; }
}
///
/// Indique si la collection est en lecture seule
///
/// Obtenir la valeur de cette propriété est une opération en O(1).
public bool IsReadOnly
{
get { return false; }
}
#endregion
}
}