基于数组的堆排序中的数组索引超出界限

时间:2016-01-08 22:03:57

标签: java arrays sorting heapsort

我试图编写基于数组的堆排序算法实现。目标是在数组中构建一个堆,然后删除数组根部的最小元素并将其放回原始数组中。这样做直到数组被排序。

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;

1 个答案:

答案 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;

请注意,nodeleftright始终是索引0,1和2,无论数组有多大。如果传入一个小数组(例如,大小为2),这将读取结束。

展望未来,我得到的感觉是你需要学习如何调试你的程序。当我运行代码时,这里引发的异常使我直接进入导致问题的程序行,并且从那里起来并不太难以找出发生异常的地方。我希望这有助于指出你正确的方向,祝你好运!

相关问题