“合作销售”事件队列的正确术语是什么?

时间:2019-09-27 09:42:46

标签: algorithm data-structures

说我有一个“事件”对象队列,其中每个对象都有一个“事件类型”和某种数据字段。在C ++中,可能是这样的:

enum class EventType
{
    A,
    B,
    C
};

struct Event
{
     EventType type;
     std::string message;
};

说,我想要这些事件的队列,并且希望该队列具有以下属性:

  • 将事件推送到队列时,将删除同一EventType的所有现有事件。因此,当事件从队列中弹出时,它始终是其EventType
  • 中最新添加的实例
  • 不同事件 EventType会按推送的顺序弹出。 (pop()不希望有任何参数)。

因此,队列相对于Event是FIFO,相对于LIFOEventType

示例:

以下事件被推入队列(字母是事件类型,数字是实例号)

A1 A2 C1 C2 C3 B1 B2 A3

如果随后调用pop()3次,则按顺序返回的项目将是

C3 B2 A3

这种数据结构有名称吗,并且有实现的例子吗?

1 个答案:

答案 0 :(得分:0)


免责声明:设计非常高效的数据结构是与数据的域(体系结构)和上下文严格相关的内容。以下解决方案旨在在一般情况下在理论上有效。有关更多详细信息,请参见最终注意事项。


结构设计

这个想法很简单。

保留表示队列基础数据结构

每次插入新事件时,请检查类型是否已经存在。在这种情况下,我们可以删除该元素。这样,我们维护第一个属性(每个类型仅一个实例,这意味着我们始终会弹出该类型的最新实例)。

最后,我们将新实例插入队列的末尾。因此,我们保留第二个属性。


简单实现的示例

#include <algorithm>
#include <list>
#include <utility>

class QueueWithAGoodName {
 public:
  using reference = Event&;

  void push(Event event) {
    if (const auto finder =
            std::find_if(queue_.begin(),
                         queue_.end(),
                         [eventType = event.type](const Event& event) {
                           return event.type == eventType;
                         });
        finder != queue_.end()) {
      queue_.erase(finder);
    }
    queue_.push_back(std::move(event));
  }

  reference front() { return queue_.front(); }

  void pop() { queue_.pop_front(); }

 private:
  std::list<Event> queue_;
};

Live Example


考虑和分析

  • 在我的示例中,我使用了std::list作为基础数据结构。确实,如果您在“中间”频繁删除,则std::list很方便。此外,删除后,迭代器不会无效。如果我们想改善队列,这是一个很好的特性。

  • QueueWithAGoodName::push具有运行时时间复杂度:O(N)(因为我们应用了线性扫描来查找类型)。其中N是队列的大小。

  • QueueWithAGoodName::popQueueWithAGoodName::frontO(1)

其他注意事项

  • 对于这种类型的数据结构,有一个重要的属性。每个类型只有一个实例。这意味着N(队列的大小)的上限是EventType的数量。
  • 如果事件类型的数量受到限制,则可以应用几个注意事项,因为(对于通用体系结构)运行时复杂度O(N)可以近似为O(1)。在这种情况下,由于缓存的原因,std::vector作为基础数据结构可能更有效。
  • 在我报告的简单示例中,pushO(N)。如果您有几种EventType类型,则可以使推入操作中的数据结构更有效。简而言之,可以使用辅助std::unordered_map<EventType, list::iterator>(即 hash map )来避免线性搜索。擦除后,std::list不会使迭代器无效,因此哈希表保持一致。