#c #c 11 #bubble-sort #stdlist
#c #c 11 #пузырьковая сортировка #стандартный список
Вопрос:
Я создал код, отвечающий за выполнение пузырьковой сортировки в списке. Кажется, что это работает, но для выполнения требуется много времени. Я был бы рад, если бы кто-нибудь сказал мне, что в этом не так, чтобы я мог избежать повторения той же ошибки в будущем
Подумал, что это может быть как-то связано с auto , но переписывание кода ничего не дало.
void Sorting::bubblesort(std::list<int>::iterator start, std::list<int>::iterator stop)
{
int k = 0;
int temp;
std::list<int>::iterator j_1 ;
for (auto i = start; i != stop; i )
{
for (auto j = std::next(start, 1); j != std::prev(stop, k); j )
{
j_1= std::prev(j, 1);
if (*j_1 > *j)
{
temp = *j_1;
*j_1 = *j;
*j = temp;
}
}
k ;
}
}
Протестировано на 1000 элементах — 9032 с (измерено с помощью std:: chrono)
Комментарии:
1. Было бы лучше поместить всю программу целиком, чтобы у людей был шанс воспроизвести относительную медлительность.
2.
std::prev(stop, k)
имеет линейную сложность. Итак, если я не ошибаюсь в своем интуитивном анализе, временная сложность вашего алгоритма равнаO(n*n*n)
3. Кажется, что это работает, но для выполнения требуется много времени — Конечно, это занимает много времени — это пузырьковая сортировка.
4. @PaulMcKenzie 1000 элементов — это ничто, 9 секунд — это вечность, это не (только) потому, что пузырьковая сортировка, а из-за способа ее реализации
5. как говорит @eerorika, вы тратите свое время на
std::prev(stop, k)
, около 99% на ит в-O3
, смотрите Мой ответ, чтобы иметь альтернативу
Ответ №1:
делать
void bubblesort(std::list<int>::iterator start, std::list<int>::iterator stop)
{
std::list<int>::iterator k = stop;
int temp;
std::list<int>::iterator j_1 ;
for (auto i = start; i != stop; i )
{
for (auto j = std::next(start, 1); j != k; j )
{
j_1= std::prev(j, 1);
if (*j_1 > *j)
{
temp = *j_1;
*j_1 = *j;
*j = temp;
}
}
k--;
}
}
чтобы не выполнять непрерывные перерасчеты std::prev(stop, k)
все время, ваша программа делает почти только это
Конечно, список также не является лучшей коллекцией для хранения int и их сортировки
Полный пример :
#include <list>
#include <iostream>
#include <chrono>
#include <ctime>
void bubblesort(std::list<int>::iterator start, std::list<int>::iterator stop)
{
#ifdef YOU
int k = 0;
#else
std::list<int>::iterator k = stop;
#endif
int temp;
std::list<int>::iterator j_1 ;
for (auto i = start; i != stop; i )
{
for (auto j = std::next(start, 1);
#ifdef YOU
j != std::prev(stop, k);
#else
j != k;
#endif
j )
{
j_1= std::prev(j, 1);
if (*j_1 > *j)
{
temp = *j_1;
*j_1 = *j;
*j = temp;
}
}
#ifdef YOU
k ;
#else
k--;
#endif
}
}
int main()
{
std::list<int> l;
for (int i = 0; i != 1000; i)
l.push_front(i);
#ifdef DEBUG
for (auto i : l)
std::cout << i << ' ';
std::cout << std::endl;
#endif
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
bubblesort(l.begin(), l.end());
end = std::chrono::system_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() / 1000.0
<< " sec" << std::endl;
#ifdef DEBUG
for (auto i : l)
std::cout << i << ' ';
std::cout << std::endl;
#endif
}
Компиляция и выполнение :
pi@raspberrypi:/tmp $ g b.cc
pi@raspberrypi:/tmp $ ./a.out
0.183 sec
pi@raspberrypi:/tmp $ g -DYOU b.cc
pi@raspberrypi:/tmp $ ./a.out
3.98 sec
pi@raspberrypi:/tmp $
pi@raspberrypi:/tmp $ g -O3 b.cc
pi@raspberrypi:/tmp $ ./a.out
0.004 sec
pi@raspberrypi:/tmp $ g -O3 -DYOU b.cc
pi@raspberrypi:/tmp $ ./a.out
0.413 sec
Обратите также внимание на преимущество компиляции в O3 …
Комментарии:
1. Спасибо, но теперь мне немного любопытно, как именно в вашем коде работают #ifdef в этом случае и флаги, которые вы добавили в команду компиляции?
2. опция
-DYOU
определяет ВАШ идентификатор препроцессора (-DYOU=123
также установите его равным 123, но мне не нужно заданное значение), что позволяет мне выбирать, скомпилировать ваш код или мой, не имея двух программ / файлов.#ifdef XX
является сокращением для#if defined(XX)
и#if
работает как if , но во время компиляции, а не во время выполнения
Ответ №2:
Это скорее дополнение к ответу Бруно, лучше попытаться отделить реализацию sort от реальных типов, например
template <class InIt>
void bubblesort(InIt start, InIt stop)
{
InIt k = stop, j_1;
for (auto i = start; i != stop; i)
{
for (auto j = std::next(start, 1); j != k; j)
{
j_1 = std::prev(j, 1);
if (*j_1 > *j)
{
/*auto temp = *j;
*j = *j_1;
*j_1 = temp;*/
std::swap(*j,*j_1);
// - no real performance difference on GCC with -O2.
}
}
--k;
}
}