对具有 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 个元素按升序排列最低(就地算法)

分治策略合并多个排序数组

在 n 个元素的数组中,首先对 n-(root)n 个元素进行排序,我们要对数组进行排序

合并 K 个排序数组/向量的复杂性

TopK (MinK) 实现

寻找数组中的第K大的元素,多种解法以及分析