如何使InsertationSort更快?

时间:2018-10-15 13:02:48

标签: c++ algorithm sorting object children

所以我有这个代码

printf

我有一个Child对象数组,我想按不同的字段对其进行排序,这取决于从stdin提取的ordering_chars数组。例如,如果ordering_chars为['a','d','m'],则意味着avg相等,则按距离排序,如果也相等,则按月份排序。该代码正在运行,但是处理大数据时速度很慢。您有一些解决方案可以使这项工作更有效率吗?我当时在考虑使用函数指针,但不确定如何确切地做到这一点。

PS。我必须使用InsertionSort,它不能是任何其他排序方式,也不能使用STL,这是因为此代码是为了进行在线评审(我不参加任何形式的竞赛,只是为了测试自己和学习一些东西。

2 个答案:

答案 0 :(得分:3)

这太慢了,因为您正在为Child变量制作大量副本。

更改 Request method: POST Request URI: https://testurl.com/atRegId Proxy: <none> Request params: <none> Query params: <none> Form params: <none> Path params: <none> Headers: Authorization=Bearer sdweqweweqwewe Accept=*/* Content-Type=application/json; charset=UTF-8 Cookies: <none> Multiparts: <none> Body: {"id": "4KJ34K324K3K4K3K","response": "json data"}" ,以引用方式引用Child&而不是值。 并更改Child tmp。将其放入循环中,并同时更改其引用。

还可以根据您的建议优化比较功能。 对于每种后一种情况,使3个lambda都返回一个int -1、0、1(小于,等于或更大):

Child::isSmallerThan

在InsertionSort中,您可以创建比较函数:

auto get_comparator(char c) {
  if (c == 'a')
   return +[] (Child& x, Child& y) { /* compare x.avg and y.avg */ }
  if (c == 'd') 
   return +[] (Child& x, Child& y) { ... }
  if (c == 'm')
   return +[] (Child& x, Child& y) { ... }
}

并用那个来比较孩子们

答案 1 :(得分:0)

一旦找到正确的商品位置,最后只进行一次即可避免很多小额掉期。在代码中(请注意,未经测试-偏离一处的错误可能会看不见),

for(int j = 1; j < n; j++) {
   Child temp = array[j];
   int swaps = 0;
   for(int i = j-1; (i >= 0) && array[i].isSmallerThan(temp, ordering); i--) {
      swaps ++;
   }
   if (swaps) {
        // make space & place new element where it belongs
        // beware: this may be problematic for more complex classes
        memmove(array+i+2, array+i+1, swaps);
        array[i+1] = temp;
   }
}

另一个节省的资源将来自更快的比较功能。有关可能的实现,请参见Bob's answer。不使用lambda,我会争取

bool Child::isSmallerThan(const Child &o, char *ordering_chars) const {
    int m = month == o.month ? 0 : month < o.month ? 1 : -1;
    int d = distance == o.distance ? 0 : distance < o.distance ? 1 : -1;
    int a = avg == o.avg ? 0 : avg < o.avg ? 1 : -1;

    switch (ordering_chars[0]) {
      case 'a': a <<= 2; break;
      case 'd': d <<= 2; break;
      case 'm': m <<= 2; break;
    }
    switch (ordering_chars[1]) {
      case 'a': a <<= 1; break;
      case 'd': d <<= 1; break;
      case 'm': m <<= 1; break;
    }

    return a+d+m > 0;
}