प्राथमिकता कतार .Net में [बंद]


216

मैं एक प्राथमिकता कतार या ढेर डेटा संरचना के .NET कार्यान्वयन की तलाश कर रहा हूं

प्राथमिकता कतार डेटा संरचनाएं हैं जो सरल छंटाई की तुलना में अधिक लचीलापन प्रदान करती हैं, क्योंकि वे नए तत्वों को मनमाने अंतराल पर एक प्रणाली में प्रवेश करने की अनुमति देते हैं। इस तरह के प्रत्येक आगमन पर सब कुछ फिर से छांटने की तुलना में एक नई नौकरी को प्राथमिकता कतार में शामिल करना अधिक लागत प्रभावी है।

मूल प्राथमिकता कतार तीन प्राथमिक कार्यों का समर्थन करती है:

  • सम्मिलित करें (क्यू, एक्स)। कुंजी k के साथ एक आइटम x दिया, इसे प्राथमिकता कतार Q में डालें।
  • खोजें-न्यूनतम (क्यू)। एक पॉइंटर को उस आइटम पर लौटाएं जिसका मुख्य मूल्य प्राथमिकता कतार में किसी भी अन्य कुंजी से छोटा है।
  • हटाएँ-न्यूनतम (क्यू)। उस आइटम को प्राथमिकता कतार Q से निकालें जिसकी कुंजी न्यूनतम है

जब तक मैं गलत जगह देख रहा हूं, फ्रेमवर्क में कोई नहीं है। क्या किसी को एक अच्छे के बारे में पता है, या मुझे अपना रोल करना चाहिए?


34
FYI करें मैंने एक आसान-उपयोग, अत्यधिक अनुकूलित C # प्राथमिकता-कतार विकसित की है , जिसे यहां पाया जा सकता है । इसे विशेष रूप से एप्लिकेशन (ए *, आदि) के लिए पाथफाइंग के लिए विकसित किया गया था, लेकिन किसी भी अन्य एप्लिकेशन के लिए भी पूरी तरह से काम करना चाहिए। मैं इसे एक उत्तर के रूप में पोस्ट करूंगा, लेकिन सवाल हाल ही में बंद कर दिया गया है ...
ब्लूराजा - डैनी पफ्लुगुफ्ट


बेशर्मी से प्रायोरिटी का परिचय दें , स्प्रिंग.नेट के लिए जावा समवर्ती एपीआई को पोर्ट करने के प्रयास के भाग के रूप में। यह पूरी तरह से सामान्य समर्थन के साथ एक ढेर और कतार है। बाइनरी यहां डाउनलोड की जा सकती है
केनेथ जू

@ BlueRaja-DannyPflughoeft क्या आप इसे एक उत्तर जोड़ सकते हैं?
माफ़ू

1
सिर्फ संक्षेप में। .Net में कोई ढेर डेटा संरचना नहीं है, न तो .net कोर में अब। हालांकि Array.Sort यूजर्स इसे बड़ी संख्या के लिए। आंतरिक कार्यान्वयन मौजूद हैं।
Artyom

जवाबों:


44

मैं प्राथमिकता कतार के रूप में PowerCollections में OrderedBagऔर OrderedSetवर्गों का उपयोग करना पसंद करता हूं ।


60
ऑर्डरडैबग / ऑर्डरडसेट आवश्यक से अधिक काम करते हैं, वे ढेर के बजाय लाल-काले पेड़ का उपयोग करते हैं।
दान बेरिंडी

3
@DanBerindei: जरूरी काम नहीं अगर आपको रनिंग कैलकुलेशन करने की जरूरत है (पुरानी वस्तुओं को हटा दें), मिनट या मैक्स को डिलीट करने के लिए केवल सपोर्ट
Svisstack

69

आपको C5 जेनेरिक कलेक्शन लाइब्रेरी से इंटरवल हैप पसंद हो सकता है । उपयोगकर्ता गाइड को उद्धृत करने के लिए

जोड़े के एक सरणी के रूप में संग्रहीत अंतराल ढेर का उपयोग करते हुए क्लास IntervalHeap<T>इम्प्लीमेंट इंटरफ़ेस IPriorityQueue<T>। FindMin और FindMax ऑपरेशंस, और इंडेक्सर के गेट-एक्सेसर, O (1) का समय लेते हैं। DeleteMin, DeleteMax, Add and Update ऑपरेशंस और इंडेक्सर के सेट-एक्सेसर, O (लॉग एन) समय लेते हैं। एक साधारण प्राथमिकता कतार के विपरीत, अंतराल अंतराल एक ही दक्षता के साथ न्यूनतम और अधिकतम संचालन दोनों प्रदान करता है।

