查找计数排序的起始索引
Finding the beginning index for counting sort
int schoolToIndex(string school) {
if (school == "UCB") return 0;
if (school == "UCD") return 1;
if (school == "UCI") return 2;
if (school == "UCLA") return 3;
if (school == "UCM") return 4;
if (school == "UCSD") return 5;
if (school == "UCSF") return 6;
cerr << "Unknown school " << school << endl;
return -1;
}
void sortByGroupById2(Student students[], int len) {
int numberofschools = 7;
int counters[numberofschools];
for (int i = 0; i < numberofschools; i++) {
counters[i] = 0;
}
for (int i = 0; i < numberofschools; i++) {
counters[schoolToIndex(students[i].getSchool())]++;
}
Student *sortedArray = new Student[len];
for (int i = 0; i < len; i++) {
sortedArray[counters[schoolToIndex(students[i].getSchool())]] = students[i];
counters[schoolToIndex(students[i].getSchool())]++;
}
for (int i = 0; i < len; i++) {
students[i] = sortedArray[i];
}
}
int main() {
const int LEN = 350000;
// Rough timing
Student* uc2 = readStudentsFromFile("uc_students_sorted_by_id.txt", LEN);
time(&start);
sortByGroupById2(uc2, LEN);
time(&end);
cout << "Using counting sort it took " << difftime(end, start) << " seconds." << endl;
writeStudentsToFile(uc1, LEN, "uc_by_school_by_id1.txt");
writeStudentsToFile(uc2, LEN, "uc_by_school_by_id2.txt");
return 0;
}
我有问题的具体问题在代码中
sortedArray[counters[schoolToIndex(students[i].getSchool())]] = students[i],
我的起始指数sortedArray
学校的学生人数。我不确定该怎么做的是让开始指数是以前学校的累计学生人数。
例如,如果我想要加州大学洛杉矶分校的起始索引,我需要添加UCB和ucd和UCI的学生人数,以获得此存储桶的起始索引。
所以我的行动计划是让计数器数组来存储学生人数的组合值。例如,如果我的计数器数组将 [5, 10, 15, 20] 作为学生人数,我希望它将 [5, 15, 30, 50] 存储为我的 sortedArray 的起始索引数组。
有什么方法可以用于此吗?我使用递归吗?
计数排序的一部分是将counters[]
数组从简单的直方图转换为索引到sortedArray[]
的转换。
为此,您可以使用称为部分和的算法。
对于每个元素,使其等于所有先前元素加上该元素的总和。例如:
0 1 3 0 4 0 --> 0 1 4 4 7 7
(您可以手动执行此操作,也可以使用 <numeric>
中的 std::partial_sum()
函数。
现在,您可以使用索引将内容移动到输出中的最终位置。为了保持稳定,请从students[]
中的最后一个元素开始,然后在直方图输出索引数组中查找它。
从值中减去 1(修改输出索引(并将源元素复制到最终数组:
for (int i = len; i-->0; )
{
sortedArray[ --counters[ students[i].getSchool() ] ] = students[i];
}
希望这有帮助。
对于起始索引数组,您可能希望得到的是 [0,5,15,30](请注意,不使用最后一个计数 20(。您可以使计数器 1 个元素更大来执行此操作,也可以使用两个计数变量。计数需要扫描所有学生,这是镜头,而不仅仅是学校数量。
使用两个临时变量,总和 CNT:
for (int i = 0; i < len; i++) {
counters[schoolToIndex(students[i].getSchool())]++;
}
sum = 0;
for (int i = 0; i < numberofschools; i++) {
cnt = counters[schoolToIndex(students[i].getSchool())];
counters[schoolToIndex(students[i].getSchool())] = sum;
sum += cnt;
}
如果将计数器放大一个:
int counters[numberofschools+1];
// ...
for (int i = 0; i <= numberofschools; i++) {
counters[i] = 0;
}
for (int i = 0; i < len; i++) {
// note the [1 + ...] only used here, not later in the actual sort
counters[1+schoolToIndex(students[i].getSchool())]++;
}
for (int i = 2; i <= numberofschools; i++) {
counters[schoolToIndex(students[i ].getSchool())] +=
counters[schoolToIndex(students[i-1].getSchool())];
}
在任何一种情况下,都不会使用最后一个计数/索引,因为这是数据末尾的索引,并且数组将用作起始索引数组。
排序将从第一个元素开始稳定,到最后一个元素结束。我看到了另一种答案,即从最后一个元素开始向后遍历到第一个元素的替代方法,该方法也很稳定,但不像从第一个元素开始那样缓存友好。
- 如何根据排序索引的向量对 std::index 集进行排序?
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- 排序谓词没有传递对索引对象的引用?
- 如何在对向量排序后更改索引值?c++
- 在不进行排序的情况下查找数组中n个最小值的索引
- 如何解决索引和排序问题
- 使用C++中的排序对索引进行排序
- 如何使equal_range迭代器在 Boost 多索引中按不同的索引排序?
- 为什么我的代码没有对数组中第二个索引上的数据进行排序?
- 根据某些条件对索引子集进行排序
- 如果我将索引变量更改为零,并且合并函数中的k = 0,则获得合并排序的错误结果
- 如何对同一数组索引下的结构成员进行排序?
- 如何在保留原始索引的同时对向量的向量进行排序
- 如何不对数组的元素进行排序,而是对数组的索引进行排序?
- C++ 将多索引提升为 LRU 缓存的索引排序问题
- C++ std::lower_bound() 函数来查找索引排序向量的插入点
- boost多索引排序索引中插入的匹配函数
- 使用变量索引排序向量的向量
- 使用索引排序,但保持索引顺序
- 比较c++中排序函数的索引排序