【问题标题】:C++ time() functionC++ 时间() 函数
【发布时间】:2015-02-05 12:04:37
【问题描述】:

我调用 time() 函数,对向量运行排序算法,然后再次调用 time() 函数。当我这样做时,从 time() 返回的值对于两个调用都是完全相同的,所以我无法计算完成排序需要多长时间。当向量有任意数量的元素时会发生这种情况;它没有改变。我在底部的 sort() 函数中调用 time(NULL)。任何帮助表示赞赏。谢谢!

ma​​in.cpp

#include <cstdlib>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <ctime>

using namespace std;

int listSize, listType;
static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

template <typename E>
void printVector(vector<E>& list)
{
    typename vector<E>::iterator it;
    for (it = list.begin(); it != list.end(); it++)
        cout << *it << " ";
}

template <typename E>
vector<E> generateList(int listType, int listSize)
{   
    vector<E> list;
    if (listType == 1)
    {
        for (int i = 0; i < listSize; i++)
        {
            int random = rand() % 10001;
            list.push_back(random);
        }
    } 
    else if (listType == 2)
    {
        for (int i = 0; i < listSize; i++)
        {
            double random = (10000 * (double)rand() / (double)RAND_MAX);
            list.push_back(random);
        }
    }
    else if (listType == 3)
    {
        for (int i = 0; i < listSize; i++)
        {
            char random = alphabet[rand() % (sizeof(alphabet) - 1)];
            list.push_back(random);
        }
    }
    else
    {
        cout << "Invalid type\n";
        exit(0);
    }

    return list;
}

template <typename E>
void insertionSort(vector<E>& list)
{
    E i, j, tmp;

    for (i = 1; i < list.size(); i++)
    {
        j = i;
        tmp = list[i];
        while (j > 0 && tmp < list[j-1])
        {
            list[j] = list[j-1];
            j--;
        }
        list[j] = tmp;
    }
}

template <typename E>
vector<E> merge(vector<E>& list, vector<E>& left, vector<E>& right)
{
    vector<E> result;
    unsigned left_it = 0, right_it = 0;

    while(left_it < left.size() && right_it < right.size())
    {
        if(left[left_it] < right[right_it])
        {
            result.push_back(left[left_it]);
            left_it++;
        }
        else
        {
            result.push_back(right[right_it]);
            right_it++;
        }
    }

    while(left_it < left.size())
    {
        result.push_back(left[left_it]);
        left_it++;
    }

    while(right_it < right.size())
    {
        result.push_back(right[right_it]);
        right_it++;
    }
    list = result;              
    return list;
}

template <typename E>
vector<E> mergeSort(vector<E>& list)
{
    if(list.size() == 1)
    {
        return list;
    }

    typename vector<E>::iterator middle = list.begin() + (list.size() / 2);

    vector<E> left(list.begin(), middle);
    vector<E> right(middle, list.end());

    left = mergeSort(left);
    right = mergeSort(right);

    return merge<E>(list, left, right);
}

template <typename E>
void shiftRight(vector<E>& list, int low, int high)
{
    int root = low;
    while ((root*2)+1 <= high)
    {
        int leftChild = (root * 2) + 1;
        int rightChild = leftChild + 1;
        int swapIndex = root;
        if (list[swapIndex] < list[leftChild])
        {
            swapIndex = leftChild;
        }
        if ((rightChild <= high) && (list[swapIndex] < list[rightChild]))
        {
            swapIndex = rightChild;
        }
        if (swapIndex != root)
        {
            double tmp = list[root];
            list[root] = list[swapIndex];
            list[swapIndex] = tmp;
            root = swapIndex;
        }
        else
        {
            break;
        }
    }
    return;
}

template <typename E>
void heapify(vector<E>& list, int low, int high)
{
    int midIndex = (high - low - 1)/2;
    while (midIndex >= 0)
    {
        shiftRight(list, midIndex, high);
        midIndex--;
    }
    return;
}

template <typename E>
void heapSort(vector<E>& list, int size)
{
    heapify(list, 0, size - 1);
    int high = size - 1;
    while (high > 0)
    {
        double tmp = list[high];
        list[high] = list[0];
        list[0] = tmp;
        high--;
        shiftRight(list, 0, high);
    }
    return;
}

template <typename E>
int pivot(vector<E>& list, int first, int last) 
{
    int p = first;
    E pivotElement = list[first];

    for(int i = first+1 ; i <= last ; i++)
    {
        if(list[i] <= pivotElement)
        {
            p++;
            E temp = list[i];
            list[i] = list[p];
            list[p] = temp;
        }
    }

    E temp = list[p];
    list[p] = list[first];
    list[first] = temp;

    return p;
}

