0% found this document useful (0 votes)
56 views15 pages

Homework 8

Uploaded by

manojreddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
56 views15 pages

Homework 8

Uploaded by

manojreddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Homework 8

R-6.1 Suppose an initially empty stack S has performed a total of 25 push


operations, 12 top operations, and 10 pop operations, 3 of which returned null to
indicate an empty stack. What is the current size of S?

Answer:

The current size of stack S is 18.

Here's the breakdown:

➢ Push operations add elements to the stack, so they increase the size. We've
had 25 push operations.
➢ Pop operations remove elements from the stack, so they decrease the size.
However, 3 pop operations returned null, indicating the stack was already
empty. These pops didn't affect the size.

Therefore, to calculate the actual number of elements removed, we need to subtract


the ineffective pops from the total pops:

➢ Successful pops (elements removed) = Total pops - Ineffective pops


➢ Successful pops = 10 pops - 3 pops (returned null)
➢ Successful pops = 7 pops

Now, we can find the current size:

➢ Current size = Push operations - Successful pops


➢ Current size = 25 pushes - 7 pops
➢ Current size = 18

So, the stack S currently holds 18 elements.

R-6.3 What values are returned during the following series of stack operations, if
exe- cuted upon an initially empty stack? push(5), push(3), pop(), push(2), push(8),
pop(), pop(), push(9), push(1), pop(), push(7), push(6), pop(), pop(), push(4), pop(),
pop().

Answer:

The following values are returned during the series of stack operations on an initially
empty stack:
Operations Returned Values

push(5) (None) - Stack is empty

push(3) (None)

pop() 3 - Top element is popped and returned

push(2) (None)

push(8) (None)

pop() 8 - Top element is popped and returned

pop() 2 - Top element is popped and returned

push(9) (None)

push(1) (None)

pop() 9 - Top element is popped and returned


Operations Returned Values

push(7) (None)

push(6) (None)

pop() 7 - Top element is popped and returned

pop() 6 - Top element is popped and returned

push(4) (None)

pop() 4 - Top element is popped and returned

pop() (None) - Stack is empty

Explanation:

1. We start with an empty stack.


2. push(5) adds 5 to the stack (no return value).
3. push(3) adds 3 to the stack (no return value).
4. pop() removes and returns the top element, which is 3.
5. push(2) adds 2 to the stack (no return value).
6. push(8) adds 8 to the stack (no return value).
7. pop() removes and returns the top element, which is 8.
8. pop() removes and returns the top element, which is 2.
9. push(9) adds 9 to the stack (no return value).
10. push(1) adds 1 to the stack (no return value).
11. pop() removes and returns the top element, which is 9.
12. push(7) adds 7 to the stack (no return value).
R-6.5 Give a recursive method for removing all the elements from a stack.

Answer:

Here's a recursive method for removing all elements from a stack,

Java:

public void clear() {


if (isEmpty()) {
// Base case: If the stack is empty, there's nothing to remove.
return;
} else {
// Recursive case: Pop the top element and call clear() again to remove remaining
elements.
pop();
clear();
}
}

Explanation:

1. Base Case: The method checks if the stack is empty using isEmpty(). If it's
empty, there are no elements to remove, so the method simply returns.
2. Recursive Case: If the stack is not empty, the method performs the following
steps:
➢ Pop: It removes the top element from the stack using pop().
➢ Recursive Call: It calls itself (clear()) recursively. This call removes the
remaining elements from the stack after the top element has been removed.

How it Works:

➢ The initial call to clear() starts the recursion.


➢ If the stack is empty (base case), the recursion stops.
➢ If the stack is not empty, the top element is removed, and clear() is called
again on the remaining stack (recursive case).
➢ This process continues until the stack becomes empty, at which point the
recursion stops.

Note:

This method assumes you have a pop() method that removes the top element from
the stack and an isEmpty() method that checks if the stack is empty. These methods
would be specific to your stack implementation (e.g., ArrayStack, LinkedStack).
R-6.7 Suppose an initially empty queue Q has performed a total of 32 enqueue
opera- tions, 10 first operations, and 15 dequeue operations, 5 of which returned null
to indicate an empty queue. What is the current size of Q?

