Implementation of stack using vectors in c++ - c++

#include<iostream>
#include<vector>
using namespace std;
class Stack {
private:
int maxSize;
vector<int> v;
int top;
public:
Stack(int size) {
this->maxSize = size;
this->v.reserve(this->maxSize);
this->top = -1;
}
void push(int j) {
if (!(this->isFull())) {
this->v[++this->top] = j;
} else {
cout << "stack is full"<<endl;
}
}
int pop() {
if (!(this->isEmpty())) {
return this->v[this->top--];
} else {
cout << "\nstack is empty"<<endl;
cout<< "StackOverflow "<<endl;
}
}
int peak() {
return this->v[this->top];
}
bool isEmpty() {
return (this->top == -1);
}
bool isFull() {
return (this->top == this->maxSize - 1);
}
};
int main() {
Stack s(10);
s.push(10);
s.push(20);
cout<<s.pop();
cout<<"\n"<<s.pop();
s.push(40);
cout<<"\n"<<s.pop();
}
How can I make this code more better and reliable for these reasons:
The output of this code is 20 10 40 .
But in the output I want to print "Stack is empty" after every
time the stack is empty after popping out all the elements from the
stack
It fails toprint "Stackis Empty " every time .

You have UB in your code:
this->v[++this->top] = j;
return this->v[this->top--];
ans so on. The fact that you reserved space in a std::vector does not make accessing thous elements legal, you access elements out of bounds. And you overcomplicated your code - std::vector maintains it's size so you do not need index top at all. All you need is push_back() adding element and use back() to access last and then pop_back() to remove it. You can use std::vector>::empty()or std::vector::size() to check if there are elements left.

The specific problem in your code is due to your attempting out of bounds access with a std::vector; the behaviour of which is undefined. Note that reserve does not make that number of elements available for use; only potentially available without a subsequent memory reallocation. If you had used at rather than [] then your C++ standard library would have thrown a runtime error.
std::vector has push_back and a pop_back functions which does allow you to use it to model a stack reasonably effectively.
But, typedef std::stack<int> Stack; in place of all your code is by far the best way.
Don't use C++ standard library container objects to model other containers that are also in the C++ standard library. Container objects are really difficult to write properly; and take a lot of debugging.

