2016-03-16 4 views
0

Я создаю набор библиотеки C++ в качестве части моего назначения Data Structures, который включает выборочную реализацию векторных алгоритмов сортировки, стеков и т. Д. Я должен работать над время работы алгоритмов сортировки, сортировка пузырьков, сортировка выбора, быстрая сортировка и т. д., которые являются частью моей библиотеки.Показывать процент завершения процесса в программе на C++

Теперь набор данных задан для проверки алгоритмов в порядке порядка 10^6. Я запустил сортировку пузыря по данным 2 * 10^6 элементов, и для запуска программы потребовалось около 138 минут, и за все это время я не знал, работает ли мой алгоритм сортировки правильно или нет. даже работая или нет. Я хотел бы добавить еще одну функцию к функциям сортировки, т. Е. Они могли бы отображать процент сортировки, и я думаю, что это возможно, поскольку алгоритмы, подобные сортировке пузырьков, детерминированы.

мне нужно сообщение как-то появляться, как только я начинаю процесс:

пузыря рода под прогрессом. Совершено: 17%

Этот процент определяется по алгоритму. Рассмотрим пример сортировки пузырьков со 10000 элементами. Если вы посмотрите на алгоритм сортировки пузырьков (см. Здесь: https://en.wikipedia.org/wiki/Bubble_sort), он имеет 2 цикла, и после каждой итерации основного цикла один элемент фиксируется в правильное положение в отсортированном массиве. Итак, после 1-й итерации процент должен увеличиться на 0,01%.

Хотя этот процентный расчет имеет проблему, в этом случае время для увеличения процента продолжает уменьшаться, но что-то вроде этого.

Кроме того, это число должно увеличиваться по мере необходимости и в том же месте. Но я не знаю, как его реализовать.

+0

Проблема в том, что большинство компьютеров не просто запускают вашу программу. У них есть другие вещи, которые влияют на производительность, поэтому им придется сделать предположение. –

+0

Время первого x% и экстраполировать. –

+1

Как вы собираетесь рассчитать этот процент? Как только вы это определите, дисплей прост. Однако расчет не является чем-то простым. Учитывая 1000 пунктов, как ваш алгоритм сортировки знает, что он достиг 17% от своего рода, когда по своей природе сортировка пузырьков очень повторяется? –

ответ

1

Вы можете передать функцию обратного вызова общего типа вашей функции bubblesort и вызвать функцию через разумные промежутки времени.

Это будет влиять на производительность, но это не должно вызывать беспокойства, когда вы используете пузырьки в любом случае.

Сначала нужно некоторое включает в себя:

#include <iostream> 
#include <vector> 
#include <random> 
#include <chrono> 

, а затем функцию BubbleSort, которую я по существу взял из википедии: https://en.wikipedia.org/wiki/Bubble_sort#Optimizing_bubble_sort

template <typename T, typename Func> 
void bubblesort(std::vector<T> &v, Func callback) { 
    size_t const len = v.size(); 
    size_t n = v.size(); 
    while(n > 0) { 
     size_t newn = 0; 
     for(size_t i = 1; i <= n-1; ++i) { 
      if (v[i - 1] > v[i]) { 
       std::swap(v[i-1], v[i]); 
       newn = i; 
      } 
     } 
     n = newn; 
     callback(100-static_cast<int>(n*100/len)); 
    } 
} 

Мы будем называть данную функцию обратного вызова (или использование operator() на объект) всякий раз, когда выполняется сортировка в одном элементе.

Параметр, который мы передаем, представляет собой целочисленный процент от того, как далеко мы пришли. Обратите внимание, что из-за целочисленной арифметики вы не можете изменить порядок операций с n * 100/v.size(), иначе он всегда будет равен 0, так как n всегда будет меньше v.size();

using namespace std::chrono; //to avoid the horrible line becoming even longer 

int main() { 
    std::vector<int> vec; 

    /* fill vector with some data */ 
    std::mt19937 generator(static_cast<unsigned long>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count())); //oh god 
    for(int i = 0; i < 100000; ++i) { 
     vec.push_back(static_cast<int>(generator())); 
    } 

Для инициализации мы создаем генератор случайных чисел и засеваем его текущим временем. Затем мы помещаем некоторые элементы в вектор.

char const *prefix = "Bubble sort under progress. Done: "; 
    int lastp = -1; 
    bubblesort(vec, [&lastp,prefix](int p){ 
     //if progress has changed, update it 
     if(p != lastp) { 
      lastp = p; 
      std::cout << "\r" << prefix << p << "%" << std::flush; 
      /*std::flush is needed when we don't start a new line 
       '\r' puts the cursor to the start of the line */ 
     } 
    }); 

    std::cout << "\r" << prefix << "100%" << std::endl; 
    //make sure we always end on 100% and end the line 
} 

Теперь основная часть: мы передаем функцию лямбда C++ для нашей функции bubblesort в качестве обратного вызова. Затем наша функция bubblesort вызовет эту лямбда с процентным значением и запишет ее на экран.

И вуаля, мы получили себя некоторый аккуратный выход:

https://youtu.be/iFGN8Wy9T3o

Заключительные ноты:

Вы, конечно, можете интегрировать функцию LAMDA в самой функции сортировки, но я бы не рекомендовал этот поскольку вы теряете большую гибкость. Но это выбор дизайна, который зависит от вас - если вам не нужна гибкость, просто переустановите его.

Процент не очень точный, ведь зная, что вы на 20% (и как долго это нужно, чтобы добраться туда), совсем не говорит о том, сколько времени потребуется, чтобы добраться до 100% вполне возможно, что последние 20% вектора были отсортированы (и, следовательно, быстро отсортировались с bubblesort - O (n)), но остальные 80% были случайными и берут O (n^2) для сортировки. На самом деле все это говорит вам, что вы добиваетесь прогресса, но это все, что вам нужно в первую очередь, поэтому я думаю, что все в порядке.

Если вы хотите получить более точный процент настроить программу так:

#include <iomanip> 
/* ... */ 
callback(10000-static_cast<int>(n*10000/len)); 
/* ... */ 
std::cout.fill('0'); //to fill leading zero of p%100 
std::cout << "\r" << prefix << p/100 << "." << std::setw(2) << p%100 << "%" << std::flush; 

Если вы решили использовать значение с плавающей точкой, а не помнит, чтобы очистить остаточные символы из предыдущих выходов - «\ г» только сбрасывает курсор , но не очищает линию.

Используйте std::cout.precision(3); для фиксированной точности или напишите некоторые пробелы после сообщения, чтобы очистить предыдущие прогоны.

+0

Ого! Это золото. Я не знаю, почему я тогда не принял этот ответ. Большое спасибо! Кроме того, почему бы вам не сделать видео общедоступным? –

1

Для частного случая с пузырьковой дорожкой вы можете взять количество элементов, которые у вас есть, а затем разделите их на 100. Если у вас есть 552 элемента, то вы получите 5. (целые числа имеют смысл работать). Затем у вас есть счетчик в вашем цикле. Если счетчик кратен 5 (вы до сих пор сортировали 5 элементов), вы можете увеличить процент на 1 и распечатать его. Если вы печатаете его так, чтобы процент отображался на месте вместо печати ниже, вы можете распечатывать обратные пространства! Либо это, либо попробуйте использовать библиотеку ncurses, хотя это может быть излишним. Наконец, другой способ сделать это может состоять в том, чтобы использовать индикатор выполнения в стиле Linux, длина которого составляет 50 символов или что-то подобное.

+0

Я думал о баре прогресса только после публикации вопроса! Я все равно попробую. И не может использовать библиотеку ncurses. –