Answer:

The current size of queue Q is 22.

Here's how we can calculate it,

1. Enqueue Operations: These operations add elements to the back of the queue.
Since there were 32 enqueue operations, we can assume there were initially 32
elements added.
2. Dequeue Operations: These operations remove elements from the front of the
queue. However, 5 of these dequeues returned null, indicating the queue was
already empty during those operations. So, these 5 dequeues didn't actually
remove any elements.
3. Successful Dequeues: To find the number of elements actually removed, we
subtract the ineffective dequeues from the total:
➢ Successful Dequeues = Total Dequeues - Ineffective Dequeues
➢ Successful Dequeues = 15 Dequeues - 5 (returned null)
➢ Successful Dequeues = 10 Dequeues
4.Current Size: Now, we can calculate the current size of the queue by subtracting
successful dequeues from the number of elements initially added:
➢ Current Size = Initial Elements - Successful Dequeues
➢ Current Size = 32 Elements - 10 Dequeues
➢ Current Size = 22 Elements

Therefore, the queue Q currently holds 22 elements.

R-6.9 What values are returned during the following sequence of queue operations,
if executed on an initially empty queue? enqueue(5), enqueue(3), dequeue(),
enqueue(2), enqueue(8), dequeue(), dequeue(), enqueue(9), enqueue(1),
dequeue(), enqueue(7), enqueue(6), dequeue(), dequeue(), enqueue(4), dequeue(),
dequeue().

Answer:

The following values are returned during the series of queue operations on an
initially empty queue:
Operations Returned Values

enqueue(5) (None) - Queue is empty

enqueue(3) (None)

dequeue() 5 - Top element is removed and returned

enqueue(2) (None)

enqueue(8) (None)

dequeue() 3 - Top element is removed and returned

dequeue() 2 - Top element is removed and returned

enqueue(9) (None)

enqueue(1) (None)

dequeue() 9 - Top element is removed and returned


Operations Returned Values

enqueue(7) (None)

enqueue(6) (None)

dequeue() 1 - Top element is removed and returned

dequeue() 7 - Top element is removed and returned

enqueue(4) (None)

dequeue() 8 - Top element is removed and returned

dequeue() 4 - Top element is removed and returned

dequeue() (None) - Queue is empty

Explanation:

1. We start with an empty queue.


2. enqueue(5) adds 5 to the back of the queue (no return value).
3. enqueue(3) adds 3 to the back of the queue (no return value).
4. dequeue() removes and returns the first element added, which is 5.
5. enqueue(2) adds 2 to the back of the queue (no return value).
6. enqueue(8) adds 8 to the back of the queue (no return value).
7. dequeue() removes and returns the first element added (after dequeue in step
4), which is 3.
8. dequeue() removes and returns the first element added (after dequeue in step
7), which is 2.
9. enqueue(9) adds 9 to the back of the queue (no return value).
10. enqueue(1) adds 1 to the back of the queue (no return value).
11. dequeue() removes and returns the first element added (after dequeue in step
8), which is 9.
12. enqueue(7) adds 7 to the back of the queue (no return value).
13. enqueue(6) adds 6 to the back of the queue (no return value).
14. dequeue() removes and returns the first element added (after dequeue in step
11), which is 1.
15. dequeue() removes and returns the first element added (after dequeue in step
14), which is 7.
16. enqueue(4) adds 4 to the back of the queue (no return value).
17. dequeue() removes and returns the first element added (after dequeue in step
15), which is 8.
18. dequeue() removes and returns the first element added (after dequeue in step
16), which is 4.
19. dequeue() tries to remove an element from an empty queue, so it returns None
(or an equivalent null value).

This sequence demonstrates how enqueue and dequeue operations interact with the
queue, modifying its contents and returning the removed elements based on a First-
In-First-Out (FIFO) principle.

R-6.11 Give a simple adapter that implements the queue ADT while using an
instance of a deque for storage.

Answer:

Here's a Java class that implements the Queue ADT using a deque for storage,

Java:

