Function that will leave the smallest occurrences at the bottom of stack - c++

I am trying to write a stack so that all of the occurrences of the smallest element are at the bottom of the stack, while the order of the other elements stays the same. For example, if I have the stack [4,3,1,5,8,1,4] it will become [4,3,5,8,4,1,1], but my problem is that the order changes
so i will get something like this[4,5,3,4,8,1,1]
#include <iostream>
#include <stack>
using namespace std;
void minstack(stack<int> &s)
{
stack<int> t1,t2;
int count=0,min;
if(!s.empty())
{
while(!s.empty())
{
if(s.top() <min)
{ min=s.top();
count=0;
}
t1.push(s.top()); s.pop();
count++;
}
for(int i = 0 ; i<count;i++)
{
s.push(min);
}
while(!t1.empty())
{
if(t1.top()!=min);
{ s.push(t1.top());
}
t1.pop();
}
}
}
int main()
{
stack <int> s;
s.push(4);
s.push(3);
s.push(1);
s.push(5);
s.push(8);
s.push(1);
s.push(4);
minstack(s);
while(!s.empty())
{
cout<<s.top()<<" "; s.pop();
}
}

Here's an idea. First we'll need to find the smallest element of the stack. Define a temporary stack t. We'll now pop all elements one by one from s and push them into t. At the same time, keep track of the minimum value min and the number of times it has been encountered so far in the popping process in count. Once this is done, notice that you'll have the reverse order of elements in t and have min and count. Now we'll push count number of elements of value min back into s. Then start popping and pushing from t to s except for the elements which equal min.

Related

how to reverse a stack using recursion in C++

I am trying to reverse stack without using extra space through recursion. But unable to find my error.
Here is my code. It is printing the same stack again.
#include<iostream>
#include<stack>
using namespace std;
void insert( stack<int>& k , int j){
k.push(j);
}
void reverse(stack<int> &s){
if(s.empty()){
return;
}
int temp = s.top();
s.pop();
reverse(s);
insert(s,temp);
}
int main()
{
stack<int>s;
for( int i = 5;i>0;i--){
s.push(i);
}
reverse(s);
while(!s.empty()){
cout << s.top() << " ";
s.pop();
}
return 0;
}
Your insert() function is incorrect since you only push temp into the stack and once the stack is empty the value of temp will be 5 so 5 is pushed then 4 and so on. Hence the stack is filled in the same order. This insert() should work.
void insert( stack<int>& k , int j){
if(k.empty()){
k.push(j);
return;
}
int temp = k.top();
k.pop();
insert(k, j);
k.push(temp);
}
insert() just inserts j to the bottom of the stack.
Your recursivity is not correct. You remove the top, call the same function (reverse) recursively and then push it back on top. This does not change its position! The same applies to all elements recursively: they do not change their position. A pure recursive solution (without using another stack or any data structure like an array or a list) to your problem is impossible.

Copy elements from queue to stack

I want to write a code that copies queue elements in to a stack, and this copied elements should be sorted in the stack.
i've written the code below:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,x;
queue<int> q;
stack<int> s;
cin >> n;
for(int i=0;i<n;i++){
cin >> x;
q.push(x);
}
while(!q.empty()){
if(s.empty()){
s.push(q.front());
q.pop();
}
else{
if(q.front()>=s.top()){
s.push(q.front());
q.pop();
}
else{
while(q.front()<s.top() && !s.empty()){
q.push(s.top());
s.pop();
}
}
}
}
while(!s.empty()){
cout << s.top() << " ";
s.pop();
}
return 0;
}
but for some test cases like:3 1 2 3,the code does not seem to work.
please help me to figure out the problem with my code.
Your code seems to have a logic error in your inner while loop. You test s.top() before you test for s.empty(), which is the wrong order. s.top() is invalid if s.empty() is true. However, the exercise can be resolved relatively easily as described below.
You can retrieve the underlying container of a container adapter using the following helper:
template <class ADAPTER>
typename ADAPTER::container_type & get_container (ADAPTER &a)
{
struct hack : ADAPTER {
static typename ADAPTER::container_type & get (ADAPTER &a) {
return a.*&hack::c;
}
};
return hack::get(a);
}
Then, after populating the queue, you can copy the contents directly to the stack's underlying container, and sort it.
auto &qc = get_container(q);
auto &sc = get_container(s);
sc.assign(qc.begin(), qc.end());
std::sort(sc.begin(), sc.end());
You have to do what is essentially a selection sort: go through the queue N times, each time selecting the largest element to push onto the stack. The general idea is:
queue = queue containing items
stack = new empty stack
while queue.count > 0
// push the first item from the queue onto the stack
stack.push(queue.pop())
count = queue.count
// for each item remaining in the queue
for (i = 0; i < queue.count; ++i)
// if the item from the queue is larger than what's on the stack,
// then remove the item from the stack and put it back in
// the queue. And put the item from the queue onto the stack.
if (queue.peek() > stack.peek())
queue.push(stack.pop())
stack.push(queue.pop())

