颠倒某种顺序

Reversing the order of a sort

本文关键字:顺序      更新时间:2023-10-16

你好,我有一个与大学课程表有关的程序,它有几个排序函数,我们将处理升序gpa函数和降序gpa函数。

这是下降功能,功能正常:

void classSchedule::downGPA(classSchedule schedule[], int& numElems)
{
    classSchedule temp;
    int end;
    for (end = numElems - 1; end >= 0; end--)
    {
        for (int counter = 0; counter < end; counter++)
        {
            if (schedule[counter].classNumber == 000)
                counter++;
           if (schedule[counter].currentGPA < schedule[counter + 1].currentGPA)
           {
              temp = schedule[counter];
              schedule[counter] = schedule[counter + 1];
              schedule[counter + 1] = temp;
           }
       }
    }
    schedule->outputToConsole(schedule, numElems);
}

这是一个升序函数,由于某种原因,它什么也不显示:

void classSchedule::upGPA(classSchedule schedule[], int& numElems)
{
    classSchedule temp;
    int end;
    for (end = numElems - 1; end >= 0; end--)
    {
        for (int counter = 0; counter < end; counter++)
         {
            if (schedule[counter].classNumber == 000)
                counter++;
           if (schedule[counter].currentGPA > schedule[counter + 1].currentGPA)
           {
              temp = schedule[counter];
              schedule[counter] = schedule[counter + 1];
              schedule[counter + 1] = temp;
           }
       }
    }
    schedule->outputToConsole(schedule, numElems);
}

我更改了标志,但它什么都不显示,有人明白为什么吗?

编辑:

根据要求,输出功能

void classSchedule::outputToConsole(classSchedule currentSchedule[], int numElems)
{
    int i;
    cout << endl << "Dept" << "t" << "Class Numbert" "Credit Hours" << "t" << "Name"
         << "t" << "Room Number" << "tGPA"
         << endl << "----" << "t------------" << "t-------------   ----"
         << "t-----------" << "t---";
    for (i = 0; i < numElems; i++)
    {
        if (currentSchedule[i].displayOrNot == "FALSE")
            i++;
        if(currentSchedule[i].currentGPA == -1)
        {
            break;
        }
        cout << endl << currentSchedule[i].classDepartment << "         " << currentSchedule[i].classNumber << "    t"
             << "      " << currentSchedule[i].creditHours << "    t"
             << currentSchedule[i].teacherLastName << " " << currentSchedule[i].teacherFirstName
             << "t" << currentSchedule[i].roomWingAndNumber << "t" <<      currentSchedule[i].currentGPA;
    }
}

您的排序函数有几个问题:

  • 您的循环条件是counter < end,并且您使用[counter+1]作为数组索引,您将在第一次迭代时超出数组边界,建议将条件更改为counter < end -1
  • 代码if (schedule[counter].classNumber == 000)很危险,不清楚为什么需要它。可能是为了避免以前的错误

Coolprit似乎是这个代码:

if(currentSchedule[i].currentGPA == -1)
{
    break;
}

当你按降序排序时,记录会一直到最后,而且效果很好。但当你按升序排序时,记录就开始了,你就中断了循环。如果您想跳过GPA-1的记录,请将该代码中的break替换为continue

这里有一个小助手,可以让按某些派生值排序变得简单:

template<class F>
struct order_by_t {
  F f;
  template<class Lhs, class Rhs>
  bool operator()( Lhs const& lhs, Rhs const& rhs ) const {
    return f(lhs) < f(rhs);
  }
};
template<class F>
order_by_t< F > order_by( F f ) { return {std::move(f)}; }

调用order_by( function ),它返回一个函数对象,该对象接受值,并根据函数返回的值对值进行排序。

所以order_by( function )返回一个函数对象,它包含两个内容,并根据function告诉的顺序,告诉左一个是否比右一个"少"。

这是有用的,因为C++的标准库可以通过对函数对象进行排序来传递,并使用它们有很多原因。

这个助手使编写upGPA变得很短:

void classSchedule::upGPA(classSchedule schedule[], int numElems) {
  classSchedule* start = &schedule[0];
  classSchedule* finish = start+numElems;
  std::sort( start, finish,
    order_by( [](classSchedule const& s){return s.currentGPA;} )
  );
}

order_by( [](classSchedule const& s){return s.currentGPA;} )是魔法发生的地方。

我将展开它。更简单的书写方式是:

[](classSchedule const& lhs, classSchedule const& rhs){
  return lhs.currentGPA < rhs.currentGPA;
}

但我喜欢我的方式。

order_by接受一个参数的函数,并构建一个排序(<的替换)。

它接受A->B类型的函数(读作"a类型的元素到B类型的元素"),以便对B进行排序(支持<),并生成(A,A)->bool类型的函数,该函数是对A s的排序。它通过获取每个参数,将其映射到A->B映射,然后比较B s来实现这一点。

因此order_by属于(A->B) -> (A,A) -> bool类型,它返回基于A->B函数的排序。

我发现这种从类型到顺序的投影非常有用。在这种情况下,这可能有些过头了。


downGPA的一个简单实现——排序,然后反转:

void classSchedule::downGPA(classSchedule schedule[], int numElems) {
  upGPA(schedule, numElems);
  classSchedule* start = &schedule[0];
  classSchedule* finish = start+numElems;
  std::reverse( start, finish );
}

相反,您可以使用反向迭代器,或者使用否定的order by,或者其他什么。但以上内容很简单,而且不太容易出错。

函数upGPAdownGPA不应该是outputToConsole。换一步做。打印是一个不同于按向上或向下顺序重新排序的问题。

上面使用的是C++11。对于gcc或clang,您可能需要传递一个标志来启用支持。

如果你缺少C++11,这将起作用:

template<class F>
struct order_by_t {
  F f;
  order_by_t(F in):f(in) {}
  order_by_t(order_by_t const& o):f(o.f) {}
  template<class Lhs, class Rhs>
  bool operator()( Lhs const& lhs, Rhs const& rhs ) const {
    return f(lhs) < f(rhs);
  }
};
template<class F>
order_by_t< F > order_by( F f ) { return f; }
int getCurrentGPA( classSchedule const& s ) {
  return s.currentGPA;
}

然后:

void classSchedule::upGPA(classSchedule schedule[], int numElems) {
  classSchedule* start = &schedule[0];
  classSchedule* finish = start+numElems;
  std::sort( start, finish,
    order_by( getCurrentGPA )
  );
}

应该起作用。

甚至更容易:

bool orderByCurrentGPA( classSchedule const& lhs, classSchedule const& rhs ) {
  return lhs.currentGPA < rhs.currentGPA;
}
void classSchedule::upGPA(classSchedule schedule[], int numElems) {
  classSchedule* start = &schedule[0];
  classSchedule* finish = start+numElems;
  std::sort( start, finish,
    orderByCurrentGPA
  );
}

它做同样的事情。(此处删除了order_by)。