public class QueueAdapter<T> implements Queue<T> {

private Deque<T> deque;

public QueueAdapter() {
deque = new LinkedList<T>(); // Initialize with a LinkedList deque
}

@Override
public void enqueue(T item) {
deque.addLast(item); // Add to the back of the deque (FIFO order)
}
@Override
public T dequeue() {
if (isEmpty()) {
return null; // Return null for empty queue
}
return deque.removeFirst(); // Remove from the front of the deque (FIFO order)
}

@Override
public boolean isEmpty() {
return deque.isEmpty();
}
}

Explanation:

1. Class Definition: This code defines a class named QueueAdapter that


implements the Queue interface. It uses generics (<T>) to allow storing elements
of any data type T.
2. Deque Instance: The class has a private member variable deque of type
Deque<T>. It's initialized with a LinkedList instance in the constructor
(QueueAdapter()). While any deque implementation would work, LinkedList
offers efficient addLast and removeFirst operations for FIFO behavior.
3. enqueue: This method overrides the enqueue method from the Queue interface.
It takes an element item as input and adds it to the back of the deque using
deque.addLast(item). This ensures elements are added in the order they are
enqueued, maintaining the FIFO property.
4. dequeue: This method overrides the dequeue method from the Queue interface.
It first checks if the queue is empty using isEmpty(). If empty, it returns null to
indicate this. Otherwise, it removes the first element from the deque using
deque.removeFirst() and returns the removed element. This follows the FIFO
principle of removing the element that was added first.
5. isEmpty: This method overrides the isEmpty method from the Queue interface.
It simply delegates the check to the deque.isEmpty() method, as an empty deque
implies an empty queue.

This adapter class provides a convenient way to use a deque for queue functionality.
You can use this class just like any other queue implementation in your Java code.

C-6.17 Show how to use the transfer method, described in Exercise R-6.4, and two
temporary stacks, to replace the contents of a given stack S with those same
elements, but in reversed order.

Answer:
Here's the Java code demonstrating how to use the transfer method (assuming its
implementation from Exercise R-6.4) and two temporary stacks to reverse the
contents of a stack S.

Java:

public static void reverseStack(Stack<Integer> S, Stack<Integer> temp1,


Stack<Integer> temp2) {
// Move all elements from S to temp1 (preserving order)
while (!S.isEmpty()) {
temp1.push(S.pop());
}

// Move elements from temp1 to temp2 in reverse order (effectively reversing)


while (!temp1.isEmpty()) {
temp2.push(temp1.pop());
}

// Move elements from temp2 back to S, reversing the original order


while (!temp2.isEmpty()) {
S.push(temp2.pop());
}
}

public static void main(String[] args) {


Stack<Integer> S = new Stack<>();
S.push(1);
S.push(2);
S.push(3);

System.out.println("Original stack: " + S); // Output: [3, 2, 1]

Stack<Integer> temp1 = new Stack<>();


Stack<Integer> temp2 = new Stack<>();

reverseStack(S, temp1, temp2);

System.out.println("Reversed stack: " + S); // Output: [1, 2, 3]


}

Explanation:

1. reverseStack Method: This method takes the stack to be reversed (S), and two
empty temporary stacks (temp1 and temp2) as arguments.
2. Moving Elements to temp1: It iterates through S using a loop (while
(!S.isEmpty())). In each iteration, it pops an element from S using S.pop() and
pushes it onto temp1 using temp1.push(S.pop()). This effectively transfers
elements from S to temp1 while preserving their original order.
3. Reversing Order in temp2: Another loop (while (!temp1.isEmpty())) iterates
through temp1. In each iteration, it pops an element from temp1 using
temp1.pop() and pushes it onto temp2 using temp2.push(temp1.pop()). Since
elements are added to the top of temp2, this process reverses the order of
elements from temp1 (which originally held them in the same order as S).
4. Restoring Reversed Order in S: Finally, a third loop (while (!temp2.isEmpty()))
iterates through temp2. In each iteration, it pops an element from temp2 using
temp2.pop() and pushes it onto S using S.push(temp2.pop()). This effectively
transfers elements from temp2 (which now holds them in reversed order) back to
S, reversing the original order of elements in S.