एपीआई काफी सरल है

> var heap = new C5.IntervalHeap<int>();
> heap.Add(10);
> heap.Add(5);
> heap.FindMin();
5

Nuget https://www.nuget.org/packages/C5 या GitHub https://github.com/sestoft/C5/ से इंस्टॉल करें


3
यह एक बहुत ही ठोस पुस्तकालय है और यह 1400 यूनिट परीक्षणों के साथ आता है।
ECC-Dan

2
मैंने इसका उपयोग करने की कोशिश की लेकिन इसमें गंभीर खामियां हैं। IntervalHeap के पास प्राथमिकता की एक अंतर्निहित अवधारणा नहीं है और आपको IComparable या IComparer को कार्यान्वित करने के लिए मजबूर करता है, जिससे यह एक छाँटा हुआ संग्रह "प्राथमिकता" नहीं है। इससे भी बदतर पिछले कुछ प्रविष्टि की प्राथमिकता को अद्यतन करने का कोई सीधा तरीका नहीं है !!!
मोर्टेजा खोसरावी

52

यहाँ एक .NET हीप पर मेरा प्रयास है

public abstract class Heap<T> : IEnumerable<T>
{
    private const int InitialCapacity = 0;
    private const int GrowFactor = 2;
    private const int MinGrow = 1;

    private int _capacity = InitialCapacity;
    private T[] _heap = new T[InitialCapacity];
    private int _tail = 0;

    public int Count { get { return _tail; } }
    public int Capacity { get { return _capacity; } }

    protected Comparer<T> Comparer { get; private set; }
    protected abstract bool Dominates(T x, T y);

    protected Heap() : this(Comparer<T>.Default)
    {
    }

    protected Heap(Comparer<T> comparer) : this(Enumerable.Empty<T>(), comparer)
    {
    }

    protected Heap(IEnumerable<T> collection)
        : this(collection, Comparer<T>.Default)
    {
    }

    protected Heap(IEnumerable<T> collection, Comparer<T> comparer)
    {
        if (collection == null) throw new ArgumentNullException("collection");
        if (comparer == null) throw new ArgumentNullException("comparer");

        Comparer = comparer;

        foreach (var item in collection)
        {
            if (Count == Capacity)
                Grow();

            _heap[_tail++] = item;
        }

        for (int i = Parent(_tail - 1); i >= 0; i--)
            BubbleDown(i);
    }

    public void Add(T item)
    {
        if (Count == Capacity)
            Grow();

        _heap[_tail++] = item;
        BubbleUp(_tail - 1);
    }

    private void BubbleUp(int i)
    {
        if (i == 0 || Dominates(_heap[Parent(i)], _heap[i])) 
            return; //correct domination (or root)

        Swap(i, Parent(i));
        BubbleUp(Parent(i));
    }

    public T GetMin()
    {
        if (Count == 0) throw new InvalidOperationException("Heap is empty");
        return _heap[0];
    }

    public T ExtractDominating()
    {
        if (Count == 0) throw new InvalidOperationException("Heap is empty");
        T ret = _heap[0];
        _tail--;
        Swap(_tail, 0);
        BubbleDown(0);
        return ret;
    }

    private void BubbleDown(int i)
    {
        int dominatingNode = Dominating(i);
        if (dominatingNode == i) return;
        Swap(i, dominatingNode);
        BubbleDown(dominatingNode);
    }

    private int Dominating(int i)
    {
        int dominatingNode = i;
        dominatingNode = GetDominating(YoungChild(i), dominatingNode);
        dominatingNode = GetDominating(OldChild(i), dominatingNode);

        return dominatingNode;
    }

    private int GetDominating(int newNode, int dominatingNode)
    {
        if (newNode < _tail && !Dominates(_heap[dominatingNode], _heap[newNode]))
            return newNode;
        else
            return dominatingNode;
    }

    private void Swap(int i, int j)
    {
        T tmp = _heap[i];
        _heap[i] = _heap[j];
        _heap[j] = tmp;
    }

