views:

188

answers:

1

I have a priority queue implementation in C# that I want to add a .IndexOf method to.

However, since the priority queue doesn't really concern itself with the order of the values themselves (that is, if I were to just grab all the values, disregarding their priorities, they wouldn't necessarily have any order at all), only the priority of them, I don't have any criteria for the generic type T of the priority queue, that is, I don't specify that they need to have some intrinsic order, or comparability.

As such, when I came to implement .IndexOf(T value) I have a minor problem.

Is there a standard in what/how I should implement this? My initial thoughts was simply to use EqualityComparer<T>.Default to figure if I have found the value or not, but then there are so many similar such types these days.

For instance, here's what I came up with to cover my basis, but this seems overkill:

  • public Int32 IndexOf(T value) (internally calls one of the others with ClassThatImplementsInterface.Default)
  • public Int32 IndexOf(T value, IComparer<T> comparer)
  • public Int32 IndexOf(T value, IEqualityComparer<T> comparer)
  • public Int32 IndexOf(T value, IEquatable<T> comparer)
  • public Int32 IndexOf(T value, Predicate<T> predicate)

What do you do? Marking this as both subjective and wiki as this is more of an opinion poll than anything else.

On re-reading my own question I guess I can just use the one without a comparer, and then add the predicate version, this way the user of this class can call just about anything.

Also note that I can also do pq[index] to get hold of a item that contains both the priority and the value itself, so I could also get by without IndexOf at all, but I'd also like to have methods that says change the priority of value X to priority P, which would necessitate some form of IndexOf/search internally. And thus I'd also like to avoid having to have umpteenth overloads of all these methods as well.


Response to comment: Yes, the priority queue is based on a heap.

Basically, the two classes are defined like this:

public class Heap<T> : IEnumerable<T>, ICloneable { ... }
public class PriorityQueue<T> : Heap<PriorityQueueElement<T>> { ... }

PriorityQueueElement is a simple immutable structure with Priority and Value properties.

Response to forthcoming comment: Since the priority queue is based on a heap, an "interesting property" is that by changing the priority of a value through its index means that afterwards, the value won't necessarily be at that index. I intend to just document this as in some cases I foresee a need for independent locate/change-priority operations.

+2  A: 

I would make the comparison an optional constructor parameter; this is comparable to how things like Dictionary<,>, SortedList<,> etc allow you to specify the comparison mechanism.

Whether to accepts an IComparer<T> or an IEqualityComparer<T> depends on whether you are going to sort the data, or just look for an equality match; if the match, then you'll need something like IEqualityComparer<T>. Unfortunately, since this has 2 methods (GetHashCode() and Equals()) there is no direct delegate version of this, except perhaps Predicate<T> or Func<T,T,bool>.

For the default constructor, I'd pass in the [Equality]Comparer<T>.Default.

Marc Gravell
That's basically what I've decided to do for now, at least while I'm still developing the class.
Lasse V. Karlsen