我如何排序对象?

时间:2009-09-16 17:20:46

标签: c++ class sorting

我创建了一个类,并在该类下创建了一个对象数组,并用数据填充了所有对象。现在我想通过该类的特定成员对整个数组进行排序,如何使用stable_sort()函数执行此操作?

编辑:好的,我现在有这个,

class sortContiner 
{
public:
    double position;
    int key;
    double offsetXposition;
    double offsetYposition;
    int origXposition;
    int origYposition;
};

我已经声明了这样的数组:

sortContiner * sortList = new sortContiner [length];

现在我想要使用stable_sort()这样的sortList .position成员对它进行排序:

stable_sort(sortList, sortList + length, ????);

比较器功能应该是什么样的?

7 个答案:

答案 0 :(得分:5)

您需要在数组中使用迭代器和一些排序标准。让我们从迭代器开始:

您需要一个 begin 迭代器和一个 end 迭代器。 begin迭代器需要指向第一个元素,end迭代器需要指向后面的最后一个元素。指针是完美的迭代器。数组可以隐式转换为指向其第一个元素的指针,因此您有一个开始迭代器。将数组中的元素数添加到它,你有一个结束迭代器。通过将数组的大小(字节数)除以单个元素的大小,可以获得数组中元素的数量。把它们放在一起:

foo array[10];
const std::size_t array_size = sizeof(array)/sizeof(array[0]);
const int* array_begin = array; // implicit conversion
const int* array_end = begin + array_size;

现在你需要一些算法来决定你班级的两个给定对象中哪一个是较小的一个。一个简单的方法是为您的班级重载operator<

bool operator<(const foo& lhs, const foo& rhs)
{
  // compares using foo's bar
  return lhs.get_bar() < rhs.get_bar();
}

现在您可以对数组进行排序:

std::stable_sort( array_begin, array_end );

如果排序标准不是解决方法(例如,有时您希望根据foo的{​​{1}}数据进行排序,有时基于其bar数据,则可以将不同的排序标准作为可选的第三个参数传递给排序算法。排序标准应该是类似函数的实体。这可以是函数或函数对象。后者提供内联,这就是为什么它们通常更好。这两个都是:

wrgly

这就是你使用它们的方式:

bool compare_by_bar(const food& lhs, const foo& rhs)
{
  return lhs.get_bar() < rhs.get_bar();
}

struct wrgly_comparator {
  bool operator()(const food& lhs, const foo& rhs) const
  {
    return lhs.get_wrgly() < rhs.get_wrgly();
  }
};

您还可以动态创建比较器:

std::stable_sort( array_begin, array_end, compare_by_bar );
wrgly_comparator wc;
std::stable_sort( array_begin, array_end, wc );

编辑:根据您的扩​​展问题,这里有一些提示:

std::stable_sort( array_begin, array_end, wrgly_comparator() ); 将在上创建一个动态数组。在C ++中,没有垃圾收集,你负责自己清理堆(在这种情况下通过调用sortContainer * sortList = new sortContiner [length];)。对于新手而言,这是非常难以做到的,即使是经验丰富的程序员也容易出错。你想要的是一个非常好的机会是自动数组:堆栈上的delete[] sortList;

标识符sortContainer sortList[length];告诉我该东西是一个容器。但是,它是要放入容器的物品的类型。选择标识符要小心。正确的命名在可读和可维护的代码方面有很长的路要走。

答案 1 :(得分:4)

您可以将对象放在容器中(例如,std :: vector)并编写一个仿函数并在stable_sort中使用它。

class Functor
{
    public:
        bool operator() (const Data& info1, const Data& info2)
        {
            return info1.AnyMemberOfData>info2.AnyMemberOfData;
        }
};

std::stable_sort(aVector.begin(), aVector.end(),functor);

修改: 使用数组(建议使用@sbi和@ wrang-wrang):

Data anArray[10];
//Fill anArray
std::stable_sort(anArray, anArray + 10,functor);

或者为您的班级写operator <并直接致电stable_sort

答案 2 :(得分:2)

以下是stable_sort()的声明:


template <class RandomAccessIterator>
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class StrictWeakOrdering>
void stable_sort(RandomAccessIterator first, RandomAccessIterator last, 
                 StrictWeakOrdering comp);

您必须使用第二个重载并为您提供自己的比较函数。一些事情:


class obj; // your type
struct obj_cmp
{
  bool operator()( const obj& lhs, const obj& rhs ) const
  {
     return lhs.member_ < rhs.member_;
  } 
};

它也可以是免费功能 - 您可以应用()的任何内容,例如:


bool obj_cmp_func( const obj& lhs, const obj& rhs )
{
  return lhs.member_ < rhs.member_;
} 

然后你的排序语句将是:


obj array[X]; // X is a compile-time constant
// populate array
std::stable_sort( array, array + X, obj_cmp());
// or with the function
std::stable_sort( array, array + X, obj_cmp_func );

请注意,您的类型的对象必须可以自由复制。 查看here了解详情。

答案 3 :(得分:1)

您必须编写自己的谓词并将其传递给标准算法。

答案 4 :(得分:1)

作为其他答案的补充:可以使用boost(或tr1)bind动态创建谓词。例如,要按“关键”成员排序:

std::stable_sort(sortList, sortList + length,
  boost::bind(&sortContiner::key, _1) < boost::bind(&sortContiner::key, _2)
);

答案 5 :(得分:1)

我看到已经有几个解决方案了,但是因为我已经输入了我的,所以无论如何我想发布它。这是一个有点工作的解决方案,可以给你一个想法:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib> 
using namespace std;    //i know :-/


//A very useless class
class myClass{          
private:
  int value;
public:
  myClass(int val){value = val;}
  int getValue(){return value;}
};

//a function which defines how to compare my objects
bool myComparsion (myClass m ,myClass n)
{
    return (m.getValue()<n.getValue());
}

int main(){

  vector<myClass> myvector;
  vector<myClass>::iterator it;

  //Filling up the vector with my objects which are initialized with random numbers
  for (int n=0;n<10;++n)
    myvector.push_back(*(new myClass(rand()%100)));

  //looking at my vector 
  cout<<"Before:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    cout<< " "<<it->getValue();
  cout << endl;     

  //sorting the vector and looking again      
  stable_sort (myvector.begin(), myvector.end(), myComparsion);    //this is where the magic happens
  cout<<"After:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    cout << " " << it->getValue();
  cout << endl;

  //...

  }

输出应该是这样的

Before: 83 86 77 15 93 35 86 92 49 21
After: 15 21 35 49 77 83 86 86 92 93

答案 6 :(得分:0)

你可以这样:代码是自我解释的:

class A
{
public:
    A() : m_a(0), m_b(0)
    {
    }
    void setA(int n)
    {
        m_a = n;
    }
    void setB(int n)
    {
        m_b = n;
    }

    int getA() const
    {
        return m_a;
    }


    int getB() const
    {
        return m_b;
    }


private:
    int m_a;
    int m_b;
};

bool compareA(const A& first, const A& second)
{
    return first.getA() < second.getA();
}

bool compareB(const A& first, const A& second)
{
    return first.getB() < second.getB();
}


int _tmain(int argc, _TCHAR* argv[])
{
    A a[10];
    for(int i = 10; i >= 0; --i)
    {
        a[i].setA(i);
        a[i].setB(i);
    }

    //Sort on variable m_a
    std::stable_sort(a, a + 10, compareA);

    //Sort on variable m_b
    std::stable_sort(a, a + 10, compareB);
}