Stack (Data structure) implementation - c++

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

Related

How to correctly delete an allocated array (queue data structure)

I created a queue data structure using a struct and a dynamically allocated array, I don't understand what is the right way to free or delete it without any memory leaks.
I have tried using the following:
delete[] q->data;
delete[] &(q->data);
delete &(q->data);
#include "queue.h"
void initQueue(queue* q, unsigned int size)
{
q->maxSize = size;
q->size = 0;
q->data = new unsigned int[size];
q->front = 0;
q->rear = 0;
}
void enqueue(queue* q, unsigned int newValue)
{
if (q->size != q->maxSize)
{
q->data[q->rear] = newValue;
q->size++;
q->rear++;
}
else
{
std::cout << "Queue is full! you can clean it and initialize a new one" << std::endl;
}
}
int dequeue(queue* q)
{
int i = 0;
if (q->size == 0)
{
std::cout << "Queue is empty!" << std::endl;
return EMPTY;
}
else
{
q->front++;
q->size--;
return q->data[q->front];
}
}
void cleanQueue(queue* q)
{
//the delete function
}
The technical right answer here is to delete q->data, as others have suggested. But...
right way to free or delete it without any memory leaks
The right way in C++, unless you're doing some exotic with allocation, is not to do your own memory management. Write a class that allocates in the constructor, and deletes in the destructor, as Chris suggested, is a great way to learn about RAII and how it saves you from the mental burden of manually writing "delete" everywhere.
But the right right way, if someone was paying me? I'd skip all that and use a vector.
#include <vector>
class MyQueue {
public:
MyQueue(unsigned int size) : data(size) { }
void enqueue(unsigned int value) { /* whatever... */ }
int dequeue() { /* whatever... */ }
private:
std::vector<unsigned int> data;
};
When this class goes out of scope or gets deleted, the vector will automatically be cleaned up. You don't even need to free or delete anything.

Implementation of stack in C++ without using <stack>

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;
}

How to implement a dynamically resizable stack in C++?

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;
}

Implementing a Hash Table (rehash scope error)

