The basic ideas of the priority queue specification, and also its implementation, really do not depend very much on the type of the elements. All that is required is that there is a way to compare two elements.
We would really like to avoid rewriting the priority queue class for every different kind of element.
We can use Java's interface facility to avoid such wasteful re-writing.
Syntax:
interface < interface name > { < constant declarations > // all are public and final < abstract method declarations > // all are public and abstract }Then you can have a class that implements an interface:
class < class name > implements < interface name > { // rest of class definition }In fact, a class can implement several interfaces. The syntax is
class < class name > implements < interface1 >, < interface2 >, ... {It can only extend (inherit from) one. It can extend one and implement others. For instance,
class < class name > extends < parent class > implements < interface name > {
Constants declared in an interface can be used as if they were declared locally in a class that implements the interface. An interface is a useful way to group together a collection of constants to be shared by several class hierarchies.
We can use the name of the interface as a type. Thus a method can have as a formal parameter an object whose type is a particular interface. The corresponding actual parameter can be any object that implements the interface.
interface ComparisonKey { // k1.compareTo(k2) returns 0 if k1 "equals" k2 // 1 if k1 "is greater than" k2 // -1 if k1 "is less than" k2 int compareTo(ComparisonKey k); // convert the object to a printable string: String toString(); }As is always the case with an interface, compareTo and toString are abstract methods: they have no body. Any class that implements this interface must provide actual code for these methods.
What's the usefulness of this interface? It will allow us to have a priority queue class that will work with any kinds of items, as long as they implement this interface.
Now suppose we use the array representation of a priority queue. We just have to change int to ComparisonKey in the right places:
class PriorityQueue { private ComparisonKey[] A = new ComparisonKey[100]; // int -> ComparisonKey private int next; PriorityQueue() { next = 0; } public void insert(ComparisonKey x) { // int -> ComparisonKey A[next] = x; next++; } public ComparisonKey remove() { // int -> ComparisonKey int max = A[0]; int maxLoc = 0; for (int cur = 1; cur < next; cur++) { if (max.compareTo(A[cur]) == -1) { // use compareTo method!!! max = A[cur]; maxLoc = cur; } } A[maxLoc] = A[next-1]; next--; return max; } }
Now, here is a possible PQItem class. This is for integers. Note that there is overhead in doing this for integers, but it gives us generality.
class PQItem implements ComparisonKey { private int key; PQItem(int value) { // constructor key = value; } public int compareTo(ComparisonKey k) { int otherKey = ( (PQItem) k).key; // convert argument to a PQItem // and extract its key if (key < otherKey) return -1; if (key > otherKey) return 1; return 0; // keys are equal }(If you don't like having to remember that -1 means "less than" etc., you can put some constants in the ComparisonKey interface, such as LT equals -1, EQ equals 0, GT equals 1, say, and then return LT, EQ or GT.)
If we want a PQItem class for strings, we would change the implementation of PQItem as follows:
Finally, here is the sorting algorithm:
void sortPQ (ComparisonKey[] A) { // type of A is only difference int n = A.length; PriorityQueue pq = new PriorityQueue(); for (int i = 0; i < n; i++) pq.insert(A[i]); for (int i = n-1; i >= 0; i++) A[i] = pq.remove(); }IMPORTANT TO NOTICE:
The public/private visibility modifiers of Java, and the discipline of not making the internal details be available outside are forms of information hiding.
Information hiding promotes modular programming -- you can switch implementations of one class without affecting (correctness of) other classes.
The key to abstraction is separating WHAT (the specification) from HOW (the implementation.