算法和算法性能的缺陷

时间:2009-07-08 05:55:44

标签: c++ string algorithm memory-management

char *stringmult(int n)
{
    char *x = "hello ";
    for (int i=0; i<n; ++i)
    {
        char *y = new char[strlen(x) * 2];
        strcpy(y,x);
        strcat(y,x);
        delete[] x;
        x=y;
    }
    return x;
}

我想弄清楚这个细分市场的缺陷是什么。例如,它删除x,然后尝试将其值复制到y。另一个是y的大小是x的两倍,y永远不会被删除。有什么我想念的吗?而且,我需要弄清楚如何获得算法性能。如果你有一个快速链接,你学习了如何,我会很感激。

7 个答案:

答案 0 :(得分:5)

y需要比strlen(x) * 2多一个字节来为终止空字符腾出空间 - 仅适用于初学者。

无论如何,当你返回一个new内存区域时,由调用者删除它(eek)。

在我看来,你所缺少的是std::string ......! - )

至于性能,用strcpy复制N个字符是O(N);将N1个字符连接到具有前一个N2的strlen的char数组是O(N1 + N2)(std :: string更快,因为它将字符串的长度保持在O(1)-accessible属性中! - )。因此,只需将N + N ** 2加到N,直到你感兴趣的限制为止(你可以忽略N+部分,如果你想要的只是一个大的估计,因为它显然会逐渐消失更大的N! - )。

答案 1 :(得分:3)

首先删除[] x;在一些静态存储器上第一次循环操作。不好。

它看起来像是尝试返回包含2 ^ n个字符串“hello”的缓冲区。因此,最快的方法是找出副本数量,然后为整个结果分配足够大的缓冲区,然后用内容填充并返回它。

void repeat_string(const std::string &str, int count, std::vector<char> &result)
{
    result.resize(str.size() * count);
    for (int n = 0; n < count; n++)
        str.copy(&result[n * s.size()], s.size());
}

void foo(int power, std::vector<char> &result)
{
    repeat_string("hello ", 1 << (power + 1), result); 
}

答案 2 :(得分:2)

  1. 无需在循环中调用strlen() - 只调用一次;
  2. 当调用new时,没有为空字符请求空间 - 将导致未定义的行为;
  3. 应该使用strcpy而不是strcat - 你已经知道在哪里复制第二个字符串并且通过strcat找到字符串的结尾需要额外的计算;
  4. delete []用于静态分配的字符串文字 - 将导致未定义的行为;
  5. 内存不断重新分配,尽管你事先知道结果长度 - 内存重新分配非常昂贵
  6. 您应该立即计算结果长度并立即分配内存并将char *作为in-parameter传递:

    char* stringMult(const char* what, int n)
    {
         const size_t sourceLen = strlen( what );
         int i;
         size_t resultLen = sourceLen;
         // this computation can be done more cleverly and faster
         for( i = 0; i < n; i++ ) {
            resultLen *= 2;
         }
         const int numberOfCopies = resultLen / sourceLen;
         char* result = new char[resultLen + 1];
         char* whereToWrite = result;
         for( i = 0; i < numberOfCopies; i++ ) {
            strcpy( whereToWrite, what );
            whereToWrite += sourceLen;
         }
         return result;
    }
    

    我的实现的某些部分可以进行优化,但仍然要好得多,而且(我希望)不包含任何未定义的行为类错误。

答案 3 :(得分:1)

你必须在为Y分配空间时为NULL终止字符串添加一个 检查以下位置http://codepad.org/tkGhuUDn

的代码

答案 4 :(得分:0)

char * stringmult (int n)
{
    int i;
    size_t m;
    for (i = 0, m = 1; i < n; ++i; m *= 2);
    char * source = "hello ";
    int source_len = strlen(source);
    char * target = malloc(source_len*m+1) * sizeof(char));
    char * tmp = target;
    for (i = 0; i < m; ++i) {
        strcpy(tmp, source);
        tmp += source_len;
    }
    *tmp = '\0';
    return target;
}

这里有一个更好的版本。你的代码的大多数缺点已被消除,即删除一个未分配的指针,使用 strlen new 。 尽管如此,我的版本可能意味着与您的版本相同的内存泄漏,因为调用者负责随后释放字符串。

编辑:更正了我的代码,感谢sharptooth。

答案 5 :(得分:0)

char * string_mult(int n)

{

const char* x = "hello ";

char* y;

    int i;



for (i = 0; i < n; i++)

{

    if ( i == 0)

    {

        y = (char*) malloc(strlen(x)*sizeof(char));

        strcpy(y, x);

    }

    else

    {

        y = (char*)realloc(y, strlen(x)*(i+1));

        strcat(y, x);

    }

}

return y;

}

答案 6 :(得分:0)

没有人会指出“y”实际上已被删除了?

甚至没有一个对Schlmeiel the Painter的引用?

但我对这个算法做的第一件事就是:

int l = strlen(x);
int log2l = 0;
int log2n = 0;
int ncopy = n;
while (log2l++, l >>= 1);
while (log2n++, n >>= 1);
if (log2l+log2n >= 8*(sizeof(void*)-1)) {
    cout << "don't even bother trying, you'll run out of virtual memory first";
}