我的函数sort
有时会抛出读取位置的访问冲突,有时它会起作用。
我无法找到它之间的联系,以及它何时没有。
sort函数将使用d-max-heap对arr
中的元素与n
项进行排序。它必须使用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;
}
}
}
答案 0 :(得分:1)
在我看来,你正在努力与d-ary堆和heapsort。 通常,在处理堆时,您将需要两个辅助功能:
sink()
:从堆顶部开始,您将进行排列以确保满足堆属性。检索堆顶部时,sink()
是维护堆属性所必需的。swim()
:从给定位置开始,您将进行排列以强制执行堆条件。向堆中添加元素时,必须swim()
来维护堆属性。但是,如果我们只想使用堆属性进行排序,我们只需要sink()
,因为不需要在任何地方添加任何元素。 heapsort是如何工作的?
array
,我们重新排序元素,以便数组满足堆属性。这是我使用d-ary堆作为支持的heapsort实现:
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
您可以在行动here ...
中看到此实施现在,假设我们手头有一些类似你的功能(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;
}
使用OP的辅助功能以及我的sink()
实施的heapsort实现完全可用HERE。我使用与我自己的实现相同的示例数组。