template <typename E>
void quickSort(vector<E>& list, int first, int last) 
{
    E pivotElement;

    if(first < last)
    {
        pivotElement = pivot(list, first, last);
        quickSort(list, first, pivotElement-1);
        quickSort(list, pivotElement+1, last);
    }
}
template <typename E>
bool sort(vector<E>& list)
{
    int again = 0;
    int sort = 0;
    long int start, finish, duration;

    cout << "Which sorting algorithm would you like to use?" << endl;
    cout << " 1 for Insertion Sort\n 2 for Merge Sort\n 3 for Heapsort\n 4 for Quicksort" << endl;
    cin >> sort;
    cout << endl;

    printVector(list);    
    cout << "\n" << endl;

    start = time(NULL);
    if (sort == 1)
        insertionSort(list);
    else if (sort == 2)
        mergeSort(list);
    else if (sort == 3)
        heapSort(list, list.size());
    else if (sort == 4)
        quickSort(list, 0, list.size() - 1);
    else {
        cout << "Invalid command\n";
        exit(0);
    }    
    finish = time(NULL);

    duration = finish - start;

    cout << start << endl;
    cout << "Sorting the list took " << duration << " seconds." << endl;  
    cout << finish << endl;

    printVector(list);

    while (again == 0) {
        cout << "\n\nWould you like to go again? (1 for yes, 2 for no)\n";
        cin >> again;
        if (again == 1)
            return true;
        else if (again == 2)
            return false;
    }
}

int main(int argc, char** argv) 
{
    bool again = true;
    while (again) {
        cout << "How many items do you want to sort? (0 to quit)" << endl;
        cin >> listSize;
        if (listSize == 0)
            exit(0);
        else if (listSize < 0) {
            cout << "Invalid input.\n";
            exit(0);
        }
        /* Change first parameter of generateList() to 1-3
         * 1 for ints, 2 for doubles, 3 for chars
         * 
         * Also change vector types in the three places below to
         * the corresponding parameter type.
         */
        vector<char> list = generateList<char>(3, listSize);
        again = sort<char>(list);
    }
}

【问题讨论】:

    标签: c++ sorting vector time timer


    【解决方案1】:

    第一个问题是你通过finishstart时间之间的差异来计算时间:

    • time_t 通常以秒表示。

    • 并且可移植程序不应该直接使用time()返回的值,而总是依赖于调用标准库的其他元素来将它们转换为可移植类型(例如localtime、gmtime或difftime )。

    • 使用difftime(),您将获得以秒为单位的双精度值,但使用您使用的特定库实现可用的精度(可能低于秒)。

    更好的方法是使用 C++11 &lt;chrono&gt;

    chrono::high_resolution_clock::time_point t = high_resolution_clock::now();
    ...
    chrono::high_resolution_clock::time_point t2 = high_resolution_clock::now();
    long elapsed_milisecs = duration_cast<milliseconds>(t2 - t).count();
    

    但是,还有第二个问题:虽然这是可移植且精确的,但您必须受到操作系统时钟分辨率的限制

    例如,在 Windows 上,此时钟分辨率为 15 ms。任何低于 15 毫秒的时间都可能显示为 0 的持续时间。

    改进时间测量的最简单方法,尤其是在基准测试的情况下,可能是增加测量的迭代次数。不是执行一次测量的代码,而是测量数千次连续迭代的时间,并计算每次迭代的平均时间。

    一种不太便携的方法是使用本机操作系统高分辨率计时器,以规避库实现限制:

    • 对于 Windows,您可以使用 QueryPerformanceCounter,如 this blog 中所述。
    • 对于 linux,您可以使用 clock_gettime(),如 this SO question 中所述。

    【讨论】:

    • .count() 是从哪里来的?
    • 它是 chrono::duration (cplusplus.com/reference/chrono/duration) 的成员。顺便说一句,我认为 chrono::milliseconds 会更好(我的代码中有一个 using 子句)。
    【解决方案2】:

    time() 只有第二个分辨率。您的排序可能完成得足够快,以至于您看不到它滴答作响。如果要计时,则需要使用更精确的时钟。

    如果您可以访问 C++11,最简单的方法是:

    auto begin = std::chrono::high_resolution_clock::now();
    // do sort() stuff here
    auto end = std::chrono::high_resolution_clock::now();
    
    auto elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();;
    

    Pre-C++11,你可以使用这个:

    struct timeval begin, end;
    gettimeofday(&begin, NULL);
    // do sort() stuff here
    gettimeofday(&end, NULL);
    
    long elapsed_usec = (end.tv_sec - begin.tv_sec) * 1e6 + 
                        (end.tv_usec - begin.tv_usec);
    

    【讨论】:

    • 我如何获得对 C++11 的访问权限?
    • @AlishasPayPal 如果您使用的是足够晚版本的 gcc 或 clang,您可以添加 -std=c++11 标志,然后添加 #include &lt;chrono&gt;
    • .count() 是从哪里来的?
    • @AlishasPayPal Here 是一个参考。
    猜你喜欢
    • 2012-08-13
    • 2021-12-23
    • 2012-07-23
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多