我正在制作一套C ++库作为我的数据结构分配的一部分,其中包括矢量,排序算法,堆栈等的自定义实现。我应该研究排序算法的运行时间,冒泡排序,选择排序,快速排序等,这是我的图书馆的一部分。
现在用于测试算法的数据集大约为10 ^ 6。我对2 * 10 ^ 6个元素的数据进行冒泡排序,程序运行大约需要138分钟,而且在这段时间里,我不知道我的排序算法是否正常工作,或者是不是甚至工作与否。我想在排序功能中添加另一个功能,即它们可以显示完成排序的百分比,我认为这是可能的,因为像冒泡排序这样的算法是确定性的。
一旦我开始这个过程,我需要一个像某些东西出现的消息:
正在进行冒泡排序。完成:17%
此百分比由算法确定。考虑具有10000个元素的冒泡排序示例。如果你看一下冒泡排序算法(参见这里:https://en.wikipedia.org/wiki/Bubble_sort),它有2个循环,并且在主循环的每次迭代之后,一个元素被固定到排序数组中的正确位置。因此,在进行1次迭代后,百分比应该增加0.01%。
虽然这个百分比计算存在一个问题,在这种情况下,百分比增加的时间会继续减少,但这样的事情会发生。
此外,该号码应在需要时在同一地点增加。但我不知道如何实现它。
答案 0 :(得分:1)
对于bubblesort的特殊情况,你可以获取你拥有的元素数量,然后除以100.如果你有552个元素,那么你将得到5.(整数有意义使用)。然后,在你的循环中有一个计数器。如果计数器是5的倍数(你到目前为止已经排序了5个元素),那么你可以将百分比增加1并打印出来。打印它以使百分比显示在现场而不是在下面打印,您可以打印退格!或者尝试使用ncurses库,尽管这可能有点过分。最后,另一种方法可能是使用长度为50个字符或类似的Linux样式进度条。
答案 1 :(得分:1)
您可以将泛型类型的回调函数传递给bubblesort函数,并以合理的间隔调用该函数。
这会影响性能,但无论如何,当你使用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 ++ lambda函数作为回调传递给我们的bubblesort函数。然后我们的bubblesort函数将使用百分比值调用此lambda并将其写入屏幕。
瞧,我们得到了一些整洁的输出:
你当然可以将lamda函数集成到sort函数本身,但是我不建议这样做,因为你失去了很多灵活性。但这是一个由您自己决定的设计选择 - 如果您不需要灵活性,只需对其进行硬编码即可。
百分比不是很准确,事实上知道你达到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;
如果您决定使用浮点值,请记住清除先前输出中的剩余字符 - “\ r \ n”仅重置光标位置,但不清除该行。
使用std::cout.precision(3);
获得固定精度,或在信息后写一些空格以清除之前的运行。