C++ 对于较大的输入大小,按0到100之间的键对对象进行排序的高效算法
我有以下代表学生信息的课程:C++ 对于较大的输入大小,按0到100之间的键对对象进行排序的高效算法,c++,algorithm,sorting,C++,Algorithm,Sorting,我有以下代表学生信息的课程: struct Student { std::string name; int id = 0; short rank = 0; }; “评分”字段可以是0到100之间的任意数字。 我需要实现以下按降序排列学生的功能: void fast_sort(std::vector<Student>& students) { // TODO: } void快速排序(std::vector和students) { //待办事项:
struct Student
{
std::string name;
int id = 0;
short rank = 0;
};
“评分”字段可以是0
到100
之间的任意数字。
我需要实现以下按降序排列学生的功能:
void fast_sort(std::vector<Student>& students)
{
// TODO:
}
void快速排序(std::vector和students)
{
//待办事项:
}
我能在适当的地方做这种事吗?对于大尺寸输入,最有效的方法是什么
我已经试着计算每个等级的学生人数:
std::map<short, int> counter;
for(size_t i = 0; i < students.size(); ++i)
{
short rank = students[i].rank;
++counter[rank];
}
std::map计数器;
对于(size_t i=0;i
现在,我正在考虑如何在不使用额外的
std::vector
的情况下将学生放在正确的位置,std::sort
可能对您有用,因为它允许使用用户定义的比较函数,如以下示例所示:
//排序算法示例
#include//std::sort
#include//std::vector
#包括“Student.h”//您学生的班级标题
bool-myfunction(constudent&x,constudent&y){
return(x.getRating()您几乎自己解决了这个问题,对计数代码做了一点更改
(完全未经测试的代码)
std::map计数器;
对于(size_t i=0;i
到
std::数组计数器;
对于(size_t i=0;i
其中values是连续不同值0..values-1的数量
然后使用计数排序(基数排序的基础)< /P>
std::array pos={0};
std::部分和(counter.begin(),std::prev(counter.end()),std::next(pos.begin());
现在你有了每个等级的起点
std::向量螺柱;
对于(int i=螺柱.size();i<螺柱.end();++i){
int=pos[studs[i].rank];
while(通缉!=i){
pos[studs[i].秩]++;
交换(螺柱[i],螺柱[需要]);
通缉犯=职位[钉[i].等级];
}
}
计数排序
统计每个级别的学生人数
使用累积计数查找每个级别的第一个学生的索引
将学生放在第一个可用的排名索引中
这三个步骤中的每一步都具有复杂性O(n+k),其中n是学生数量,k是等级数量
我将展示一个有10名学生的例子,排名从0到2,而不是从0到100
# define NBSTUDENTS 10
# define NBRANKS 3
struct Student students[NBSTUDENTS] =
{("Alice", 0), ("Bob", 2), ("Charlie", 1), ("Daenerys", 1), ("Eleonore", 2),
("Farouk", 1), ("Gabriel", 0), ("Hector", 1), ("Iris", 2), ("Julien", 2)};
计算每个等级的学生人数
使用累积计数查找每个级别的第一个学生的索引
您可以使用获取累积计数;请参阅
将学生放在第一个可用的排名索引中
struct Student sorted_students[NBSTUDENTS]={}
for(自动学生=学生.begin();学生<学生.end();++student)
{
已排序的学生[可用的学生索引[学生->排名]]=*学生;
可用_索引[学生->排名]++;
}
std::sort
std::sort
的复杂度是O(n log(n))。上面的计数排序的复杂度是O(n+k)。这些O()符号隐藏了一个常数;您可以预期经过良好优化的std::sort
的常数比自定义实现的排序小得多。当n趋于无穷大时,log(n)也趋于无穷大。但是对数增长非常缓慢。你的大尺寸输入有多大?我假设你的学生不到一百万。1000000的二进制对数是20。如果我们假设n<1000000,那么n log(n)<20 n.我们的自定义计数排序真的比std::sort
快吗?计数排序..你不允许使用std::sort?计数排序。如果评级
(显然,又称为等级
),你就是在攻击自己的脚效率。)域实际上是1..100。如果没有受限制的域(当然不是那么小的域),映射将更有意义,而且此时std::sort
将是您的最佳选择。请在问题中澄清,您正在寻找比std::sort
更好的映射(因为它是高效的)注意,即使aO(N)
对于相当小的输入大小,排序不一定比std::sort
快。您是否真的尝试过std::sort
,并且有证据表明它花费了太多的时间?您知道,现在您得到的答案对您提出的问题来说很好,但对您真正想提出的问题来说却不是;)这个问题并不清楚,但OP正在寻找比std::sort
更好的方法。注意std::sort
在一般情况下非常有效,但是当输入范围有限时,就会有复杂度更低的算法可用。无论如何,我投了你一票,因为std::sort
是有效的;)我想一想这样使用std::partial_sum
会得到一个偏移结果;也就是说,它会将{2,4,3,3}
转换为{2,6,9,12}
,但是你想要的是{0,2,6,9}
@stef是的,这是正确的,我马上就会找到正确的代码。
int count_per_rank[NBRANKS] = {2, 4, 4};
int available_index[NBRANKS] = {0, 0+2, 0+2+4};