2016-07-30 6 views
1

私はC#で新しいです。私はヒープ構造を作成しようとしましたが、この質問を思いつきました。ヒープ構造に「比較クラス」を渡すにはどうすればいいですか?つまり、私はヒープを作成したいと思っています:Heap<int, cmp<int>> heap = new Heap<int, cmp<int>>(); "cmp"はヒープを優先順位にする比較クラスです(私はC++のpriority_queueという考え方を取っていました)。C#でジェネリック型の比較クラスを渡す

public class Heap<T, Priority> 
    where Priority : IPriority<T>, new() 
    where T : IComparable 
{ 
    private List<T> storage = new List<T>();   
    private Priority HeapPriority = new Priority(); 
    private void UpHeap(int position) 
    {    
     for(var i = position; i > 0; i = (i - 1) >> 1) 
     { 
      // Check whether storage[i] is more Priority than storage[(i - 1) >> 1] 
      if (HeapPriority.MorePriority(storage[i], storage[(i - 1) >> 1]) 
       .CompareTo(storage[i]) == 0) 
      { 
       storage.Swap(i, (i - 1) >> 1); 
      } 
      else break; 
     } 
    } 
} 

、ここではIPriorityインタフェースである:私は最大 - 最小比較子を取るヒープを作る際に(と思う)成功してい

public interface IPriority<T> 
    where T : IComparable 
{ 
    T MorePriority(T a, T b); 
} 

と私はこのようなヒープの使用:

public class Min<T> : IPriority<T> 
     where T : IComparable 
    { 
     public Min() { } 
     public T MorePriority(T a, T b) 
     { 
      return a.CompareTo(b) <= 0 ? a : b; 
     } 
    } 
static public void TestHeap() 
    { 
     var heap = new Heap<Pair<long, int>, Min<Pair<long, int>>>();    
     heap.Add(Pair<long, int>(10, 20)); 
     heap.Add(Pair<long, int>(21, 100)); 
     // ... 
    } 

しかし、max-minオーダーだけでなく、必要な方法でアイテムをソートするヒープが必要です。さらに、 "Ipriority.MorePriority"を静的メソッドとして使用する方法はありますか?静的メソッドと同じように機能するためです。誰も私にいくつかのアドバイスを与えることができますか? 私の悪い英語を申し訳ありません。

+1

明白な答えは、 'IComparer 'を使用することです。なぜあなたはいないのですか?問題にアプローチする方法はたくさんあります。 _something_を試してください。その後、_specific_質問がある場合は、あなたが持っている特定の問題を明確に示す良い[mcve]で新しい質問を投稿してください。 –

+0

ありがとうございます。ちゃんと覚えておきますよ。これは私の最初の質問ですので、何か愚かな質問をおかけして申し訳ありません –

+0

愚かな質問はありません。ここで問題となるのは、可能な回答を調査していることを示す兆候はなく、決して解決策を実装しようとする際にどのような問題があったかは心配しないことです。あなたが明白なことを見逃していればそれはいいですし、それは実際には答えですが、明白な答えを逃した人さえもおそらく_何かを試すでしょう。 –

答えて

2

IComparer<T>従属として処理してコンストラクタに渡すことをお勧めします。このような何か:

// You can create a heap of any type, right? 
    // But in some cases (e.g. Heap<Button>) you should provide a comparer: 
    // how to compare Button instances 
    public class Heap<T> { 
    //TODO: implement here Heap as well as Unheap method having IComparer<T> m_Comparer 
    ... 
    private IComparer<T> m_Comparer; 

    // comparer = null - if comparer is not provided, try to use default one 
    // if it's possible (e.g. in case of Heap<double>) 
    public Heap(IComparer<T> comparer = null): base() { 
     // Do we have a default comparer (e.g. for int, double, string)? 
     if (null == comparer) 
     if (typeof(IComparable).IsAssignableFrom(typeof(T)) || 
      typeof(IComparable<T>).IsAssignableFrom(typeof(T))) 
      comparer = Comparer<T>.Default; 

     if (null == comparer) 
     throw new ArgumentNullException("comparer", string.Format(
      "There's no default comparer for {0} class, you should provide it explicitly.", 
      typeof(T).Name)); 

     m_Comparer = comparer; 
    } 
    ... 
    } 

ですから、ヒープ

// heap of integers, default comparer 
    Heap<int> heap1 = new Heap<int>(); 

    // heap of integers, custom comparer (via lambda) 
    Heap<int> heap2 = new Heap<int>(Comparer<int>.Create((x, y) => -x.CompareTo(y))); 

    // heap of Buttons, custome comparer 
    Heap<Button> heap3 = new Heap<Button>(Comparer<Button>.Create((x, y) => ...)); 

そして、この意志スロー例外作成することができます:あなたはちょうどIComparer<T>を使用する必要がありますButtonクラスの無既定の比較

Heap<Button> heapErr = new Heap<Button>(); 
+0

ご協力いただきありがとうございます。しかし、私は例外をスローするかスローしないのですか?私はTがIComparableになるように制約することができます。つまり、 "T"にデフォルトの比較関数がない場合、実行時ではなくコンパイル時に問題を検出できます。私が間違っていれば私を修正してください。 –

+0

@AnhHaoTrントn:もし* T *に*デフォルト*の比較者がいなくても 'Heap 'を作成するのは合理的だと思われますが、*カスタム比較者*を提供するのは難しいでしょうか?可能であれば 'List .Sort'を参照してください。デフォルトの比較機能を試すことができます。あなたはカスタムと拘束を提供することができます。 –

+0

ああ、わかりました。どうもありがとうございます。 –

0

を、これは.NETのすべてのコレクションが使用するものです。たとえば:

public class Heap<T> 
{ 
    private IComparer<T> comparer; 
    private List<T> storage = new List<T>();  

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

    public Heap(IComparer<T> comparer) 
    { 
     this.comparer = comparer; 
    } 

    private void UpHeap(int position) 
    {    
     for(var i = position; i > 0; i = (i - 1) >> 1) 
     { 
      // Check whether storage[i] is more Priority than storage[(i - 1) >> 1] 
      if (comparer.Compare(storage[i], storage[(i - 1) >> 1]) > 0) 
      { 
       storage.Swap(i, (i - 1) >> 1); 
      } 
      else break; 
     } 
    } 
} 

これにはいくつかの利点があります。

  • あなたは他の方法でヒープを参照するときに、より多くの便利な比較演算、のための余分なタイプのパラメータは必要ありません。
  • TIComparableにする必要はありません。
  • ICompatableInt32のように)を実装している場合、Comparer<T>.Defaultはその実装を使用します。
+0

ありがとうございます。あなたのソリューションは私のためにも機能します。 –

関連する問題