    private static int Parent(int i)
    {
        return (i + 1)/2 - 1;
    }

    private static int YoungChild(int i)
    {
        return (i + 1)*2 - 1;
    }

    private static int OldChild(int i)
    {
        return YoungChild(i) + 1;
    }

    private void Grow()
    {
        int newCapacity = _capacity*GrowFactor + MinGrow;
        var newHeap = new T[newCapacity];
        Array.Copy(_heap, newHeap, _capacity);
        _heap = newHeap;
        _capacity = newCapacity;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _heap.Take(Count).GetEnumerator();
    }

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

public class MaxHeap<T> : Heap<T>
{
    public MaxHeap()
        : this(Comparer<T>.Default)
    {
    }

    public MaxHeap(Comparer<T> comparer)
        : base(comparer)
    {
    }

    public MaxHeap(IEnumerable<T> collection, Comparer<T> comparer)
        : base(collection, comparer)
    {
    }

    public MaxHeap(IEnumerable<T> collection) : base(collection)
    {
    }

    protected override bool Dominates(T x, T y)
    {
        return Comparer.Compare(x, y) >= 0;
    }
}

public class MinHeap<T> : Heap<T>
{
    public MinHeap()
        : this(Comparer<T>.Default)
    {
    }

    public MinHeap(Comparer<T> comparer)
        : base(comparer)
    {
    }

    public MinHeap(IEnumerable<T> collection) : base(collection)
    {
    }

    public MinHeap(IEnumerable<T> collection, Comparer<T> comparer)
        : base(collection, comparer)
    {
    }

    protected override bool Dominates(T x, T y)
    {
        return Comparer.Compare(x, y) <= 0;
    }
}

कुछ परीक्षण:

[TestClass]
public class HeapTests
{
    [TestMethod]
    public void TestHeapBySorting()
    {
        var minHeap = new MinHeap<int>(new[] {9, 8, 4, 1, 6, 2, 7, 4, 1, 2});
        AssertHeapSort(minHeap, minHeap.OrderBy(i => i).ToArray());

        minHeap = new MinHeap<int> { 7, 5, 1, 6, 3, 2, 4, 1, 2, 1, 3, 4, 7 };
        AssertHeapSort(minHeap, minHeap.OrderBy(i => i).ToArray());

        var maxHeap = new MaxHeap<int>(new[] {1, 5, 3, 2, 7, 56, 3, 1, 23, 5, 2, 1});
        AssertHeapSort(maxHeap, maxHeap.OrderBy(d => -d).ToArray());

        maxHeap = new MaxHeap<int> {2, 6, 1, 3, 56, 1, 4, 7, 8, 23, 4, 5, 7, 34, 1, 4};
        AssertHeapSort(maxHeap, maxHeap.OrderBy(d => -d).ToArray());
    }

    private static void AssertHeapSort(Heap<int> heap, IEnumerable<int> expected)
    {
        var sorted = new List<int>();
        while (heap.Count > 0)
            sorted.Add(heap.ExtractDominating());

        Assert.IsTrue(sorted.SequenceEqual(expected));
    }
}

2
मैं ExtractDominating में ढेर मूल्य को साफ करने की सिफारिश करूंगा, इसलिए यह आवश्यक (संभावित मेमोरी मेमोरी) की तुलना में लंबे समय तक संदर्भित ऑब्जेक्ट पर पकड़ नहीं करता है। मूल्य प्रकारों के लिए यह स्पष्ट रूप से चिंता का विषय नहीं है।
Wout

5
अच्छा है, लेकिन आप इसमें से आइटम नहीं निकाल सकते? प्राथमिकता वाले कतारों के लिए यह एक महत्वपूर्ण ऑपरेशन है।
टॉम लार्कोवर्टी 22

ऐसा लगता है कि अंतर्निहित वस्तु एक सरणी है। क्या यह बाइनरी ट्री के रूप में बेहतर नहीं होगा?
ग्रुनियन शाफ़्टो

1
@OhadSchneider बहुत अच्छा है, मैं सिर्फ मिन हीप में देख रहा था और यह करने की कोशिश की कि आपने इसे सामान्य और न्यूनतम या अधिकतम हीप कैसे बनाया है! महान काम
गिल्ड

1
@ गिल्ड IEqualityComparer<T>पर्याप्त नहीं होगा, क्योंकि यह केवल आपको बताएगा कि क्या दो आइटम समान हैं, जबकि आपको उनके (जो छोटे / बड़े) के बीच संबंध जानने की आवश्यकता है। यह सच है कि मैं IComparer<T>हालांकि इस्तेमाल किया जा सकता है ...
Ohad श्नाइडर

23

यहाँ एक मैं सिर्फ लिखा है, शायद यह के रूप में अनुकूलित नहीं है (बस एक हल शब्दकोश का उपयोग करता है) लेकिन समझने के लिए सरल है। आप विभिन्न प्रकार की वस्तुओं को सम्मिलित कर सकते हैं, इसलिए कोई सामान्य कतार नहीं।

using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;

namespace PrioQueue
{
    public class PrioQueue
    {
        int total_size;
        SortedDictionary<int, Queue> storage;

