Reputation: 1082
I'm trying to reverse a stack using recursion :
I'm able to print the elements of the stack in reverse order. But if I try to push the reverse elements it is not working.
Let the stack be [0,1,2,3,4]. 4 is top.
This is what I've tried:
private static void reverseStack(Stack<Integer> stack) {
if (!stack.isEmpty()){
int n=stack.pop();
reverseStack(stack);
System.out.println(n);
}
}
With this I'm getting the correct output.
Output is :
0
1
2
3
4
This is what I've expected.
If I try to push these elements back to stack I'm getting the same stack back without getting reversed :
This is the code used for reversing :
private static void reverseStack(Stack<Integer> stack) {
if (!stack.isEmpty()){
int n=stack.pop();
reverseStack(stack);
System.out.println(n);
stack.push(n);
}
}
This is the step wise stack obtained from this code :
private static void reverseStack(Stack<Integer> stack) {
if (!stack.isEmpty()){
int n=stack.pop();
System.out.println(stack);
reverseStack(stack);
System.out.println(n);
stack.push(n);
}
}
We can clearly see that the output stack is same as input stack but still elements are printed in reverse order. Where am I doing wrong ?
Upvotes: 5
Views: 2350
Reputation: 1
This implementation is generic for Stack,List,Vector
For Stack :
private static void reverseStack(Stack<Integer> stack) {
for (int i = 0, j = stack.size() - 1; i < j; i++) {
stack.add(i, stack.pop());
}
}
For List :
private static void reverseList(List<Integer> list) {
for (int i = 0, j = list.size() - 1; i < j; i++) {
list.add(i, list.remove(j));
}
}
Upvotes: -1
Reputation: 2203
In Java normally one would not use recursion to reverse a list-like data structure that is designed to support a large number of elements.
Since Java does not use tail call optimizations such algorithms may produce large stacks, or even stack overflows. And they probably would not be considered "without extra space" either.
You could simply reverse the stack in a loop with O(n) time and constant space complexity by swapping elements pairwise, i.e. first with last, second with second last, and so on. The following code which is adopted from JDK classes shows this approach.
private static void reverseStack(Stack<Integer> stack) {
for (int i = 0, mid = stack.size() >> 1, j = stack.size() - 1; i < mid; i++, j--)
stack.set(i, stack.set(j, stack.get(i)));
}
Upvotes: 0
Reputation: 111
Here's a different approach. I"m trying to use fixed set of variables (5 - max,A,A1,B,B1) and re-utilizing these variables, re-populating stack in reverse order.
No-Recursion. Recursive Solutions for this means O(n) extra space.
Only works for Integers
Let's say Stack = [1,2,-3,4] with 4 on top.
max = 5
A = ((((((1*5)+2)*5)+3)*5)4)*5
A1 = (((((((0+5)*5)+5)*5)+6)*5)+5)*5
With the help of A and A1 you can re-populate the stack but in the same order so calculating B and B1 which are in reverse order.
A1 & B1 are to remember negative integers.
Here, + max is for positive and + (max + 1) to remember negative integers.
import java.util.Stack;
//Not ideal solution. This is only because no other data structure can be used
/*
* 1. Find Max. Any number > max can be used for max
* 2. Find A and A1
* 3. Find B and B1
* 4. Fill the Stack using B and B'
* O( 4n ) = O( n )
*/
class Stack_Reversal_Using_Recursion {
static Stack<Integer> stack = new Stack<>();
public static void main(String[] args) {
stack.push(1);
stack.push(8);
stack.push(-3);
stack.push(0);
stack.push(4);
System.out.println(stack);
better_Solution();
System.out.println("Using mathematical approch");
System.out.println(stack);
}
private static void better_Solution() {
int size = stack.size();
//Finding Max
int max = 0;
for(int item : stack){
if( max < Math.abs(item) )
max = Math.abs(item);
}
max = max + 1;
//Finding A and A1
int A = 0;
int A1 = 0;
while( stack.size() > 0 )
{
int x = stack.pop();
A += Math.abs(x);
A *= max;
if( x < 0 )
A1 += (max+1);
else
A1 += max;
A1 *= max;
}
//A and A' hold single sum total value from which using max we can find out entire stack but in same order so we find out B and B1
int B = 0;
int B1 = 0;
for( int i = 0; i < size; i++)
{
A = A / max;
A1 = A1/ max;
int A_mdl = A % max;
A -= A_mdl;
int A1_mdl = A1 % max;
if( A1_mdl == 0 )
A1_mdl = max;
else
A1_mdl = max + 1;
A1 -= A1_mdl;
B += A_mdl;
B *= max;
B1 += A1_mdl;
B1 *= max;
}
//Now that we have B and B1 in desired order let's re-populate the Stack
for( int i = 0; i < size; i++)
{
B = B / max;
B1 = B1/ max;
int B_mdl = B % max;
B -= B_mdl;
int B1_mdl = B1 % max;
if( B1_mdl != 0 )
B_mdl = -B_mdl;
if( B1_mdl ==0 )
B1 -= max;
else
B1 -= (max+1);
stack.push( B_mdl );
}
}
}
As stated earlier, This approach is only for Integers and one can always debate what if numbers are vary large! In that case As and Bs can be Big Integers.
Upvotes: 1
Reputation: 6312
If you are doing recursive call to reverse the stack, then you are using extra space. (When you pop the element and store it to add it later).
However if you use 2nd stack approach mentioned by @Scott and @Berkley then it's not taking extra space. So this will be right answer to your question.
while(!stack.isEmpty()) {
reversedStack.push(stack.pop());
}
Upvotes: 3
Reputation: 293
When you hit the base case for the call, you are putting that element back onto the stack. That function is then completed, then goes back up to the element above it, and adds that back.
First call ([0,1,2,3,4])
int n = 4
Second call ([0,1,2,3])
int n = 3
Third call ([0,1,2])
int n = 2
Fourth call ([0,1])
int n = 1
Fifth call ([0])
int n = 0
Sixth call ([])
empty is reached, return
add 0 to stack then return ([0])
add 1 to stack then return ([0,1])
add 2 to stack then return ([0,1,2])
add 3 to stack then return ([0,1,2,3])
add 4 to stack then return ([0,1,2,3,4])
This problem could be resolved in a simpler fashion by using a loop and two different stacks.
while(!stack.isEmpty()) {
int n = stack.pop();
stack2.push(n);
}
Upvotes: 2
Reputation: 1456
You have problem in visualizing the recursion, the sysout's (System.out.println) will not be executed till the exit criteria of recursion is fulfilled i.e . when stack is empty.
At this point the recursion will wind up and all the elements will be printed in that order i.e. 0,1,2,3,4
And only then you are pushing the elements in that order , so that stack becomes [0,1,2,3,4]
See attached pic, pardon my handwriting :)
https://i.sstatic.net/Xc7jN.jpg
Upvotes: 2
Reputation: 49813
You have to build a new stack, so that the first one popped from the old stack is the first one pushed onto the new one. There won't be "extra space", as every original item will be in one of the 2 stacks. I'd do it using a helper function that knows about the stack you are building.
Upvotes: 3