【发布时间】:2016-09-13 10:06:24
【问题描述】:
在搜索有序列表时,程序的一部分需要检查两个 c 字符串是否相同(例如{"AAA", "AAB", "ABA", "CLL", "CLZ"})。列表可以变得非常大是可行的,因此速度上的微小改进值得降低可读性。假设您仅限于 C++(请不要建议切换到汇编)。如何改进?
typedef char StringC[5];
void compare (const StringC stringX, const StringC stringY)
{
// use a variable so compareResult won't have to be computed twice
int compareResult = strcmp(stringX, stringY);
if (compareResult < 0) // roughly 50% chance of being true, so check this first
{
// no match. repeat with a 'lower' value string
compare(stringX, getLowerString() );
}
else if (compareResult > 0) // roughly 49% chance of being true, so check this next
{
// no match. repeat with a 'higher' value string
compare(stringX, getHigherString() );
}
else // roughly 1% chance of being true, so check this last
{
// match
reportMatch(stringY);
}
}
您可以假设stringX 和stringY 的长度始终相同,您不会得到任何无效的数据输入。
据我了解,编译器将编写代码,以便 CPU 将检查第一个 if 语句并在它为假时跳转,因此最好是第一个语句最有可能为真,因为跳转干扰管道。我还听说在进行比较时,[n Intel] CPU 将进行减法并查看标志的状态,而不保存减法的结果。有没有办法只执行一次strcmp,而不将结果保存到变量中,但仍然能够在前两个 if 语句中检查该结果?
【问题讨论】:
-
我建议您切换到 C++(目前您的 C 代码具有 C++ 语法的 touch)。关于代码路径的微优化:不要费心去猜测,检查生成的程序集输出(你可能会感到惊讶...)而且往往更重要的输入模式 (有多少个连续的
< 0?)比最常见的代码路径。最后说明:如果您在 C 中执行此操作,您可能希望使用memcmp而不是strcmp来处理 固定长度字符串 -
“只做一次 strcmp 的方法,而不将结果保存到变量中,” 为什么?!
strcmp无论如何都会以int的形式生成结果。已经为此目的分配了一个变量。如果您不存储在compareResult中,您将一无所获。如果你选择 C 风格的语法,你现在的代码看起来不错。 -
compare是提高程序运行时间的错误级别。您提到它是一个有序序列,因此更好的方法不是对您的序列进行线性搜索(我猜),而是二进制搜索。由于您使用的是 C++,因此您可以使用适当的容器(例如:std::set<std::string>)来为您处理此类算法改进。 -
@FrerichRaabe,您不能进行二进制搜索,主要是因为您不知道相等的字符串在字符串空间中的位置。您必须进行线性搜索,但仅将每个字符串 与数组中的下一个字符串进行比较,因为您知道数组已排序,您知道如果数组中有两个相等的字符串,它们必须在一起.
-
@LuisColorado 我不明白 - 我的理解是 OP 想要测试某个 C 字符串是否是其他(有序)C 字符串集的成员。为此,他实现了一个
compare函数,该函数比较两个字符串和,然后尝试选择下一个要与之比较的字符串。我的评论是,这似乎是在排序的值序列中测试成员资格的基本问题,而且这个问题已经解决了——根本不需要单独的compare函数。
标签: c++ performance search c-strings