Quicksort (n массивов следует рассматривать как 1 и значения переназначить по мере необходимости)
У меня есть связанный список массивов (структура внизу сообщения)
Каждый массив может иметь значения, подобные приведенному ниже примеру
Array1[] = {6,36,8,23};
Array2[] = {8,23,5,73};
Array3[] = {2,5,1,9};
Мне нужно отсортировать их так, чтобы все 3 массива обрабатывались как один большой массив...
Мне нужно использовать quicksort, чтобы он использовал обработку на месте... Я работаю с очень большими массивами и не могу позволить себе использовать дополнительную память.
Результат должен быть примерно таким
Array1[] = {1,2,5,5};
Array2[] = {6,8,8,9};
Array3[] = {23,23,36,73};
В настоящее время я могу сортировать каждый массив отдельно... но это не совсем то, что мне нужно: (
struct iSection {
unsigned long Section_Count; // Total # of points in this block of memory
int *Section_Arr; // Point cloud for current block of memory
struct iSection *Next; // Pointer to next section
} iSection;
struct iDatabase {
struct iSection *First_Section;
struct iSection *Last_Section;
} iDatabase;
Ответы
Ответ 1
Это не так сложно, скорее проблема сопряжения, а затем проблема с алгоритмикой.
Напишите контейнер-оболочку, предоставляющий интерфейс для доступа к элементам и записи (скажем operator[]
в С++), и внутренне он сопоставляет аргумент size_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];
}
Затем используйте этот класс-оболочку, поскольку вы должны использовать обычный контейнер в своем алгоритме Quicksort.
Ответ 2
Если вы можете убедиться, что Array1, Array2, and Array3
объявлены один за другим и в макете непрерывной памяти, вы можете дать Array1
(первый) в sort()
и дать объединенный размер всех массивов.
Чтобы проверить непрерывное выравнивание, вы можете использовать следующий трюк.
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);
}
Использование
bool aligned = Check(Array1, Array2, Array3);
Это пример для 3 массивов, вы можете сделать это в соответствии с вашими потребностями. И вы можете передать Array1,2,3 или Array3,2,1 в зависимости от вашей машины.
Ответ 3
Протестировано только в моем мозгу:
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];