Statement 1: False. A priority queue doesn’t provide LIFO ordering, while a stack only provides LIFO ordering. Also, a priority queue uses priorities, while a stack doesn’t.
Statement 2: Not false. If the priority queue stores values in LIFO order, then it’s effectively a stack. The priority queue keeps a separate counter that increases by one whenever a value is added to the queue. Each value added to the queue is assigned the priority shown by the counter. Because the newest value added has the highest priority among all values in the queue, it becomes the queue head, and the values are stored in LIFO order.
The answers, in no particular order and approximately verbatim:1: Dequeues can add or remove values at either end, not queues; it’s also not relevant because the question’s about priority queues, not queues.
2: I don’t think “acted upon” is the phrase you want. Also, how do a priority queue’s methods act like (for example) a stack?
3: Stacks are more strict than what? Priority queues? But why is that a problem for priority queues?
4: I don’t think “acted upon” is the phrase you want. Also, how do a priority queue’s methods act like (for example) a stack?
5: Does this answer deal with the statement 2?
6: What does it mean to be a more specific call?
7: How is LIFO able to implement priority-queue ordering?
8: This should probably be “values”.
9: That’s always the case for any linked-sequence ADT.
10: Why is this true? What mechanism makes it so?
11: The previous sentence makes two claims; to which is “this” referring?
12: Which priority-queue functions can’t be implemented, and where can’t they be implemented (the stack presumably).
13: This takes care of stacks implementing priority queues (I guess); what about the other way around?
14: Ha, FILO; I like it.
15: Neither stacks nor priority queues have FIFO behavior, although priority queues could be made to have it.
16: And not be an abstract class.
17: Priority queue.
18: That’s true, but not too relevant because priority queues effectively insert anywhere in the queue due to priority ordering. Also, what about question 2?
19: What does it mean for a value store to be less rigid?
20: What about statement 2?
21: You mean that values in the stack are in a specific order.
22: What about statement 2?
23: What about priority?
24: What about the second statement?
25: What about the second statement?
26: What about the second statement?
27: Also because a priority queue can implement a stack.
28: What about the second statement?
enqueue()
s, seven see()
s
and eight dequeue()
s in some unspecified order (and, in particular, not in
the order given in this sentence). When the sequence is applied to an
initially empty queue, all of the enqueue()
s were successful, three of the
see()
s failed with a queue underflow and the rest were successful, and three
of the dequeue()
s failed with a queue underflow, the rest were successful.
Assuming the errors were ignored, how many values where in the queue at the end
of the sequence? Explain your answer.
see()
method calls don’t change the number of values in the queue
and can be ignored. Three of the dequeue()
method calls fail on an empty
queue, which doesn’t change the queue; the other five calls remove an
element each from the queue. All the enqueue()
method calls succeed, adding
ten elements to the queue. Ten go in, five come out, and five are left.
The answers, in no particular order and approximately verbatim:
see()
s, which do not affect the value count. Ten
are enqueue()
s and five are dequeue()
s, which leaves five (5) values in
the end.
see()
s were successful and 5 dequeue()
s were successful this
means 91 were removed from the 10 enqueues that were added to the
sequence.
1: A see()
call doesn’t remove anything from the sequence.
If three see()
s and three dequeue()
s were unsuccessful due to
a queue underflow and the other methods were successful, then 5 values were
in the queue once the sequence ended.
Because the queue was initially empty we can go through, followed by
enqueue()
adding 10 values to the queue, with dequeue()
successfully
removing 5 once the queue was not empty.
see()
s that were successful do not add or
remove values so n is still 10. Only 5 of the dequeue()
s succeeded, so 5
values were removed from the sequence, so n = 10 - 5 which means n =
5.
enqueue()
s
and dequeue()
s will end up canceling out2 and the see()
is only
to view the value at the top of the queue at the time.
2: All of the dequeue()
s cancel?
3: Plus or minus how many?
enqueue()
s were
successful, we have 10 values. see()
is a queue method and does not change
the values. If 3 of the dequeue()
s failed, 5 went through, giving us 15
values at the end of the sequence.4
4: dequeue()
s remove values; it should be 10 - 5 not 10 + 5.
see()
s and dequeue()
s fail
with a queue underflow, the queue had nothing to be seen or removed. Since
the 10 enqueues were successful and the other 5 dequeues succeeded, by any
combination of the sequences,5 five values would be removed, leaving
5. The see()
s do not affect how many values are contained in the queue,
merely peek inside.
5: Any sequence not causing queue underflow.
see()
s worked that doesn’t
matter because it all depends on when the see()
was called. For example the
see()
could have been looking for v, but v had just been dequeued
before the see()
.6
6: An see()
don’t look for particular values, it just returns the
sequence head, if it exists.
see()
s do not effect the values in the queue, they only look at
them.
see()
s and dequeue()
s due to underflow the
sequence must have been executed7 as such: enqueue, dequeue x 2,
see, enqueue, dequeue x 2, see, enqueue, dequeue x 2, see, enqueue x 7, see x
4, dequeue x 2. Leaving 5 values remaining and all criteria met.
7: It’s not clear why this sequence is necessary.
see()
method does not add or remove any
values so it does not matter how many times it is called. There were 8
dequeues called which could remove up to 8 values, however 3 of them failed,
therefore 5 were executed removing 5 of the 10 values in the queue leaving us
with 5 remaining values.
8: And what about see()
s?
String whatADT(LinkedSequence ls)
accepts an instance of a
class implementing the linked-sequence interface, and returns a string
describing the linked-sequence ADT implemented: "stack"
, "queue"
, or
"linked list"
. Describe the smallest sequence of linked-sequence method
calls that will determine if ls
is a stack, a queue, or a linked list.
Justify your answer. Assume ls
is empty when passed into whatADT()
.
Adding one element can’t distinguish anything. Adding a second, distinguished element differentiates queues: the head of the ADT will be the first element added. Adding an element after the first element distinguishes between stacks and linked lists: linked lists allow the addition and stacks don’t. The code sequence is
ls.insertAfter(null, 1) if !ls.insertAfter(1, 2), return "stack" if ls.insertAfter(1, 3), return "linked list" return "queue"
The answers, in no particular order and approximately verbatim:
isEmpty()
- check if it is empty.1add(T w)
2 - add a value w
of type T
.push(T v)
- add a value v
of type T
enqueue(T z)
- add a value z
of type T
has(T w || z || v)
- check if value w
or z
or v
is
return value. w
if linked list. z
if queue. v
if
stack.3
1: Why? You can assume that.
2: Is this a linked-sequence method?
3: Perhaps you mean if has() == w,return "linked list"
?
4: But you can’t read the 2nd value of a queue either. And how do you read the second value using linked-sequence methods?
5: How can you not delete the first element?
insertAfter()
, enqueue()
, and pop()
. I chose these three because
each has to do with a different linked sequence. If insertAfter
does
not give an error then ls
would be a linked list because you can only
insert after a random value in the sequence if it is a linked list.6
That leaves the other two methods,7 if enqueue()
is called and
value 2 is placed into the list and pop()
is called, but returns value 2.
Then you know it is a stack because enqueue placed 2 at the head. Queues go
by FIFO and stacks go by LIFO.
6: Why is it that insertAfter
not failing mean that ls
is a
linked list?
7: Are these linked-sequence methods?
The easiest to determine would be the stack as by rule, only the
value stored at the top can be accessed at any given time.8
boolean insertAfter(old, new)
is an easy give away to stack because the
only time you can “insertAfter” in a stack is when the old (top) value
is null, in other cases the method returns false,9 meaning nothing can
be isolated. Remove() can also determine this by the same properties.
A linked list is less restrictive as one can fetch all values in the
linked list. We can see this by checking remove(v)
. In a linked
list we can cycle through all values in the list, find the value, remove it,
and reset the pointers.
A queue is similar to a stack only it contains FIFO properties. Give the
top of the queue will be the first value is searched calling the see()
method will return the first value inserted into the queue, not the last
value.
8: But isn’t that true for queues too?
9: Is that how insertAfter()
works? Can’t you insert after null
for any linked-sequence ADT?
insertAfter(null, value)
insertAfter(value, value2)
ls
is a stack because stacks do not support
arbitrary insertions at random points.insertAfter(value,
value3)
ls
is a queue because queues will
only let the head and tail be changed, not the middle.ls
is a linked list since it supports
insertion at every value.100
see()
because you know that an empty linked list will
be null10 where as a stack refers to the links between the indexes
and is instantiated with a zero.11 You could also call size
to get
similar conclusions.12 75
10: Won’t calling see()
on any empty linked-sequence ADT return
false?
11: What?
12: How? Won’t calling size()
on any empty linked-sequence ADT
return 0?
whatADT()
could possibly determine the ADT implemented by using
methods that insert values into the otherwise empty ls
and subsequently
determine the ADT by checking the way in which a value is removed. Linked
lists, for example will insert the values in the order they were
entered13 and remove them by taking away the farthest one. Queues
and stacks both insert values from the left side14 but differ in the
way they are removed. Stacks are first in, first out whereas queues are last
int, first out.15 Using a method to see how the values were implemented
would ultimately determine the type of ADT.16 75
13: That’s one possibility, but linked lists can insert values at any point in the list.
14: Aren’t queues double-ended?
15: Other way around: stacks are LIFO and queues are FIFO.
16: Yes, but how? That’s the question.
75
17: All of them? In what order? How do you interpret the results?
18: What variable? ls
?
ls
is a stack, a queue, or a linked
list is to try to add the items before/after values in the middle of the
sequence because that cannot be done is a stack or a queue. To determine the
difference between a stack and a queue would be to add strings and remove
them.19 Depending on the order they are removed in determines which ADT
it is. Stacks are last in first out, queues are first in first
out.
19: What would go wrong if I tried to add and remove ints?
ls
is a stack, queue or linked list first
determine the methods used to add/remove values into the ADT.20 Each
ADT has a specific method call so if you call add()
21 and it
doesn’t respond or reads as an error you know it is not linked list,
therefore you call push and whether or not you get an error message will
determine the ADT. So at most you need two method calls.
20: Isn’t that insertAfter()
and remove()
for all linked-sequence
ADTs?
21: Is add()
a linked-sequence method?
insertAfter()
, would determine if it is a
linked list. If it works, it is a linked list. If it doesn’t it is either a
queue or a stack.22push()
23 followed by
another, and then a pop()
would tell if it is a (LIFO) or a (FIFO) by
using see()
. If it is a LIFO, it is a stack. If it is a FIFO, it is a
queue.22: But calling insertAfter(1, 2)
on an empty linked list fails
too.
23: Is push()
a linked-sequence method?
insertAfter(E old, E v)
to determine what
type of ADT is being used because if you pass in 2 arguments in this method,
as opposed to 1 null and 1 argument, a stack | queue will return false for
the method and a linked list would return true and insert the arguments into
the ADT. (A stack | queue will return false because they can’t insert values
between other values, only at one end of the ADT or the other.) To then
determine if it is a stack or a queue, insert 2 values using the
insertAfter()
method,24 and then use the see()
method. If the
see
method returns the first value inserted, it is a queue, if the
see()
method returns the second value inserted it is a stack, because stacks
only have access to the top value.
24: Insert them how? Presumably using null as the first argument.
insertAfter(null, 1)
, then insertAfter(1, 2)
. If
insertAfter(1, 2)
returns true then it is a linked list because they are
the only ones that let the user do an insert after a value. If it returns
false then it must be a stack or queue. Continue with
insertAfter(null, 2) remove(1);
If remove(1)
returns true it is a queue because it was the first value
in, so it would be the first value allowed out of a queue. If it were a
stack it would return false because stacks may only remove from the top of
the stack which in this case would be 2.
The most recently operation performed should be the operation undone; this is LIFO order and a stack is called for.
1: Recycles what?
2: How would the program know where the pointers pointed before?
3: This is a good answer, but it’s way too long.
4: Not a good answer, but the explanation saved it.
5: Why is easier to undo what was done of values are stored at both ends?
6: What is the it that is quick and has access?
push()
, the only that
you can do to undo or remove the value that was added is to pop()
it out
and it will remove the value from your sequence.7 You do not have to
reference the value that you want to undo because pop()
removes the last
value that was added to the sequence.8
7: True, but why is this useful behavior? Why isn’t queue behavior as useful?
8: True, but why is referencing values important to undoing commands?
push()
” command, which adds an
element to the array, and the “pop()
” command, which removes the
last element added to the array.9
9: True, but why is that behavior useful for undoing commands?
10: This answer is rather more about undoing than about ADTs, but it’s still a good answer.
11: But why would you want to do that?
12: But do queues present command undo information in the order you would want to use them?
13: True, but on the other hand, the only commands you can undo are commands which have been executed, and these are necessarily previous commands.
14: True, but how does that help in undoing commands?
15: Simplest in what way? To operate or to implement?
16: True, but why is that an important property to have when implementing command undo?
if user used the push command18 pop value pushed else if user used the pop command push value popped else return
17: But how does the code know the user used the push command. This is what’s known as “begging the question.”
18: I could write similar pseudocode for a queue: just replace “push” with “enqueue” and “pop” with “dequeue”. Why is this harder than a stack?
19: Why are stacks most expensive? Expensive in what way?
20: Why is it appropriate to be the most expensive and time consuming ADT to use?
This page last modified on 2 March 2010.