        public PrioQueue ()
        {
            this.storage = new SortedDictionary<int, Queue> ();
            this.total_size = 0;
        }

        public bool IsEmpty ()
        {
            return (total_size == 0);
        }

        public object Dequeue ()
        {
            if (IsEmpty ()) {
                throw new Exception ("Please check that priorityQueue is not empty before dequeing");
            } else
                foreach (Queue q in storage.Values) {
                    // we use a sorted dictionary
                    if (q.Count > 0) {
                        total_size--;
                        return q.Dequeue ();
                    }
                }

                Debug.Assert(false,"not supposed to reach here. problem with changing total_size");

                return null; // not supposed to reach here.
        }

        // same as above, except for peek.

        public object Peek ()
        {
            if (IsEmpty ())
                throw new Exception ("Please check that priorityQueue is not empty before peeking");
            else
                foreach (Queue q in storage.Values) {
                    if (q.Count > 0)
                        return q.Peek ();
                }

                Debug.Assert(false,"not supposed to reach here. problem with changing total_size");

                return null; // not supposed to reach here.
        }

        public object Dequeue (int prio)
        {
            total_size--;
            return storage[prio].Dequeue ();
        }

        public void Enqueue (object item, int prio)
        {
            if (!storage.ContainsKey (prio)) {
                storage.Add (prio, new Queue ());
              }
            storage[prio].Enqueue (item);
            total_size++;

        }
    }
}

हालांकि यह एक ही प्राथमिकता के साथ कई प्रविष्टियों के लिए अनुमति नहीं देता है?
लेट्सएटलचंच

2
ऐसा होता है। जब आप एन्केयू विधि लागू करते हैं, तो यह आइटम को उस प्राथमिकता की कतार में जोड़ देगा। (
एनक्यू

5
आपका क्या मतलब है "यह कंप्यूटर विज्ञान के अर्थ में वास्तव में एक प्राथमिकता कतार नहीं है"? इसके बारे में आपको क्या लगता है कि यह एक प्राथमिकता कतार नहीं है?
मार्क बायर्स

14
-1 जेनेरिक का उपयोग नहीं करने के लिए।
cdiggins

2
हीप / प्रायोरिटी क्यू के सबसे बड़े लाभों में से एक है ओ (1) मिन / अधिकतम निष्कर्षण की जटिलता, यानी पीक ऑपरेशन। और यहाँ इसमें एन्यूमरेटर सेटअप, फॉर-लूप, आदि शामिल हैं क्यों !? इसके अलावा, O (logN) होने के बजाय "Enqueue" ऑपरेशन - हीप की एक अन्य प्रमुख विशेषता, "ContainsKey" की वजह से एक O (longN) स्वाइप है, क्यू प्रविष्टि को जोड़ने के लिए एक दूसरा (फिर से O (longN)) (यदि आवश्यक हो), एक तीसरा वास्तव में क्यू (भंडारण [पुजारी] लाइन) को पुनः प्राप्त करता है, और अंत में उस कतार में एक रैखिक जोड़ रहा है। यह वास्तव में कोर एल्गोरिदम कार्यान्वयन के प्रकाश में पागल है।
जोनन जॉर्जिएव

10

मुझे यहां जूलियन बकनेल ने अपने ब्लॉग पर पाया - http://www.boyet.com/Articles/PriorityQueueCShar.html

हमने इसे थोड़ा संशोधित किया ताकि कतार पर कम-प्राथमिकता वाले आइटम अंततः समय के साथ शीर्ष पर 'बबल-अप' कर सकें, इसलिए उन्हें भुखमरी का सामना करना पड़ेगा।


9

जैसा कि .NET के लिए Microsoft संग्रह में उल्लेखित है , Microsoft ने .NET फ्रेमवर्क के भीतर 2 आंतरिक प्रायोरिटी क्लासेस लिखे (और ऑनलाइन साझा किए गए हैं) । उनका कोड आज़माने के लिए उपलब्ध है।

EDIT: जैसा कि @ mathusum-mut ने टिप्पणी की है, माइक्रोसॉफ्ट के आंतरिक प्रायोरिटी क्यू वर्गों में से एक में बग है (एसओ समुदाय ने, निश्चित रूप से, इसके लिए फ़िक्स प्रदान किया है): Microsoft के आंतरिक प्रायोरिटी क्यू में बग <T>?


10
यहाँ एक कार्यान्वयन में एक बग पाया गया: stackoverflow.com/questions/44221454/…
माथुसम मट

ओह! मैं देख सकता हूं कि PriorityQueue<T>Microsoft के साझा स्रोत में ये सभी कक्षाएं internalएक्सेस स्पेसियर के साथ चिह्नित हैं । इसलिए इनका उपयोग केवल रूपरेखा की आंतरिक क्रियाओं द्वारा किया जाता है। वे केवल windowsbase.dllC # प्रोजेक्ट में संदर्भित करके सामान्य उपभोग के लिए उपलब्ध नहीं हैं । केवल तरीका साझा स्रोत को एक वर्ग फ़ाइल के अंदर प्रोजेक्ट में कॉपी करना है।
RBT


7
class PriorityQueue<T>
{
    IComparer<T> comparer;
    T[] heap;
    public int Count { get; private set; }
    public PriorityQueue() : this(null) { }
    public PriorityQueue(int capacity) : this(capacity, null) { }
    public PriorityQueue(IComparer<T> comparer) : this(16, comparer) { }
    public PriorityQueue(int capacity, IComparer<T> comparer)
    {
        this.comparer = (comparer == null) ? Comparer<T>.Default : comparer;
        this.heap = new T[capacity];
    }
    public void push(T v)
    {
        if (Count >= heap.Length) Array.Resize(ref heap, Count * 2);
        heap[Count] = v;
        SiftUp(Count++);
    }
    public T pop()
    {
        var v = top();
        heap[0] = heap[--Count];
        if (Count > 0) SiftDown(0);
        return v;
    }
    public T top()
    {
        if (Count > 0) return heap[0];
        throw new InvalidOperationException("优先队列为空");
    }
    void SiftUp(int n)
    {
        var v = heap[n];
        for (var n2 = n / 2; n > 0 && comparer.Compare(v, heap[n2]) > 0; n = n2, n2 /= 2) heap[n] = heap[n2];
        heap[n] = v;
    }
    void SiftDown(int n)
    {
        var v = heap[n];
        for (var n2 = n * 2; n2 < Count; n = n2, n2 *= 2)
        {
            if (n2 + 1 < Count && comparer.Compare(heap[n2 + 1], heap[n2]) > 0) n2++;
            if (comparer.Compare(v, heap[n2]) >= 0) break;
            heap[n] = heap[n2];
        }
        heap[n] = v;
    }
}

आसान।


13
कभी-कभी मुझे सामान दिखाई देता है for (var n2 = n / 2; n > 0 && comparer.Compare(v, heap[n2]) > 0; n = n2, n2 /= 2) heap[n] = heap[n2]; और आश्चर्य होता है कि क्या यह एक-अस्तर के लायक था

1
@ डस्टबिनके व्यक्तिगत शैली :)
शिमौ डोंग

3
लेकिन निश्चित रूप से दूसरों के लिए पठनीय नहीं है। लेखन कोड पर विचार करें जो डेवलपर के सिर के ऊपर एक प्रश्न चिह्न तैरता नहीं है।
अलज़ीमार

3

जावा कलेक्शंस फ्रेमवर्क में जावा कार्यान्वयन (java.util.PyerityQueue) पर जावा से C # अनुवादक का उपयोग करें, या अधिक समझदारी से एल्गोरिथ्म और कोर कोड का उपयोग करें और इसे C # कलेक्शन फ्रेमवर्क के अनुरूप बनाने वाले अपने स्वयं के C # वर्ग में प्लग करें। क्यू के लिए एपीआई, या कम से कम संग्रह।


यह काम करता है, लेकिन दुर्भाग्य से IKVM जावा जेनरिक का समर्थन नहीं करता है, इसलिए आप प्रकार की सुरक्षा खो देते हैं।
मेकैनिकल घोंघा

8
जब आप संकलित जावा बाइटकोड के साथ काम कर रहे हैं तो "जावा जेनरिक" जैसी कोई चीज नहीं है। IKVM इसका समर्थन नहीं कर सकता।
मार्क

3

AlgoKit

मैं कहा जाता है एक खुला स्रोत पुस्तकालय लिखा AlgoKit , उपलब्ध के माध्यम से NuGet । इसमें शामिल है:

