使用模板Bubblesort与结构数组的麻烦

时间:2016-11-30 03:28:54

标签: c++ arrays templates struct

所以我的目标是读取一些数据并按人口排序,但我必须使用可以接受多种数据类型的排序。我被指示使用模板来执行此操作,但每次我传递数组"结果[i] .pop"到我的bubblesort函数我收到错误

  

没有匹配函数来调用'bubblesort(std :: string&)'    冒泡(结果[I] .pop);"    注意:候选人是:   election.cpp:32:3:注意:模板T bubblesort(T *)    T bubblesort(T ar [])      ^   election.cpp:32:3:注意:模板参数扣除/替换失败:

     

election.cpp:106:34:注意:无法将'results [i] .election :: pop'(类型'std :: string {aka std :: basic_string}')转换为'std :: basic_string * “    冒泡(结果[I] .pop);

以下是代码:

#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <fstream>
#include <stdlib.h>
using namespace std; 

struct election {

string party;
string state;
string pop;
string reps;
int ratio;
};


template <typename T>
void bubblesort(T ar[])
{

//Bubblesort
int n = 51;
int swaps = 1;
    while(swaps)
    {
    swaps = 0;
            for (int i = 0; i < n - 1; i++)
            {
                    if (ar[i] > ar[i + 1])
                    {
                            swap(ar[i],ar[i+1]);
                            swaps = 1;
                    }
            }
    }
//End Bubblesort

}


void delete_chars(string & st, string ch)
{
    int i = st.find(ch);
    while (i > -1)
    {
            st.replace(i,1,"");
            i = st.find(ch);
    }
}



