我试图编写基于数组的堆排序算法实现。目标是在数组中构建一个堆,然后删除数组根部的最小元素并将其放回原始数组中。这样做直到数组被排序。
root的替换应该来自数组中的最后一个元素,然后将其删除并放入根目录中。如有必要,新的根元素将与其子元素交换。这一直持续到正确的位置
然而,我一直得到数组索引超出范围的异常,我只是找不到问题。我已经做了很长时间了。
如果有人可以帮助我,我会非常感激。
public class ImprovedHeapSort<T>
{
/**
* @param unsortedArr Array to be sorted
* @return sortedArr The sorted array
*
* Static method which is an improved version of the HeapSort algorithm. The array
* is used to create a sorted array, which is treated as a minheap.
*
* The root is at index 0 and the last element is at index length-1.
* Each element is compared to its children, which are at positions 2n+1 and 2(n+1).
* Swapping and comparison continues until the root is reached.
*
*
*/
public static <T extends Comparable<T>> T[] HeapSort (T[] unsortedArr)
{
/*
* Throw exception if array is empty.
*/
if (unsortedArr[0] == null)
{
throw new EmptyCollectionException("Array");
}
/*
* If array only contains one element.
*/
if (unsortedArr.length == 1)
{
return unsortedArr;
}
T[] heapArr = Arrays.copyOf(unsortedArr, unsortedArr.length);
for(int i = 0; i < unsortedArr.length; i++)
{
heapArr[i] = unsortedArr[i];
/*
* Swapping to put element in appropriate location, if necessary.
*/
int cur = i;
T temp = heapArr[i];
/*
* Swapping until root isn't reached and the element being added
* would no longer be less than its parent.
*/
while(cur > 0 && temp.compareTo(heapArr[(cur-1)/2]) < 0)
{
heapArr[cur] = heapArr[(cur-1)/2]; //Swap cur with parent
cur = (cur-1)/2; //Move up to parent
}
heapArr[cur] = temp; //Insert at appropriate spot.
}
/*
* Remove the root element from the heap array and add it to unsortedArr
*
*/
for (int y = 0; y < unsortedArr.length; y++)
{
int count = heapArr.length - (y+1); //Count decreased after every pass.
T rootElem = heapArr[0]; //Store root
heapArr[0] = heapArr[heapArr.length- (y+1)]; //Set root to last element.
unsortedArr[y] = rootElem; //Add root to unsortedArr
int node = 0;
int left = 1;
int right = 2;
int next;
if ((heapArr[left] == null) && (heapArr[right] == null))
next = count-1;
else if (heapArr[right] == null)
next = left;
else if (heapArr[left].compareTo(heapArr[right]) < 0)
next = left;
else
next = right;
T temp = heapArr[node];
/*
* Swap until appropriate location is found. Least child is shifted up.
*/
while ((next < count) &&
(heapArr[next]).compareTo(temp) < 0)
{
heapArr[node] = heapArr[next];
node = next;
left = 2 * node + 1;
right = 2 * (node + 1);
if ((heapArr[left] == null) && (heapArr[right] == null))
next = count-2;
else if (heapArr[right] == null)
next = left;
else if (heapArr[left].compareTo(heapArr[right]) < 0)
next = left;
else
next = right;
}
heapArr[node] = temp; //Insert node at appropriate location
}
return unsortedArr;
答案 0 :(得分:0)
您的代码中存在一些边界错误。
首先,让我们看一下:
/*
* Throw exception if array is empty.
*/
if (unsortedArr[0] == null)
{
throw new EmptyCollectionException("Array");
}
如果数组为空,此代码实际上不会抛出异常。相反,它尝试查看索引0,查看该值是否为null,如果是,则抛出异常。因此,如果尝试传入大小为0或空数组的数组,则会出现边界错误或空指针异常。要解决此问题,请尝试将其重写为
if (unsortedArr == null) {
...
}
你可能不想在长度为0的数组上自动失败。它是如何排序的完美定义的:它已经排序了!
另外,我不确定你在这里做什么,但我几乎是肯定的,这不是你想要的:
int node = 0;
int left = 1;
int right = 2;
int next;
if ((heapArr[left] == null) && (heapArr[right] == null))
next = count-1;
else if (heapArr[right] == null)
next = left;
else if (heapArr[left].compareTo(heapArr[right]) < 0)
next = left;
else
next = right;
请注意,node
,left
和right
始终是索引0,1和2,无论数组有多大。如果传入一个小数组(例如,大小为2),这将读取结束。
展望未来,我得到的感觉是你需要学习如何调试你的程序。当我运行代码时,这里引发的异常使我直接进入导致问题的程序行,并且从那里起来并不太难以找出发生异常的地方。我希望这有助于指出你正确的方向,祝你好运!