【问题标题】:Advice on STL data structure关于 STL 数据结构的建议
【发布时间】:2011-07-12 10:16:16
【问题描述】:

我正在实现一种显示算法,我们可以根据它们的 z 顺序拥有多个窗口层,即我从最后一个 z 值开始并合并图像,直到我们在最佳。 要维护 z 值,您推荐哪种数据结构?

例如:如果 z-order 是 2 3 4 5 1 6 7 8 9 10(应用程序的索引)并且如果用户点击了应用程序 5 的窗口,那么我们需要将 5 移到前面,然后剩余顺序应该相同,即 5 2 3 4 1 6 7 8 9 10。

如果我使用向量,那么每次都重新排列元素(或复制值)似乎效率不高。 如果我使用 deque 那么 push_front 有一些明显的优势,但再次从以前的位置删除应用程序是问题所在。 如果我使用列表,那么每次我们都需要搜索元素并将其删除。 关于哪种数据结构对我的目的最有效的想法?

【问题讨论】:

  • 你需要处理多少层?如果它的小常数因素可能占主导地位
  • 目前没有。层数不超过 32

标签: c++ algorithm stl


【解决方案1】:

鉴于窗口的数量可能会最少,我可能会使用(智能)指针向量,并对向量分量重新排序。虽然复杂度高于其他替代方案,但实际性能不会差,因为常量可能会主导复杂度。

【讨论】:

  • 无需重新订购,因为您总是拿一件物品放在最前面。有了你的论点,我会说 - 去列出。但实际上我相信使用向量可以获得更好的性能。
  • @Nim, Oleg:我在一般意义上使用了 reorder。不需要完全重新订购,但您很可能也不想进行单次交换。然后将第 5 个窗口拉到顶部,您希望之前位于顶部的窗口成为 Z 顺序中的第二个窗口,您不想将其移动到堆栈中的窗口 3 和 4 后面。即,该实现将拉动第 5 个的指针,然后将元素 1..4 移动到位置 2..5(注意移动顺序),然​​后将第 5 个的窗口作为第一个插入。
【解决方案2】:

显而易见的答案是使用boost multi-index。然而,这有时会变得棘手。你可以通过两个结构来模拟它:

  • 存储顺序和值的列表
  • 将值映射到列表位置的映射

所以,你可以有类似的东西:

typedef std::list<int> pos_list_t;
pos_list_t positions;
std::map<int, pos_list_t::iterator> position_map;

然后,每次您必须搜索和更改位置时,您可以执行以下操作(简化,但您明白了):

pos_list_t::iterator pos = position_map[window_number];
// pos takes the list iterator. You can move it to the beginning
positions.erase(pos);
positions.push_front(window_number);
// update the map position
position_map[window_number] = positions.begin(); // iterator of the new position. The beginning.

你还需要一些联合初始化:

positions.push_back(value1);
positions.push_back(value2);
...
for (pos_list_t::iterator it = positions.begin(); it != positions.end(); ++it)
    position_map[*it] = it;

【讨论】:

  • map 太过分了。由于 OP 将正整数的前缀 [1..N] 映射到对象,因此他/她可以使用 vector 代替。
  • @larsmans,是的,你是对的。这取决于地图可以获得的数字。但是,仍然只是结构组织和关系的一个想法。
  • ..我不认为这是显而易见的答案,事实上,我会说,这是最令人费解的答案... :)
  • :) 更一般,然后呢?是的,对于这些数量级来说,一张地图似乎有点矫枉过正......但也许明天他或她必须处理数千个物体:)
【解决方案3】:

你实际上要做的是:

  1. 在特定位置查找元素
  2. 在开头插入新元素
  3. 删除某个位置的元素
  4. 遍历元素

因此,如果您使用列表 - 您会遇到 1. 如果您使用地图。你有麻烦了4。 我会说选择具有 1,2 和 4 常数的向量。并对需要从集合中删除的元素使用某种标记。由于您可能不会拥有数百万个窗口,因此您可以在非常罕见的向量内执行内务处理,例如每 10 秒一次。

【讨论】:

    【解决方案4】:

    似乎一个简单的链表在这里是最方便的,然后根据它们的 z 值对它们进行排序。

    【讨论】:

      【解决方案5】:

      您可以使用映射,其中键是识别窗口所需的任何内容,值是窗口的位置。假设我们使用 HWND 来识别窗口。

       map<HWND, int> windows
      

      一开始你必须初始化地图并为每个窗口设置正确的位置。前任。窗户[0x0002] = 0;窗口[0x0003] = 1; 地图将根据价值排序。 当你必须把一个窗口放在前面时,你只需要用 0 订单窗口切换它的位置

      int temp_order = windows[bringToFrontWindow]; 
      HWND front_window = windows.begin().first; // the fist window of the map has 0 z-order
      windows[bringToFrontWindow] = 0;
      windows[front_window] = temp_order;
      

      【讨论】:

        【解决方案6】:

        我在这里只使用std::list,因为 1) 列表迭代器永远不会失效(除非从列表中删除对象) 2) 拼接是恒定的时间(不是很重要,因为我们谈论的是小列表)。

        您可以维护一个std::list&lt;Window*&gt;,并在Window 类中捆绑一个std::list&lt;Window*&gt;::iterator(假设有一些管理窗口资源的Window 类)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-01
          • 1970-01-01
          • 2011-06-22
          • 2011-08-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-20
          相关资源
          最近更新 更多