Main Method:

➢ The main method demonstrates usage. It creates a stack S with elements 1, 2,


3, and prints the original stack.
➢ It then creates two empty temporary stacks temp1 and temp2.
➢ The reverseStack method is called with S, temp1, and temp2 as arguments.
This call reverses the elements in S.
➢ Finally, the reversed stack S is printed.

P-6.37: Design an ADT for a two-color, double-stack ADT that consists of two
stacks— one “red” and one “blue”—and has as its operations color-coded versions
of the regular stack ADT operations. For example, this ADT should support both a
redPush operation and a bluePush operation. Give an efficient implementation of this
ADT using a single array whose capacity is set at some value N that is assumed to
always be larger than the sizes of the red and blue stacks combined.

Answer:

Here's the design and implementation of a two-color, double-stack ADT using a


single array:

ADT Design:

➢ The ADT represents two stacks: a red stack and a blue stack.
➢ Operations are color-coded for clarity: redPush, bluePush, redPop, bluePop,
etc.

Data Structure:

➢ We'll use a single array of size N to store elements for both stacks.
➢ Two variables, redTop and blueTop, will keep track of the top indices for each
stack. Initially, both will be -1 (representing empty stacks).

Implementation:

Java:
public class TwoColorStack<T> {

private final T[] data;


private int redTop;
private int blueTop;
private final int capacity;

public TwoColorStack(int capacity) {


this.data = (T[]) new Object[capacity];
this.redTop = -1;
this.blueTop = -1;
this.capacity = capacity;
}

// Red stack operations


public void redPush(T element) throws Exception {
if (isFull()) {
throw new Exception("Stack overflow");
}

redTop++;
data[redTop] = element;
}

public T redPop() throws Exception {


if (isRedEmpty()) {
throw new Exception("Red stack underflow");
}

T element = data[redTop];
redTop--;
return element;
}

// Blue stack operations


public void bluePush(T element) throws Exception {
if (isFull()) {
throw new Exception("Stack overflow");
}

blueTop++;
data[capacity - 1 - blueTop] = element; // Push to the other end of the array
}

public T bluePop() throws Exception {


if (isBlueEmpty()) {
throw new Exception("Blue stack underflow");
}

T element = data[capacity - 1 - blueTop];


blueTop--;
return element;
}

// Helper methods
private boolean isFull() {
return redTop + 1 == capacity - 1 - blueTop; // Check if both stacks reach
combined capacity
}

private boolean isRedEmpty() {


return redTop == -1;
}

private boolean isBlueEmpty() {


return blueTop == capacity - 1;
}
}

Explanation:

➢ TwoColorStack Class: This class represents the two-color, double-stack


ADT.
➢ Data Structure:
➢ data: This is the single array that stores elements for both stacks.
➢ redTop: This variable keeps track of the top index for the red stack.
➢ blueTop: This variable keeps track of the top index for the blue stack.
➢ capacity: This variable stores the total capacity of the array.
➢ Constructor: The constructor initializes the data array, sets both redTop and
blueTop to -1, and stores the capacity.
➢ Red Push/Pop:
➢ redPush: It checks if the combined stack is full (using isFull). If not, it
increments redTop, stores the element in the array at the new index, and
performs the push operation.
➢ redPop: It checks if the red stack is empty (using isRedEmpty). If not, it
retrieves the element at redTop, decrements redTop, and returns the element.
➢ Blue Push/Pop: These functions operate similarly to red push/pop, but they
use the opposite end of the array. The bluePush uses the capacity - 1 -
blueTop index to push elements from the right side of the array, maintaining
separation from the red stack.

Benefits:

➢ Efficient space utilization: By using a single array, we avoid wasting space for
separate red and blue stack arrays.
➢ Clear color-coded operations: The use of red/blue prefixes for operations
makes the code easy to understand and use.

Limitations:
➢ Potential overflow: If the combined size of red and blue stacks exceeds the
total capacity, an overflow exception occurs. You might consider dynamic
resizing of the array for more flexibility.

You might also like