my code right now is just a simple stack that has push, pop, and display methods. How can I change my stack so that the size of the stack dynamically resizes based on the number of elements entered? So, for example, if the stack is full, I create a new stack that is twice the size of the original, and copy the data to the new stack.
Thanks.
#include <iostream>
#include <stdexcept>
using namespace std;
class Stack
{
private:
int *p;
int top,length;
public:
Stack(int = 0);
~Stack();
void push(int);
int pop();
void display();
};
Stack::Stack(int size)
{
top=-1;
length=size;
while(length <= 0) //If the stack size is zero, allow user to mention it at runtime
{
cout<<"Stack of zero size"<<endl;
cout<<"Enter a size for stack : ";
cin >> length;
}
p=new int[length];
}
Stack::~Stack()
{
delete [] p;
}
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
throw overflow_error("Can't push onto a full stack");
}
else
{
top++;
p[top]=elem;
}
}
int Stack::pop()
{
if(top==-1)
{
throw underflow_error("Can't pop from an empty stack");
}
int ret=p[top];
top--;
length--;
return ret;
}
void Stack::display()
{
for(int i = 0; i <= top; i++)
cout<<p[i]<<" ";
cout<<endl;
}
int main()
{
int len;
cout<<"Enter a size for stack : ";
cin >> len;
Stack s1(len);
try{
s1.push(1);
s1.display();
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
}
catch(overflow_error){
cerr<< "Illegal operation. Cannot push onto a full stack.";
return -1;
}
catch(underflow_error){
cerr<< "Illegal operation. Cannot pop from an empty stack.";
return -1;
}
}
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
int* newp = new int[length * 2];
std::memcpy(newp, p, sizeof(int) * length);
delete[] p;
p = newp;
top++;
p[top]=elem;
length*=2;
}
else
{
top++;
p[top]=elem;
}
}
The stack class in the standard library (std::stack) solves this by delegating to a container class such as std::vector. That's slightly cheating, though.
However, the idea behind std::vector<> is fairly straightforward and reusable. When you hit the maxiumum size, do the following things in order:
Allocate new memory. No big problem if it fails (no data lost)
Copy all existing elements over. Use std::uninitialized_copy not std::copy
Swap the new and old pointer
Delete the old objects
Free the old allocation
One simple way is to double the stack size each time pushing a new element would overflow the stack. In that instance, you detect the potential overflow and then you would use declare a new int array that is twice the size of the old one and then copy the old array into this new array and reassign the pointer to that new array and delete the old array. The are other more optimal ways, but that is a simplistic way of doing it, you can use up considerably more memory than is necessary to add the new item, but it's a lot faster than reallocating with every new item that would overflow your stack.
Instead of throwing the exception overflow_error("Can't push onto a full stack") you can allocate more memory using new and copy the contents to that memory and release the previously allocated memory(memory swapping).
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
//throw overflow_error("Can't push onto a full stack");
int *pTemp = new int[length + 10/*value u want to increment*/];
memcpy(p,pTemp,length); //for using this include stdlib
delete[] p;
p = pTemp;
}
top++;
p[top]=elem;
}
Related
I want to make a char stack implementation, but i think something is wrong with it because when i try to use it for my other function it does not word and library stack works. Can you help to find an issue:
using namespace std;
Stack::Stack(int size)
{
arr = new char[size];
capacity = size;
t = -1;
}
int Stack::size()
{
return (t + 1);
}
Stack::~Stack()
{
delete[] arr;
}
bool Stack::empty()
{
return size()==0;
}
void Stack::push(char x)
{
if (size()==capacity) {
cout<<"Push to full stack";
arr[++t]=x;
}
}
char Stack::pop()
{
if (empty()) {
cout<<"Pop from empty stack";
--t;
}
return 0;
}
char Stack::top()
{
if (!empty())
return arr[t];
else
cout<<"Top of the stack is empty";
return 0;
}
I want to make a char stack implementation, but i think something is wrong with it because when i try to use it for my other function it does not word and library stack works. Can you help to find an issue:
Thank you in advance!
I think you need to make some changes to the push and pop function for your Stack to work
In push, you should put arr[++t]=x; outside the if statement instead of inside as you want to add value to arr if the current size is less than its capacity instead of when it is equal
In pop, you should put arr[--t]; outside the if statement instead of inside as you want to remove and return the last value in the array if the stack is not empty. When it is empty, you should consider returning a default character such as the null terminator character \0. You should also want to use arr[t--] instead of arr[--t] as the last element is currently at t so you want it to evaluate arr[t] before decreasing its value (t--)
void Stack::push(char x)
{
if (size()==capacity) {
cout<<"Push to full stack";
return;
}
arr[++t]=x;
}
char Stack::pop()
{
if (empty()) {
cout<<"Pop from empty stack";
return '\0';
}
return arr[t--];
}
I am trying to solve a problem related to stack data structure, I have an implementation of a stack, and a main method that uses it, this is a for-learning question as i am a beginner, can you guys tell me, why i get this error?:
GDB trace:
Reading symbols from solution...done.
[New LWP 24202]
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 main () at solution.cc:70
70 cin >> N;
#0 main () at solution.cc:70
my code is the following:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX_SIZE 5000000
class Stack
{
private:
int A[MAX_SIZE]; // array to store the stack
int top; // variable to mark the top index of stack.
public:
// constructor
Stack()
{
top = -1; // for empty array, set top = -1
}
// Push operation to insert an element on top of stack.
void Push(int x)
{
if(top == MAX_SIZE -1) { // overflow case.
printf("Error: stack overflow\n");
return;
}
A[++top] = x;
}
// Pop operation to remove an element from top of stack.
void Pop()
{
if(top == -1) { // If stack is empty, pop should throw error.
printf("Error: No element to pop\n");
return;
}
top--;
}
// Top operation to return element at top of stack.
int Top()
{
return A[top];
}
// This function will return 1 (true) if stack is empty, 0 (false) otherwise
int IsEmpty()
{
if(top == -1) return 1;
return 0;
}
// ONLY FOR TESTING - NOT A VALID OPERATION WITH STACK
// This function is just to test the implementation of stack.
// This will print all the elements in the stack at any stage.
void Print() {
int i;
printf("Stack: ");
for(i = 0;i<=top;i++)
printf("%d ",A[i]);
printf("\n");
}
};
int main() {
int N;
cin >> N;
Stack S1;
Stack S2;
for(int i = 0; i < N; i++)
{
int q;
cin >> q;
if(q == 1)
{
int x;
cin >> x;
if(S1.IsEmpty() || S2.IsEmpty())
{
S1.Push(x);
S2.Push(x);
}
else
{
S1.Push(x);
if(x >= S2.Top()) S2.Push(x);
}
}
if(q==2)
{
if(S1.Top() == S2.Top())
{
S1.Pop();
S2.Pop();
}else
{
S1.Pop();
}
}
if(q==3)
{
cout << S2.Top() << endl;
}
}
return 0;
}
if i set MAX_SIZE variable to a lower number the code runs well, i want to know why is that the case, how std::cin and macros interact??, i am a beginner, sorry if this is a simple question it is the first time that i am asking in stackoverflow,
MAX_SIZE is far too big. MAX_SIZE determines the size of your Stack objects. As the total size of local variables in a function is limited to a few megabytes (depending on the platform), you simply exceed this size.
In your case you have two local Stack objects in main (S1and S2), each of them taking roughly 20 Mbytes (assuming sizeof int is 4).
This is totally unrelated to cin though.
Your Stack objects are allocated on the stack.
By default the stack is limited to something like 1-8 MB per thread depending on your platform.
Each of your stack objects takes up 20 MB so you are running out of stack space. To fix this change your code to:
std::unique_ptr<Stack> S1(new Stack());
std::unique_ptr<Stack> S2(new Stack());
This will allocate your objects on the heap which is only limited by the size of the available memory and swap space on your machine.
So I'm just starting to learn about data structures through a course on Coursera and I learned that it's possible to create a stack data structure by using an array. I was just wondering if what I have written is what a stack is supposed to do.
#include <iostream>
using namespace std;
const int MAX_SIZE = 10000;
class Stack {
public:
Stack();
~Stack();
void push(int n);
void pop();
int top();
bool isEmpty() const;
void print() const;
private:
int* array [MAX_SIZE];
int curNum;
};
Stack::Stack() {
curNum = 0;
}
Stack::~Stack() {
for (int i = 0; i < curNum; ++i)
delete array[i];
}
void Stack::push(int n) {
if (curNum >= MAX_SIZE) {
cout << "reached maximum capacity...can't add an element\n";
return;
}
array[curNum] = new int(n);
curNum++;
}
void Stack::pop() {
delete array[curNum];
curNum--;
}
int Stack::top() {
return *array[curNum];
}
void Stack::print() const{
for (int i = 0; i < curNum; ++i)
cout << *array[i] << endl;
}
bool Stack::isEmpty() const{
return curNum == 0;
}
int main () {
Stack stack;
stack.push(5);
stack.print();
stack.pop();
}
Also, I see that a lot of people don't use dynamic memory allocation for this kind of task. Is there a reason why? It seems like specifying a size for the array at compile time might lead to insufficient memory or over-allocating memory to me
Yes, this is one way to implement a stack. The important thing that defines a stack is LIFO (last in, first out). So as long as you are only adding to and removing from the top, then that is a stack. Think of it as a stack of dishes; if 10 dishes are put one by one into a stack, and then one by one removed from said stack, the first dish put on will also be the last dish removed. You can't remove a dish that's not at the top, as it is covered by all the dishes above it. The same is true with a stack data structure.
So your implementation is indeed a stack.
The stack we use when we want something in reverse order and stack also takes constant time means O(1) time to push and pop means to remove or to add it will work much faster
I want to add X to the end of my Array if the array is full I double the size but i'm having trouble inserting it into newArray after I get it into newArray I use pointers to switch dynamicArray to newArray.
#include <iostream>
using namespace std;
class IntegerDynamicArray {
public:
IntegerDynamicArray();
~IntegerDynamicArray();
int add(int x);
private:
int * dynamicArray;
int currentSize=maxSize;
int maxSize=4;
};``
IntegerDynamicArray::IntegerDynamicArray()
{
dynamicArray = new int [maxSize];
}
IntegerDynamicArray::~IntegerDynamicArray()
{
delete [] dynamicArray;
}
int IntegerDynamicArray::add(int x)
{
cout<<x<<endl;
if(dynamicArray[currentSize-1]!=0)
{
int * newArray;
newArray= new int[currentSize*2];
for(int i =0;i<currentSize;i++)
{
newArray[i]=dynamicArray[i];
newArray[currentSize]=x;
}
currentSize=currentSize*2;
dynamicArray = newArray;
}
else
{
int * newArray;
newArray= new int[currentSize];
for(int i =0;i<currentSize;i++)
{
newArray[i]=dynamicArray[i];
newArray[currentSize-1]=x;
}
dynamicArray = newArray;
}
return *dynamicArray;
}
int main() {
IntegerDynamicArray intDynArray;
while (1) {
char input;
cout << "Enter A for add or anything else to quit: ";
cin >> input;
if (input == 'A') {
cout << "Enter number to add: ";
int x;
cin >> x;
cout << intDynArray.add(x) << endl;
} else {
break;
}
}
}
There are several problems with your code. Because you didn't asked a dedicated question these are the main ones:
Your class lacks a variable containing the index of the last written (or next free) index of the array. Instead you (mis)use currentSize as such index variable.
On each call of add() you allocate a new array although it might not be full already.
As already mentioned in the comments you do not delete [] your old arrays after copying into the new one.
You use 0 as indicator that a slot in your array is empty, but you do not prevent adding 0 as regular element and you do not initialize your array to zero.
As Thomas Matthews pointed out:
You are leaking memory while calling add(int x). For each use of new, there should be a call for delete
Consider the following:
int n=10;
int* x= new int[n];
//assign some values
int* temp=new int[n*2]; //create new array
for(int i=0;i<n;i++)
temp[i]=x[i]; //assign values from x
delete[] x; //free memory
x=temp; //assign to x address of new array
Manual memory managment can be risky, so consider using std::vector in future
I want to make an implementation of stack, I found a working model on the internet, unfortunately it is based on the idea that I know the size of the stack I want to implement right away. What I want to do is be able to add segments to my stack as they are needed, because potential maximum amount of the slots required goes into 10s of thousands and from my understanding making the size set in stone (when all of it is not needed most of the time) is a huge waste of memory and loss of the execution speed of the program. I also do not want to use any complex prewritten functions in my implementation (the functions provided by STL or different libraries such as vector etc.) as I want to understand all of them more by trying to make them myself/with brief help.
struct variabl {
char *given_name;
double value;
};
variabl* variables[50000];
int c = 0;
int end_of_stack = 0;
class Stack
{
private:
int top, length;
char *z;
int index_struc = 0;
public:
Stack(int = 0);
~Stack();
char pop();
void push();
};
Stack::Stack(int size) /*
This is where the problem begins, I want to be able to allocate the size
dynamically.
*/
{
top = -1;
length = size;
z = new char[length];
}
void Stack::push()
{
++top;
z[top] = variables[index_struc]->value;
index_struc++;
}
char Stack::pop()
{
end_of_stack = 0;
if (z == 0 || top == -1)
{
end_of_stack = 1;
return NULL;
}
char top_stack = z[top];
top--;
length--;
return top_stack;
}
Stack::~Stack()
{
delete[] z;
}
I had somewhat of a idea, and tried doing
Stack stackk
//whenever I want to put another thing into stack
stackk.push = new char;
but then I didnt completely understand how will it work for my purpose, I don't think it will be fully accessible with the pop method etc because it will be a set of separate arrays/variables right? I want the implementation to remain reasonably simple so I can understand it.
Change your push function to take a parameter, rather than needing to reference variables.
To handle pushes, start with an initial length of your array z (and change z to a better variable name). When you are pushing a new value, check if the new value will mean that the size of your array is too small (by comparing length and top). If it will exceed the current size, allocate a bigger array and copy the values from z to the new array, free up z, and make z point to the new array.
Here you have a simple implementation without the need of reallocating arrays. It uses the auxiliary class Node, that holds a value, and a pointer to another Node (that is set to NULL to indicate the end of the stack).
main() tests the stack by reading commands of the form
p c: push c to the stack
g: print top of stack and pop
#include <cstdlib>
#include <iostream>
using namespace std;
class Node {
private:
char c;
Node *next;
public:
Node(char cc, Node *nnext){
c = cc;
next = nnext;
}
char getChar(){
return c;
}
Node *getNext(){
return next;
}
~Node(){}
};
class Stack {
private:
Node *start;
public:
Stack(){
start = NULL;
}
void push(char c){
start = new Node(c, start);
}
char pop(){
if(start == NULL){
//Handle error
cerr << "pop on empty stack" << endl;
exit(1);
}
else {
char r = (*start).getChar();
Node* newstart = (*start).getNext();
delete start;
start = newstart;
return r;
}
}
bool empty(){
return start == NULL;
}
};
int main(){
char c, k;
Stack st;
while(cin>>c){
switch(c){
case 'p':
cin >> k;
st.push(k);
break;
case 'g':
cout << st.pop()<<endl;
break;
}
}
return 0;
}