【问题标题】:Sort part of array with heapsort, bug使用堆排序对数组的一部分进行排序,错误
【发布时间】:2017-08-18 10:01:05
【问题描述】:

这是我的介绍代码。我无法让代码的堆排序部分正常工作。

partition()sort() 工作正常,但堆排序部分没有正确排序。我得到这样的排序数组(大小 = 10):

10
18
26
35
25
39
49
49
57
89

除了少数数字外,大部分都是排序的。我只是想在每个heapsort() 调用中对数组的一部分进行排序。

public class IntroSort {

    public static void sort(int[] arrayToSort){     
        int depth = ((int) Math.log(arrayToSort.length))*2;
        sort(arrayToSort, depth, 0, arrayToSort.length-1);
    }

    private static void sort(int[] arrayToSort, int depth, int start, int end){
        int length = arrayToSort.length;
        if(length <= 1){
            return;
        }else if(depth == 0){
            heapSort(arrayToSort, start, end);
        }else{
            if(start >= end)
                return;
            int pivot = arrayToSort[(start + end)/2];
            int index =  partition(arrayToSort, start, end, pivot);
            sort(arrayToSort, depth-1, start, index-1);
            sort(arrayToSort, depth-1, index, end);
        }
    }

    private static void heapSort(int[] arrayToSort, int start, int end){
        for (int i = end / 2 - 1; i >= start; i--)
            heapify(arrayToSort, end, i);
        for (int i=end-1; i>=start; i--){
            int temp = arrayToSort[start];
            arrayToSort[start] = arrayToSort[i];
            arrayToSort[i] = temp;
            heapify(arrayToSort, i, start);
        }
    }

    private static void heapify(int[] arrayToSort, int n, int i){
        int largest = i;
        int l = 2*i + 1;
        int r = 2*i + 2;
        if (l < n && arrayToSort[l] > arrayToSort[largest])
            largest = l;
        if (r < n && arrayToSort[r] > arrayToSort[largest])
            largest = r;
        if (largest != i){
            int swap = arrayToSort[i];
            arrayToSort[i] = arrayToSort[largest];
            arrayToSort[largest] = swap;
            heapify(arrayToSort, n, largest);
        }
    }

    private static int partition(int[] arrayToSort, int start, int end, int pivot){
        while(start <= end){
            while(arrayToSort[start] < pivot){
                start++;
            }
            while(arrayToSort[end] > pivot){
                end--;
            }
            if(start <= end){
                int temp = arrayToSort[start];
                arrayToSort[start] = arrayToSort[end];
                arrayToSort[end] = temp;
                start++;
                end--;
            }
        }
        return start;
    }

}

有什么想法吗?

【问题讨论】:

    标签: java algorithm sorting quicksort heapsort


    【解决方案1】:

    卡尔顿, 我在一些数组上运行了您的代码,并且该数组中的数据已被排序。 你能举例说明你的算法没有正确运行吗?

    int[] arr = new int[]{17,1,15,1,2,3,18,100,100,454};
        heapSort(arr, 0, arr.length);
        for (int i:arr)
            System.out.print(i+" ");
    

    结果我得到了:

    1 1 2 3 15 17 18 100 100 454 
    

    进程以退出代码 0 结束

    【讨论】:

    • 当您尝试仅对数组的一部分进行排序时会出错,就像您调用 heapSort(arr, 3, 6)
    【解决方案2】:

    因为您的heapify 方法不能只为输入数组的部分 构建最大堆。

    让我们看一个示例:假设您有一个长度为 10 的数组,并且您想将部分从 3 排序到 6,您将从代码中调用 heapSort(array, 3, 6)

    private static void heapSort(int[] arrayToSort, int start, int end){
        for (int i = end / 2 - 1; i >= start; i--)
            heapify(arrayToSort, end, i);
        for (int i=end-1; i>=start; i--){
            int temp = arrayToSort[start];
            arrayToSort[start] = arrayToSort[i];
            arrayToSort[i] = temp;
            heapify(arrayToSort, i, start);
        }
    }
    

    它会在第一步的第一个 for 循环中调用 heapify(array, 6, 2),然后在你的 heapify 实现中,你会将 2nd 元素与 5th6th 元素进行比较,甚至可能交换它与后两者之一。所以2nd元素在你想将第3部分排序到第6部分时出现意外,甚至可能与5th6th元素交换,导致结果不正确。

    如果你想构建一个portionHeapSort,我认为最好先构建一个heapSort,然后像下面的代码一样在它的基础上构建portionHeapSort

    private static void portionHeapSort(int[] arrayToSort, int start, int end) {
        // start and end both inclusive
        int[] subArray = Arrays.copyOfRange(arrayToSort, start, end + 1);
        heapSort(subArray);
        for (int i = start; i <= end; i++) {
            arrayToSort[i] = subArray[i - start];
        }
    }
    

    希望这对你有帮助:-)

    【讨论】:

      【解决方案3】:

      我最近写了一个代码来解决这个问题。 Here's a link to my post.

      为了简单起见,我还将代码粘贴在这里:

      def buildMaxHeap(arr, arrayLength, indexStart, attr):
          for i in range(arrayLength):
      
              # if child is bigger than parent
              if getattr(arr[indexStart + i], attr) > getattr(arr[indexStart + int((i - 1) / 2)], attr):
                  j = i
      
                  # swap child and parent until
                  # parent is smaller
                  while getattr(arr[indexStart + j], attr) > getattr(arr[indexStart + int((j - 1) / 2)], attr):
                      (arr[indexStart + j],
                       arr[indexStart + int((j - 1) / 2)]) = (arr[indexStart + int((j - 1) / 2)], arr[indexStart + j])
                      j = int((j - 1) / 2)
      
      
      def heapSort(arr, arrayLength, indexStart, attr):
          buildMaxHeap(arr, arrayLength, indexStart, attr)
      
          for i in range(arrayLength - 1, 0, -1):
      
              # swap value of first indexed
              # with last indexed
              arr[indexStart + 0], arr[indexStart + i] = arr[indexStart + i], arr[indexStart + 0]
      
              # maintaining heap property
              # after each swapping
              j, index = 0, 0
      
              while True:
                  index = 2 * j + 1
      
                  # if left child is smaller than
                  # right child point index variable
                  # to right child
                  if (index < (i - 1) and getattr(arr[indexStart + index], attr) < getattr(arr[indexStart + index + 1], attr)):
                      index += 1
      
                  # if parent is smaller than child
                  # then swapping parent with child
                  # having higher value
                  if index < i and getattr(arr[indexStart + j], attr) < getattr(arr[indexStart + index], attr):
                      arr[indexStart + j], arr[indexStart + index] = arr[indexStart + index], arr[indexStart + j]
      
                  j = index
                  if index >= i:
                      break
      

      【讨论】:

        猜你喜欢
        • 2011-04-28
        • 1970-01-01
        • 2020-04-08
        • 2012-07-04
        • 1970-01-01
        • 1970-01-01
        • 2017-02-24
        • 1970-01-01
        • 2022-01-07
        相关资源
        最近更新 更多