2

This is a somewhat follow-up question on how to represent priorities
The answers direct me towards basing the design on the Priority Queue ADT.

My problem is that I can not figure out how to model this problem (I understand how a PQ works).
So using my original (trivial example) assume I have PersonA PersonB ...PersonY (represented as classes) which favor various dishes Pizzas Spaggeti Steak etc.
I want to find a way to specify which dish should be served to wish person according to Preference (which could be an extra class as friends in answers of the starting question thread also suggested).
I am not sure how this should be modelled. My first thought is to create a PriorityQueue for each dish (PizzaPQ, SpaggetiPQ etc), throw-in each queue all the Persons and start removing the top from each queue (as the one that has the max preference for that dish) and remove that Person from the other queues. This process goes over all queues sequentially.
Now although conceptually it seems correct (but it is not best approach since I have in my mind that discrepancies will appear due to the process itself), I don't think that I am on the right track, since

  1. The remove from the other queues is linear operation (I am talking about remove(Object) where Object has already been served Pizza and should not be in the other queues any more) and would cost O(N*k) where k is the number of queues (and this seems to me to add quite a lot to the usage of the priority queue in the first place)
  2. It seems to me that I need some abstraction to work over a "pool" of priority queues and I am not sure if there is actually such data structure and I am not aware of it.

I guess this problem could generalize as how to assign jobs or how to manipulate multiple queues (perhaps?)
There must be a standard design approach for problems like these.
Any input is highly welcome

Update after @Thomas answer:
The problem is slightly more complicated.
Besides the preference there could be other attributes (of a person) that could come into place.
E.g. PersonA and PersonB both prefer steak over anyother dish. But PersonA has high cholesterol and PersonB is an athlete. Taking somehow these attributes into account then PersonB should get the steak. And perhaps PersonA could eventually end up with something else.
This is why I orinally thought about PQs of dishes

Community
  • 1
  • 1
Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • When you mention: "throw-in each queue all the Persons" do you mean that every person would be in every queue? If so, why, what's the use-case for that? Why not only add people to the dish queues that they are interested in? – Brady May 02 '12 at 17:37
  • @Brady:Good point.I am mentioning the worse case where all the persons are interested in all dishes but with different preference over each – Cratylus May 02 '12 at 19:38

3 Answers3

1

Is it possible that this application could be executed in a multi-threaded environment? If so, I have a few ideas that could help.

  1. Create a dispatcher thread whose job is to take a Person object and assign it to a PQ. Assuming that a Person should only be on 1 PQ, this helps solve your problem about removing Persons from other PQs mentioned above. This would move the logic (and CPU processing time) of where a Person should be placed away from the PQ execution part of the code allowing the PQ to be more cohesive and lowering its coupling with the Person. If it is possible for a Person to be on more than one PQ, or you want to move them from one PQ to another, etc this should be performed in the dispatcher code.

  2. If there are more PQs than available threads, create a thread pool for the PQs, else just simply create a thread per PQ. This way you wont have to worry about how to iterate over the PQs and possible PQ starvation. The code to handle the PQ and Person objects would be the same for each thread.

Even if you dont go with a multi-threaded model, I would consider making the Person object inherit from a PQitem object that the PQ knows about so the PQ doesnt have to know anything about the Person object, maybe something like this: (sorry for the c++, but I think you get the idea)

class PQitem
{
public:
    virtual void execute() = 0;
    virtual void getPriority() = 0;
private:
    // PQ specific stuff here
};

class Person : public PQitem
{
public:
    void execute() { /* logic executed when taken off the PQ */ }
    void getPriority() { /* logic used to determine where to place this Person */ }
};
Brady
  • 10,207
  • 2
  • 20
  • 59
0

What about inverting the logic?

  • put all the dishes into a map
  • loop over all persons
    • loop over the person's priority queue of dishes
    • check if the dish is still in the map
    • if the dish is on the map remove it and end the loop

This way, you'd have a map of dishes and a list of persons with their priority queues (or a map person->queue).

Iteration would then be O(n * m) where n is the number of persons and m is the length of a person's dish priority queue.

If you later add a counter to the dish map, e.g. you have 5 pizzas available, all you'd need to change would be to remove the dish from the map when the counter reaches 0 (and incrementing the counter when serving a dish, of course :) ).

You'd still have to handle the following:

  • Who's gonna start getting served?
  • What happens if none of the dishes in a person's priority queue is in the map anymore?

One approach to those questions might be to start with the persons that have the shortest priority queues since it's more likely for them not to get any dish. This still doesn't solve the entire problem (what if two persons only want pizza and there's only a single pizza around?).

Thomas
  • 87,414
  • 12
  • 119
  • 157
0

Here is a link to java's priority queue: http://docs.oracle.com/javase/7/docs/api/

The key to defining priorities is defining a Comparator that compares the different dishes. It could be that you have only 1 comparator or a Comparator for each person which defines their preference.

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80