int main()
{
int i = 0;
int n = 51;
election results[n];

int population[n];
int electoralVotes[n];
int ratio[n];
string st;
fstream inData;

//Read in Data from Text File
inData.open("electionresults.txt");



//Print Array as is
cout << "Array Printed As is" << endl;
cout << left << setw(10) << "Party" << setw(20) << "State" << setw(20) <<     "Population" << setw(15) << "Representatives" << endl;
for (int i = 0; i < n; i++)
{
    getline(inData,st);
    results[i].party = st.substr(0,1);
    results[i].state = st.substr(8,14);
    results[i].pop = st.substr(24,10);
    results[i].reps = st.substr(40,2);
    cout << left << setw(10) << results[i].party << setw(20) <<     results[i].state << setw(20) << results[i].pop << setw(15) << results[i].reps << endl;
}

 //Array Sorted by Population
cout << "Array Sorted By Population" << endl;
cout << endl;
cout << endl;
cout << left << setw(10) << "Party" << setw(20) << "State" << setw(20) <<              "Population" << setw(15) << "Representatives" << endl;



for(int i = 0; i < n; i++){
bubblesort<string>(results[i].pop);
}

2 个答案:

答案 0 :(得分:0)

要使你的bubblesort工作,你需要为选举结构实现大于运算符(&gt;):

struct election 
{

    string party;
    string state;
    string pop;
    string reps;
    int ratio;
    bool operator>( election a)
    {
        return pop > a.pop;
    }
};

现在通过传递结果数组来调用bubblesort:

bubblesort<election>(results);

旁注,你的函数应该传递大小,而不是硬编码函数中的大小(void bubblesort(T ar[], int size))。这为您的功能提供了更多功能和适应性。

答案 1 :(得分:0)

如果你只想对pop进行排序,另一个答案就解决了这个问题。然而,这是一个有限的解决方案,并不会解决在任何领域排序的真正问题(今天它是“流行”,但如果明天不是这种情况,你想要对“比率”排序呢?) 。问题是,您无法提供多个operator >来执行此操作,并且您基本上只能在pop上进行排序。

另一个解决方案是为bubblesort函数提供一个额外的模板参数,该参数定义了给定两个T时要执行的操作,是否应将T放在另一个T之前{排序数组中的{1}}。

#include <functional>
#include <algorithm>
//...
template <typename T, typename cmp>
void bubblesort(T ar[], int n, cmp compare_fn)
{
    int swaps = 1;
    while (swaps)
    {
        swaps = 0;
        for (int i = 0; i < n - 1; i++)
        {
            if (!compare_fn(ar[i], ar[i + 1]))
            {
                std::swap(ar[i], ar[i + 1]);
                swaps = 1;
            }
        }
    }
}

// keep our original 2 param bubble sort, but let it call the one above
template <typename T>
void bubblesort(T ar[], int n)
{
    // call general version using <
    bubblesort(ar, n, std::less<T>());
}

我们基本上有两个函数,其中两个参数bubblesort函数调用通用3参数bubblesort版本,该版本采用第三个参数,该参数描述了比较。

如果您想为“简单”案例调用bubblesort,则使用bubblesort的双参数版本,其中您的商品为

  1. 在数组中
  2. 您可以使用T
  3. 比较<
  4. 您希望按升序排序(这就是为什么我们使用<而不是>来解决一般情况。)
  5. 例如,需要对int数组进行排序,您只想按升序对其进行排序:

    int someArray[10];
    //...
    bubblesort<int>(someArray, 10);  // sort ascending
    

    但是,我们不想对int,甚至std::string进行“简单”排序。我们希望在election上对election.pop进行排序,而不仅仅是bubblesort

    如果您查看上面的第一个>函数,请注意我们使用compare_fn替换了比较函数bubblesort的比较。请注意,该参数默认为std::less函数对象。这就是第二个std::less函数适用于简单类型的原因,因为<使用bubblesort进行比较。

    但是,如果您尝试使用election仅使用两个参数调用election,则会遇到另一个编译器错误,基本上说明operator <没有election到与之比较。解决方法是

    1)提供这样的运营商&lt; (与给出的其他答案类似)election结构或

    2)编写自定义比较函数。

    让我们回顾一下这些解决方案。

    解决方案1:

    如果我们使用1),struct election { std::string party; std::string state; std::string pop; std::string reps; int ratio; bool operator <(const election& e) const { return pop < e.pop; } }; int main() { //... bubblesort<election>(results, n); } 结构将如下所示:

    results

    现在,pop使用operator <作为要排序的项目进行排序,因为election正在使用std::less<>中定义的operator <

    Here is an example using overloaded < in election

    但是,此解决方案与其他答案存在相同的问题,因为您只能定义一个const election&作为参数。ratio。例如,如果你想对pop进行排序,那么你运气不好,或者如果你想按降序排序true,那你就不走运了。这是上面选项2)的用法。

    解决方案2:

    我们可以通过提供自定义比较函数,函数对象或lambda function来定义我们要排序的内容,排序顺序等,如果第一个T则返回T应该在传递给比较函数的第二个false之前,否则bool compare_pop(const election& e1, const election& e2) { return e1.pop < e2.pop; // if e1.pop comes before e2.pop, return true, else false } int main() { //... bubblesort<election>(results, n, compare_pop); }

    我们试试一个函数:

    bubblesort

    现在将发生的是,这将调用bubblesort的第一个版本,它将比较函数作为参数。 compare_pop模板函数现在将调用compare_pop来确定项目是否出现故障。如果false返回bubblesort,则int main() { //... bubblesort<election>(results, n, [&](const element& e1, const element& e2) { return e1.pop < e2.pop; }); } 函数会交换项目,否则会让他们独自一人。

    Here is a live example with an array of 3 elections, sorted on pop

    如果你想使用lambda函数而不是编写另一个比较函数,那也可以使用:

    pop

    上面将与函数示例做同样的事情,除了你不再需要编写一个单独的函数,因为lambda语法被用作函数。

    Example using lambda syntax

    现在,如果我们想对bubblesort进行排序,但是降序而不是升序怎么办?简单 - 使用不同的函数或lambda调用bool compare_pop_up(const election& e1, const election& e2) { return e1.pop > e2.pop; // if e1.pop comes after e2.pop, return true, else false } int main() { //... bubblesort<election>(results, n, compare_pop_up); }

    int main()
    {
       //...
       bubblesort<election>(results, n, 
                     [&](const element&e1, const element& e2) 
                     { return e1.pop > e2.pop;});
    }
    

    或使用lambda:

    bubblesort

    而且神奇地,pop完成了工作,按ratio降序排序。

    Here is a live example with an array of 3 elections, sorted on pop, descending

    如果您想对bool compare_ratio(const election& e1, const election& e2) { return e1.ratio < e2.ratio; } int main() { //... bubblesort<election>(results, n, compare_ratio); } 进行排序怎么办?同样的事情 - 提供不同的功能或lambda:

    int main()
    {
       //...
       bubblesort<election>(results, n, 
                     [&](const element&e1, const element& e2) 
                     { return e1.ratio < e2.ratio;});
    }
    

    或使用lambda:

    ratio

    这将按ratio的升序排序election results[n];

    您的代码的另一个问题是您在定义数组时使用非标准C ++语法。你这样做了:

    Variable Length Arrays

    这不是标准的C ++语法,因为C ++只允许使用编译时表达式创建数组来表示项目数。您正在使用名为#include <vector> //... std::vector<election> results(n); //... bubblesort<election>(results.data(), results.size(), compare_pop) 的内容,不是标准。

    相反,您可以使用标准C ++的std::vector

    {{1}}