2-я функция выполняет больше работы, чем 1-я, поэтому, конечно, это займет больше времени. Профилирование кода должно было показать вам, где именно код тратит свое время. Например, 1-я функция циклически повторяет str
самое большее 1 раз, но 2-я функция может l oop через те же str
2 раза, что по определению занимает больше времени.
И у вас есть Также не исключены все выделения памяти из 2-й функции. to_string()
выделяет память, и вы вызываете ее много раз до и после вызова reserve()
. Устранить все выделения to_string()
довольно просто, используя std::snprintf()
в локальном буфере и затем std::string::append()
, чтобы добавить этот буфер к вашему выводу std::string
.
Вы можете за go все предварительные вычисления и просто reserve()
полную str
длину, даже если вы не используете всю эту память. Вы не собираетесь использовать больше, чем исходная длина str
в худшем случае (сжатие вообще невозможно):
inline int to_buffer(size_t number, char *buf, size_t bufsize)
{
return snprintf(buf, bufsize, "%zu", number);
}
string commpres3(const string &str)
{
string::size_type strLen = str.length();
string strOut;
strOut.reserve(strLen);
size_t count = 0;
char buf[25];
for (string::size_type i = 0; i < strLen; ++i)
{
++count;
if (i < strLen - 1)
{
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
count = 0;
}
}
else
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
}
if (strOut.length() >= strLen)
return str;
}
return strOut;
}
Или, если необходимо предварительно рассчитать, вы можете заменить 1-й набор to_string()
вызывает что-то еще, что возвращает необходимую длину без динамического выделения памяти ( см. для идей). При расчете размера для резервирования вам не нужно фактически преобразовывать целое число 123 в выделенную строку «123», чтобы знать, что это займет 3 символа.
inline int to_buffer(size_t number, char *buf, size_t bufsize)
{
return snprintf(buf, bufsize, "%zu", number);
}
inline int to_buffer_length(size_t number)
{
return to_buffer(number, nullptr, 0);
}
string commpres3(const string &str)
{
string::size_type strLen = str.length();
string::size_type compressedLength = 0;
size_t countConsecutive = 0;
for (string::size_type i = 0; i < strLen; ++i)
{
++countConsecutive;
if (i < (strLen - 1))
{
if (str[i + 1] != str[i])
{
strOut += 1 + to_buffer_length(countConsecutive);
countConsecutive = 0;
}
}
else
{
strOut += 1 + to_buffer_length(countConsecutive);
}
}
if (compressedLength >= strLen)
return str;
string strOut;
strOut.reserve(compressedLength);
size_t count = 0;
char buf[25];
for (string::size_type i = 0; i < strLen; ++i)
{
++count;
if (i < strLen - 1)
{
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
count = 0;
}
}
else
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
}
}
return strOut;
}