我将其包括在内只是因为您应该知道如何排序此列表的替代方法。Lol4t0 已经谈到了拥有一个复制成本高昂的比较器的可怕之处(而且您将很难拥有一个比您的原始实现更昂贵的比较器)。
当std::sort
给定一个尽可能简单的比较器时,算法效果最好,尽可能多地内联它的实现。理想情况下,您可以像这样实现比较器运算符功能:
struct cmpObjects
{
bool operator ()(const Object& left, const Object& right) const
{
return (left compared to right somehow);
}
}
首先注意 const 引用的使用。您唯一应该考虑不这样做的情况是您的基础数据是本机内在类型(例如int
,char
等)。在这些情况下,按值传递实际上更快。但在这种情况下,您的学生记录通过引用访问无疑会更有效(无需复制)。
关于您的特定任务,您的任务会稍微复杂一些,因为您的排序标准是基于选择的。如果你想最大化排序速度,你最好为每个选择情况提供一个单一的、紧凑的、廉价的可复制比较器。然后,根据该选择使用适当的比较器,在调用之前std::sort
确定。
例如,如果您知道要按姓氏排序,则:
// compares last name
struct cmp_LName
{
bool operator ()(const studentType& left, const studentType& right) const
{
return left.lastName < right.lastName;
}
}
或者也许是名字,姓氏,例如:
// compares first name, then last name only if first name is identical.
struct cmp_FNameLName
{
bool operator ()(const studentType& left, const studentType& right) const
{
int res = left.firstName.compare(right.firstName);
return res < 0 || (res == 0 && left.lastName < right.lastName);
}
}
这使得您的构造函数的部分窥视sBinary
现在看起来像这样:
sBinary(const std::vector<studentType>& sList_, char choice)
: sList(sList_)
{
switch (choice)
{
case 'L':
case 'l':
std::sort(sList.begin(), sList.end(), cmp_LName());
break;
case 'R':
case 'r':
std::sort(sList.begin(), sList.end(), cmp_FNameLName());
break;
....
}
}
首先请注意,我们在实际调用之前选择了我们选择的比较技术std::sort
。当我们这样做时,我们清楚地定义了我们正在使用的自定义比较器中的确切标准,并且管理它的开销为零。
那么有什么取舍呢?您将需要四个比较器(cmp_LName、cmp_FName、cmp_FNameLName 和 cmp_LNameFName),根据您的传入选择触发要使用的比较器。但是,这样做的好处不容小觑:这将是根据选择对列表进行排序的最快方法。
附录:单个比较器
如果您完全赞同使用单个比较器的想法,那么请尽可能降低复制成本,并将排序条件中的选择隐藏在其中,const
以便为编译器提供清理代码的最佳机会。我在sBinary
下面包含了一个完整的扩展来展示如何做到这一点,但我强调,如果速度是您的主要关注点,这不是最佳选择。
class sBinary
{
// compare student based on fixed choice determine at construction.
struct cmp_student
{
const char choice;
cmp_student(char choice) : choice(choice) {};
bool operator()(const studentType& left, const studentType& right) const
{
switch (choice)
{
case 'F':
case 'f':
return left.firstName < right.firstName;
case 'L':
case 'l':
return left.lastName < right.lastName;
case 'R':
case 'r':
{
int res = left.firstName.compare(right.firstName);
return res < 0 || (res == 0 && left.lastName < right.lastName);
}
default:
{
int res = left.lastName.compare(right.lastName);
return res < 0 || (res == 0 && left.firstName < right.firstName);
}
}
}
};
public:
sBinary(const std::vector<studentType>& sList, char choice)
: sList(sList)
{
std::sort(sList.begin(), sList.end(), cmp_student(choice));
}
std::vector<studentType> sList;
};