The way you programmed it, it only prints "Stack is empty" if the stack is already empty when you call pop, not when it has 1 element and is only empty after calling pop.
Suppose you have 1 element on the stack. So top is 0.
int pop() {
if (!(this->isEmpty())) {
This if evaluatetes to true, and therefore nothing will be printed. This is because isEmpty() evaluates to false with top set to 0.
What you want to do is doing the pop first, and then checking if the stack is empty. On top of checking it at the beginning either way, because you can't pop an empty stack.

Related

Implementation of Queue using Arrays in C++

I have written this code and am confused about why is it showing segmentation fault. I think my dynamic memory allocation is causing problems for me here. Can anyone tell me what is causing the segmentation fault in here and how to improve the code.
Also, please tell me if I can create the object with the ClassName obj(); and store it in the stack instead of the heap. Or would this implementation be needed in some problems
#include<bits/stdc++.h>
using namespace std;
class Queue
{
public:
int rear, front, size,capacity;
int* arr;
Queue(int c)
{
capacity=c;
rear=c-1;
front=0;
int *arr= new int[c*sizeof(int)];
}
};
int isEmpty(Queue* queue)
{
return (queue->size==0);
}
int isFull(Queue* queue)
{
return (queue->size==queue->capacity);
}
void enqueue(Queue* queue, int x)
{
if(isFull(queue))
return;
queue->rear=(queue->rear+1)%queue->capacity;
queue->arr[queue->rear]=x;
queue->size+=1;
}
int dequeue (Queue* queue)
{
if(isEmpty(queue))
return 0;
int x = queue->arr[queue->front];
queue->front= (queue->front+1)%queue->capacity;
queue->size-=1;
}
int front (Queue* queue)
{
if(isEmpty(queue))
return 0;
return queue->arr[queue->front];
}
int rear (Queue* queue)
{
if(isEmpty(queue))
return INT_MIN;
return queue->arr[queue->rear];
}
int main()
{
Queue* queue=new Queue();
enqueue(queue,10);
enqueue(queue,20);
enqueue(queue,30);
enqueue(queue,40);
cout << "Front item is "
<< front(queue) << endl;
cout << "Rear item is "
<< rear(queue) << endl;
}
Your code have at least 3 problems:
Firstly,
Queue* queue=new Queue();
will lead to compilation error because no default constructor is defined and another constructor is defined in the class Queue.
To fix this, you should do one of:
Change this line to match the defined constructor like Queue* queue=new Queue(1024);
Add default constructor to the class Queue
Add default value of the argument c for the constructor of the class Queue like Queue(int c = 1024)
Secondly, the function dequeue have an execution path in which the execution reach at end of funciton without executing any return statement.
It seems return x; should be added at end of the function.
Thirdly, the line
int *arr= new int[c*sizeof(int)];
is bad because:
This stores the pointer to local variable that will vanish at end of this constructor instead of the member variable.
You don't need to multiply sizeof(int) because what to specify is the number of elements to allocate, not number of bytes.
The line should be
arr= new int[c];

C++, stack and pointers of struct

Hello I have a problem with pointer on struct in a stack.
I have a stack of struct:
stack<Somethink*> stack1;
And i want to push and pop array of "Somethink"
void Search(Somethink* array_Somethink, int s, int d,) {
stack1.push(&(array_Somethink[s])); //
while (stack1.size() != 0) {
int i = 0;
array_Somethink[i] = *(stack1.pop()); // this return a error
i++;
}
}
I hope someone can give me a tip, how to properly push and pop from this stack
Thank you :D
void Search(Somethink* array_Somethink, int s, int d,) {
stack1.push(&(array_Somethink[s])); //
while (!stack1.empty()) {
int i = 0;
array_Somethink[i] = *(stack1.top());
stack1.pop();
i++;
}
}
My modified code assumes, you have "owning" pointers to the elements on the stack somewhere else. If that is not the case, you would end with memory leaks here, as the pointers in the stack become dangling objects (leaks).
In order to avoid the potential for memory leaks, here, it might be a good idea if you used std::shared_ptr<Somethink> instead of raw pointers. Then, your stack would become a std::stack< std:shared_ptr<Somethink> >.
For details on std::stack operations empty(),pop(),top(), see std::stack in the usual place.
There, you will find explanations such as this:
std::stack::top
C++ Containers library std::stack
reference top();
const_reference top() const;
Returns reference to the top element in the stack. This is the most recently pushed element. This element will be removed on a call to pop(). Effectively calls c.back().
top will return a pointer to the struct and you are trying to assign it to an instance of the struct. Basically you are trying to assign a pointer to Somethink to a position in an array of Somethink's

C++ Stack: Program not executing

My assignment is to implement a stack (array-based) with a given capacity that, when attempting to add another element after the stack is full, will grow by a constant value (I used 100).
The problem here I believe lies in my push() function, which adds 100 element to the stack... probably syntactical but I'm not sure at all why my program won't execute.
template<class Type>
class ArrayStack{
enum {default_cap=100};
private:
Type* S; //array storing elements
int CAP; //capacity of stack
int TOP; //top element of stack
public:
ArrayStack(int defc = default_cap); //constructor with default parameter
~ArrayStack(){} //is "delete [] S;" supposed to go in here? not sure
bool isEmpty() const { return (TOP<0); }//is the stack empty?
int size() const { return (TOP+1); }
const Type& top(){ return S[TOP];} //has exception handling, not displayed
Type pop() {--TOP;} //removes top element
//here's the function that concerns me:
//--------------------------------------------
void push (const Type& e){
if(size() == CAP) {
Type* Snew = new Type[CAP+100];
for(int i = 0; i < CAP; i++){
Snew[i] = S[i];
}
delete [] S;
++CAP;
S = Snew;
}
S[++TOP] = e;
}
//--------------------------------------------
//other functions...
};
//constructor:
template<typename T> ArrayStack<T>::ArrayStack(int d)
: S(new T[d]), CAP(d), TOP(-1){}
It's a bit hard to comment since you've only provided partial code, and haven't demonstrated usage (e.g. with a main() function).
However, an obvious problem [which I notice Roger Rowland has identified in his comment too] with the push() function is that it increases allocated size by 100, but only increments CAP. So it will add 100 elements to the array, but only report ability to use the first one added.
The pop() function also discards the top element, and doesn't return it. If the caller ever tries to use the return value from pop() - and users of a stack type do normally expect to be able to use values they pop - the result will be undefined behaviour.
Your destructor definitely needs to use operator delete, unless you clean up dynamically allocated memory in some other way (and you've shown nothing like that). The whole point of operator new is that memory is NOT released until a corresponding operator delete. It will not be cleaned up magically if you forget to do it, and will present a memory leak for (at least) as long as your program runs.
If you want to do things a bit more safely, use a std::vector instead of a pointer (and avoid using operator new directly).

Compare a Queue and a Stack's content

Suppose we have in c++, using STL Stack and Queue
Stack: [1 2 3 4 5] <=>
Queue: => [5 4 3 2 1] =>
What is the most elegant way to recursively check that the data entries are the same in terms of content and order? Say the stack and queue shown above have the same data and same order.
I'm having a problem conceptually understanding what to do because the data pop() in opposite order.
A partially recursive solution would be to recursively pop all the elements from the queue in an auxiliary stack and then check if the auxiliary stack and the original stack are the same. This check can be done also recursively.
No need for recursion, this would be a useless waste of resources. No need to mutate your queue and stack either (in other words, this works even on const's).
Assuming your std::stack and std::queue both internally use the same type of underlying container (which should be std::dequeue if you used the default) then you can access the protected members c (your real containers) of both queue and stack and compare them using operator ==:
#include <iostream>
#include <queue>
#include <stack>
template<typename Adapter>
typename Adapter::container_type const& getContainer(const Adapter& adapter) {
struct AccessProtected : private Adapter {
static typename Adapter::container_type const& getContainer(const Adapter& adapter) { return adapter.*&AccessProtected::c; }
};
return AccessProtected::getContainer(adapter);
}
int main() {
std::queue<int> queue;
std::stack<int> stack;
for (int i = 0; i < 10; ++i) {
queue.push(i);
stack.push(i);
}
std::cout << (getContainer(queue) == getContainer(stack) ? "equal" : "not equal") << std::endl;
return 0;
}
Now, if you use different containers types as the underlying implementation of queue and stack, you can still use that same getContainer() technique to obtain containers that are sorted in the same order: both queue::push() and stack::push() call the underlying container's push_back() method, it's only when you pop() (and similar operations) that the reversing happens for stack. Since those underlying containers will be in the same order, you can then compare things more easily (left as an exercise to the reader ;)).
Credit: I was too lazy to reimplement a protected member accessor again, so I shamelessly copied and modified this one.
If by recursion, you do not mean a recursive function call, but just looping, then here's an answer. The function first checks if the stack and queue are the same size. If they aren't the same size, the function returns false. The function has a local stack object that gets the stack parameter's elements, in order to be popped in the reverse order as the stack parameter that is passed in. Then a loop checks each front/top element of stack and queue for equality. If equal, the loop continues to the next iteration. If not equal, the function returns false. If the loop finishes without returning false, the function returns true.
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
bool check(stack<int> stackPar, queue<int> queuePar)
{
if (stackPar.size() != queuePar.size())
{
return false;
}
stack<int> reverseStack;
for (int i = 0, initialSize = stackPar.size(); i < initialSize; ++i)
{
reverseStack.push(stackPar.top());
stackPar.pop();
}
for (int i = 0; i < reverseStack.size(); ++i)
{
if (reverseStack.top() == queuePar.front())
{
reverseStack.pop();
queuePar.pop();
}
else
{
return false;
}
}
return true;
}
int main()
{
stack<int> myStack;
queue<int> myQueue;
for(int i = 1; i <= 5; ++i)
{
myStack.push(i);
myQueue.push(i);
}
cout << "Stack and queue are ";
cout << ( check(myStack, myQueue) ? "equal." : "not equal." ) << endl;
return 0;
}
U may not pop them simultaneously, u can try to pop one(use something record it) ADT(dont pop queue, pop stack), and to the base(size==1), and u compare and made some change to the queue, and returns. Then do something with the recorder and the currently queue's front after every recursion calls, you will find the answer.

Programming error in allocating new stack

I am writing a program to implement a stack which works like a real world stack means it topples when the size of a stack reaches threshold and therefore need to create a new stack for inserting that new element.
Below is my program for this:
#include <iostream>
#include<vector>
#include<stack>
using namespace std;
class stack_of_plates
{
vector<stack<int> > stacks;
unsigned int stack_size;
public:
stack_of_plates(unsigned int size=100)
{
stack_size=size;
}
void push(int data)
{
if(stacks.empty())
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
vector<stack<int> >::iterator it=stacks.end();
if(it->size()==stack_size)
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
it->push(data);
}
void pop()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return ;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
it->pop();
}
int top()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return 0;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
return it->top();
}
};
int main()
{
stack_of_plates ss;
ss.push(1);
ss.push(2);
cout<<ss.top();
return 0;
}
On compiling it gives no error or warning. However program terminates with unusual error.
On debugging its giving segmentation fault error indicating problem in allocating new stack.
Kindly help me how should i change my code while allocating the new stack. Please help me removing this error.
stacks.end(); refers to the (nonexistent) element after the end of the vector. You can't dereference it; doing so will cause undefined behaviour, possibly a segmentation fault.
It's not quite clear what you're doing there, but if you want an iterator for the last element, then either decrement it:
vector<stack<int> >::iterator it=stacks.end(); // points past the end
--it; // points to last element
or use a reverse iterator (in which case, you use ++ rather than -- to move backwards through the sequence):
vector<stack<int> >::reverse_iterator it=stacks.rbegin();
Adding an element to a vector can invalidate it, so the it->push_back(data) at the end of push() is incorrect. You could avoid using an iterator here:
void push() {
if (stacks.empty() || stacks.back().size()==stack_size) {
// See below for explanation of this change
stacks.push_back(stack<int>());
}
stacks.back().push(data);
}
In pop(), you probably want to remove the last stack if it's empty; otherwise, you'll end up with two empty stacks at the end, and your code will erroneously try to pop from one of those. Again, doing that could cause a segmentation fault or other undefined behavoiur. You probably want something like:
void pop() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return ;
}
stacks.back().pop();
if (stacks.back().empty()) {
stacks.pop_back();
}
}
And now we've established an invariant that the last stack is never empty, top can be a bit simpler:
int top() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return 0;
}
return stacks.back().top();
}
Also, you usually don't want to create objects using new, especially in a case like this where you're putting a copy of the object into the vector and then discarding the pointer, leaking the allocated memory. You can add an empty stack to the vector like this:
stacks.push_back(stack<int>());
Sometimes (but not in this case) you might want to store pointers to allocated objects in a container; in that case, either remember to delete them when they're removed from the container, or store smart pointers such as std::unique_ptr. But in this case, just store objects.
There are many problems with the code, so it is hard to say which one is the direct cause of your problem. You need the clean them up one by one and then retest. If you still have a problem, post your new code here.
Here is the list:
You have a memory leak from your allocation with new. Since you have a vector of stacks, all you need to do is resize the vector and a new stack will be allocated. So
stacks.resize(stacks.size() + 1);
instead of
stack<int> *sptr= new stack<int>;
stacks.push_back(*sptr);
vector<>.end() returns an iterator that point to an element AFTER the last one, which is why #Joachim suggested that you need to decrement the iterator before you use it.
You have a logical error when you check whether to transfer storage to a new stack - after checking is the size of the last stack is the max, and creating a new one, you keep pushing on the old one.
I hope this helps.
std::stack<int> already has the functionality you show in your example, so there is no need for a std::vector< std::stack<int> >. By just pushing and popping to the std::stack<int> you avoid most of the issues your having in your code. There is no reason to limit std::stack<int> to stack_size.
Next to that, when you need the last entry in a container, use back() instead of end().