通过值获取std :: queue中元素的索引

时间:2019-01-22 14:18:18

标签: c++ stl queue

是否有一种简单的方法可以通过C ++中的值获取元素在std::queue中的位置?

例如:

std::queue<int> numbers;

numbers.push(7);
numners.push(4);
numbers.push(11);

int position = numbers.getPosition(4); //should be 1

4 个答案:

答案 0 :(得分:8)

如果要获取元素的索引,则可能应该考虑使用std::deque容器而不是std::queue容器 adapter ,如{{3 }}。


如果您出于其他原因仍要坚持使用this other answer容器适配器,则应该知道它确实通过受保护的数据成员{{ 1}}。

您可以从c派生以便访问基础容器,并使用std::queue函数模板在该容器中查找具有此类值的元素。然后,只需使用std::find()返回该元素的位置。

std::queue

如果未找到该元素,则索引将对应于#include <algorithm> #include <queue> template<typename T> class Queue: std::queue<T> { public: auto getPosition(const T& val) const { auto it = std::find(this->c.begin(), this->c.end(), val); return std::distance(this->c.begin(), it); } // ... }; 成员函数返回的索引。

如果存在重复项,则基于size()的解决方案将返回第一个元素的位置,即找到的第一个元素具有请求的值std::find()

答案 1 :(得分:4)

您可以改用std::deque

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>



<div class="container min-vh-100 d-flex flex-column" id="container">

  <!-- header -->
  <div class="row align-items-start bg-info" id="header">
    <div class="col text-center">
      <button type="button" class="btn" id="cancel">&#10007;</button>
      <button type="button" class="btn" id="back">&#8617;</button>
    </div>
    <div class="col text-center">
      <h4 id="title">Notebook</h4>
    </div>
    <div class="col text-center">
      <button type="button" class="btn" id="submit">&#10004;</button>
    </div>
  </div>

  <br />

  <!-- Screen list show -->
  <div class="row" id="screen">
    <div class="col-12">
      <ul id="list">

      </ul>
    </div>
  </div>

  <!-- Note show -->
  <div class="row" id="fullnote">
    <div class="col-12">
      <p id="text">
      </p>
    </div>
  </div>


  <!-- textarea -->
  <div class="row flex-grow-1">
    <div class="col" id="main">
      <textarea class="form-control textarea h-100" value="" placeholder="write note" id="note"></textarea>
    </div>
  </div>


  <!-- footer -->
  <div class="row align-items-end" id="footer">
    <div class="col d-flex justify-content-start" style="padding: 10px; padding-left: 25px;">
      <button id="add" class="btn btn-info rounded-circle"><h4 style="padding: 0px; margin: 0px;">&#x2b;</h4></button>
      <button id="delete" class="btn btn-info rounded-circle">&#128465;</button>
    </div>
  </div>

</div>

请注意,#include <algorithm> std::deque<int> names; names.push_back(7); names.push_back(4); names.push_back(11); auto it = std::find(names.begin(), names.end(), 4); if(it != names.end()) int distance = it - names.begin(); else //no element found 使用std::queue作为默认实现,因此任何操作都与在队列中花费相同的时间。

std::deque还支持随机访问,因此std::deque将返回7。它也可以像其他任何队列一样使用:

names[0]

答案 2 :(得分:2)

另一种通用方式是定义以下新容器,该容器是{{ question.render_question }} 的继承,并定义std::queuebegin()返回受保护成员end()的迭代器。 然后,您可以在此容器中使用各种STL算法:

std::queue::c

...是的,众所周知,STL容器没有虚拟析构函数。 通过基类指针破坏此派生类将导致未定义的行为。 因此,我建议当且仅当您确实需要它时,才使用上面的派生类。


对于当前位置问题,可以找到第一个元素的位置,如下所示:

DEMO

#include <queue>

template<
    class T,
    class Container = std::deque<T>
>
class Queue : public std::queue<T, Container>
{
public:
    using iterator               = typename Container::iterator;
    using const_iterator         = typename Container::const_iterator;
    using reverse_iterator       = typename Container::reverse_iterator;
    using const_reverse_iterator = typename Container::const_reverse_iterator;

    iterator        begin()       noexcept { return this->c. begin(); }
    const_iterator  begin() const noexcept { return this->c.cbegin(); }
    const_iterator cbegin() const noexcept { return this->c.cbegin(); }

    iterator        end()       noexcept { return this->c. end(); }
    const_iterator  end() const noexcept { return this->c.cend(); }
    const_iterator cend() const noexcept { return this->c.cend(); }

    reverse_iterator        rbegin()       noexcept  { return this->c. rbegin(); }
    const_reverse_iterator  rbegin() const noexcept  { return this->c.crbegin(); }
    const_reverse_iterator crbegin() const noexcept  { return this->c.crbegin(); }

    reverse_iterator        rend()       noexcept  { return this->c. rend(); }
    const_reverse_iterator  rend() const noexcept  { return this->c.crend(); }
    const_reverse_iterator crend() const noexcept  { return this->c.crend(); }
};

答案 3 :(得分:2)

您还可以使用these answers提出的以下功能来访问基础受保护成员std::queue::c

#include <queue>

template <class ADAPTER>
const auto& get_container(ADAPTER& a)
{
    struct hack : private ADAPTER {
        static auto& get(ADAPTER& a) {
            return a.*(&hack::c);
        }
    };

    return hack::get(a);
}

然后,您可以按以下方式获取元素的索引。 此功能也可以应用于其他容器适配器std::stackstd::priority_queue

DEMO(C++11)

DEMO(C++14 and over)

#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    std::queue<int> q;
    q.push(7);
    q.push(4);
    q.push(11);

    auto& c = get_container(q);

    const auto it = std::find(c.cbegin(), c.cend(), 4);
    const auto position = std::distance(c.cbegin(), it);
    std::cout << "Position is " << position << "." <<std::endl;

    return 0;
}