CS 305-503, Data Structures & Algorithms

Quiz 2, 25 November 2008


  1. A priority queue arranges queued elements in ascending order based on an integer priority assigned to each element as it’s enqueued. Explain how to assign priorities to enqueued elements so that the priority queue acts like a stack.


    If the priority queue removes the enqueued element with the largest priority, then assigning each element a priority larger than that of any elements already enqueued would provide first-in, first-out behavior. The easiest priority to assign is the queue size. If the priority queue dequeues the element with the smallest priority, then assign negative of the queue size as the new element’s priority.

    The answers, approximately verbatim and in no particular order:

    • A queue is a fifo based data structure, meaning the first element in is the first element out. Priority queue would assign the nth element in with the nth integer priority as it is enqueued, and the arrange then as stated above. To make a priority queue act like a stack, the priority would have to be set to lifo, which is last in first out. So the integer priority would have to be in descending order, meaning before enqueueing, one should know how many elements the will be and set one of the elements to that priority value all the way down to priority 1, then arrange them in descending order from the top so they would dequeue as last in first out.

    • If you always assign the item going into the queue with the lowest priority it will be enqueued if first in last out order. This will give us the first in last out behavior of the stack.

    • Well, a stack can only have the top taken off, so automatically assign the last item entered highest priority, and then make it so that once that’s removed, the one under it is immediately #1.

    • If the integer priority assigned to each element causes the queue to arranged in ascending order according to the # of elements in the queue, then it can assign the integer priority (the integer starting at n = # of elements and going to 0) backwards in order to make the priority queue act like a stack.

    • Since a stack has the last in first out behavior the assignment of the priority queue needs to be arranged in descending order so the last element in the queue is the 1st one to come out. Just in the same manner as a stack removes the last element of the stack first. So in a manner of speaking the last element of a priority queue is the 1st element in an stack.

    • Queues and stacks differ in the way they behave. A queue uses first in first out behavior allowing the elements to be dequeued or displayed in the same order there were enqueued. A stack uses last in first out behavior so the elements are simply reversed. For a priority queue to act as a stack, the elements enqueued in the queue will need to be reversed.

    • Assign the priorities from least significant to most significant. The most important element priority-wise would then be on the top.

      Put the elements on a stack in descending order such as 321 priority and they will be removed in a 123 order. This is known as LIFO.

    • Stacks have the ‘lifo’ property. Enqueuing is done at the tail of the queue. And dequeing is done at the head of the queue. Therefore the last element in the ascending order should be enqueued into the priority queue so that when we dequeue the priority queue, from the head, we will get the list in the ascending order.

  2. Using a circular buffer in an array-based implementation of a queue avoids the need to shift elements within the array. Why doesn’t a stack use the same technique?


    A stack implemented as an array only varies at one end of the data block; the other end remains stationary. Because the data block doesn’t move through the array, there’s no need to shift data and no advantage to using a circular buffer.

    • Because with stacks, you can only remove the top data piece of said stack. You can’t shift elements in a stack anyway.

    • The elements are not supposed to be shifted in a stack. The bottom element (the first element pushed in the stack) remains stationary while the other elements being pushed into the stack are added.

    • Queues use the first in first out method and by using the circular buffer implementation when a element is removed from the array the item that was removed loops around like a circle and becomes the empty spot at the beginning of the array for the next element to be added without having to shift any elements. But a stack uses the last in first out implementation which basically allows us to “stack” elements on top of each other like a stack of books, and by removing an element we remove from the top and not from the bottom as in the queue. So the circular buffer is not needed.

    • A stack does not use the same technique as a queue because it’s behavior is LIFO as opposed to FIFO, which reverses the elements of a stack. As a queue’s enqueue function is utilized at the tail of the array and it’s dequeue function is used at the head, the circular buffer is possible with a stack, elements are pushed at the head of the array and popped at the head of the array.

    • A queue has a tail that data gets inserted into and a head where data is extracted. A stack only has top where you put elements and remove them. A circular buffer would not work and would not provide any benefit. Also it would be impossible to tell if it was full or not as top would be the same element, as opposed to having a head and a tail.

    • A stack always gives the last element that went in to stack; in other words, we can only access a stack from only one side (head side).

      Whereas queue can be accessed from either top or the bottom, which enables the circular arrangement.

      Since stacks does not allow access from either sides, ie top and bottom, similar circular technique cannot be applied for stacks.

    • A stack doesn’t use the same techniques because in a stack, the elements are last in first out meaning elements will be being pushed onto the stack, which will cause the elements already in the stack to be pushed down on more in the array.

    • Because a stack only has access to the first element. A queue can only have the circular property because it has access to both the head and tail elements.

  3. What role does operator precedence play when using a stack to convert an infix expression to post-fix?


    See pages 374 to 379 in Nyhoff.

    The answers, approximately verbatim and in no particular order:

    • The operator precedence changes the stack from infix to post-fix by having the operator that has more precedence change the behavior of the stack.

    • Stacks use the property of last in first out. In converting an infix expression to post fix, operator precedence can be used to set priorities by which how one wants to arrange the post fix expression.

    • Operator precedence is what decides how to convert from infix to post-fix, so the role of operator precedence is extremely important. A possible approach to ensuring the order will be correct is to use parenthesis first. Operator precedence ensures you arrive at the correct answer mathematically.

    • As stacks are sequential, they follow the before and after relationship.

    • With post-fix notation we want to move the operators to the right-most part of the string. When we reach an operator we push it onto the operator stack, when we reach a number we push it onto the number stack. When we reach the end of the input, we pop off 2 numbers and an operator. This will reverse the input and turn 2*2 into 22*.

    • Operator precedence would play a major role when converting from infix to post-fix using a stack because of the way that it is implemented. Considering stacks are lifo, the operator precedence would have to be inverted to accommodate the stack’s behavior. If not, the infix expression that is pushed will not come out post-fix if the precedence order is not accounted for. Although () would done first still, addition might come before multiplication after being popped off the stack, throwing off operator precedence.

    • Primarily it has to do with what expressions are first converted to post-fix expressions.

    • The operator precedence plays the role of comparing the infix expression to the post-fix expression.

  4. A colleague of yours has to implement a linked-list data structure for which it is important to be able to reverse the order of the elements in the list quickly. Your colleague thinks that by using a doubly-linked list the reverse operation can take constant time by just swapping the head and tail pointers. What do you think of your colleague’s scheme? Explain.


    It won’t work, because the next and previous pointers on each element link are backwards. When a linked list is first reversed, for example, the next pointer for the new queue head (formally the queue tail) points to nil.

    Your colleague can flip the pointers with O(n) work, but there’s another way that preserves constant time behavior: store the pointers in a two-element array neighbors indexed by the variables next = 0 and last = 1. When it comes time to reverse the queue, the pointers can be flipped in constant time by doing next = (next + 1) % 2 and last = (last + 1) % 2.

    The answers, approximately verbatim and in no particular order:

    • My colleague would be correct, but using a stack would be more beneficial in his situation. Since stacks work in last in and first out, that means the last element in would be the first one printed out when prompted to. Example: “Hello world” when pushed into a stack would pop out like “dlrow olleh” when popped.

    • It would take constant time (just the swap of two pointers) however it would only work to reverse the elements one time. If you want to insert to a list that has been reversed using this technique it will not work the way you want it to. Essentially after the swap you will have two separate fifo lists, where the second list starts at the tail of the first list.

    • As linked-lists do not have access to the head or tail, this procedure will not work. If the colleague used a stack implemented with a doubly linked list, constant time may be achieved.

    • A doubly linked list is twice the overhead of a singly-linked list. It would be quicker to sort the linked list or to insert them in order.

      There is also overhead with creating new nodes for the linked list in order to perform the swap.

      Putting the linked list into a stack would be another option, for reverse order, that is.

    • Surely the reversing can be done I guess. But again it still takes O(n) amount of work to get this done. Not only that, by having the double-linked list, the overhead is now twice than a singly-linked list. A stack using list would be my suggestion.

    • I think that the method that he is proposing will not work because, every element has a node that points to another node and at the end of the linked list the tail is always a null. If he switches the head and tail pointers (the pointer point to those pointers will also be switched) the beginning of the list will be the node with the null in it. So it will not reverse the order of the linked list.

    • If you swap head and tail pointers, only the head and tail pointer references would be changed. The pointers between the head and tail would remain the same and the linked-list would not be reversed. If the colleague wants to reverse the order of the elements, I think he/she should create a stack using linked list implementation, which already stores the elements in reverse order. This will also be constant time since there is only access at one end.

    • I think it’s a good idea. The problem is that linked lists are really dependent on all it’s data pieces and how they are connected by pointers. If it is so necessary, use a sort, done in descending/ascending order, y’know?

      I feel iffy about messing with pointer, but it seems like it’d work.


This page last modified on 25 November 2008.