Limit velikost fronty <T> v .NET?

hlasů
50

Mám fronty <T> objekt, který jsem se inicializuje s kapacitou 2, ale samozřejmě, že je jen kapacita a stále rozšiřuje, jak jsem přidávat položky. Je tam už objekt, který automaticky dequeues položky, když je dosažen limit, nebo je nejlepším řešením vytvořit svůj vlastní dědičnou třídu?

Položena 04/08/2008 v 13:47
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
3

Proč by ne jen použít pole o velikosti 2? Fronta má být schopen dynamicky zvětšit a zmenšit.

Nebo vytvořit třídu obálky kolem instanci Queue<T>instance a pokaždé jeden enqueues <T>objektů, zkontrolujte velikost fronty. -Li větší než 2, dequeue první položku.

Odpovězeno 04/08/2008 v 13:52
zdroj uživatelem

hlasů
5

Ty by měly vytvořit vlastní třídu, je ringbuffer by pravděpodobně vyhovovat vašim potřebám.

Datové struktury v NET, která umožňuje určit schopnost, s výjimkou pole, používá toto vybudovat vnitřní datové struktury používané pro uložení interních dat.

Například, pro seznam, kapacita se používá k velikosti vnitřní pole. Když začnete přidávat prvky do seznamu, bude to začít vyplnění tohoto pole z indexu 0 a nahoru, a když dosáhne své možnosti, zvyšuje kapacitu na novou vyšší kapacitou, i nadále plnit to nahoru.

Odpovězeno 04/08/2008 v 13:56
zdroj uživatelem

hlasů
32

Já jsem vyrazil do základní verzi toho, co jsem hledal, že to není dokonalé, ale to bude dělat svou práci, dokud něco lepšího přijde.

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);
    }
}
Odpovězeno 04/08/2008 v 13:57
zdroj uživatelem

hlasů
17

Doporučila bych, abyste vytáhnout C5 knihovny . Na rozdíl od SCG (System.Collections.Generic), C5 je naprogramován tak, aby rozhraní a navrženy tak, aby se dále dělit na podtřídy. Většina veřejných metody jsou virtuální a žádná ze tříd jsou uzavřeny. Tímto způsobem, nebudete muset používat tuto fuj „nové“ slovo, které by nemusely být důvodem, pokud vaše LimitedQueue<T>byli obsazeni do A SCG.Queue<T>. S C5 a použití v blízkosti stejný kód, jak si předtím, měli byste odvodit z CircularQueue<T>. CircularQueue<T>Vlastně implementuje stoh a fronty, takže se můžete dostat obě možnosti s limitem téměř zadarmo. Jsem přepsat jej dále s některými 3.5 konstrukty:

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();
            }
        }
    }
}

Myslím si, že tento kód by měl dělat přesně to, co jste hledali.

Odpovězeno 24/10/2008 v 12:51
zdroj uživatelem

hlasů
3

No já doufám, že tato třída bude vám pomůže:
Vnitřně oběžník FIFO Buffer použít fronty <T> podle zadané velikosti. Jakmile se dosáhne velikost vyrovnávací paměti, bude to nahradí starší položky za nové.

Poznámka: Nemůžete odstranit položky v náhodném pořadí. Jsem na metodu Odebrat (T položka) pro návrat falešný. Pokud chcete, můžete upravit, aby neobsahovaly předměty náhodně

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
}
Odpovězeno 15/11/2011 v 10:40
zdroj uživatelem

hlasů
1

Pokud je to k ničemu nikoho, udělal jsem 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; }
    }
}

To odstraní nejstarší položky (dno zásobníku), když se dostane příliš velké.

(Tato otázka byla první výsledek Google za „C # limit velikosti zásobníku“)

Odpovězeno 15/01/2012 v 03:28
zdroj uživatelem

hlasů
0

Souběžný 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);
        }
    }
}

Poznámka: Vzhledem k tomu, Enqueueovládací prvky přidání prvků, a činí tak jeden po druhém, není třeba vykonat whilepro TryDequeue.

Odpovězeno 09/05/2018 v 19:39
zdroj uživatelem

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