.Net의 우선 순위 대기열 [닫힘]


216

우선 순위 대기열 또는 힙 데이터 구조의 .NET 구현을 찾고 있습니다.

우선 순위 대기열은 새로운 정렬이 임의의 간격으로 시스템에 들어갈 수 있기 때문에 간단한 정렬보다 유연성이 뛰어난 데이터 구조입니다. 도착할 때마다 모든 항목을 다시 정렬하는 것보다 우선 순위 대기열에 새 작업을 삽입하는 것이 훨씬 비용 효율적입니다.

기본 우선 순위 큐는 세 가지 기본 조작을 지원합니다.

  • 삽입 (Q, x). 키 k가있는 x 항목이 있으면 우선 순위 큐 Q에 삽입하십시오.
  • 최소값 찾기 (Q). 우선 순위 큐 Q의 다른 키보다 키 값이 작은 항목에 대한 포인터를 리턴하십시오.
  • 최소 삭제 (Q). 키가 최소 인 우선 순위 큐 Q에서 항목을 제거하십시오.

내가 틀린 곳을보고 있지 않는 한, 틀 안에는 없습니다. 누구든지 좋은 것을 알고 있습니까, 아니면 내 자신을 굴려야합니까?


34
참고로 나는 개발했습니다 찾을 수 있습니다 사용하기 쉬운, 고도로 최적화 된 C #을 우선 순위 큐, 여기를 . 경로 찾기 응용 프로그램 (A * 등)을 위해 특별히 개발되었지만 다른 응용 프로그램에서도 완벽하게 작동합니다. 나는 대답으로이 게시 것이지만, 문제는 최근에 ... 닫힌
대니 Pflughoeft - BlueRaja

1
ParallelExtensionsExtras는 ConcurrentPriorityQueue가 code.msdn.microsoft.com/ParExtSamples
VoteCoffee

Spring.Net을 위해 Java 동시 API를 .net으로 포팅하려는 노력의 일환으로 PriorityQueue를 뻔뻔스럽게 소개 합니다. 완전히 일반 지원되는 힙 및 대기열입니다. 바이너리는 여기에서 다운로드 할 수 있습니다 .
Kenneth Xu

@ BlueRaja-DannyPflughoeft 답변을 추가 할 수 있습니까?
mafu

1
요약하면됩니다. .net에는 힙 데이터 구조가 없으며 .net 코어에는 없습니다. 비록 에 Array.sort의 큰 숫자에 대한 사용자를. 내부 구현 이 존재합니다.
Artyom

답변:


44

PowerCollectionsOrderedBagOrderedSet클래스 를 우선 순위 대기열로 사용하는 것이 좋습니다.


60
OrderedBag / OrderedSet은 필요한 것보다 많은 작업을 수행하며 힙 대신 빨강-검정색 트리를 사용합니다.
Dan Berindei

3
@ DanBerindei : 당신이 실행 계산 (오래된 항목 삭제), 힙 만 또는 최대 삭제를 지원 해야하는 경우 필요한 작업이 없습니다
Svisstack

69

C5 Generic Collection Library 의 IntervalHeap을 좋아할 것 입니다. 사용 설명서 를 인용하려면

클래스 는 쌍의 배열로 저장된 간격 힙을 사용하여 IntervalHeap<T>인터페이스 IPriorityQueue<T>를 구현 합니다. FindMin 및 FindMax 작업과 인덱서의 get-accessor는 시간이 O (1)입니다. DeleteMin, DeleteMax, 추가 및 업데이트 작업 및 인덱서의 set 접근자는 시간이 O (log n)입니다. 일반 우선 순위 큐와 달리 간격 힙은 동일한 효율성으로 최소 및 최대 조작을 모두 제공합니다.

API는 충분히 간단합니다

> 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를 구현해야합니다. 더 나쁜 것은 이전의 일부 항목의 우선 순위를 직접 업데이트 할 수있는 방법이 없습니다 !!!
morteza khosravi

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
멋지지만 항목을 제거 할 수 없습니까? 우선 순위 대기열에 중요한 작업입니다.
톰 Larkworthy

기본 개체가 배열 인 것 같습니다. 이것은 이진 트리보다 좋지 않습니까?
Grunion Shaftoe

1
@OhadSchneider는 매우 멋지다. 최소 힙을 조사하고 일반 및 최소 또는 최대 힙으로 한 일을하려고했습니다! 훌륭한 작품
Gilad

1
@Gilad IEqualityComparer<T>는 두 항목이 같은지 여부 만 알려주는 것만으로는 충분하지 않지만 그 사이의 관계를 알아야합니다 (작은 사람 / 큰 사람). 내가 IComparer<T>비록 그것을 사용할 수 있었던 것은 사실이다. ..
Ohad Schneider

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++;

        }
    }
}

그래도 우선 순위가 같은 여러 항목을 허용하지 않습니까?
Letseatlunch

2
그렇습니다. Enqueue 메서드를 호출하면 해당 우선 순위의 큐에 항목이 추가됩니다. (enqueue 방법의 다른 부분.)
kobi7

