Please make sure you adhere to the policies on academic honesty.
NOTE: Please give a piece of Java code as your solution. Your
method should be defined in the spirit of,
Node concatenate(Node headerL, Node headerM) {
In creating the new list, you are free to damage or destroy the
original lists if you wish.
Please remember to report the running time!
A further hint can be found through Hint Server on textbook's website.
NOTE: Please give a piece of Java code as your solution.
Your method should be defined in the spirit of,
DLNode concatenate(DLNode headerL, DLNode trailerL,
DLNode headerM, DLNode trailerM) {
where the node returned is the header of the resulting list.
In creating the new list, you are free to damage or destroy the
original lists if you wish.
Please remember to report the running time!
So in a moment, we are going to design a new implementation for a Queue, which again is based on using two Stack's. Although the worst-case time per operation is still not O(1) (as it would be when we implement a Queue directly with an array or a linked list), it turns out that we can show that each operation requires only O(1) amortized time.
Your job is to prove this amortized bound using the accounting method of the text. Specifically, you should imagine yourself in the role of the Queue implementor. The person who has implemented the Stack has demanded that you pay $1 cyber-dollar every time your code calls one of the Stack methods.
Here is a sample such table:
Queue operation | Paid to Stack implementor | |
---|---|---|
"worst case" | "standard case" | |
Queue.size() | 2 | 2 |
Queue.isEmpty() | 2 (when S1 is empty) |
1 |
Queue.enqueue() | ||
Queue.dequeue() | ||
Queue.front() |
As an example, you may want to charge $2 cyber-dollars for your Queue.size() method so that you will collect exactly enough money to pay for the two Stack methods you call. You may also feel free to overcharge your customer, so that you can build up a surplus of money to use on a rainy day.
Here is a sample such table:
Queue operation | Price List (paid to us) |
---|---|
Queue.size() | 2 |
Queue.isEmpty() | |
Queue.enqueue() | |
Queue.dequeue() | |
Queue.front() |
The remaining text gives the Java code for the new approach. Whereas the original solution used stack S2 only temporarily to hold objects, this new method uses both stacks S1 and S2 for storing objects. Although you are not required to argue the correctness of this new method, you will certainly need to understand how and why it works to complete this assignment.
public class QueueImplementation implements Queue {
private Stack S1 = new StackImplementation();
private Stack S2 = new StackImplementation();
public int size() { return (S1.size() + S2.size()); }
public boolean isEmpty() { return (S1.isEmpty() && S2.isEmpty()); }
public void enqueue(Object obj) {
S1.push(obj);
}
public Object dequeue() throws QueueEmptyException {
if (S2.isEmpty()) {
if (S1.isEmpty()) {
throw new QueueEmptyException("Queue is empty.");
} else {
// move items from S1 onto S2
while (S1.size()>0) {
S2.push(S1.pop());
}
}
}
return(S2.pop());
}
public Object front() throws QueueEmptyException {
if (S2.isEmpty()) {
if (S1.isEmpty()) {
throw new QueueEmptyException("Queue is empty.");
} else {
// move items from S1 onto S2
while (S1.size()>0) {
S2.push(S1.pop());
}
}
}
return(S2.top());
}
}
Note: Though you will need to understand Exercise C-5.3, you do not need to writeup that solution.