find the number of previous towers less than or equal to the current one

Hi I am trying to find the number of previous towers less than or equal to the current one , this solution is working great for inputs(NumOfTowers) <=10, but for the NumOfTowers >10 the code is going in segfault, i could not see the issue here,
#include <iostream>
#include <stack>
using namespace std;
int main()
{
std::stack<int> Towers; //for storing the Height of the towers
std::stack<int> TempTowers; // Temrory buffer stack
std::stack<int> CountTowers; //for storing the count of all previous
towers less than the current one
unsigned int NumTestCases,NumOfTowers,i,j,count=1,temp,temp_height;
cin>>NumTestCases;
cin>>NumOfTowers;
while(NumTestCases){
while(!Towers.empty()){
Towers.pop();
}
for(i=0;i<NumOfTowers;i++){
cin>>temp;
Towers.push(temp);
}
for(i=0;i<NumOfTowers-1;i++){
count=1;
temp_height=Towers.top();
Towers.pop();
temp=Towers.top();
while(temp<temp_height){
count++;
TempTowers.push(temp);
Towers.pop();
temp=Towers.top();
}
CountTowers.push(count);
while(!TempTowers.empty()){
temp=TempTowers.top();
TempTowers.pop();
Towers.push(temp);
}
}
NumTestCases--;
cout<<"1"<<" ";
while(!CountTowers.empty()){
cout<<CountTowers.top()<<" ";
CountTowers.pop();
}
cout<<"\n";
}
}
any help would be great.
Change this
while(temp<temp_height){
count++;
TempTowers.push(temp);
Towers.pop(); // Popped the last element
temp=Towers.top(); // no more elements left
}
to this
while(!Towers.empty() && Towers.top() < temp_height)
{
++count;
TempTowers.push(Towers.top());
Towers.pop();
}
The issue wasn't with the length of the input but the order of it. If I/p = {1, 2, 3, 4} your code would give a error when it tried to access top() of a empty stack.
You are calling temp=Towers.top(); on an empty stack, here
while(temp<temp_height){
count++;
TempTowers.push(temp);
Towers.pop();
temp=Towers.top();
}
Change this line to the follwing two lines:
if (Towers.size() > 0) temp = Towers.top();
else break;

C++- How to increase stack size to allow more recursion for Kosaraju's Algorithm to compute Strongly Connected Components

I am using a mac, 4GB of RAM and CLion IDE. Compiler is Clang. I need to allow more recursion in this recursive implementation of Depth First Search (currently fails on a graph with 80k nodes).
typedef unordered_map <int, vector<int>> graph;
void DFS (graph &G, int i, vector <bool> &visited) {
visited[i] = true;
for (int j = 0; i < G[i].size(); j++) {
if (!visited[G[i][j]]) {
DFS(G, G[i][j], visited);
}
}
t++;
finishingTime[t] = i; //important step
}
This is for an implementation of Kosaraju's algorithm to compute strongly connected components in a graph. https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm I know it is possible to implement DFS as iterative instead but the last step is important, and I can't find a way to include it using iteration. This is because that step is done when DFS fails and backtracking occurs, and recursion provides a very natural way to do this.
So currently I have only two options:
Increase the stack size to allow more recursion
Or find an iterative solution
Any ideas how to do either?
As suggested by a comment you can put each call to DFS on a stack allocated on heap made from the parameter list of DFS and then iterate through the stack. Each entry in the stack is essentially a task.
Pseudo-like code:
Start and run "recursion":
nr_of_recursions = 0;
dfs_task_stack.push(first_task_params)
while dfs_task_stack not empty
DFS(dfs_task_stack.pop)
nr_of_recursions += 1
end while;
true_finishingtime[] = nr_of_recursions - finishingtime[];
DFS:
for each recursion found
dfs_task_stack.push(task_params)
end for;
t++; finishingtime...
Not sure of your algorithm but it may be significant which order you push your tasks to the stack, i.e. the order of "for each ...".
I took the liberty of redefining the meaning of "finishingtime" to its inverse. To get the original definition substract the new finishingtime with the total number of recursions made.
I don't know if this is the best solution but you can build the list of finished times using just a stack and a visited state array, by having more than one visited state.
The following code is just to illustrate the algorithm. I didn't actually tested it a lot (just a little {{0, {1}}, {1, <>}, {2, <>}} small test) but I already used this technique in the very same way in the past for bigger graphs and I know it works.
The idea is to keep the visited node in the stack after it's being visited until all visited before it are pop, thus emulating the recursive call but with less data pushed and in a stack object.
#include <iostream>
#include <vector>
#include <stack>
#include <cassert>
#include <unordered_map>
using namespace std;
typedef enum {
vssClean,
vssPushed,
vssVisited
} VerticeStackState;
typedef unordered_map <int, vector<int>> graph;
void kosarajuBuildFinishOrder(const int inital, graph &G, vector<int> &finish, vector<VerticeStackState> &state, int &lastFinished) {
assert(vssClean == state[inital]);
std::stack<int> stack;
stack.push(inital);
state[inital] = vssPushed;
int current;
while (!stack.empty())
{
current = stack.top();
if (vssPushed == state[current])
{
state[current] = vssVisited;
for (const auto to: G[current])
{
if (state[to]==vssClean)
{
state[to] = vssPushed;
stack.push(to);
}
}
}
else {
assert(vssVisited == state[current]);
stack.pop();
finish[--lastFinished] = current;
}
}
}
int main() {
graph G;
G.insert({0, vector<int>(1, 1)});
G.insert({1, vector<int>()});
G.insert({2, vector<int>()});
vector<int> finish(G.size(), 0);
vector <VerticeStackState> state(G.size(), vssClean);
int lastFinished = G.size();
for (int i=0; i < G.size(); ++i) {
if (vssClean == state[i]){
kosarajuBuildFinishOrder(i, G, finish, state, lastFinished);
}
}
for (auto i: finish) {
cout << i << " ";
}
return 0;
}
For one of the options you mentioned about increasing the stack size, you can do as such:
g++ -Wl,--stack,16777216 -o kosaraju.exe kosaraju_stl.cpp
This increases the stack size to 16MiB. While as mentioned in earlier answers, it's just postponing the problem.
typedef unordered_map <int, vector<int>> graph;
void DFS (graph &G, vector <bool> &visited) {
std::stack<int> stack;
stack.push(0); // root
int i, j;
while(!stack.empty())
{
i = stack.pop_back();
visited[i] = true;
for (j= (int) G[i].size() -1; j >= 0; j--)
{
if (!visited[G[i][j]])
{
stack.push_back(G[i][j]);
}
}
t++;
finishingTime[t] = i; //important step
} // end while.
}
Anyone can make a programming error and since I don't have your test data I can't test this, but is output the same?

