c ++循环在每次迭代时变慢

时间:2012-08-04 05:45:05

标签: c++ for-loop

在C ++中,我使用嵌套的for循环来匹配具有相同名称的对象对。我预计程序需要很长时间才能运行(比较数千个字符串),但随着程序的进展,程序运行得越来越慢。它会在几分钟内比较前20%的字符串,但一旦达到约30%完成,则需要将近60秒的时间来检查其中一个字符串。

我的“新数据”包含字段“可用”,“eff”和“numIdeas”的正确值,以及与其匹配的“新”伙伴共享“数据”字段的旧数据。新数据和旧数据的顺序不同,我无法对它们进行排序,因为它们当前的顺序是有意义的。我认为最好的办法就是通过它“蛮力”。就像我说的那样,它们没有特别的顺序,因此循环迭代的极端减慢让我感到困惑。据我所知,速度应保持不变。

for(int i=0; i< newDO.getNumItems(); i++)
{
    Item newItem = newDO.getItem(i);

    for(int k=0; k < oldDO.getNumItems(); k++)
    {
        Item oldItem = oldDO.getItem(k);
        if(oldItem.getType()==1)
        {
            bool same = testStrings(oldItem.getData(), newItem.getData());

            if(same)
            {
               oldItem.setFeas(newItem.getFeas());
               oldItem.setEff(newItem.getEff());
               oldItem.setNumIdeas(newItem.getNumIdeas());
               break;
            }
        }
    }
}

我没有写这个testStrings函数,但我没有看到任何真正的问题。这个函数接受字符串(大约5-20个字符)并取出任何空格和'('。

(据我所知,我之前的人已经导入了数千个文件,然后才意识到正在解析它们的函数没有删除'('正确地从某些数据中删除',所以他对此的修复就是忽略它们)检查字符串是否相等时。)

bool testStrings(string s1, string s2)
{
    string s1def ="";
    for(int i=0; i<s1.length(); i++)
    {
        if(s1[i]!=' ' || s1[i]!=')'){s1def+=s1[i];}
    }
    string s2def = "";
    for(int i=0; i<s2.length(); i++)
    {
        if(s2[i]!=' ' || s2[i]!=')'){s2def+=s2[i];}
    }
    if(s1def == s2def){return true;}
    else{return false;}
}

任何见解都会非常有用。

感谢。

4 个答案:

答案 0 :(得分:4)

这段代码几乎可以写成如何解决所有错误。

正如@jahhaj已经提到的,你似乎在使用二次算法。

你通过剥离比较函数中的额外字符来复合它,因为这意味着你每次进行比较时都会剥离多余的字符,而不是只是一次前置。

如果我这样做,我首先要创建一个类似的结构:

struct index { 
   std::string key;
   size_t subscript;
}

您可以通过将您要比较的字符串复制到key,并将该项目的下标复制到subscript来初始化。

然后从这些字符串中走出并删除多余的字符(''和')')。然后对这些数组进行排序,仅比较key字段。然后使用std::set_intersection查找常用项目。

通过复制和排序键,您将能够利用排序而不会影响(重要的)现有数据顺序。通过预先剥离多余的字符,您只需对每个键进行一次剥离。通过使用set::intersection,您可以获得具有线性复杂度而非二次的常见项。

明显的缺点是复制字符串显然会增加您必须存储的数据量。但是,如果项目的数量足够大,以便产生很大的差异,那么您也有足够的资源,从二次到线性的复杂性将代表巨大的时间节省。复制数据将是合理的,即使这意味着您必须暂时将其他数据写入磁盘才能执行此操作。

答案 1 :(得分:3)

1)如果没有a)看到更多的实际代码,b)理解你的数据集,我们无法确切地说出任何事情。

2)看起来你并没有“添加”任何东西,或“增长”任何结构。

...但是(这只是猜测)....

3)假设两个数组都已排序:array1 = {1,2,3,... 999}; array2 = {1,3,4,... 1001}。

在你的早期迭代中,你会很快达到“休息”。例如,在你甚至循环一次之前,array1 [0]将匹配array2 [0]。

但是,在以后的迭代中,您必须执行内部循环100次或更多次才能找到您要查找的项目。

也许整个问题是a)迭代地执行b)有序数据集的线性搜索c)。

再次 - 只是一个猜测。

... IMHO

答案 2 :(得分:0)

这里减速的唯一原因可能是以数据为中心,如果您的新集合很大,并且包含旧集合中不存在的大量新项目,在这种情况下,将为每个字符串搜索整个新集合从旧。

请遵循Jerry Coffin的建议,使用已清理的字符串复制您的集合,根据string::compare对其进行排序,然后以std::merge正在进行的线性方式迭代这两个字符串:

1  2  4 5   8  10 11 12 14 17 20 24  ...
1  2  4  6  8  10             20       50 ...

由于您需要更新旧集合中的原始项目,请在其每个项目的副本中添加另一个字段,并带有指向要复制的原始项目指针,并更新 找到副本时。然后丢弃两份副本。

两个系列的尺寸有多大?

答案 3 :(得分:-1)

你是如何衡量表现的?实际上,这种行为可能有很多原因(算法问题,cpu缓存,编译器设置),但是如果没有看到你的代码使用的源代码和实际字符串数据就很难回答你的问题......你能表现出来吗?你的字符串比较算法的实现?