  • अव्यवस्थित डी-आर्य ढेर (ArrayHeap),
  • द्विपद ढेर ,
  • जोड़ीदार ढेर

कोड का बड़े पैमाने पर परीक्षण किया गया है। मैं निश्चित रूप से आपको यह कोशिश करने की सलाह देता हूं।

उदाहरण

var comparer = Comparer<int>.Default;
var heap = new PairingHeap<int, string>(comparer);

heap.Add(3, "your");
heap.Add(5, "of");
heap.Add(7, "disturbing.");
heap.Add(2, "find");
heap.Add(1, "I");
heap.Add(6, "faith");
heap.Add(4, "lack");

while (!heap.IsEmpty)
    Console.WriteLine(heap.Pop().Value);

वो तीनों ढेर क्यों?

कार्यान्वयन के इष्टतम पसंद दृढ़ता से इनपुट पर निर्भर है - लार्किन, सेन, और में Tarjan शो के रूप में एक बैक-टू-मूल बातें प्राथमिकता कतारों की अनुभवजन्य अध्ययन , arXiv: 1403.0252v1 [cs.DS] । उन्होंने अंतर्निहित डी-आर्य ढेर, युग्मन ढेर, फाइबोनैचि ढेर, द्विपद ढेर, स्पष्ट डी-आर्य ढेर, रैंक-जोड़ी ढेर, भूकंप ढेर, उल्लंघन ढेर, रैंक-आराम से कमजोर ढेर और सख्त फाइबोनैचि ढेर का परीक्षण किया।

AlgoKit में तीन प्रकार के ढेर लगे हैं जो उन लोगों के बीच सबसे अधिक सक्षम हैं जो परीक्षण किए गए थे।

पसंद पर इशारा

तत्वों की अपेक्षाकृत कम संख्या के लिए, आपको संभवतः अंतर्निहित ढेर, विशेष रूप से चतुर्धातुक ढेर (अंतर्निहित 4-आर्य) का उपयोग करने में रुचि होगी। बड़े ढेर के आकार पर काम करने के मामले में, द्विपद ढेर और युग्मन ढेर जैसी परिशोधन संरचनाएं बेहतर प्रदर्शन करना चाहिए।



1

मेरे पास हाल ही में एक ही मुद्दा था और इसके लिए एक NuGet पैकेज बनाना था।

यह मानक हीप-आधारित प्राथमिकता कतार को लागू करता है। इसमें बीसीएल संग्रह की सभी सामान्य बारीकियां भी हैं: ICollection<T>और IReadOnlyCollection<T>कार्यान्वयन, कस्टम IComparer<T>समर्थन, एक प्रारंभिक क्षमता निर्दिष्ट करने की क्षमता, और एकDebuggerTypeProxy डीबगर में संग्रह को आसान बनाने के लिए।

पैकेज का एक इनलाइन संस्करण भी है जो सिर्फ एक एकल .cs फ़ाइल को आपकी परियोजना में स्थापित करता है (यदि आप बाहरी रूप से दृश्यमान निर्भरता लेने से बचना चाहते हैं तो उपयोगी है)।

अधिक जानकारी जीथूब पेज पर उपलब्ध है ।


1

एक साधारण अधिकतम हीप कार्यान्वयन।

https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/MaxHeap.cs

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

namespace AlgorithmsMadeEasy
{
    class MaxHeap
    {
        private static int capacity = 10;
        private int size = 0;
        int[] items = new int[capacity];

