Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 快速排序(n个数组应视为1,并根据需要重新映射值)_C++_C - Fatal编程技术网

C++ 快速排序(n个数组应视为1,并根据需要重新映射值)

C++ 快速排序(n个数组应视为1,并根据需要重新映射值),c++,c,C++,C,我有一个数组的链表(文章底部的struct) 每个数组可能有如下示例所示的值 Array1[] = {6,36,8,23}; Array2[] = {8,23,5,73}; Array3[] = {2,5,1,9}; 我需要对这些数组进行排序,以便所有3个数组都被视为1个大数组 我需要使用快速排序,以便它使用就地处理。。。我使用的是非常大的阵列,无法使用额外的内存 结果应该是这样的 Array1[] = {1,2,5,5}; Array2[] = {6,8,8,9}; Array3[] = {

我有一个数组的链表(文章底部的struct)

每个数组可能有如下示例所示的值

Array1[] = {6,36,8,23};
Array2[] = {8,23,5,73};
Array3[] = {2,5,1,9};
我需要对这些数组进行排序,以便所有3个数组都被视为1个大数组

我需要使用快速排序,以便它使用就地处理。。。我使用的是非常大的阵列,无法使用额外的内存

结果应该是这样的

Array1[] = {1,2,5,5};
Array2[] = {6,8,8,9};
Array3[] = {23,23,36,73};
目前我只能对每个数组单独排序。。。但这并不是我所需要的:(


如果可以确保在连续内存布局中依次声明
Array1、Array2和Array3
,则可以在
sort()
中给出
Array1
(第一个),并给出所有数组的组合大小

要检查连续对齐,可以使用以下技巧

template<size_t SIZE1, size_t SIZE2, size_t SIZE3>
bool Check(int (&a1)[SIZE1], int (&a2)[SIZE2], int (&a3)[SIZE3])
{
  return (&a3[SIZE3 - 1] - &a1[0]) == (SIZE1 + SIZE2 + SIZE3);
}

这是3个数组的示例,您可以根据需要制作。您可以根据您的机器传递数组1、2、3或数组3、2、1。

这并不难,更多的是接口问题,而不是算法问题

编写一个包装器容器,该容器提供一个用于访问成员和写入的接口(例如C++中的
运算符[]
),并在内部将
size\u t index
参数映射到正确的数组。虽然此包装器类需要每个数组的大小,但它能够正确映射索引

伪代码运算符[]的示例如下:

int& JointDatabase::operator[](size_t index) {
    // database is an iDatabase
    iSection *cur = database.First_Section;

    while (cur != database.Last_Section && index >= cur->Section_Count) {
        index -= cur->Section_Count;
        cur = cur->Next;
    }

    return cur->Section_Arr[index];
}

然后使用此包装类,就像在快速排序算法中使用普通容器一样。

仅在我的大脑中测试:

struct ArrayWrapper {
    int** arrays;
    int* running_sums;
    ArrayWrapper(int **arrays, int *arrays_length, int N) {
        running_sums = new int*[N+1];
        int sum = 0;
        for (int i = 0; i < N; i++) {
            running_sums[i+1] = sum;
            sum += arrays_length[i];
        }
    }
    int& operator[] (int index) {
        int array_start = binary search `running_sum` for the closest number to `index` (round down)
        return arrays[array_start][index - running_sums[array_start]]
    }
}

@所有人都在等待大师回答这个奇妙的问题。@Steve:在你的例子中,所有数组的元素数都相同。总是这样吗?还有,为什么需要使用快速排序?你的链表大吗?如果不大,你可以创建一个包含所有节点的数组(iSection)和此部分的所有数组的大小。使用此数组可以获得对集合中任何元素的O(1)访问时间,并且通过为其定义迭代器,可以像往常一样简单地使用快速排序和O(nlogn)平均值。如果这样做有效,并且您在技术部分遇到问题(为std::sort定义迭代器)我也可以澄清这一部分。我强烈建议您不要尝试使用多语言解决方案。单语言解决方案将更易于理解/修改,并且更为有效(因为它们可以针对每种语言使用特定的内容)取决于您拥有多少元素和多少组,以及您是否愿意临时分配更多内存(以及分配多少)最好做些别的事情,例如,对每个列表进行单独的快速排序,然后将列表合并到一起。接受的答案会起作用,但在某些情况下会产生糟糕的性能,例如,每个元素有一百万节。情况并非总是如此。@Steve,同意。我的回答是,如果你想在完成任务后再冒险一次数组非常大。数组太大,无法放入连续内存布局中。我认为这种方法行不通。好的……顺便问一下,您是否检查过一个接一个地声明它们?并使用上述函数检查它们是否对齐。这只是一个建议,如果您有时间:)这听起来是正确的方法,但是,我不知道怎么做。你能举个例子吗?如果数组大小可变(不相等),你会如何在恒定时间内编写这个运算符?@Mark B:考虑到内存限制,我认为O(1)有点乐观,不是吗@史蒂夫:给出了一些示例代码。示例代码的最坏情况复杂度为O(n),其中n是数组的数量。@nightcracker我只是观察到,如果函数不是常数时间,则排序本身开始接近多项式时间,并且对于OP所具有的大量元素,可能需要比预期更长的时间。这很可能是一个性能稳定且易于理解的解决方案。您可能希望缓存后面部分的累积开始索引,而不是每次遍历列表。但我不敢相信,对每个读写元素进行这种查找会比将一些逻辑编码到排序代码中或使用不同的排序策略更有效。OP希望有一个就地排序,我相信没有新的分配。-1,询问者特别提到了链表,这极大地改变了情况。
int& JointDatabase::operator[](size_t index) {
    // database is an iDatabase
    iSection *cur = database.First_Section;

    while (cur != database.Last_Section && index >= cur->Section_Count) {
        index -= cur->Section_Count;
        cur = cur->Next;
    }

    return cur->Section_Arr[index];
}
struct ArrayWrapper {
    int** arrays;
    int* running_sums;
    ArrayWrapper(int **arrays, int *arrays_length, int N) {
        running_sums = new int*[N+1];
        int sum = 0;
        for (int i = 0; i < N; i++) {
            running_sums[i+1] = sum;
            sum += arrays_length[i];
        }
    }
    int& operator[] (int index) {
        int array_start = binary search `running_sum` for the closest number to `index` (round down)
        return arrays[array_start][index - running_sums[array_start]]
    }
}
array1 = {...} 
array2 = {...}
...
arrayN = {...}

arrays = {array1, array2, ..., arrayN}
arrays_length = {array1_length, array2_length, ..., arrayN_length}

ArrayWrapper wrapper = new ArrayWrapper(arrays, arrays_length, N);
// wrapper then can be treated like normal array:
wrapper[10] = x;
x = wrapper[10];