Для ясности, это домашнее задание. Я не прошу кого-нибудь сделать это за меня, я просто застрял на небольшой части этого.

Меня просят реализовать сортировку слиянием, но каждый новый массив, который я создаю, должен быть помещен в стек указателей. В приведенном ниже коде я пытаюсь рекурсивно разделить массив, а затем объединить их вместе. Мой стек называется ptrs. Функция merge () принимает два отсортированных массива и их размеры.

template <typename T>
T* MergeSort<T>::mergeSort(T arr[], int size) {

    int size1 = (int)size/2;
    int size2 = size - size1;

    //I'll have a base case to cover the arrays of size 1 or 2

    ptrs.push(new T[size1]);
    for(int i = 0; i < size1; i++) {
        ptrs.top()[i] = arr[i];
    }

    ptrs.push(new T[size2]);
    for(int i = 0; i < size2; i++) {
        ptrs.top()[i] = arr[i + size1];
    }

    return merge(mergeSort(TODO, size1), mergeSort(ptrs.top(), size2), size1, size2);

Моя проблема отмечена моим TODO. Как я могу получить доступ к первому массиву, если второй теперь находится на вершине стека?

0
user3448821 24 Мар 2014 в 17:43
Какой тип ptrs?
 – 
sp2danny
24 Мар 2014 в 17:50
Ptrs - это стек массивов типа T. В своих тестах я использовал двойники. И стек берется из std :: stack.
 – 
user3448821
24 Мар 2014 в 17:56
Stack - плохой выбор контейнера, могу я предложить deque? При использовании двухсторонней очереди push становится push_back, pop становится pop_back, top становится back, а доступ ко второму последнему элементу можно получить с помощью ptrs [ptrs.size () - 2]
 – 
sp2danny
24 Мар 2014 в 18:03
Хм. Похоже, это могло сработать. К сожалению, назначение ограничено использованием стека. Возможно, мой код выше просто использует неправильный подход?
 – 
user3448821
24 Мар 2014 в 18:54
Я только что увидел этот комментарий после того, как написал свой ответ. Но для меня использование стека не имеет смысла. Интерфейс стека предназначен для просмотра или извлечения только верхнего элемента. Вы можете просмотреть вторую только в том случае, если выберете первую. Но потом вы начинаете понимать, что вам не нужен стек, а нужны только два предмета.
 – 
iavr
24 Мар 2014 в 19:02

1 ответ

Лучший ответ

Зачем вообще нужен стек? Поскольку вы выделяете два новых массива и копируете две части входного массива, вы можете напрямую выполнять рекурсию по ним:

T* left = new T[size1];
for(int i = 0; i < size1; i++) //...

T* right = new T[size2];
for(int i = 0; i < size2; i++) /...

T* left_sorted  = mergeSort(left,  size1);
T* right_sorted = mergeSort(right, size2);

Затем слейте, стараясь освободить:

delete[] left;
delete[] right;

T* merged = merge(left_sorted, right_sorted, size1, size2);

delete[] left_sorted;
delete[] right_sorted;

return merged;

Если это разрешено назначением, я настоятельно рекомендую использовать std::vector вместо простых массивов + размеров. Вы также можете рассмотреть возможность слияния на месте чтобы избежать всех этих распределений.

0
Community 23 Май 2017 в 13:26
Хотя по-вашему это не то, как мне разрешили, спасибо за рабочий ответ. Это привело меня к моему решению, которое заключалось в том, чтобы создать указатели на массивы и использовать их в обычном режиме, но не забудьте нажать все, что я "создал", прежде чем покинуть метод. Затем я позволяю деструктору позаботиться о моем стеке.
 – 
user3448821
26 Мар 2014 в 06:40
Надеюсь, у вашего инструктора для этого есть веские причины :-)
 – 
iavr
26 Мар 2014 в 06:44