Last active
May 9, 2017 16:33
-
-
Save willeccles/11ad20b121355e02373215b8f9ba40c8 to your computer and use it in GitHub Desktop.
Node-based stack in C++ using C-style pointers vs. C++11 smart pointers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is the right way to do this in C++11+, which is a lot of +'s. | |
* This uses the std::shared_ptr type to manage memory and access to it magically. | |
*/ | |
#ifndef STACK_H | |
#define STACK_H | |
#include <iostream> | |
#include <vector> | |
#include <memory> // std::shared_ptr | |
template <class T> | |
class stack { | |
private: | |
// the node class to be used in the stack | |
template <class nT = T> | |
class node { | |
private: | |
nT _value; | |
std::shared_ptr<node<nT>> _next; | |
public: | |
node(nT value): _value(value) { _next = nullptr; }; | |
node(nT value, std::shared_ptr<node<nT>> next): _value(value), _next(next) {}; | |
nT getValue() { return _value; }; | |
void setValue(nT newValue) { _value = newValue; }; | |
std::shared_ptr<node<nT>> getNext() { return _next; }; | |
}; | |
std::shared_ptr<node<T>> _top; // shouldn't change or we lose the list | |
size_t _numItems = 0; | |
public: | |
// constructors | |
stack() { | |
_top = nullptr; // set _top to nullptr | |
}; | |
stack(T firstVal) { | |
_top = std::make_shared<node<T>>(firstVal); | |
_numItems = 1; | |
}; | |
// push a new value to the stack | |
void push(T val) { | |
if (_top == nullptr) { | |
_top = std::make_shared<node<T>>(val); | |
} else { | |
std::shared_ptr<node<T>> newNext = _top; | |
_top = std::make_shared<node<T>>(val, newNext); | |
} | |
_numItems++; | |
}; | |
// pop a value from the stack | |
T pop() { | |
if (_top == nullptr) { | |
return static_cast<T>(NULL); | |
} else { | |
std::shared_ptr<node<T>> old = _top; | |
_top = _top->getNext(); | |
_numItems--; | |
T rval = old->getValue(); | |
return rval; | |
} | |
}; | |
// remove all the items from the stack | |
void popAll() { | |
std::shared_ptr<node<T>> curr = _top; | |
while (curr != nullptr) { | |
std::shared_ptr<node<T>> next = curr->getNext(); | |
curr = next; | |
} | |
_top = nullptr; | |
_numItems = 0; | |
} | |
// peek at the top of the stack | |
T peek() { | |
return _top->getValue(); | |
}; | |
// for printing the stack out | |
void print() { | |
if (isEmpty()) { | |
std::cout << "Stack is empty." << std::endl; | |
} else { | |
std::shared_ptr<node<T>> curr = _top; | |
while (curr != nullptr) { | |
std::cout << curr->getValue() << ' '; | |
curr = curr->getNext(); | |
} | |
std::cout << std::endl; | |
} | |
} | |
// if you want to loop through and apply an operation to each value in the stack | |
void doForEach(T (*op)(T)) { | |
std::shared_ptr<node<T>> curr = _top; | |
while (curr != nullptr) { | |
curr->setValue(op(curr->getValue())); | |
curr = curr->getNext(); | |
} | |
}; | |
// getSize and isEmpty are pretty self-explanatory | |
size_t getSize() { return _numItems; }; | |
bool isEmpty() { return !_numItems; }; | |
// destructor because we like having memory amirite | |
~stack() { | |
_top.reset(); | |
}; | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is the old way of doing a node-based stack, with old C-style pointers. | |
* newstack.h (included) uses the newer C++11 smart pointers. | |
*/ | |
#ifndef STACK_H | |
#define STACK_H | |
#include <iostream> | |
#include <vector> | |
template <class T> | |
class stack { | |
private: | |
// the node class to be used in the stack | |
template <class nT = T> | |
class node { | |
private: | |
nT _value; | |
node<nT>* _next; | |
public: | |
node(nT value): _value(value) { _next = nullptr; }; | |
node(nT value, node<nT>* next): _value(value), _next(next) {}; | |
nT getValue() { return _value; }; | |
void setValue(nT newValue) { _value = newValue; }; | |
node<nT>* getNext() { return _next; }; | |
}; | |
node<T>* _top; // shouldn't change or we lose the list | |
size_t _numItems = 0; | |
public: | |
// constructors | |
stack() { | |
_top = nullptr; // set _top to nullptr | |
}; | |
stack(T firstVal) { | |
_top = new node<T>(firstVal); | |
_numItems = 1; | |
}; | |
// push a new value to the stack | |
void push(T val) { | |
if (_top == nullptr) { | |
_top = new node<T>(val); | |
} else { | |
node<T>* newNext = _top; | |
_top = new node<T>(val, newNext); | |
} | |
_numItems++; | |
}; | |
// pop a value from the stack | |
T pop() { | |
if (_top == nullptr) { | |
return static_cast<T>(NULL); | |
} else { | |
node<T>* old = _top; | |
_top = _top->getNext(); | |
_numItems--; | |
T rval = old->getValue(); | |
delete old; | |
return rval; | |
} | |
}; | |
// remove all the items from the stack | |
void popAll() { | |
node<T>* curr = _top; | |
while (curr != nullptr) { | |
node<T>* next = curr->getNext(); | |
curr = next; | |
} | |
_top = nullptr; | |
_numItems = 0; | |
} | |
// peek at the top of the stack | |
T peek() { | |
return _top->getValue(); | |
}; | |
// for printing the stack out | |
void print() { | |
if (isEmpty()) { | |
std::cout << "Stack is empty." << std::endl; | |
} else { | |
node<T>* curr = _top; | |
while (curr != nullptr) { | |
std::cout << curr->getValue() << ' '; | |
curr = curr->getNext(); | |
} | |
std::cout << std::endl; | |
} | |
} | |
// if you want to loop through and apply an operation to each value in the stack | |
void doForEach(T (*op)(T)) { | |
node<T>* curr = _top; | |
while (curr != nullptr) { | |
curr->setValue(op(curr->getValue())); | |
curr = curr->getNext(); | |
} | |
}; | |
// getSize and isEmpty are pretty self-explanatory | |
size_t getSize() { return _numItems; }; | |
bool isEmpty() { return !_numItems; }; | |
// destructor because we like having memory amirite | |
~stack() { | |
node<T>* curr = _top; | |
while (curr != nullptr) { | |
node<T>* next = curr->getNext(); | |
delete curr; | |
curr = next; | |
} | |
delete _top; | |
}; | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment