【问题标题】:Check that element belongs to std::stack检查元素是否属于 std::stack
【发布时间】:2021-06-07 13:59:45
【问题描述】:

我在编写代码/函数来检查提供用户的号码是否属于std::stack 时遇到问题。我尝试以不同的方式制作它,但我没有找到任何可行的解决方案。

我试过了:

std::stack<int> myStack;
const bool isInStack = myStack.find(userNumber) != myStack.end(); 

我也试过了:

std::stack<int> myStack;
if (myStack.count(userNumber)) {
   // x is in the set, count is 1
} else {
   // count zero, i.e. x not in the set
}

我也尝试编写自己的模板,但我做不到,它也无法正常工作。我不知道如何让它工作。

我收到class std::stack&lt;int, std::deque&lt;int, std::allocator&lt;int&gt;&gt;&gt;" has no member "find" 之类的错误

谁能帮帮我?我真的很生气。

【问题讨论】:

  • 在使用标准库组件时遇到错误,check the reference 首先确保您正确使用它。正如您在链接中看到的,std::stack 没有findcount 函数。你确定你应该使用std::stack而不是std::set吗?
  • std::stack 提供了一个栈接口,它可以将新元素压入栈顶,也可以弹出栈顶元素。如果您需要更多操作,std::stack is not the appropriate container. std::vector` 提供了push_backpop_back,因此它可以用作堆栈,并且可以访问其所有元素。
  • 我知道我可以用矢量来做,但我的工作是用堆栈来做......我不知道我该怎么做。也许我可以创建帮助程序堆栈或某事,但我不知道如何
  • std::stack 应该作为堆栈工作,因此 Last In First Out 功能。此模板提供了满足 LIFO 要求的最小 API。不允许随机或顺序访问元素。所以基本上你应该用其他容器替换std::stack。如果您的任务有其他内容,也许您可​​以提供完整的描述,这样我们就可以清楚地了解您为什么有这个奇怪的要求。
  • 你在问如何用锤子拧螺丝。 std::stack 不是用于此目的的正确工具。如果您必须使用std::stack,那么您可能需要清空堆栈以检查每个元素,例如将堆栈的每个元素移出另一个堆栈,检查每个元素以查看它是否您正在寻找的那个。严格来说,可以从std::stack派生来访问protected成员c可以直接访问底层容器。但这通常是一个非常人为的解决方案。正确的解决方案是不要为此使用std::stack

标签: c++ stack


【解决方案1】:

正如其他人所指出的,std::stack 可能不是最好的选择,但假设您没有其他选择,那么您将不得不逐个检查堆栈并检查每个元素:

bool found_in_stack(int to_find, std::stack<int> stack) {
    while (!stack.empty()) {
        if (stack.top() == to_find) return true;
        stack.pop();
    }
    return false;
}

请注意,我按值获取堆栈以便制作副本,这样原始堆栈根本不会更改。

如果您不想制作副本,另一种选择是改变原件,这需要临时存储弹出的元素:

bool found_in_stack(int to_find, std::stack<int>& stack) {
    // keep track of elements we've popped here, we'll add them back at the end
    std::stack<int> tmp;

    bool done = false;
    while (!stack.empty()) {
        if (stack.top() == to_find) {
            done = true;
            break;
        }
        
        tmp.push(stack.top());
        stack.pop();
    }

    // add popped elements back
    while (!tmp.empty()) {
        stack.push(tmp.top());
        tmp.pop();
    }
    return done;
}

【讨论】:

  • 第二种解决方案的优点是它也适用于不可复制的类型,并且对于复制速度可能较慢的类型(如大型容器或字符串)可能更快。然而,最大的权衡是它不是异常安全的。例如tmp.push 会抛出,那么stack 将不会有它的原始值。
【解决方案2】:

std::stack 中没有find,但您可以使用提供相同功能的std::deque。将push_back() 用于push(),将pop_back() 用于pop()std::vector 也提供了这样的功能。

示例代码:

#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;

int main()
{
    deque<int> x;
    for (int i = 1; i <= 5; i++) {x.push_back(i);}

    if (find(x.begin(), x.end(), 5) != x.end()) {cout << "Yes";} else {cout << "No";} 
    cout << "\n";
    if (find(x.begin(), x.end(), 7) != x.end()) {cout << "Yes";} else {cout << "No";}
}

输出:

Yes
No

编辑:std::deque 是一个容器模板,std::stack 是基于它构建的(正如@François Andrieux 提到的):

template<
    class T,
    class Container = std::deque<T>
> class stack;
//Defined in header <stack>

文档:

std::stack 类是一个容器适配器,为程序员提供 堆栈的功能 - 具体来说,LIFO(后进, 先出)数据结构。

一般来说,它具有基本相同的功能。更多信息here.

【讨论】:

  • OP 需要使用stack
【解决方案3】:

std::stack 没有公共接口来检查堆栈中存在的内容,而无需弹出每个元素并检查它们。

它所拥有的是底层容器的受保护成员变量。

所以如果你必须使用std::stack,唯一的办法就是继承它并访问底层容器

template<class T>
class my_stack : private std::stack<T>
{
public:
    using std::stack<T>::stack;
    using std::stack<T>::operator=;

    using std::stack<T>::top;
    using std::stack<T>::empty;
    using std::stack<T>::size;
    using std::stack<T>::push;
    using std::stack<T>::emplace;
    using std::stack<T>::pop;
    using std::stack<T>::swap;
    
    using typename std::stack<T>::const_reference;

    bool contains(const_reference val) const
    {
        return std::find(this->c.begin(), this->c.end(), val) != this->c.end();
    }
};

【讨论】:

    猜你喜欢
    • 2015-02-14
    • 1970-01-01
    • 2015-10-17
    • 2021-08-24
    • 2010-12-14
    • 2011-10-25
    • 1970-01-01
    • 2020-07-09
    • 2019-02-23
    相关资源
    最近更新 更多