        private int getLeftChildIndex(int parentIndex) { return 2 * parentIndex + 1; }
        private int getRightChildIndex(int parentIndex) { return 2 * parentIndex + 2; }
        private int getParentIndex(int childIndex) { return (childIndex - 1) / 2; }

        private int getLeftChild(int parentIndex) { return this.items[getLeftChildIndex(parentIndex)]; }
        private int getRightChild(int parentIndex) { return this.items[getRightChildIndex(parentIndex)]; }
        private int getParent(int childIndex) { return this.items[getParentIndex(childIndex)]; }

        private bool hasLeftChild(int parentIndex) { return getLeftChildIndex(parentIndex) < size; }
        private bool hasRightChild(int parentIndex) { return getRightChildIndex(parentIndex) < size; }
        private bool hasParent(int childIndex) { return getLeftChildIndex(childIndex) > 0; }

        private void swap(int indexOne, int indexTwo)
        {
            int temp = this.items[indexOne];
            this.items[indexOne] = this.items[indexTwo];
            this.items[indexTwo] = temp;
        }

        private void hasEnoughCapacity()
        {
            if (this.size == capacity)
            {
                Array.Resize(ref this.items,capacity*2);
                capacity *= 2;
            }
        }

        public void Add(int item)
        {
            this.hasEnoughCapacity();
            this.items[size] = item;
            this.size++;
            heapifyUp();
        }

