C++ c++;算法:搜索';列表';,无序

C++ c++;算法:搜索';列表';,无序,c++,algorithm,performance,C++,Algorithm,Performance,更新:我的坏消息。这并不是双重减速的原因。我还有其他的虫子 C++MFC。Visual Studio 12 我试图在绘制循环中优化性能。我有一个我所有对象的列表(ListAll),假设它有300个对象,所有对象都有唯一的ID。我有第二个需要呈现的ID列表(ListNow),大小为100。ListAll中的所有值现在都具有存储在ListAll中的关联对象 目前,ListAll是一个CMap,ListNow是一个CArray // this is the slower, current method

更新:我的坏消息。这并不是双重减速的原因。我还有其他的虫子

C++MFC。Visual Studio 12

我试图在绘制循环中优化性能。我有一个我所有对象的列表(ListAll),假设它有300个对象,所有对象都有唯一的ID。我有第二个需要呈现的ID列表(ListNow),大小为100。ListAll中的所有值现在都具有存储在ListAll中的关联对象

目前,ListAll是一个CMap,ListNow是一个CArray

// this is the slower, current method
for (int i = 0; i < ListNow.GetSize(); i++)
{
    UINT id = ListNow.GetAt(i);
    if (ListAll->Lookup(id, object))
    {
        object->draw();
    }
}
从技术上讲,这两种算法都以O(n)的速度执行……但简单地将CMap::Lookup函数添加到循环中所需的时间增加了一倍。我已将CMap大小正确设置为大于CMap中对象数的素数。这种放缓是显而易见的,规模在30万人以上

我切换到这个系统,这样我可以将所有对象存储在绘制列表中,并可以使用相同的对象列表在不同窗口之间快速切换正在绘制的对象。这会大大加快切换时间,但会减慢每个抽签呼叫的速度。现在调回不是一个选项,我们知道这会让每次平局都慢一点,但不会这么多。我向您展示的代码中肯定存在速度减慢的问题,因为当我切换回绘制所有内容(删除查找)时,它会将时间缩短一半

提高性能的唯一方法是在列表中记录LastDrawed对象指针,并通知函数是否需要更改(调用lookup())或是否可以简单地重复使用最后绘制的对象指针(GetNext())。90%的时间里,两次通话之间没有任何变化


有人有比这更快的解决方案吗?我梦想着一个巧妙的掩蔽解决方案,不知怎的产生我想要的对象指针,我不知道。在这一点上,任何事情都会有所帮助。

如果您将对象的指针而不是其ID存储到
列表中,您的问题似乎会得到解决现在

您确定CMap::lookup的速度变慢了吗?好的散列映射实现不应该以O(1)的平均复杂度降低您的速度。如果已分析并确认,请尝试查看
std::unordered_map
,查看
查找
,签名,看起来它正在复制周围的数据?啊。。。。您真的应该查看
无序映射
。关于ListNow中有多少项对应于ListAll?@SergeyA True,它正在复制到提供的
右值
,但是
GetNextAssoc
也会对第二个循环中映射中的每个成员执行此操作。如何生成id,它们是顺序的还是随机的,有初始起始值吗,还是从0开始?CMap使用散列算法,因此如果您的唯一标识符导致大量散列冲突,您可能会看到您描述的那种减速。另外,你能给你测量的速度加上一些实数吗?重新绘制300个对象中的100个对象需要多少秒/毫秒/微秒?如果不是散列冲突问题,它可能有助于了解我们预期的减速类型。您是否可以向存储在
ListAll
中的对象类添加一个简单的布尔标志?迭代所有项目以确定哪些项目需要绘制,这是您无论如何都需要以某种方式进行的事情;然后,简单地检查渲染循环中的标志不应该那么昂贵(除非
ListAll
ListNow
大几个数量级)。哇。这真是个好主意。这么简单。XD我正在处理的系统比这个例子复杂得多,但这可能是可以实现的。
// this is the faster, old method
POSITION pos = ListAll->GetStartPosition();
while (pos)
{
    ListAll->GetNextAssoc(pos, id, object);
    object->Draw();
}