Περιορίστε το μέγεθος της ουράς <T> στη ΝΕΤ;

ψήφοι
50

Έχω μια ουρά <T> αντικείμενο που έχω σε εκκίνηση με χωρητικότητα 2, αλλά προφανώς αυτό είναι μόνο η ικανότητα και συνεχίζει να επεκτείνεται και να προσθέσω στοιχεία. Υπάρχει ήδη ένα αντικείμενο που dequeues αυτόματα ένα στοιχείο όταν ξεπεραστεί το όριο, είτε είναι η καλύτερη λύση για να δημιουργήσετε το δικό μου κληρονόμησε τάξη;

Δημοσιεύθηκε 04/08/2008 στις 15:47
πηγή χρήστη
Σε άλλες γλώσσες...                            


7 απαντήσεις

ψήφοι
32

Έχω χτύπησε μια βασική έκδοση του τι ψάχνω, δεν είναι τέλεια, αλλά αυτό θα κάνει τη δουλειά μέχρι κάτι καλύτερο έρχεται.

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);
    }
}
Απαντήθηκε 04/08/2008 στις 15:57
πηγή χρήστη

ψήφοι
17

Θα ήθελα να συστήσω ότι θα τραβήξει μέχρι το C5 Βιβλιοθήκη . Σε αντίθεση με SCG (System.Collections.Generic), C5 είναι προγραμματισμένο να interface και σχεδιαστεί για να subclassed. Οι περισσότερες δημόσιες μέθοδοι είναι εικονικές και καμία από τις κατηγορίες σφραγίζονται. Με αυτό τον τρόπο, δεν θα πρέπει να χρησιμοποιεί το εν λόγω icky «νέο» λέξη-κλειδί που δεν θα προκαλέσει αν σας LimitedQueue<T>πετάχτηκαν σε ένα SCG.Queue<T>. Με C5 και τη χρήση κοντά στο ίδιο κωδικό που είχατε πριν, θα προέρχονται από το CircularQueue<T>. Η CircularQueue<T>πραγματικότητα εφαρμόζει τόσο στοίβα και ουρά, ώστε να μπορείτε να πάρετε και τις δύο επιλογές, με όριο σχεδόν δωρεάν. Το έχω ξαναγράψει παρακάτω με περίπου 3,5 κατασκευές:

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

Νομίζω ότι αυτός ο κώδικας θα πρέπει να κάνουν ακριβώς αυτό που ψάχνατε.

Απαντήθηκε 24/10/2008 στις 14:51
πηγή χρήστη

ψήφοι
5

Θα πρέπει να δημιουργήσετε τη δική σας τάξη, μια ringbuffer θα ταίριαζε μάλλον τις ανάγκες σας.

Οι δομές δεδομένων στη ΝΕΤ που σας επιτρέπει να καθορίσετε την ικανότητα, εκτός από την ποικιλία, χρησιμοποιεί αυτό για να οικοδομήσουμε την εσωτερική δομή δεδομένων που χρησιμοποιείται για να κρατήσει τα εσωτερικά δεδομένα.

Για παράδειγμα, για μια λίστα, χωρητικότητα χρησιμοποιείται το μέγεθος μιας εσωτερικής συστοιχίας. Όταν ξεκινάτε την προσθήκη στοιχείων στη λίστα, αυτό θα αρχίσει να καλύψει αυτό το φάσμα από το δείκτη 0 και πάνω, και όταν φτάσει η ικανότητά σας, αυξάνει την ικανότητα για ένα νέο μεγαλύτερη χωρητικότητα, και συνεχίζει γεμίζουν.

Απαντήθηκε 04/08/2008 στις 15:56
πηγή χρήστη

ψήφοι
3

Λοιπόν ελπίζω ότι αυτή η κατηγορία θα σας βοηθά να:
Εσωτερικά η εγκύκλιος FIFO Ρυθμιστικό χρησιμοποιήσετε μια ουρά <T> με το καθορισμένο μέγεθος. Μόλις επιτευχθεί το μέγεθος του buffer, θα αντικαθιστά τα μεγαλύτερα αντικείμενα με νέα.

ΣΗΜΕΙΩΣΗ: Δεν μπορείτε να καταργήσετε στοιχεία τυχαία. Έθεσα τη μέθοδο Αφαιρέστε (σημείο Τ) για να επιστρέψει false. Αν θέλετε, μπορείτε να τροποποιήσετε για να καταργήσετε στοιχεία τυχαία

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
}
Απαντήθηκε 15/11/2011 στις 13:40
πηγή χρήστη

ψήφοι
3

Γιατί δεν θα μπορείτε απλά να χρησιμοποιήσετε μια σειρά με το μέγεθος των 2; Η ουρά είναι υποτιθέμενο για να είναι σε θέση να δυναμικά αναπτύσσονται και να συρρικνωθεί.

Ή να δημιουργήσετε μια κατηγορία περιτύλιγμα γύρω από μια εμφάνιση του Queue<T>βαθμού και κάθε φορά που ένας enqueues ένα <T>αντικείμενο, ελέγξτε το μέγεθος της ουράς. Αν μεγαλύτερο από 2, dequeue το πρώτο στοιχείο.

Απαντήθηκε 04/08/2008 στις 15:52
πηγή χρήστη

ψήφοι
1

Αν είναι για κάθε χρήση σε κανέναν, έκανα ένα 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; }
    }
}

Αφαιρεί το παλαιότερο στοιχείο (κάτω μέρος της στοίβας), όταν παίρνει πάρα πολύ μεγάλο.

(Η ερώτηση αυτή ήταν η κορυφαία αποτέλεσμα Google για «C # όριο μεγέθους στοίβα»)

Απαντήθηκε 15/01/2012 στις 06:28
πηγή χρήστη

ψήφοι
0

Ταυτόχρονη Λύση

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

Σημείωση: Από Enqueueτους ελέγχους η προσθήκη στοιχείων, και το κάνει ένα κάθε φορά, δεν υπάρχει καμία ανάγκη για να εκτελέσει μια whileγια TryDequeue.

Απαντήθηκε 09/05/2018 στις 20:39
πηγή χρήστη

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