Моя функция sort
иногда выдает нарушение доступа при чтении местоположения, а иногда это работает.
Я не могу найти связь между тем, когда это происходит, а когда нет.
Функция сортировки собирается отсортировать элементы в arr
с n
предметы с помощью d-max-heap. Это должно использовать addToHeap
а также removeFromHeap
,
template <typename Comparable>
void sort(Comparable arr[], int n, int d){
Comparable* tempArray = new Comparable[n];
Comparable* removeArr = new Comparable[n];
makeCopyOfArray(arr, removeArr, n);
buildHeap(removeArr, n, d);
printArray(removeArr, n);
int x = 0;
for (int i = n; i > 0; i--) {
Comparable temp = removeFromHeap(removeArr, i, d);
addToHeap(tempArray, temp, x, d);
x++;
printArray(tempArray, x);
}
for (int y = 0; y < n; y++){
arr[y] = tempArray[y];
}
printArray(arr, n);
}
template <typename Comparable>
void addToHeap(Comparable heap[], Comparable elem, int n, int d){
int parentIndex, tmp, nodeIndex;
if (n == SIZE_OF_ARRAY){
throw "Exception at addToHeap, full array";
}heap[n] = elem;
n++;nodeIndex = n - 1;
parentIndex = (n - 1) / d;while (nodeIndex != 0) {
if (heap[parentIndex] < heap[nodeIndex]) {
tmp = heap[parentIndex];
heap[parentIndex] = heap[nodeIndex];
heap[nodeIndex] = tmp;
}
nodeIndex = parentIndex;
parentIndex = (nodeIndex - 1) / d;
}
}template <typename T>
void printArray(T arr[], int n){
for (int x = 0; x < n; x++){
cout << arr[x] << " ";
}
cout << endl;
}
template <typename Comparable>
Comparable removeFromHeap(Comparable heap[], int n, int d){
Comparable root = heap[0];
heap[0] = heap[n - 1];
heap[n - 1] = NULL;rootHeapyfiDown(heap, n - 1, d);return root;
}template <typename Comparable>
void rootHeapyfiDown(Comparable heap[], int n, int d){
int x = 1,z=0,y=0, rootIndex=0, indexOfLargestChild=NULL, largestChild=0;
Comparable root = heap[0], temp=NULL;
bool rootLarger = false;do{
indexOfLargestChild = (rootIndex*d) + 1;for (y = 1; y < d; y++){
largestChild = heap[indexOfLargestChild];
if (largestChild < heap[(rootIndex*d) + 1+y]){
indexOfLargestChild = (rootIndex*d) + 1+y;
}
}if (heap[rootIndex] < heap[indexOfLargestChild]){
temp = heap[rootIndex];
heap[rootIndex] = heap[indexOfLargestChild];
heap[indexOfLargestChild] = temp;
rootIndex = indexOfLargestChild;
}
else
rootLarger = true;} while (rootLarger == false);
}
template <typename Comparable>
int posOfMaxChild(Comparable heap[], int thePos, int n, int d){
int x = 0,child;
child = thePos*d;
while (x < d){ //HITTAR STÖRSTA BARNET
if (child != n && heap[child + x] > heap[child]){
child = child + x;
}
x++;
}
return child;
}
template <typename Comparable>
void buildHeap(Comparable arr[], int n, int d){
for (int i = (n / d) - 1; i>=0; --i){
int child, x = 1;
Comparable tmp = arr[i];
for (; i*d + 1 <= n; i = child){
child=posOfMaxChild(arr, i, n, d);
if (arr[child] > tmp){
arr[i] = arr[child];
arr[child] = tmp;
}
else
break;
}
}
}
Мне кажется, что ты борешься с кучей д-ар и кучи.
Обычно при работе с кучами вам понадобятся две вспомогательные функции:
sink()
: Начиная с вершины кучи, вы сделаете перестановки, чтобы убедиться, что свойство кучи удовлетворяется. sink()
необходимо поддерживать свойство кучи при извлечении вершины кучи.swim()
: Начиная с заданной позиции, вы будете делать перестановки, увеличивая условие кучи. swim()
необходимо поддерживать свойство кучи при добавлении элементов в кучу.Но если мы хотим отсортировать только с использованием свойства heap, нам понадобится только sink()
потому что нет необходимости добавлять какой-либо элемент в любом месте. Как работает порт?
array
, мы переупорядочиваем элементы так, чтобы массив удовлетворял свойству кучи.Вот моя реализация heapsort, использующая кучи d-ary в качестве поддержки:
template <typename T>
void sink(T arr[], int pos, int N, int d) {
int start(pos*d + 1), max_index(start);
while(start < N) {
// Find the max amongst direct "children" of position `pos`
for(int i = start + 1; (i < start + d) && (i < N); i++) {
if (arr[i] > arr[max_index]) {
max_index = i;
}
}
// If arr[pos] is less than the max we found, switch them and proceed
if (arr[pos] < arr[max_index]) {
// Switch arr[pos] and arr[max_index] to enforce heap condition
T tmp = arr[pos];
arr[pos] = arr[max_index];
arr[max_index] = tmp;
// Update pos and start to sink "recursively"pos = max_index;
start = pos*d + 1;
max_index = start;
} else { // Else, there is nothing to worry about further ...
break;
}
}
}
template <typename T>
void dheapsort(T arr[], int N, int d) {
// The for loop "heapify" the array.
for (int k = N/d; k >= 0; k--) {
sink<T>(arr, k, N, d);
}
// We exchange the max (located at arr[0] since the array became a heap)
// with the last element.
// Then we enforce the heap condition on the N-1 remaining elements.
// N is then decreased
// (...) so on.
while (N > 1) {
T tmp = arr[N-1];
arr[N-1] = arr[0];
arr[0] = tmp;
sink<T>(arr, 0, --N, d);
}
}
Тогда вам просто нужно использовать его с параметрами, которые вы хотите …
Пример :
int main() {
int test[10] = {1, 3, 2, 5, 6, 8, 2, 8, 10, 11};
dheapsort(test, 10, 3);
for (int i = 0; i < 10; i++)
cout << "test[" << i << "] : " << test[i] << endl;
return 0;
}
Выходы:
тест [0]: 1
тест [1]: 2
тест [2]: 2
тест [3]: 3
тест [4]: 5
тест [5]: 6
тест [6]: 8
тест [7]: 8
тест [8]: 10
тест [9]: 11
Вы можете увидеть эту реализацию в действии Вот …
Теперь предположим, что у нас есть некоторые функции, подобные вашей (removeFromHeap, buildHeap …):
template <typename T>
void dheapsort(T arr[], int N, int d) {
buildHeap(arr, N, d);
while (N > 1) {
T tmp = removeFromHeap(arr, N, d);
arr[--N] = tmp;
}
}
Но ваши реализации buildHeap()
а также removeFromHeap()
нужно исправить, я буду использовать мою функцию sink()
таким образом posOfMaxChild()
больше не понадобится. Но с тех пор posOfMaxChild()
был сломан, вот исправление …
template <typename Comparable>
int posOfMaxChild(Comparable heap[], int thePos, int n, int d) {
int child(thePos*d+1), posMax(child);
// You had improper loop conditions ...
for (int x = child + 1; (x < child+d) && (x < n); x++) {
if (arr[posMax] < arr[x])
posMax = x;
}
return (posMax < n) ? posMax : -1;
}
Потом идет buildHeap()
:
template <typename Comparable>
void buildHeap(Comparable arr[], int n, int d) {
// 1. The first index that might have children is n/d, not (n/d) - 1 !
// Be careful of how integer division works ...
for (int i = (n/d); i>=0; --i){
sink(arr, i, n, d);
}
}
И наконец removeFromHeap()
:
template <typename Comparable>
Comparable removeFromHeap(Comparable heap[], int n, int d) {
Comparable root = heap[0];
heap[0] = heap[n-1];
sink(heap, 0, n-1, d);
return root;
}
Реализация heapsort с использованием вспомогательных функций OP вместе с моим sink()
реализация полностью доступна ВОТ. Я использовал тот же массив примеров, что и в моей собственной реализации.