对具有 k 个已排序部分的 n 个元素的数组进行排序
Posted
技术标签:
【中文标题】对具有 k 个已排序部分的 n 个元素的数组进行排序【英文标题】:Sort array of n elements which has k sorted sections 【发布时间】:2020-04-22 22:27:30 【问题描述】:如第二张图片所示,对按节排序的数组进行排序的最佳方法是什么?
问题是使用Message Passing Interface 执行快速排序。解决方案是对使用MPI_Scatter()
获得的数组部分执行快速排序,然后加入排序的
使用MPI_Gather()
.
问题是数组作为一个整体是未排序的,但它的部分是。
类似于this solution 合并子部分似乎是对数组进行排序的最佳方式,但考虑到子数组已经在一个数组中,其他排序算法可能会更好。
排序函数的输入是数组,它的长度和同等排序的子部分的数量。
签名看起来像int* sort(int* array, int length, int sections);
sections
参数可以是 1 到 25 之间的任意值。length
参数值大于 0、sections
的倍数且小于 2^32。
这是我目前使用的:
int* merge(int* input, int length, int sections)
int* sub_sections_indices = new int[sections];
int* result = new int[length];
int section_size = length / sections;
for (int i = 0; i < sections; i++) //initialisation
sub_sections_indices[i] = 0;
int min, min_index, current_index;
for (int i = 0; i < length; i++) //merging
min_index = 0;
min = INT_MAX;
for (int j = 0; j < sections; j++)
if (sub_sections_indices[j] < section_size)
current_index = j * section_size + sub_sections_indices[j];
if (input[current_index] < min)
min = input[current_index];
min_index = j;
sub_sections_indices[min_index]++;
result[i] = min;
return result;
【问题讨论】:
数组的典型大小是多少?它有多少个部分?您是否尝试过实现几种算法并进行比较? “最佳”在什么意义上?最容易编写和维护/作为库函数可用?还有什么? 合并排序而不排序? @DragoșCirca,知道它大于零/一并没有真正的帮助。您很可能需要不同的算法来对 34 和 34'000 个元素进行排序。 我读到Smoothsort 如果输入数组有排序部分,则接近 O(n)。 【参考方案1】:性能优化
我认为this answer 维护每个子数组的最小项的最小堆是处理任意输入的最佳方式。但是,对于较小的 k
值,请考虑介于 10 到 100 之间,实现 the question you linked to 中给出的更简单的解决方案可能会更快;虽然每个步骤的最小堆维护时间仅为 O(log n),但对于较小的 n 值,它可能比来自简单解决方案的简单线性扫描具有更高的开销。
所有这些解决方案都会创建输入的副本,并保持 O(k) 状态。
空间优化
我看到的唯一节省空间的方法是就地排序。这将是上述算法的一个问题。就地算法将有两个交换元素,但任何交换都可能破坏每个子数组排序的属性,除非交换对中较大的一个被重新排序到它正在交换的子数组中,这将导致 O(n²) 算法。因此,如果您确实需要节省内存,我认为必须使用常规的就地排序算法,这违背了您的目的。
【讨论】:
以上是关于对具有 k 个已排序部分的 n 个元素的数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章
对一个 n 元素数组进行排序,使前 k 个元素按升序排列最低(就地算法)