mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-02-11 22:46:39 +08:00
Merge branch 'master' into temp
This commit is contained in:
@@ -66,7 +66,7 @@
|
||||
* [Reverse A Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/reverse_a_linked_list.cpp)
|
||||
* [Skip List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/skip_list.cpp)
|
||||
* [Sparse Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/sparse_table.cpp)
|
||||
* [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/stack.h)
|
||||
* [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/stack.hpp)
|
||||
* [Stack Using Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/stack_using_array.cpp)
|
||||
* [Stack Using Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/stack_using_linked_list.cpp)
|
||||
* [Stack Using Queue](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/stack_using_queue.cpp)
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/**
|
||||
* @file stack.h
|
||||
* @author danghai
|
||||
* @brief This class specifies the basic operation on a stack as a linked list
|
||||
**/
|
||||
#ifndef DATA_STRUCTURES_STACK_H_
|
||||
#define DATA_STRUCTURES_STACK_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
/** Definition of the node as a linked-list
|
||||
* \tparam Type type of data nodes of the linked list should contain
|
||||
*/
|
||||
template <class Type>
|
||||
struct node {
|
||||
Type data; ///< data at current node
|
||||
node<Type> *next; ///< pointer to the next ::node instance
|
||||
};
|
||||
|
||||
/** Definition of the stack class
|
||||
* \tparam Type type of data nodes of the linked list in the stack should
|
||||
* contain
|
||||
*/
|
||||
template <class Type>
|
||||
class stack {
|
||||
public:
|
||||
/** Show stack */
|
||||
void display() {
|
||||
node<Type> *current = stackTop;
|
||||
std::cout << "Top --> ";
|
||||
while (current != nullptr) {
|
||||
std::cout << current->data << " ";
|
||||
current = current->next;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
std::cout << "Size of stack: " << size << std::endl;
|
||||
}
|
||||
|
||||
/** Default constructor*/
|
||||
stack() {
|
||||
stackTop = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/** Copy constructor*/
|
||||
explicit stack(const stack<Type> &otherStack) {
|
||||
node<Type> *newNode, *current, *last;
|
||||
|
||||
/* If stack is no empty, make it empty */
|
||||
if (stackTop != nullptr) {
|
||||
stackTop = nullptr;
|
||||
}
|
||||
if (otherStack.stackTop == nullptr) {
|
||||
stackTop = nullptr;
|
||||
} else {
|
||||
current = otherStack.stackTop;
|
||||
stackTop = new node<Type>;
|
||||
stackTop->data = current->data;
|
||||
stackTop->next = nullptr;
|
||||
last = stackTop;
|
||||
current = current->next;
|
||||
/* Copy the remaining stack */
|
||||
while (current != nullptr) {
|
||||
newNode = new node<Type>;
|
||||
newNode->data = current->data;
|
||||
newNode->next = nullptr;
|
||||
last->next = newNode;
|
||||
last = newNode;
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
size = otherStack.size;
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
~stack() {}
|
||||
|
||||
/** Determine whether the stack is empty */
|
||||
bool isEmptyStack() { return (stackTop == nullptr); }
|
||||
|
||||
/** Add new item to the stack */
|
||||
void push(Type item) {
|
||||
node<Type> *newNode;
|
||||
newNode = new node<Type>;
|
||||
newNode->data = item;
|
||||
newNode->next = stackTop;
|
||||
stackTop = newNode;
|
||||
size++;
|
||||
}
|
||||
|
||||
/** Return the top element of the stack */
|
||||
Type top() {
|
||||
assert(stackTop != nullptr);
|
||||
return stackTop->data;
|
||||
}
|
||||
|
||||
/** Remove the top element of the stack */
|
||||
void pop() {
|
||||
node<Type> *temp;
|
||||
if (!isEmptyStack()) {
|
||||
temp = stackTop;
|
||||
stackTop = stackTop->next;
|
||||
delete temp;
|
||||
size--;
|
||||
} else {
|
||||
std::cout << "Stack is empty !" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear stack */
|
||||
void clear() { stackTop = nullptr; }
|
||||
|
||||
/** Overload "=" the assignment operator */
|
||||
stack<Type> &operator=(const stack<Type> &otherStack) {
|
||||
node<Type> *newNode, *current, *last;
|
||||
|
||||
/* If stack is no empty, make it empty */
|
||||
if (stackTop != nullptr) {
|
||||
stackTop = nullptr;
|
||||
}
|
||||
if (otherStack.stackTop == nullptr) {
|
||||
stackTop = nullptr;
|
||||
} else {
|
||||
current = otherStack.stackTop;
|
||||
stackTop = new node<Type>;
|
||||
stackTop->data = current->data;
|
||||
stackTop->next = nullptr;
|
||||
last = stackTop;
|
||||
current = current->next;
|
||||
/* Copy the remaining stack */
|
||||
while (current != nullptr) {
|
||||
newNode = new node<Type>;
|
||||
newNode->data = current->data;
|
||||
newNode->next = nullptr;
|
||||
last->next = newNode;
|
||||
last = newNode;
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
size = otherStack.size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
node<Type> *stackTop; /**< Pointer to the stack */
|
||||
int size; ///< size of stack
|
||||
};
|
||||
|
||||
#endif // DATA_STRUCTURES_STACK_H_
|
||||
106
data_structures/stack.hpp
Normal file
106
data_structures/stack.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file
|
||||
* @author danghai
|
||||
* @author [Piotr Idzik](https://github.com/vil02)
|
||||
* @brief This class specifies the basic operation on a stack as a linked list
|
||||
**/
|
||||
#ifndef DATA_STRUCTURES_STACK_HPP_
|
||||
#define DATA_STRUCTURES_STACK_HPP_
|
||||
|
||||
#include <iostream> /// for IO operations
|
||||
#include <memory> /// for std::shared_ptr
|
||||
#include <stdexcept> /// for std::invalid_argument
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
/** Definition of the node as a linked-list
|
||||
* \tparam ValueType type of data nodes of the linked list should contain
|
||||
*/
|
||||
template <class ValueType>
|
||||
struct node {
|
||||
ValueType data = {}; ///< data at current node
|
||||
std::shared_ptr<node<ValueType>> next =
|
||||
{}; ///< pointer to the next ::node instance
|
||||
};
|
||||
|
||||
template <typename Node, typename Action>
|
||||
void traverse(const Node* const inNode, const Action& action) {
|
||||
if (inNode) {
|
||||
action(*inNode);
|
||||
traverse(inNode->next.get(), action);
|
||||
}
|
||||
}
|
||||
|
||||
/** Definition of the stack class
|
||||
* \tparam value_type type of data nodes of the linked list in the stack should
|
||||
* contain
|
||||
*/
|
||||
template <class ValueType>
|
||||
class stack {
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
|
||||
/** Show stack */
|
||||
void display() const {
|
||||
std::cout << "Top --> ";
|
||||
traverse(stackTop.get(), [](const node<value_type>& inNode) {
|
||||
std::cout << inNode.data << " ";
|
||||
});
|
||||
std::cout << std::endl;
|
||||
std::cout << "Size of stack: " << size << std::endl;
|
||||
}
|
||||
|
||||
std::vector<value_type> toVector() const {
|
||||
std::vector<value_type> res;
|
||||
res.reserve(this->size);
|
||||
traverse(stackTop.get(), [&res](const node<value_type>& inNode) {
|
||||
res.push_back(inNode.data);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
void ensureNotEmpty() const {
|
||||
if (isEmptyStack()) {
|
||||
throw std::invalid_argument("Stack is empty.");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/** Determine whether the stack is empty */
|
||||
bool isEmptyStack() const { return (stackTop == nullptr); }
|
||||
|
||||
/** Add new item to the stack */
|
||||
void push(const value_type& item) {
|
||||
auto newNode = std::make_shared<node<value_type>>();
|
||||
newNode->data = item;
|
||||
newNode->next = stackTop;
|
||||
stackTop = newNode;
|
||||
size++;
|
||||
}
|
||||
|
||||
/** Return the top element of the stack */
|
||||
value_type top() const {
|
||||
ensureNotEmpty();
|
||||
return stackTop->data;
|
||||
}
|
||||
|
||||
/** Remove the top element of the stack */
|
||||
void pop() {
|
||||
ensureNotEmpty();
|
||||
stackTop = stackTop->next;
|
||||
size--;
|
||||
}
|
||||
|
||||
/** Clear stack */
|
||||
void clear() {
|
||||
stackTop = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<node<value_type>> stackTop =
|
||||
{}; /**< Pointer to the stack */
|
||||
std::size_t size = 0; ///< size of stack
|
||||
};
|
||||
|
||||
#endif // DATA_STRUCTURES_STACK_HPP_
|
||||
@@ -1,59 +1,203 @@
|
||||
#include <iostream>
|
||||
#include <cassert> /// for assert
|
||||
#include <iostream> /// for std::cout
|
||||
#include <stdexcept> /// std::invalid_argument
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
#include "./stack.h"
|
||||
#include "./stack.hpp"
|
||||
|
||||
template <typename T>
|
||||
void testConstructedStackIsEmpty() {
|
||||
const stack<T> curStack;
|
||||
assert(curStack.isEmptyStack());
|
||||
}
|
||||
|
||||
void testPush() {
|
||||
using valueType = int;
|
||||
stack<valueType> curStack;
|
||||
curStack.push(10);
|
||||
curStack.push(20);
|
||||
curStack.push(30);
|
||||
curStack.push(40);
|
||||
const auto expectedData = std::vector<valueType>({40, 30, 20, 10});
|
||||
assert(curStack.toVector() == expectedData);
|
||||
}
|
||||
|
||||
void testTop() {
|
||||
using valueType = unsigned;
|
||||
stack<valueType> curStack;
|
||||
curStack.push(1);
|
||||
curStack.push(2);
|
||||
curStack.push(3);
|
||||
curStack.push(4);
|
||||
assert(curStack.top() == static_cast<valueType>(4));
|
||||
}
|
||||
|
||||
void testPop() {
|
||||
using valueType = int;
|
||||
stack<valueType> curStack;
|
||||
curStack.push(100);
|
||||
curStack.push(200);
|
||||
curStack.push(300);
|
||||
|
||||
assert(curStack.top() == static_cast<valueType>(300));
|
||||
curStack.pop();
|
||||
assert(curStack.top() == static_cast<valueType>(200));
|
||||
curStack.pop();
|
||||
assert(curStack.top() == static_cast<valueType>(100));
|
||||
curStack.pop();
|
||||
assert(curStack.isEmptyStack());
|
||||
}
|
||||
|
||||
void testClear() {
|
||||
stack<int> curStack;
|
||||
curStack.push(1000);
|
||||
curStack.push(2000);
|
||||
curStack.clear();
|
||||
assert(curStack.isEmptyStack());
|
||||
}
|
||||
|
||||
void testCopyOfStackHasSameData() {
|
||||
stack<int> stackA;
|
||||
stackA.push(10);
|
||||
stackA.push(200);
|
||||
stackA.push(3000);
|
||||
const auto stackB(stackA);
|
||||
assert(stackA.toVector() == stackB.toVector());
|
||||
}
|
||||
|
||||
void testPushingToCopyDoesNotChangeOriginal() {
|
||||
using valueType = int;
|
||||
stack<valueType> stackA;
|
||||
stackA.push(10);
|
||||
stackA.push(20);
|
||||
stackA.push(30);
|
||||
auto stackB(stackA);
|
||||
stackB.push(40);
|
||||
|
||||
const auto expectedDataA = std::vector<valueType>({30, 20, 10});
|
||||
const auto expectedDataB = std::vector<valueType>({40, 30, 20, 10});
|
||||
|
||||
assert(stackA.toVector() == expectedDataA);
|
||||
assert(stackB.toVector() == expectedDataB);
|
||||
}
|
||||
|
||||
void testPoppingFromCopyDoesNotChangeOriginal() {
|
||||
using valueType = int;
|
||||
stack<valueType> stackA;
|
||||
stackA.push(10);
|
||||
stackA.push(20);
|
||||
stackA.push(30);
|
||||
auto stackB(stackA);
|
||||
stackB.pop();
|
||||
|
||||
const auto expectedDataA = std::vector<valueType>({30, 20, 10});
|
||||
const auto expectedDataB = std::vector<valueType>({20, 10});
|
||||
|
||||
assert(stackA.toVector() == expectedDataA);
|
||||
assert(stackB.toVector() == expectedDataB);
|
||||
}
|
||||
|
||||
void testPushingToOrginalDoesNotChangeCopy() {
|
||||
using valueType = int;
|
||||
stack<valueType> stackA;
|
||||
stackA.push(10);
|
||||
stackA.push(20);
|
||||
stackA.push(30);
|
||||
const auto stackB(stackA);
|
||||
stackA.push(40);
|
||||
|
||||
const auto expectedDataA = std::vector<valueType>({40, 30, 20, 10});
|
||||
const auto expectedDataB = std::vector<valueType>({30, 20, 10});
|
||||
|
||||
assert(stackA.toVector() == expectedDataA);
|
||||
assert(stackB.toVector() == expectedDataB);
|
||||
}
|
||||
|
||||
void testPoppingFromOrginalDoesNotChangeCopy() {
|
||||
using valueType = int;
|
||||
stack<valueType> stackA;
|
||||
stackA.push(10);
|
||||
stackA.push(20);
|
||||
stackA.push(30);
|
||||
const auto stackB(stackA);
|
||||
stackA.pop();
|
||||
|
||||
const auto expectedDataA = std::vector<valueType>({20, 10});
|
||||
const auto expectedDataB = std::vector<valueType>({30, 20, 10});
|
||||
|
||||
assert(stackA.toVector() == expectedDataA);
|
||||
assert(stackB.toVector() == expectedDataB);
|
||||
}
|
||||
|
||||
void testAssign() {
|
||||
using valueType = int;
|
||||
stack<valueType> stackA;
|
||||
stackA.push(10);
|
||||
stackA.push(20);
|
||||
stackA.push(30);
|
||||
stack<valueType> stackB = stackA;
|
||||
stackA.pop();
|
||||
stackB.push(40);
|
||||
|
||||
const auto expectedDataA = std::vector<valueType>({20, 10});
|
||||
const auto expectedDataB = std::vector<valueType>({40, 30, 20, 10});
|
||||
|
||||
assert(stackA.toVector() == expectedDataA);
|
||||
assert(stackB.toVector() == expectedDataB);
|
||||
|
||||
stackB = stackA;
|
||||
stackA.pop();
|
||||
stackB.push(5);
|
||||
stackB.push(6);
|
||||
|
||||
const auto otherExpectedDataA = std::vector<valueType>({10});
|
||||
const auto otherExpectedDataB = std::vector<valueType>({6, 5, 20, 10});
|
||||
|
||||
assert(stackA.toVector() == otherExpectedDataA);
|
||||
assert(stackB.toVector() == otherExpectedDataB);
|
||||
}
|
||||
|
||||
void testTopThrowsAnvalidArgumentWhenStackEmpty() {
|
||||
const stack<long double> curStack;
|
||||
bool wasException = false;
|
||||
try {
|
||||
curStack.top();
|
||||
} catch (const std::invalid_argument&) {
|
||||
wasException = true;
|
||||
}
|
||||
assert(wasException);
|
||||
}
|
||||
|
||||
void testPopThrowsAnvalidArgumentWhenStackEmpty() {
|
||||
stack<bool> curStack;
|
||||
bool wasException = false;
|
||||
try {
|
||||
curStack.pop();
|
||||
} catch (const std::invalid_argument&) {
|
||||
wasException = true;
|
||||
}
|
||||
assert(wasException);
|
||||
}
|
||||
|
||||
int main() {
|
||||
stack<int> stk;
|
||||
std::cout << "---------------------- Test construct ----------------------"
|
||||
<< std::endl;
|
||||
stk.display();
|
||||
std::cout
|
||||
<< "---------------------- Test isEmptyStack ----------------------"
|
||||
<< std::endl;
|
||||
if (stk.isEmptyStack())
|
||||
std::cout << "PASS" << std::endl;
|
||||
else
|
||||
std::cout << "FAIL" << std::endl;
|
||||
std::cout << "---------------------- Test push ----------------------"
|
||||
<< std::endl;
|
||||
std::cout << "After pushing 10 20 30 40 into stack: " << std::endl;
|
||||
stk.push(10);
|
||||
stk.push(20);
|
||||
stk.push(30);
|
||||
stk.push(40);
|
||||
stk.display();
|
||||
std::cout << "---------------------- Test top ----------------------"
|
||||
<< std::endl;
|
||||
int value = stk.top();
|
||||
if (value == 40)
|
||||
std::cout << "PASS" << std::endl;
|
||||
else
|
||||
std::cout << "FAIL" << std::endl;
|
||||
std::cout << "---------------------- Test pop ----------------------"
|
||||
<< std::endl;
|
||||
stk.display();
|
||||
stk.pop();
|
||||
stk.pop();
|
||||
std::cout << "After popping 2 times: " << std::endl;
|
||||
stk.display();
|
||||
std::cout << "---------------------- Test overload = operator "
|
||||
"----------------------"
|
||||
<< std::endl;
|
||||
stack<int> stk1;
|
||||
std::cout << "stk current: " << std::endl;
|
||||
stk.display();
|
||||
std::cout << std::endl << "Assign stk1 = stk " << std::endl;
|
||||
stk1 = stk;
|
||||
stk1.display();
|
||||
std::cout << std::endl << "After pushing 8 9 10 into stk1:" << std::endl;
|
||||
stk1.push(8);
|
||||
stk1.push(9);
|
||||
stk1.push(10);
|
||||
stk1.display();
|
||||
std::cout << std::endl << "stk current: " << std::endl;
|
||||
stk.display();
|
||||
std::cout << "Assign back stk = stk1:" << std::endl;
|
||||
stk = stk1;
|
||||
stk.display();
|
||||
testConstructedStackIsEmpty<int>();
|
||||
testConstructedStackIsEmpty<char>();
|
||||
|
||||
testPush();
|
||||
testPop();
|
||||
testClear();
|
||||
|
||||
testCopyOfStackHasSameData();
|
||||
testPushingToCopyDoesNotChangeOriginal();
|
||||
testPoppingFromCopyDoesNotChangeOriginal();
|
||||
testPushingToOrginalDoesNotChangeCopy();
|
||||
testPoppingFromOrginalDoesNotChangeCopy();
|
||||
|
||||
testAssign();
|
||||
|
||||
testTopThrowsAnvalidArgumentWhenStackEmpty();
|
||||
testPopThrowsAnvalidArgumentWhenStackEmpty();
|
||||
|
||||
std::cout << "All tests pass!\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,17 @@
|
||||
************************************************************
|
||||
* */
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "./stack.h"
|
||||
#include "./stack.hpp"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
double GPA;
|
||||
double highestGPA;
|
||||
double GPA = NAN;
|
||||
double highestGPA = NAN;
|
||||
std::string name;
|
||||
|
||||
assert(argc == 2);
|
||||
|
||||
Reference in New Issue
Block a user