开发者

Function can only be called once within main

For some reason the check_sort function can only be called once within the main function otherwise the workflow freezes after it's first executed.

For example. The output ends at:

How many elements for container? 5000
Check: list is sorted
Elapsed time: 0.32 seconds

Instead of continuing like:

How many elements for next container? 5000
Check: list is sorted
Elapsed time: 0.30 seconds
Check: set is sorted
Elapsed time: 0.01 seconds
Check: vector is sorted
Elapsed time: 0.25 seconds

Full program below:

#include <cmath>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <list>
#include <set>
#include <algorithm>
#include <cstdlib>

using namespace std;

typedef void Inserter(vector<double>);

vector<double> gen_data(int num_elts);
void insert_list(vector<double> data);
void insert_set(vector<double> data);
void insert_vector(vector<double> data);

void time_insert( Inserter inserter, vector<double> data);

template <class Iter> bool is_sorted(Iter first, Iter last);
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind);

list<double> l;
set<double> s;
vector<double> v;

int main() {
    srand(time(0));// initialize random number generator
    cout << "How many elements for container? ";
    int num_elts = 0;

    while (cin >> num_elts) {
    if (num_elts <= 0)
        cout << "Error, should be > 1";
    else {
        vector<double> data = gen_data(num_elts);

        check_sort(l.begin(), l.end(), "list");
        time_insert(insert_list, data);
        check_sort(s.begin(), s.end(), "set");
        time_insert(insert_set, data);
        check_sort(v.begin(), v.end(), "vector");
        time_insert(insert_vector, data);

    }
    cout << "\nHow many elements for next container? ";

    }
    return 0;

} 
void time_insert( Inserter inserter, vector<double> data) {
    clock_t t1 = clock();
    if (t1 == clock_t(-1)) { //if clock() doesn’t work
    cerr << "sorry, no clock\n";
    exit(1);
    }

    inserter(data);
    clock_t t2 = clock(); 
    if (t2 == clock_t(-1)) {
    cerr << "sorry, clock overflow\n";

    exit(2);
    }

    cout << "Elapsed time: " << fixed << setprecision(2)
     << double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";

}

class Larger_than { 
    double v;
public: 
    Larger_than(double vv) : v(vv){}
    bool operator()(double x) const {return x>v;}
};

// Sorts and then inserts data into a list
void insert_list(vector<double> data)
{
    list<double> l;
    for(int i=0; i < data.size(); i++){
    list<double>::iterator p = find_if(l.begin(),l.end(), Larger_than(data[i]));
    l.insert(p, data[i]);
    }
} 
// Sort开发者_JAVA百科s and then inserts data into a list
void insert_set(vector<double> data)
{
    set<double> s; 
    for(int i=0; i < data.size(); i++){
    set<double>::iterator p = find_if(s.begin(),s.end(), Larger_than(data[i]
                          ));
    s.insert(p, data[i]);
    }
} 
// Sorts and then inserts data into a list 
void insert_vector(vector<double> data)
{
    vector<double> v; 
    for(int i=0; i < data.size(); i++){
    vector<double>::iterator p = find_if(v.begin(),v.end(), Larger_than(data
                                        [i]));
    v.insert(p, data[i]);
    }
} 

// generate num_elts random numbers in the range [0.0, 1.0), 
// which are returned in a vector

vector<double> gen_data (int num_elts) 
{
    vector<double> result; 
    for (int i = 0; i < num_elts; i++) {
    double datum = 1.0*rand()/RAND_MAX; 
    result.push_back(datum);
    }
    return result;
}

// is container spanned by [from, last) sorted?  
template <class Iter> bool is_sorted(Iter first, Iter last)  
{  
    Iter next = first;                   // next element  
    for (next++; next != last; next++, first++) {  
    if (*first > *next)  
        return false;  
    }  
    return true;  
}  

// prints a msg describing container kind, as well as whether container  
// spanned by [from, last) is sorted  
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind)  
{  
    cout << "Check: " << cont_kind << " is ";  
    if (!is_sorted(first, last)) cout << "not ";  
    cout << "sorted\n";  
} 


I don't know if this is part of your problem, but is_sorted doesn't work right if first is the end of the container. next gets incremented past end and undefined behavior is encountered.

EDIT: Actually this is definitely it: You don't populate the vector/list/set containers prior to calling the check function on them. Even if you called the insert functions before calling the check function it still wouldn't work because each insert_* function declares a local to populate which shadows the global variable you're trying to fill.

EDIT2: In insert_set the find_if is actually making your code less performant than it should be. You should just use std::set::insert and let it use its built-in sorting, which will be more efficient than find_if because it knows the implementation of the underlying set.


Your template function is_sorted() doesn't check properly whether first is equal to last before incrementing next which is a copy of first:

template <class Iter> bool is_sorted(Iter first, Iter last)  
{  
    Iter next = first;                   // next element  
    for (next++; next != last; next++, first++) {  
        if (*first > *next)  
            return false;  
    }  
    return true;  
}

This could lead to problems if you get to iterate over an empty range, I believe.

template <class Iter> bool is_sorted(Iter first, Iter last)  
{  
    if (first == last)
        return false;
    for (Iter next = first+1; next != last; next++, first++)
    {  
        if (*first > *next)  
            return false;  
    }  
    return true;  
}

I'm not certain you get empty ranges...so this may be a red herring.

Since you don't set the list before checking that it is sorted (and you don't check that it is sorted after inserting the data), you do run into issues with empty ranges. You need to reverse the sequence of your insert and check operations:

    vector<double> data = gen_data(num_elts);
    time_insert(insert_list, data);
    check_sort(l.begin(), l.end(), "list");
    time_insert(insert_set, data);
    check_sort(s.begin(), s.end(), "set");
    time_insert(insert_vector, data);
    check_sort(v.begin(), v.end(), "vector");

You should avoid duplicated code in your main loop by calling a function to get the number of elements to process. Also, it is conventional to report errors on cerr.

static int get_num_elts()
{
    int num_elts;
    cout << "How many elements for container? ";
    cin >> num_elts;
    if (num_elts < 1)
        cerr << "Error: number should be >= 1" << endl;
    return num_elts;
}


...
int num_elts;

while ((num_elts = get_num_elts()) > 0)
{
    vector<double> data = gen_data(num_elts);
    time_insert(insert_list, data);
    check_sort(l.begin(), l.end(), "list");
    time_insert(insert_set, data);
    check_sort(s.begin(), s.end(), "set");
    time_insert(insert_vector, data);
    check_sort(v.begin(), v.end(), "vector");
}


Your code does not enter the body of the loop in the is_sorted function

instead for (next++; next != last; next++, first++) do for (next; next != last; next++, first++) . Because if first == last, then it would be a problem and that is what you are facing. But not incrementing the next pointer will do no harm as the first comparison will compare the first element with itself which will always be evaluated as false in a greater than comparison with itself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