2015-02-05 112 views
0

你好,我有我的程序,与大学课程时间表有关,它有一对夫妇排序功能,我们将处理升序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 Number\t" "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; 
    } 

} 
+5

你为什么要分类排序?使用'std :: sort'并停止它。另外,我认为我看到fencepost错误(读取数组末尾)。为什么'numElem'是一个非const的int&'?为什么在其循环之外创建'int end'?为什么'计数器'在代码中以一种疯狂的方式递增? – Yakk 2015-02-05 19:08:20

+1

@Yakk使用'std :: sort()''reverse_iterator'也可以解决问题。 – 2015-02-05 19:09:53

+0

无论你如何排序:如果你已经有升序列表:只需将其颠倒过来以降序排列。这样做比较简单,而且只需花费O(n) - 比任何基于比较的排序算法都要好。 – 5gon12eder 2015-02-05 19:10:10

回答

0

这里是使一些衍生价值容易整理一个小帮手:

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类型(它读作“给B类型的元素A型元件”),使得B是有序的(支持<)的函数,并产生(A,A)->bool类型的一个函数,它是上A排序秒。它通过获取每个参数来完成此操作,通过A->B映射映射它,然后比较B

因此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); 
} 

你也可以使用反向迭代器,或使用否定的订单通过,或什么的。但上面的内容很简单,而且不易出错。

功能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)。

+0

'order_by([](classSchedule const&s){return s.currentGPA;}'这是否会得到除模板部分以外的其余部分。明白模板是什么,但不确定你用那个functin做了什么 – user2311215 2015-02-05 19:33:58

+0

我试过了,它可以工作,但是有人可以向我解释为什么它有效吗 – user2311215 2015-02-05 19:48:22

+0

'order_by'返回一个函数对象 - 一个带有operator()的对象被重载。你可以像使用函数一样使用它,但它保存状态,在这种情况下,它保存在[](classSchedule const&s){return s.currentGPA;}'中传递的lambda闭包,它是*另一个*函数对象。 [](classSchedule const&s){return s.currentGPA;}'返回一个接受'classSchedule const&'的对象,并用'()'方括号调用时返回它的'currentGpa'参见C++中的getCurrentGPA函数, +03 section?它基本上是这样做的 – Yakk 2015-02-05 19:53:17

1

你有几个问题与你的排序功能:

  • 你的循环条件是counter < end并使用[计数器+ 1]数组的索引,你会走出数组边界上的第一次迭代,建议改变条件到counter < end -1
  • 代码if (schedule[counter].classNumber == 000)是危险的,不清楚你为什么需要它。大概是为了避免以前的错误

Coolprit似乎是这样的代码:

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

当你按降序排序该记录去年底,它工作正常。但是当你按升序排序时,记录正在开始,并且你打断了你的循环。如果您想跳过GPA -1的记录,请在该代码中将break替换为continue