Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(SOURCE_FILES
# CHAPTER 2
# .cpp files not included because they are template functions implemented in .h files
# CHAPTER 3
cpp_solutions/chapter_03_stacks_and_queues/problem_03_01_threeInOne.cpp
cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp
# CHAPTER 4
cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "problem_03_01_threeInOne.h"
#include "problem_03_02_StackMin.h"
#include "problem_03_04_QueueViaStacks.h"
#include "problem_03_05_sortStack.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <cassert>

#include "problem_03_01_threeInOne.h"

namespace chapter_03 {

MultiStack::MultiStack(const std::size_t stack_num) :
data(stack_num * 10 + 1), data_idx(1), stack_heads(stack_num, 0), free_list_head(0), stack_num(stack_num)
{}

void MultiStack::push(const std::size_t stack_num, const TVal & val) {
assert(stack_num < this->stack_num);

if(data_idx >= data.capacity()) {
data.resize(data.capacity() * 2);
}

std::size_t & stack_head = stack_heads[stack_num]; // zero by default

if(free_list_head > 0) {
const auto free_list_head_new = data[free_list_head].first;
data[free_list_head].first = stack_head; // the index of the previous item
data[free_list_head].second = val;
stack_head = free_list_head;
free_list_head = free_list_head_new;
} else {
data[data_idx].first = stack_head; // the index of the previous item
data[data_idx].second = val;
stack_head = data_idx;
++data_idx;
}
}

MultiStack::TVal MultiStack::pop(const std::size_t stack_num) {
assert(stack_num < this->stack_num);

std::size_t & stack_head = stack_heads[stack_num]; // zero by default
assert(stack_head > 0);
const auto stack_head_prev = stack_head;
stack_head = data[stack_head_prev].first;
data[stack_head_prev].first = free_list_head;
free_list_head = stack_head_prev;
return data[stack_head_prev].second;
}

MultiStack::TVal & MultiStack::get(const std::size_t stack_num) {
assert(stack_num < this->stack_num);
const std::size_t stack_head = stack_heads[stack_num]; // zero by default
assert(stack_head > 0);
return data[stack_head].second;
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Chapter 03 - Problem 01 - Three in One

Problem Statement:
Describe how you could use a single array to implement three stacks

Explanation:
Each stack item has two elements: an index of the previous item and a payload.

For
push(0, 11);
push(1, 21);
push(0, 12);
push(1, 22);
push(0, 13);

The data array would be
[(0, 0), (0, 11), (0, 21), (1, 12), (2, 22), (3, 13)]

In this array, the first stack head index is 5 with the previous index 3 and the payload 13
Second stack head index is 4 with the previous index 2 and payload 22

Time complexity: amortized O(1)
Space complexity: O(2n)
*/

#pragma once
#include <utility>
#include <vector>

namespace chapter_03{
class MultiStack {
public:
typedef int TVal;

//<index, value>
typedef std::pair<std::size_t, TVal> TPair;

MultiStack(const std::size_t stack_num);

void push(const std::size_t stack_num, const TVal & val);
TVal pop(const std::size_t stack_num);
TVal & get(const std::size_t stack_num);
private:
std::vector<TPair> data;
std::size_t data_idx;
std::vector<std::size_t> stack_heads;
std::size_t free_list_head;
const std::size_t stack_num;
};
}; // namespace chapter_03
36 changes: 36 additions & 0 deletions tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,42 @@ TEST_CASE("Chapter 02 - Problem 08 - findLoop()", "test") {
REQUIRE(static_cast<chapter_02::SinglyLinkedNode<int>*>(nullptr) == chapter_02::findLoop(static_cast<chapter_02::SinglyLinkedNode<int>*>(nullptr)));
}

TEST_CASE("Chapter 03 - Three in one", "test"){
constexpr const int max_int = 10000;
constexpr const int stack_max = 10;

static std::random_device r;
static std::default_random_engine r_eng(r());
static std::uniform_int_distribution<> distr(0, max_int);

const std::size_t stack_count = abs(distr(r_eng)) % stack_max + 1;
std::vector<std::vector<chapter_03::MultiStack::TVal>> arrays(stack_count);
chapter_03::MultiStack stack(stack_count);

for(int i = 1000; --i >= 0;) {
const std::size_t stack_i = static_cast<std::size_t>(distr(r_eng)) % stack_count;
const chapter_03::MultiStack::TVal val = distr(r_eng);
arrays[stack_i].push_back(val);
stack.push(stack_i, val);
}

for(int i = 25; --i >= 0;) {
const std::size_t stack_i = static_cast<std::size_t>(distr(r_eng)) % stack_count;
assert(arrays[stack_i].size() > 0);
arrays[stack_i].pop_back();
stack.pop(stack_i);
}

for(std::size_t stack_i = 0; stack_i < stack_count; ++stack_i) {
auto & ar = arrays[stack_i];

for(std::size_t j = ar.size(); j > 1; --j) {
assert(stack.pop(stack_i) == ar.back());
ar.pop_back();
}
}
}

TEST_CASE("Chapter 03 - Stack", "test"){
chapter_03::Stack<int> myStack;
for (int i = 1; i <= 4; i++){
Expand Down