Grense størrelsen Kø <T> i .NET?

stemmer
50

Jeg har en kø <T> objekt som jeg har initialisert til en kapasitet på 2, men selvsagt det er bare kapasiteten og det holder å utvide så jeg legge til elementer. Er det allerede et objekt som automatisk dequeues et element når grensen er nådd, eller er den beste løsningen for å lage min egen arvet klasse?

Publisert på 04/08/2008 klokken 14:47
kilden bruker
På andre språk...                            


7 svar

stemmer
32

Jeg har slått opp en grunnleggende versjon av det jeg leter etter, er det ikke perfekt, men det vil gjøre jobben inntil noe bedre kommer.

public class LimitedQueue<T> : Queue<T>
{
    public int Limit { get; set; }

    public LimitedQueue(int limit) : base(limit)
    {
        Limit = limit;
    }

    public new void Enqueue(T item)
    {
        while (Count >= Limit)
        {
            Dequeue();
        }
        base.Enqueue(item);
    }
}
Svarte 04/08/2008 kl. 14:57
kilden bruker

stemmer
17

Jeg vil anbefale at du trekker opp C5 Biblioteket . I motsetning til SCG (System.Collections.Generic), er C5 programmert til grensesnitt og utformet for å bli subclassed. De fleste offentlige metoder er virtuell og ingen av klassene er forseglet. På denne måten vil du ikke å bruke den icky "nye" søkeord som ikke ville utløse hvis LimitedQueue<T>ble kastet til en SCG.Queue<T>. Med C5 og bruke nær den samme koden som du hadde før, ville du komme fra CircularQueue<T>. Den CircularQueue<T>faktisk implementerer både en stabel og en kø, så du kan få begge alternativer med en grense nesten gratis. Jeg har skrevet om det under med noen 3,5 konstruksjoner:

using C5;

public class LimitedQueue<T> : CircularQueue<T>
{
    public int Limit { get; set; }

    public LimitedQueue(int limit) : base(limit)
    {
        this.Limit = limit;
    }

    public override void Push(T item)
    {
        CheckLimit(false);
        base.Push(item);
    }

    public override void Enqueue(T item)
    {
        CheckLimit(true);
        base.Enqueue(item);
    }

    protected virtual void CheckLimit(bool enqueue)
    {
        while (this.Count >= this.Limit)
        {
            if (enqueue)
            {
                this.Dequeue();
            }
            else
            {
                this.Pop();
            }
        }
    }
}

Jeg tror at denne koden skal gjøre akkurat det du leter etter.

Svarte 24/10/2008 kl. 13:51
kilden bruker

stemmer
5

Du bør lage din egen klasse, en ringbuffer ville trolig passe dine behov.

Datastrukturer i NET som lar deg angi kapasitet, med unntak av array, bruker denne til å bygge den interne datastruktur som brukes til å holde interne data.

For eksempel, for en liste, blir kapasitet brukes til å størrelse en innvendig matrise. Når du begynner å legge elementer til listen, vil det begynne å fylle denne matrisen fra indeks 0 og opp, og når den når kapasiteten, det øker kapasiteten til en ny høyere kapasitet, og fortsetter å fylle den opp.

Svarte 04/08/2008 kl. 14:56
kilden bruker

stemmer
3

Vel jeg håper denne klassen vil hjelper deg:
Internt Circular FIFO buffer bruke en kø <T> med den angitte størrelsen. Når størrelsen på bufferen er nådd, vil det erstatter eldre elementer med nye.

MERK: Du kan ikke fjerne elementer tilfeldig. Jeg angir metoden Ta (T element) for å return false. Hvis du ønsker kan du endre for å fjerne objekter tilfeldig

public class CircularFIFO<T> : ICollection<T> , IDisposable
{
    public Queue<T> CircularBuffer;

    /// <summary>
    /// The default initial capacity.
    /// </summary>
    private int capacity = 32;

    /// <summary>
    /// Gets the actual capacity of the FIFO.
    /// </summary>
    public int Capacity
    {
        get { return capacity; }          
    }

    /// <summary>
    ///  Initialize a new instance of FIFO class that is empty and has the default initial capacity.
    /// </summary>
    public CircularFIFO()
    {            
        CircularBuffer = new Queue<T>();
    }

    /// <summary>
    /// Initialize a new instance of FIFO class that is empty and has the specified initial capacity.
    /// </summary>
    /// <param name="size"> Initial capacity of the FIFO. </param>
    public CircularFIFO(int size)
    {
        capacity = size;
        CircularBuffer = new Queue<T>(capacity);
    }

    /// <summary>
    /// Adds an item to the end of the FIFO.
    /// </summary>
    /// <param name="item"> The item to add to the end of the FIFO. </param>
    public void Add(T item)
    {
        if (this.Count >= this.Capacity)
            Remove();

        CircularBuffer.Enqueue(item);
    }

    /// <summary>
    /// Adds array of items to the end of the FIFO.
    /// </summary>
    /// <param name="item"> The array of items to add to the end of the FIFO. </param>
     public void Add(T[] item)
    { 
        int enqueuedSize = 0;
        int remainEnqueueSize = this.Capacity - this.Count;

        for (; (enqueuedSize < item.Length && enqueuedSize < remainEnqueueSize); enqueuedSize++)
            CircularBuffer.Enqueue(item[enqueuedSize]);

        if ((item.Length - enqueuedSize) != 0)
        {
            Remove((item.Length - enqueuedSize));//remaining item size

            for (; enqueuedSize < item.Length; enqueuedSize++)
                CircularBuffer.Enqueue(item[enqueuedSize]);
        }           
    }