5
"컴퓨터 과학의 의미에서 실제로 우선 순위 대기열이 아닙니다"는 무슨 뜻입니까? 이것이 우선 순위 대기열이 아니라고 생각하는 것은 어떻습니까?
Mark Byers

14
제네릭을 사용하지 않는 경우 -1입니다.
cdiggins

2
Heap / PriorityQueue의 가장 큰 장점 중 하나는 최소 / 최대 추출의 O (1) 복잡성, 즉 Peek 작업입니다. 그리고 여기에는 열거 자 설정, for 루프 등이 포함됩니다. 왜!? 또한 힙의 또 다른 주요 기능인 O (logN)가 아닌 "인큐"조작은 큐 항목을 추가하는 두 번째 (O (longN)) 인 "ContainsKey"로 인해 O (longN) 스 와이프가 있습니다. (필요한 경우) 실제로 대기열 (storage [prio] 행)을 검색하는 세 번째 대기열이며 마지막으로 해당 대기열에 선형으로 추가됩니다. 이것은 핵심 알고리즘 구현에 비추어 볼 때 정말 미쳤다.
Jonan Georgiev


9

Microsoft Collections for .NET 에서 언급했듯이 Microsoft는 .NET Framework 내에서 2 개의 내부 PriorityQueue 클래스를 작성 (온라인 공유)했습니다 . 그들의 코드는 시험해 볼 수 있습니다.

편집 : @ mathusum-mut이 언급했듯이 Microsoft 내부 PriorityQueue 클래스 중 하나에 버그가 있습니다 (SO 커뮤니티는 물론 수정 사항을 제공했습니다). Microsoft 내부 PriorityQueue <T>의 버그?


10
여기에서 구현 중 하나에서 버그가 발견되었습니다. stackoverflow.com/questions/44221454/…
MathuSum Mut

아! 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
@DustinBreakey 개인 스타일 :)
Shimou Dong

3
그러나 다른 사람들이 읽을 수는 없습니다. 개발자의 머리 위에 물음표가 떠 다니지 않는 코드 작성을 고려하십시오.
alzaimar

3

Java Collections 프레임 워크의 Java 구현 (java.util.PriorityQueue)에서 Java to C # 변환기를 사용하거나 알고리즘 및 코어 코드를보다 지능적으로 사용하여 C # Collections 프레임 워크를 준수하는 고유 한 C # 클래스에 연결하십시오. 큐용 API 또는 최소한 컬렉션입니다.


이것은 작동하지만 불행히도 IKVM은 Java 제네릭을 지원하지 않으므로 형식 안전성이 손실됩니다.
기계 달팽이

8
컴파일 된 Java 바이트 코드를 처리 할 때 "Java generics"와 같은 것은 없습니다. IKVM은이를 지원할 수 없습니다.
Mark

3

AlgoKit

NuGet을 통해 사용할 수있는 AlgoKit 이라는 오픈 소스 라이브러리를 작성했습니다 . 그것은 포함합니다 :

  • 암시 적 d-ary 힙 (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);

왜 그 세 힙입니까?

Larkin, Sen 및 Tarjan 이 우선 순위 대기열에 대한 기본 실습 연구 , arXiv : 1403.0252v1 [cs.DS] 에서 최적의 구현 선택은 입력에 따라 크게 달라 집니다. . 이들은 암시 적 이진 힙, 페어링 힙, 피보나치 힙, 이항 힙, 명시 적 이진 힙, 순위 쌍 힙, 쿼크 힙, 위반 힙, 순위 완화 약한 힙 및 엄격한 피보나치 힙을 테스트했습니다.

AlgoKit에는 테스트 된 것 중에서 가장 효율적인 것으로 보이는 세 가지 유형의 힙이 있습니다.

선택에 힌트

상대적으로 적은 수의 요소의 경우 암시 적 힙, 특히 4 차 힙 (암시 적 4-ary)을 사용하는 것이 좋습니다. 더 큰 힙 크기에서 작동하는 경우 이항 힙 및 페어링 힙과 같은 상각 구조가 더 잘 수행되어야합니다.



1

최근에 같은 문제가 발생하여 NuGet 패키지 를 만들었습니다 .

표준 힙 기반 우선 순위 큐를 구현합니다. : 또한 모든 일반적인 BCL 컬렉션의 미묘한있다 ICollection<T>IReadOnlyCollection<T>구현, 사용자 정의 IComparer<T>지원, 초기 용량을 지정하는 기능, 그리고를DebuggerTypeProxy 디버거에서 작업 할 컬렉션을 쉽게 할 수 있습니다.

도 있습니다 인라인프로젝트에 단일 .cs 파일을 설치 버전의 패키지도 있습니다 (외부에서 보이는 종속성을 피하려는 경우에 유용).

자세한 내용은 github 페이지 에서 확인할 수 있습니다 .


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가 실패하고 false를 반환합니다. 따라서 ... A.Compare (B) == 0이고 A가 이미 목록에 있으면 PriorityQueue.Enqueue 함수가 자동으로 실패합니다.
Joseph

T x그리고 무엇을 설명하는 마음 K key? 나는 이것이 복제를 허용하는 트릭이라고 추측 T x하고 있으며 고유 키 (예 : UUID)를 생성해야합니까?
Thariq Nugrohotomo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.