        public int Remove()
        {
            int item = this.items[0];
            this.items[0] = this.items[size-1];
            this.items[this.size - 1] = 0;
            size--;
            heapifyDown();
            return item;
        }

        private void heapifyUp()
        {
            int index = this.size - 1;
            while (hasParent(index) && this.items[index] > getParent(index))
            {
                swap(index, getParentIndex(index));
                index = getParentIndex(index);
            }
        }

        private void heapifyDown()
        {
            int index = 0;
            while (hasLeftChild(index))
            {
                int bigChildIndex = getLeftChildIndex(index);
                if (hasRightChild(index) && getLeftChild(index) < getRightChild(index))
                {
                    bigChildIndex = getRightChildIndex(index);
                }

                if (this.items[bigChildIndex] < this.items[index])
                {
                    break;
                }
                else
                {
                    swap(bigChildIndex,index);
                    index = bigChildIndex;
                }
            }
        }
    }
}

/*
Calling Code:
    MaxHeap mh = new MaxHeap();
    mh.Add(10);
    mh.Add(5);
    mh.Add(2);
    mh.Add(1);
    mh.Add(50);
    int maxVal  = mh.Remove();
    int newMaxVal = mh.Remove();
*/

-3

सिस्टम लाइब्रेरी से PriorityQueueउपयोग का निम्नलिखित कार्यान्वयन SortedSet

using System;
using System.Collections.Generic;

namespace CDiggins
{
    interface IPriorityQueue<T, K> where K : IComparable<K>
    {
        bool Empty { get; }
        void Enqueue(T x, K key);
        void Dequeue();
        T Top { get; }
    }

    class PriorityQueue<T, K> : IPriorityQueue<T, K> where K : IComparable<K>
    {
        SortedSet<Tuple<T, K>> set;

        class Comparer : IComparer<Tuple<T, K>> {
            public int Compare(Tuple<T, K> x, Tuple<T, K> y) {
                return x.Item2.CompareTo(y.Item2);
            }
        }

        PriorityQueue() { set = new SortedSet<Tuple<T, K>>(new Comparer()); }
        public bool Empty { get { return set.Count == 0;  } }
        public void Enqueue(T x, K key) { set.Add(Tuple.Create(x, key)); }
        public void Dequeue() { set.Remove(set.Max); }
        public T Top { get { return set.Max.Item1; } }
    }
}

6
SortedSet.Add विफल हो जाएगा (और गलत वापसी) यदि आपके पास पहले से ही "प्राथमिकता" के साथ सेट में एक आइटम है जिस आइटम को आप जोड़ने की कोशिश कर रहे हैं। तो ... यदि A.Compare (B) == 0 और A पहले से ही सूची में है, तो आपका प्रायोरिटी क्यू.इन्केयू फ़ंक्शन चुपचाप विफल हो जाएगा।
जोसेफ

समझाने के लिए मन क्या है T xऔर K key? मुझे लगता है कि यह डुप्लिकेट की अनुमति देने की एक चाल है T x, और मुझे एक अद्वितीय कुंजी (जैसे UUID) उत्पन्न करने की आवश्यकता है?
थारिक नुगरोतोमो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.