    /// <summary>
    /// Removes and Returns an item from the FIFO.
    /// </summary>
    /// <returns> Item removed. </returns>
    public T Remove()
    {
        T removedItem = CircularBuffer.Peek();
        CircularBuffer.Dequeue();

        return removedItem;
    }

    /// <summary>
    /// Removes and Returns the array of items form the FIFO.
    /// </summary>
    /// <param name="size"> The size of item to be removed from the FIFO. </param>
    /// <returns> Removed array of items </returns>
    public T[] Remove(int size)
    {
        if (size > CircularBuffer.Count)
            size = CircularBuffer.Count;

        T[] removedItems = new T[size];

        for (int i = 0; i < size; i++)
        {
            removedItems[i] = CircularBuffer.Peek();
            CircularBuffer.Dequeue();
        }

        return removedItems;
    }

    /// <summary>
    /// Returns the item at the beginning of the FIFO with out removing it.
    /// </summary>
    /// <returns> Item Peeked. </returns>
    public T Peek()
    {
        return CircularBuffer.Peek();
    }

    /// <summary>
    /// Returns the array of item at the beginning of the FIFO with out removing it.
    /// </summary>
    /// <param name="size"> The size of the array items. </param>
    /// <returns> Array of peeked items. </returns>
    public T[] Peek(int size)
    {
        T[] arrayItems = new T[CircularBuffer.Count];
        CircularBuffer.CopyTo(arrayItems, 0);

        if (size > CircularBuffer.Count)
            size = CircularBuffer.Count;

        T[] peekedItems = new T[size];

        Array.Copy(arrayItems, 0, peekedItems, 0, size);

        return peekedItems;
    }

    /// <summary>
    /// Gets the actual number of items presented in the FIFO.
    /// </summary>
    public int Count
    {
        get
        {
            return CircularBuffer.Count;
        }
    }

    /// <summary>
    /// Removes all the contents of the FIFO.
    /// </summary>
    public void Clear()
    {
        CircularBuffer.Clear();
    }

    /// <summary>
    /// Resets and Initialize the instance of FIFO class that is empty and has the default initial capacity.
    /// </summary>
    public void Reset()
    {
        Dispose();
        CircularBuffer = new Queue<T>(capacity);
    }

    #region ICollection<T> Members

    /// <summary>
    /// Determines whether an element is in the FIFO.
    /// </summary>
    /// <param name="item"> The item to locate in the FIFO. </param>
    /// <returns></returns>
    public bool Contains(T item)
    {
        return CircularBuffer.Contains(item);
    }

    /// <summary>
    /// Copies the FIFO elements to an existing one-dimensional array. 
    /// </summary>
    /// <param name="array"> The one-dimensional array that have at list a size of the FIFO </param>
    /// <param name="arrayIndex"></param>
    public void CopyTo(T[] array, int arrayIndex)
    {
        if (array.Length >= CircularBuffer.Count)
            CircularBuffer.CopyTo(array, 0);           
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return false; 
    }

    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
       return CircularBuffer.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator()
    {
        return CircularBuffer.GetEnumerator();
    }

    #endregion

    #region IDisposable Members

    /// <summary>
    /// Releases all the resource used by the FIFO.
    /// </summary>
    public void Dispose()
    {          
        CircularBuffer.Clear();
        CircularBuffer = null;
        GC.Collect();
    }

    #endregion
}
Svarte 15/11/2011 kl. 12:40
kilden bruker

stemmer
3

Hvorfor skulle ikke du bare bruke en matrise med en størrelse på 2? En kø er ment å være i stand til å vokse dynamisk og krympe.

Eller skape et omslag klasse rundt en forekomst av Queue<T>forekomst, og hver gang en enqueues et <T>objekt, kontrollere størrelsen av køen. Hvis større enn 2, dequeue det første elementet.

Svarte 04/08/2008 kl. 14:52
kilden bruker

stemmer
1

Hvis det er til nytte for noen, gjorde jeg en LimitedStack<T>.

public class LimitedStack<T>
{
    public readonly int Limit;
    private readonly List<T> _stack;

    public LimitedStack(int limit = 32)
    {
        Limit = limit;
        _stack = new List<T>(limit);
    }

    public void Push(T item)
    {
        if (_stack.Count == Limit) _stack.RemoveAt(0);
        _stack.Add(item);
    }

    public T Peek()
    {
        return _stack[_stack.Count - 1];
    }

    public void Pop()
    {
        _stack.RemoveAt(_stack.Count - 1);
    }

    public int Count
    {
        get { return _stack.Count; }
    }
}

Det fjerner den eldste elementet (nederst i bunken) når det blir for stort.

(Dette spørsmålet var toppen Google resultat for "C # grense stack size")

Svarte 15/01/2012 kl. 05:28
kilden bruker

stemmer
0

samtidig Solution

public class LimitedConcurrentQueue<ELEMENT> : ConcurrentQueue<ELEMENT>
{
    public readonly int Limit;

    public LimitedConcurrentQueue(int limit)
    {
        Limit = limit;
    }

    public new void Enqueue(ELEMENT element)
    {
        base.Enqueue(element);
        if (Count > Limit)
        {
            TryDequeue(out ELEMENT discard);
        }
    }
}

Merk: Siden Enqueuekontroller tillegg av elementer, og gjør det en av gangen, er det ikke nødvendig å utføre en whilefor TryDequeue.

Svarte 09/05/2018 kl. 20:39
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more