I am getting a very strange error in my code. This assignment is for a class I'm taking and essentially we are learning how to implement a hash table. The error i'm getting is when I try and rehash to a larger size. Here's the portion of the code giving me the problem, and I'll explain more fully what the problem is.
if(htable->size>=htable->cap)
{
cout<<htable->cap<<endl;
HashTable tempht=*htable;
delete htable;
htable=new HashTable((tempht.cap * 2) + 1);
for (size_t i=0; i<tempht.cap; i++)
{
Node* n=tempht.table[i];
while (n!=NULL)
{
htable->add(n->item);
n=n->next;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
else
{
cout<<htable->table[0]->item<<endl;
}
htable is a HashTable variable. In the HashTable class it contains an array Node* (Nodes are just objects I created that contain a string and a pointer to the next item in the chain). This part of the code is simply trying to rehash to a larger table. The issue I'm getting is once I exit the first if statement, my table's first value no longer equals NULL (the test I'm running rehashes a table with nothing in it to a table that still has nothing in it, but has a larger capacity). When I run the code, the first htable->table[0]==NULL passes while the second does not, despite there being no changes other than exiting the if statement (my expected result is that the table[0] should be NULL). My best guess is it's some kind of scoping error, but I honestly can't see where the problem is. Any help would be greatly appreciated.
Edit: Just to clarify, the initial hash table has a capacity of 0 (this is one of the project requirements). So when i try to add an item to the table, this if statement is executed (since the size is 0 and the cap is 0, we have to maintain a load factor of 1). I can confirm that once the table reaches the first and second "Hooray" checks, that htable->cap (which is the total capacity of the array) is 1, which is what it should be. The only thing that is getting messed is bucket 0 (which in this case is the only bucket). For whatever reason, it's null before exiting the if statement but not after.
I'm posting my whole HashTable class, let me know if you find anything.
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include "Node.h"
using namespace std;
class HashTable
{
public:
Node** table;
int size;
int cap;
HashTable (int c)
{
size=0;
cap=c;
table = new Node*[cap];
if (cap>0)
{
for (size_t i=0; i<cap; ++i)
{
table[i]=NULL;
}
}
}
~HashTable()
{
delete table;
}
size_t hash(string thing)
{
size_t total=0;
int asci;
char c;
size_t index;
for (size_t i=0; i<thing.length(); i++)
{
total=total*31;
c=thing[i];
asci=int(c);
total=asci+total;
}
index=total%cap;
cout<<"index"<<index<<endl;
system("pause");
return index;
}
void add(string thing)
{
size_t index;
index=hash(thing);
cout<<"index "<<index<<endl;
system("pause");
Node* temp=table[index];
if (temp==NULL)
{
cout<<"Here"<<endl;
system("pause");
}
else
{
cout<<"Here2"<<endl;
system("pause");
cout<<"temp"<<temp->item<<endl;
system("pause");
}
Node* n = new Node(thing);
cout<<"n"<<n->item<<endl;
system("pause");
if (temp==NULL)
{
table[index]=n;
}
else
{
while (temp->next!=NULL)
{
temp=temp->next;
}
temp->next=n;
}
size++;
}
Node* find(string search)
{
Node* n= NULL;
size_t index;
if(cap!=0)
{
index=hash(search);
Node* temp=table[index];
while (temp!=NULL)
{
if (temp->item==search)
{
n=temp;
return n;
}
}
}
return n;
}
void remove (string thing)
{
if (find(thing)==NULL)
{
return;
}
else
{
size_t index;
index=hash(thing);
Node* temp=table[index];
if (temp->item==thing)
{
table[index]=temp->next;
delete temp;
}
while (temp->next!=NULL)
{
if (temp->next->item==thing)
{
Node* temp2=temp->next;
temp->next=temp->next->next;
delete temp2;
break;
}
}
}
size--;
}
void print(ofstream &ofile)
{
for (size_t i=0; i<cap; i++)
{
Node* n=table[i];
ofile<<"hash "<<i<<":";
while (n!=NULL)
{
ofile<<" "<<n->item;
n=n->next;
}
}
}
};
Well, this is C++, and I'm more a Java guy, but I'll take a stab at it.
Turns out the problem IS with the
HashTable tempht=*htable;
delete htable;
block after all.
See, the first line there says "copy all of the members from *htable into tempht". So now tempht and htable SHARE their table memory, since table is just a pointer to memory that was allocated at construction, and you just copied the pointer. You wanted it to copy the nodes inside table, but it didn't do that.
So now you have two different HashTable objects with the same pointer value in table. Now, when tempht is freed, the destructor calls free on the table pointer, which effectively frees the table data in both objects htable and tempht.
What you really want to do is write a copy constructor, or do something like:
HashTable *tempht=htable;
htable=new HashTable((tempht->cap * 2) + 1);
for (size_t i=0; i<tempht->cap; i++)
{
Node* n=tempht->table[i];
while (n!=NULL)
{
htable->add(n->item);
n=n->next;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
delete tempht;
See how all I've really done is change tempht to a pointer, using it to point to the old hashtable while you copy all the nodes from it to the new htable object, then deleting the old Hashtable.

Memory leak in trivial stack implementation

I'm decently experienced with Python and Java, but I recently decided to learn C++. I decided to make a quick integer stack implementation, but it has a massive memory leak that I can't understand. When I pop the node, it doesn't seem to be releasing the memory even though I explicitly delete the old node upon poping it. When I run it, it uses 150mb of memory, but doesn't release any of it after I empty the stack. I would appreciate any help since this is my first foray into a language without garbage collection. This was compiled with gcc 4.3 on 64-bit Kubuntu.
//a trivial linked list based stack of integers
#include <iostream>
using namespace std;
class Node
{
private:
int num;
Node * next;
public:
Node(int data, Node * next);
int getData();
Node * getNext();
};
Node::Node(int data, Node * next_node)
{
num = data;
next = next_node;
}
inline int Node::getData()
{
return num;
}
inline Node* Node::getNext()
{
return next;
}
class Stack
{
private:
unsigned long int n;
Node * top;
public:
Stack(int first);
Stack();
void push(int data);
int pop();
int peek();
unsigned long int getSize();
void print();
void empty();
};
Stack::Stack(int first)
{
Node first_top (first, NULL);
top = &first_top;
n = 1;
}
Stack::Stack()
{
top = NULL;
n = 0;
}
void Stack::push(int data)
{
Node* old_top = top;
Node* new_top = new Node(data,old_top);
top = new_top;
n++;
}
int Stack::pop()
{
Node* old_top = top;
int ret_num = old_top->getData();
top = old_top->getNext();
delete old_top;
n--;
return ret_num;
}
inline int Stack::peek()
{
return top->getData();
}
inline unsigned long int Stack::getSize()
{
return n;
}
void Stack::print()
{
Node* current = top;
cout << "Stack: [";
for(unsigned long int i = 0; i<n-1; i++)
{
cout << current->getData() << ", ";
current = current->getNext();
}
cout << current->getData() << "]" << endl;
}
void Stack::empty()
{
unsigned long int upper = n;
for(unsigned long int i = 0; i<upper; i++)
{
this->pop();
}
}
Stack createStackRange(int start, int end, int step = 1)
{
Stack stack = Stack();
for(int i = start; i <= end; i+=step)
{
stack.push(i);
}
return stack;
}
int main()
{
Stack s = createStackRange(0,5e6);
cout << s.peek() << endl;
sleep(1);
cout << "emptying" <<endl;
s.empty();
cout << "emptied" <<endl;
cout << "The size of the stack is " << s.getSize()<<endl;
cout << "waiting..." << endl;
sleep(10);
return 0;
}
How do you KNOW the memory isn't being released? The runtime library will manage allocations and may not release the memory back to the OS until the program terminates. If that's the case, the memory will be available for other allocations within your program during its execution.
However.... you seem to have other problems. My C++ is really rusty since I've been doing Java for 15 years, but in your Stack::Stack constructor you're allocating a Node instance on the system stack and then storing a reference to it in your "Stack". That Node instance goes out of scope when the constructor ends, leaving a dangling pointer.
Stack::Stack(int first)
{
Node first_top (first, NULL);
top = &first_top;
n = 1;
}
This is wrong , you cant assign address of a local object to class member( top ) , since local objects get destroyed when function returns.
Create a node on heap rather than stack , do something like this :
Stack::Stack(int first)
{
top = new Node(first, NULL);
n = 1;
}
And Make the concept of link list clear and use pen and paper if you can do so.
Your Stack::Push(int) operation seems buggy check it out what you have forget to do.
My suggestion is try to implement generic stack with the help of template ,so it will work for all data type .
When createStackRange() returns it'll return a copy of the Stack using the compiler-generated copy constructor which just makes a bitwise copy (i.e., it'll copy the pointer to the first node and the size.)
More seriously, you're missing the destructor for the Stack class. Ideally you'd have it walk the list and call delete on each Node. The Stack object created on the processor stack will automatically be cleaned up automatically when main() exits, but without a destructor, the nodes will still be allocated when the program ends. You probably want something like this for it:
Stack::~Stack()
{
while ( top )
{
Next *next = top->getNext();
delete top;
top = next;
}
}
The way to think of it is that the C++ compiler will automatically generate copy constructors and destructors for you, but they're normally shallow. If you need deep behavior you've got to do it implement it yourself somewhere.
After poring over the code, I couldn't find the leak so I compiled it and ran it in a debugger myself. I agree with Jim Garrision - I think you're seeing an artifact of the runtime rather than an actual leak, because I'm not seeing it on my side. The issues pointed out by NickLarsen and smith are both actual issues that you want to correct, but if you trace the code through, neither should actually be causing the problem you describe. The code smith singles out is never called in your example, and the code Nick singles out would cause other issues, but not the one you're seeing.
Creat a stub to test your code and user Memory Analysis tool like "Valgrind". This will find out memory leaks and corruptions for you.
check man-pages for more information.
Note that you should only roll your own stack for educational purposes. For any real code, you should use the stack implementation that comes with the C++ standard library...