Why does this code crash while testing stack?

OK, so I edited my code, but I still have two problems :
But here's my code first :
#include <iostream>
using namespace std;
struct stack
{
int data[5];
int top;
};
void push (int a, stack &S)
{
S.top++;
if (S.top<5)
{
S.data[S.top]=a;
}
else cout<<"Stack is full!!!"<<endl; S.top--;
}
int pop(stack &S)
{
if (S.top==-1)
{
cout<<"Stack is empty!"<<endl;
}
else
{
int temp=S.data[S.top];
S.data[S.top]=NULL;
S.top--;
return temp;
}
}
bool isEMPTY(stack &S)
{
if (S.top==-1)
return true;
else return false;
}
bool isFULL(stack &S)
{
if (S.top==5)
return true;
else return false;
}
int main()
{
stack S = { {}, -1 };
push(5,S); cout<<"5 is pushed \n"<<endl;
push(3,S); cout<<"3 is pushed \n"<<endl;
push(1,S); cout<<"1 is pushed \n"<<endl;
push(2,S); cout<<"2 is pushed \n"<<endl;
push(6,S); cout<<"6 is pushed \n"<<endl;
push(7,S); cout<<"7 is pushed \n"<<endl;
cout<<pop(S)<<"is popped\n"<<endl;
cout<<pop(S)<<"is popped\n"<<endl;
cout<<pop(S)<<"is popped\n"<<endl;
return 0;
}
So, the first problem is, when I pop I get a "Totally random value" and it's not like LIFO.
Second is, I actually intended on inserting 6 values, when I already had the max value = 5, so the output actually showed me the 6 values.
stack S;
Since stack is POD, the above line doesn't initialize the member top. As such, using an uninitialized top in push and pop functions invokes undefined behavior.
Write this:
stack S {}; //must be compiled in C++11 mode, else write : stack S = stack();
This value-initializes S and its members, which means, top is initialized to 0. The rest of the code may still have other problems, but at least you have fixed the issues with proper initialization. If you work with 0 as initial value of top, you've write the logic of push and pop accordingly!
Once you fix that, check the value of top before pushing and poping values from the stack, as the member array can have at most 5 elements, and you cannot pop more elements when it is empty. You must maintain these invariants.
I do not see where an object of type stack was created and how data member top was initialized.
Also take nto account that member function push does not check whether there is an attempt to add an item beyond the array.
You should define the object the following way
stack S = { {}, -1 };
else cout<<"Stack is full!!!"<<endl; S.top--;
is identical to :
else
{
cout<<"Stack is full!!!"<<endl;
}
S.top--;
as a general rule, try to avoid: writing if/else without curly brackets, and, avoid writing more then one line of code in the same line.
The mistake is:
stack s;//you define the local variable "s" without been intitialized.
push(5,s);//pass the uninlitialized "s" to the function "push",when debugging your code,"s.top" is not a expected "-1",but some value incredible~(often extreamly larger than 5),so your push operation failed!
stack S;
S.top = -1;
for(int i = 0; i < 5; i++)
{
S.data[i] = 0;
}