如何在 c++ 中实现堆栈数组?

How to implement array of stacks in c++?

本文关键字:堆栈 数组 实现 c++      更新时间:2023-10-16

想象一堆盘子。如果堆栈变得太高,它可能会倒塌。因此,在现实生活中,当前一个堆栈超过某个阈值时,我们可能会启动一个新堆栈。实现一个模拟这一点的数据结构SetOfStacksSetOfStacks应由多个堆栈组成,并且应在前一个堆栈超出容量时创建一个新堆栈。SetOfStacks.push(( 和 SetOfStacks.pop(( 的行为应该与单个堆栈相同(也就是说,pop( (应该返回与只有一个堆栈时相同的值(。 实现一个函数 popAt( int index(,该函数在特定子堆栈上执行 pop 操作。

有几个要求。首先,我们将创建一个包含其他几个堆栈的数据结构。为此,我们将定义一个类。

我们将使用一个可以根据需要容纳尽可能多的std::stackstd::vector。我们还添加一个变量,它将定义std::stacksstd::vector内所有std::stack的最大堆栈大小。

然后我们将实现 3 个功能。我们从push函数开始。这很简单。

首先,我们检查是否有足够的子堆栈。如果根本没有子堆栈(std::vectorempty(,或者,如果最后一个现有的std::stack是满的(size大于我们内部定义的maxStackSize(,那么我们添加一个完整的新std::stack到我们的std::vector。之后,无论我们之前是否添加了新std::stack,我们都只需在std::vector的最后一std::stackpush请求的值。

其他 2 个函数是pop函数。有一个通用的pop函数和一个popAt,它们应该从特定的子堆栈中弹出。如果我们仔细想想,那么我们可以发现 general 函数是popAt函数的特例,索引是最后一个堆栈的索引。然后我们将简单地调用popAt(stacks.size() - 1).

好的,然后我们专注于popAt函数。

首先,我们执行边界堆栈。如果索引为负数(在空std:vector上调用pop时可能发生(,或者如果索引大于现有std::stack的数量,这将发出错误消息。

然后,我们检查所需的子堆栈是否有数据或为空。如果它为空,我们将从std::vector中删除它并减少索引。

独立于上一个操作,我们会再次检查数据是否可用。该指数现在可能是负数,因为我们可能已经删除了std::stack。但std::vector现在也可能是空的。或者,地址stack也可能empty.在所有这些情况下,我们都会显示一条错误消息。

否则,我们将从具有当前索引的std::stack返回一个值。

main中,我添加了一些驱动程序测试代码。

#include <iostream>
#include <vector>
#include <stack>
using MyType = int;
constexpr size_t DefaultMaxStackSize = 3;
class SetOfStacks {
// The class data
// The maximum size of one stack
size_t maxStackSize{ DefaultMaxStackSize };
// And a vector of stacks
std::vector<std::stack<MyType>> stacks{};
public:
// Constructor
SetOfStacks() {}
// 2nd Constructor for setting the stack size.
explicit SetOfStacks(const size_t mss) : maxStackSize(mss) {};
// ----------------------------------------------------------------------
// Simple push function
void push(MyType mt) {
// If there are no stacks at all, or the last stack is full
if (stacks.empty() || stacks.back().size() >= maxStackSize) {
// At a new stack
stacks.emplace_back(std::stack<MyType>{});
}
// Add a value to the last stack
stacks.back().push(mt);
}
// ----------------------------------------------------------------------
// Pop functions
// STandard pop will call popAt with the index being the last avaliable stack
MyType pop() { return popAt(stacks.size() - 1); }
// Main working functions with error checking
MyType popAt(int index) {
// Here we will retrun the result
MyType result{};
// Sanity check. Is the index in the correct range
if (index >= stacks.size()) {
// Index is out of bounds. Inform user
std::cerr << "n*** Error:Wrong index. No datan";
}
else {
// So, now, index is in bounds. Check, if the stack at the specified index is empty
if (stacks[index].empty()) {

// Stack at specified index was empty. Remove it and decrement index
stacks.pop_back();
--index;
}
// Sanity check. There must be data available
if (stacks.empty() || index < 0 || stacks[index].empty()) {
// If not, inform the user
std::cerr << "n*** Error: Not data availablen";
}
else {
// Return value from stack
result = stacks[index].top();
stacks[index].pop();
}
return result;
}
}
};
int main() {
// Create a Ste of stacks
SetOfStacks sos;
// Populate it
for (int i = 1; i < 12; ++i)
sos.push(i);
// Get all values from stack
for (int i = 1; i < 12; ++i)
std::cout << sos.pop() << 'n';
// Get an additional value. Will of course not work
std::cout << 'n' << sos.pop() << "nn";
// Populate stack again
for (int i = 1; i < 12; ++i)
sos.push(i);
// Get data from a specified stack
std::cout << 'n' << sos.popAt(1) << "nn";
// Get all values from stack. Will result in error for last 
// element, becuase we already removed 1 element
for (int i = 1; i < 12; ++i)
std::cout << sos.pop() << 'n';
return 0;
}