使用单个重载运算符对STL列表进行排序<

时间:2014-05-24 14:44:50

标签: c++ sorting stl linked-list

我已成功使用文本文件中的数据填充链接列表。链接列表包含structure,其中包含5个string类型的字段。

我希望按某个结构字段(升序或降序)对列表进行排序。我决定重载operator<,但我不知道如何实现它。

到目前为止,我能够按一个固定字段对列表进行排序。以下是相关代码:

#include <iostream>       
#include <list>           // std::list
#include <fstream>        // std::ifstream, std::ofstream
#include <string>         // std::string
#include <algorithm>      // std::remove, std::remove_if
#include <sstream>        // std::istringstream

class Lista
{
private:
    struct Person
    {
        // data from file
        std::string lastName;  // other fields omitted for keeping brevity

        // operator < ( needed for correctly sorting the linked list )
        bool operator< ( const Person &p )const
        {
            return lastName > p.lastName;
        }

        // constructor / destructor ... omitted for keeping brevity 
    };

    // linked list that holds all the data from files
    std::list<Person> persons;

public:

// constructor / destructor ... omitted for keeping brevity

// method for sorting the list
    void sortList()
    {
        persons.sort();
    }
};

我想添加enum个选项,因此我可以使用只有一个重载operator<进行排序。

这样的事情:

class Lista
{
private:
    struct Person
    {
        //================ here I could add enum of choices ============//

        enum choice { FIELD1, LASTNAME, FIELD2 }; // you get the point
        bool ascending;  // decides if it is ascending or descending

        //==============================================================//

        // data from file
        std::string lastName;  // other fields omitted for keeping brevity

        // operator < ( needed for correctly sorting the linked list )
        bool operator< ( const Person &p )const
        {
            if ( choice == FIELD1 )  
                return field1 < p.field1;

            if ( choice == FIELD2 )  
                return field2 < p.field2;

            if ( choice == LASTNAME )  
                 return lastName > p.lastName;
        }

        // constructor / destructor ... omitted for keeping brevity 
    };

    // linked list that holds all the data from files
    std::list<Person> persons;

public:

// constructor / destructor ... omitted for keeping brevity

// method for sorting the list
    void sortList( Person::choice ch, bool ascending)
    {
        // here I should use the parameters to invoke proper sorting 
        persons.sort();
    }

编辑:

我尝试将operator<更改为函数但失败了:

// this function is inside of my private struct
bool compare( const Person &p1, const Person &p2 )const
{
    return p1.lastName > p2.lastName;
}

然后我用这样的方法调用它:

void sortList()
{
    persons.sort( compare );
}

但是我收到以下错误:错误C2065:&#39;比较&#39; :未声明的标识符

我对如何做到这一点真的没有其他想法,你能帮助我吗?

2 个答案:

答案 0 :(得分:2)

enum sort_choice { FIELD1, LASTNAME, FIELD2 } ; // had to put it outside to make it accessible to main()

class Lista
{

private:

    struct Person
    {
        std::string field1;
        std::string field2;
        std::string lastName;
        Person(const string& f1,const string& f2,const string& lname)
        {
            field1=f1;
            field2=f2;
            lastName=lname;
        }
    };

    struct cmp_Person  // A functor for comparison
    {
        bool cmp_ascending;
        sort_choice cmp_choice;

        cmp_Person(const bool& asc,const sort_choice& ch)
        {
            cmp_ascending=asc;
            cmp_choice=ch;
        }

        bool operator ()(const Person &first, const Person& second) const
        {
            if(cmp_ascending)
            {
                if ( cmp_choice == sort_choice::FIELD1 )
                    return first.field1 < second.field1;

                if ( cmp_choice == sort_choice::FIELD2 )
                    return first.field2 < second.field2;

                if ( cmp_choice == sort_choice::LASTNAME )
                    return first.lastName > second.lastName;
            }
            else
            {
                if ( cmp_choice == sort_choice::FIELD1 )
                    return first.field1 > second.field1;

                if ( cmp_choice == sort_choice::FIELD2 )
                    return first.field2 > second.field2;

                if ( cmp_choice == sort_choice::LASTNAME )
                    return first.lastName > second.lastName;
            }

            return true;
        }
    };

    std::list<Person> persons;

public:

    void sortList( const bool& ascending, const sort_choice& ch)
    {
        persons.sort(cmp_Person(ascending,ch));
    }

    void push_to_list(const string& f1,const string& f2,const string& lname)
    {
        persons.push_back(Person(f1,f2,lname));
    }

    void display_list()
    {
        list<Person>::iterator it;
        for(it=persons.begin(); it!=persons.end(); it++)
        {
            cout<<(*it).field1<<" "<<(*it).field2<<" "<<(*it).lastName<<"\n";
        }
    }
};


int main()
{
    Lista Lobj;
    Lobj.push_to_list("a","b","c");
    Lobj.push_to_list("d","e","f");
    Lobj.push_to_list("g","h","i");
    Lobj.push_to_list("j","k","l");
    Lobj.sortList(true,sort_choice::FIELD1);
    Lobj.display_list();
    cout<<"\n\n";
    Lobj.sortList(false,sort_choice::FIELD1);
    Lobj.display_list();
}

答案 1 :(得分:0)

您可以使用以下内容:

class Lista
{
public:
    enum class Sort_Type{Name,LastName};
    void sort(Sort_Type type,bool asc=true)
    {
        switch (type) {
        case Sort_Type::Name:
            this->list_.sort([&](const Person& p1,const Person& p2){
                if(asc)
                     return p1.name.compare(p2.name)>=0 ;
                else
                    return p1.name.compare(p2.name)<0;
            });
            break;
        case Sort_Type::LastName :
            this->list_.sort([&](const Person& p1,const Person& p2){

                if(asc)
                     return p1.lastName.compare(p2.lastName)>=0 ;
                else
                    return p1.lastName.compare(p2.lastName)<0;
            });
            break;
        }
    }

private:
    struct Person
    {
        string name ;
        string lastName;
    };

    std::list<Person> list_;
};

//
    Lista l;
    l.sort(Lista::Sort_Type::Name);