颠倒某种顺序
Reversing the order of a sort
你好,我有一个与大学课程表有关的程序,它有几个排序函数,我们将处理升序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,或者其他什么。但以上内容很简单,而且不太容易出错。
函数upGPA
和downGPA
不应该是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
)。
- CMake-按正确顺序将项目与C运行时对象文件链接
- 函数调用中参数的顺序重要吗
- 为什么不;名字在地图上是按顺序排列的吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 数到第n个楼梯的路(顺序无关紧要)
- 优先顺序:智能指针和类析构函数
- 在循环中按顺序遍历成员变量
- 独立读取-修改-写入顺序
- QML按钮点击功能执行顺序
- C++中数据类型修饰符的顺序
- 当比特(而不是字节)的顺序至关重要时的持久性
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 通过选项卡的文本设置QTabWidget顺序
- c++11评估顺序(未定义的行为)
- 如何在C++中递归地按相反顺序打印集合
- 给定顺序中的事件处理
- 具有包含其他对象的类的对象创建顺序
- 如何通过替换顺序代码的while循环来添加OpenMP for循环
- 遍历顺序由 std::文件系统directory_iterator给出
- 检查 2 棵树是否具有相同的顺序