You can make a priority queue act like a normal queue by decreasing the priority of elements as you add them to the prority queue (that is, each new element has lower priority than all previously added elements). A variable can be used to keep track of the lowest priority used so far.
You can make a priority queue act like a stack by increasing the priority of elements as you add them to the priority queue.
100 / 22 / \ 11 30 / \ / 5 15 25 \ 9 / \ 7 10
15 / \ 10 25 / \ / \ 7 11 22 100 / \ / 5 9 30
Here are the hash codes
If we chain, we get
If we rehash by offsetting by one we get
If we rehash by increasing the table size by 1
The total cost of this tree is 13.
This is closely related to the minimum spanning tree algorithm, although the MST algorithms we wrote were for undirected graphs. It turns out that the policy of "pick a node to start with" doesn't work for directed graphs, as you might tell by considering a two-node graph in which it's cheap to go from A to B but expensive to go from B to A.
If you limit each person to one call, this is a close variant of the traveling salesperson problem.
/** * Compute a calling tree based on an n-by-n matrix. Assumes that * it is "free" to call the first person. Returns a dictionary that * specifies who each person calls. * pre: The matrix contains nonnegative nonnull entries. * post: A minimum caling tree is returned. * post: The underlying matrix isn't affected. */ public Dictionary callTree(Matrix m) { Iterator names = m.labels(); // The people Dictionary calls = new Dictionary(); // The thing we'll return Iterator callers = m.labels(); // Potential makers of calls Iterator callees = m.labels(); // Potential recipients of calls Iterator person; // One person in some list Iterator caller; // One person making a call Iterator callee; // One person receiving a call // Note: since we've assumed that the first call is free, we want // to make that the call to the person who would otherwise cost // more to call. Iterator max_call_cost = NOCALL; // The maximum cost of a call // found so far. Object max_caller; // The caller for that call Object max_callee; // The callee for that call // Initialize the dictionary so that each person has an empty // list of callees. for(names.reset(); names.hasMoreElements; ) { person = names.nextElement(); calls.add(person, new Linear()); } // for // For each person, determine how much it costs to call that person for(callees.reset(); callees.hasMoreElements; ) { callee = callees.nextElement(); // Get one caller callers.reset(); caller = callers.nextElement(); // Compare to others for(callers.reset(); callers.hasMoreElements; ) { person = callers.nextElement(); if (m.cost(person,callee) < m.cost(caller,callee)) { caller = person; } // if } // for // If it's cheaper to call that person than the most expensive // we've seen so far, add it. if (m.cost(caller,callee) <= max_call_cost) { calls.get(caller).add(callee); } // if cheap call // Otherwise, make the current one the most expensive and add // the previous most expensive. else { if (max_call_cost != NONCALL) { calls.get(max_caller).add(max_callee); } max_call_cost = m.cost(caller,callee); max_caller = caller; max_callee = callee; } // New most expensive call } // for each callee // We seem to be done return calls; } // callTree
This is an O(n^2) algorithm, assuming that we can get, reset, and traverse the list of nodes in O(n) time.
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
Source text last modified Tue Dec 16 17:34:35 1997.
This page generated on Wed Dec 17 08:32:44 1997 by SiteWeaver.
Contact our webmaster at rebelsky@math.grin.edu