简体   繁体   English

c ++排序自定义函数

[英]c++ sort custom function

I need to be able to pass in a variable by which to sort.我需要能够传入一个变量来进行排序。 I noticed that it only takes in the types that it will be sorting so I was wondering if it is possible to do something like that.我注意到它只接受将要排序的类型,所以我想知道是否有可能做这样的事情。

For example I need it to sort arrays each containing 3 integers by their 3rd int.例如,我需要它按第 3 个整数对每个包含 3 个整数的数组进行排序。 How would you make a function like that if you did not know in advance what value you would be sorting by?如果您事先不知道要按什么值排序,您将如何制作这样的函数?

You said "For example I need it to sort arrays each containing 3 integers by their 3rd int," and that you won't know which index (which column) is significant until run time.您说“例如,我需要它按第 3 个整数对每个包含 3 个整数的数组进行排序”,并且直到运行时您才会知道哪个索引(哪个列)是重要的。

If you are able to use C++11, it can be this simple:如果您能够使用 C++11,它可以很简单:

void mysort(vector<vector<int>>& v, int col)
{
    sort(v.begin(), v.end(),
         [col](const vector<int>& a, const vector<int>& b) -> bool
               { return a[col] < b[col]; });
}

If you are restricted to C++98, you can do the same thing, but instead of a lambda, you must write a functor that takes the column as a constructor parameter:如果您仅限于 C++98,您可以做同样的事情,但您必须编写一个将列作为构造函数参数的函子,而不是 lambda:

class ColumnSort {
    int col_;
public:
    ColumnSort(int col): col_(col) { }
    bool operator()(const vector& a, const vector& b) const {
        return a[col_] < b[col_];
    }
};

void mysort(vector< vector<int> >& v, int col)
{
    sort(v.begin(), v.end(), ColumnSort(col));
}

Finally, if you want a multi-column sort, the functor would look like this, where cols is an ordered list of columns to sort on:最后,如果你想要一个多列排序,函子看起来像这样,其中cols是一个有序的列排序列表:

class ColumnSort {
    vector<int> cols_;
public:
    ColumnSort(const vector<int>& cols): cols_(cols) { }
    bool operator()(const vector<int>& a, const vector<int>& b) const {
      for (int i = 0; i < cols_.size(); ++i) {
        if (a[cols_[i]] == b[cols_[i]]) continue;
        return a[cols_[i]] < b[cols_[i]];
      }
      return false;
    }
};

You can use a custom comparator constructed with the information about your custom sort order.您可以使用根据您的自定义排序顺序的信息构建的自定义比较器。 You do it sort of like this.你这样做有点像这样。

// Normal sort, except the specified value always comes first
class LessThanWithPreferedValue {
    int n;
public:
    LessThanWithPreferedValue(int v) : n(v) {}

    boolean operator()( int a, int b ) const {
       if( a==n ) { return true ; }
       if( b==n ) { return false ; }
       return a<b;
    }
};

int main() {
  std::vector<int> v = { 2, 3, 4 , 6 ,8 };

  // Normal sort, but with 4 first
  std::sort(v.begin(), v.end(), LessThanWithPreferedValue(4) );
  // v = { 4, 2, 3, 6, 8}

  // Normal sort, but with 8 first
  std::sort(v.begin(), v.end(), LessThanWithPreferedValue(8) );
  // v = { 8, 2, 3, 4, 6}
}

Write a functor that takes arguments to determine how to sort.编写一个使用参数来确定如何排序的函子 Here's a simple example that takes an argument to switch between ascending and descending order:这是一个简单的例子,它使用一个参数在升序和降序之间切换:

template<typename T>
class ReversibleComparator {
    bool asc;
public:
    ReversibleComparator(bool asc) : asc(asc) {}
    // This function performs the comparison,
    // returning true if a should come before b.
    bool operator()(const T& a, const T& b) {
        if(asc) return a < b;
        else return b < a;
    }
};

Of course, you could have as many parameters to the constructor as you want (or multiple constructors) and make the logic as complicated as you want, though it'll be called a lot, so making it really complicated would probably not be a good idea.当然,您可以根据需要为构造函数设置尽可能多的参数(或多个构造函数)并使逻辑尽可能复杂,尽管它会被调用很多,因此让它变得非常复杂可能不是一个好主意。

An example of calling it:调用它的一个例子:

bool asc = true;
if(argc > 1 && argv[1] == string("-d"))
    asc = false;
std::sort(my_list.begin(), my_list.end(), ReversibleComparator(asc));

(Also, this example is a little contrived, since if what you want is to reverse the ordering, you can simply use rbegin() and rend() in place of begin() and end() respectively.) (另外,这个例子有点人为,因为如果你想要颠倒顺序,你可以简单地使用rbegin()rend()代替begin()end() 。)

Here I describe the C rtl qsort, but it is almost certainly almost the same as the c++ variant:这里我描述了 C rtl qsort,但几乎可以肯定它与 c++ 变体几乎相同:

The sort function takes as a parameter a "comparison function".排序函数将“比较函数”作为参数。 Each time the comparison function is called it is passed two parameters which are pointers to the two elements to compare.每次调用比较函数时,都会传递两个参数,这些参数是指向要比较的两个元素的指针。

After coercing the type of the parameters, you can then compare anything you want.强制参数类型后,您可以比较任何您想要的内容。 For example, if the elements contain some struct with an integer array and you want to compare the nth items in them where the program's first parameter tells which column, something like this will work:例如,如果元素包含一些具有整数数组的结构,并且您想比较其中程序的第一个参数告诉哪一列的第 n 个项目,则如下所示:

int which_index = (int) strtol (argv[1]);

int comparefunc (void *item1, void *item2)
{
     widget *w1, *w2;
     w1 = (widget *) item1;
     w2 = (widget *) item2;

     return w1->myarray[which_index] - w2->myarray[which_index];
}


widget table[1000];
qsort (table, n, sizeof table[0], comparefunc);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM