当前位置: 首页 > 知识库问答 >
问题:

最大堆插入和排序Java

马坚白
2023-03-14

我试图构造一个最大堆,当插入每个新值时,值会上移或下移到正确的位置,我还没有实现下移函数,所以现在我正在使用一个测试,该测试应该只需要程序上移。测试数据按以下顺序输入:

[16, 10, 14, 9, 7, 1, 4, 2, 8, 3]

我在主类中使用以下代码在堆中插入值:

package com.company;

public class Main {

    public static void main(String[] args) {

        BinaryHeap bh = new BinaryHeap();

        bh.insert(16);
        bh.insert(10);
        bh.insert(14);
        bh.insert(9);
        bh.insert(7);
        bh.insert(1);
        bh.insert(4);
        bh.insert(2);
        bh.insert(8);
        bh.insert(3);

        bh.printHeap();

    }
}

下一位代码是插入和移位的地方:

package com.company;

public class BinaryHeap {
    private int[] Heap;
    private int size;
    private int maxsize;

    public BinaryHeap(){
        this.maxsize = 10;
        this.size = 0;
        Heap = new int[this.maxsize + 1];
    }

    public int Parent(int i){

        return (i)/2;
    }

    public int LeftChild(int i){

        return (2*i);
    }

    public int RightChild(int i){

        return ((2*1)+1);
    }

    public void insert(int value) {
        if(size <= Heap.length) {
            size++;
            Heap[size] = value;
            siftUp(size);
        }
    }


    private void siftUp(int i) {
        int parentIndex;
        int tmp;

        if (i != 0) {

            parentIndex = Parent(i);

            if (Heap[parentIndex] < Heap[i]) {
                tmp = Heap[parentIndex];
                Heap[parentIndex] = Heap[i];
                Heap[i] = tmp;
                siftUp(parentIndex);
            }

        }

    }

    public void printHeap()
    {
        for (int i = 1; i < maxsize; i++) {
            System.out.print(" PARENT : " + Heap[Parent(i)]
                    + " LEFT CHILD : " + Heap[LeftChild(i)]
                    + " RIGHT CHILD :" + Heap[RightChild(i)]);
            System.out.println();
        }
    }

}

移位函数是siftUp(),我认为这就是问题所在。当程序以这些输出运行时:

PARENT : 16 LEFT CHILD : 9 RIGHT CHILD :10
 PARENT : 14 LEFT CHILD : 8 RIGHT CHILD :10
 PARENT : 14 LEFT CHILD : 1 RIGHT CHILD :10
 PARENT : 9 LEFT CHILD : 0 RIGHT CHILD :10
 PARENT : 9 LEFT CHILD : 3 RIGHT CHILD :10
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 12 out of bounds for length 11
    at com.company.BinaryHeap.printHeap(BinaryHeap.java:61)
    at com.company.Main.main(Main.java:20)

但这是不正确的,因为1)末尾的索引越界异常来自printHeap()函数,2)每个父节点的子节点不在正确的位置,因为根节点应该是16,其中14和10作为子节点,当它打印出堆的值时,它打印出0,但是0永远不会插入堆中。我尝试过自己做一些调试,但没有多大成功,所以欢迎任何帮助。

共有1个答案

桓宜
2023-03-14
private void siftUp(int i) {
    int parentIndex;
    int tmp;
    if (i != 0) { // error is this if statement
        parentIndex = Parent(i);
        if (Heap[parentIndex] < Heap[i]) {
            tmp = Heap[parentIndex];
            Heap[parentIndex] = Heap[i];
            Heap[i] = tmp;
            siftUp(parentIndex);
        }
    }
}

导致堆未显示正确数字的错误在siftUp(if语句)中。

插入16时,堆[1]变为16。然后,它调用siftUp(1)。siftUp内部,1!=0,则执行if语句。parentIndex变为1/2=0,问题来了。默认情况下,堆[0]=0小于堆[1]=16。因此,它交换值16和0,将16移动到索引0,索引0不是您提到的头。这只是错误的开始,当你插入越来越多的数字时,它们就会到处都是。

因为堆的根位于索引1。您应该只筛选到索引1,它没有父级。将if语句更改为if(i)后

 PARENT: 0 CURRENT: 16 LEFT CHILD : 10 RIGHT CHILD : 14 
 PARENT: 16 CURRENT: 10 LEFT CHILD : 9 RIGHT CHILD : 7
 PARENT: 16 CURRENT: 14 LEFT CHILD : 1 RIGHT CHILD : 4
 PARENT: 10 CURRENT: 9 LEFT CHILD : 2 RIGHT CHILD : 8
 PARENT: 10 CURRENT: 7 LEFT CHILD : 3
 PARENT: 14 CURRENT: 1
 PARENT: 14 CURRENT: 4
 PARENT: 9 CURRENT: 2
 PARENT: 9 CURRENT: 8
public void printHeap(){
  for (int i = 1; i < maxsize; i++) {
    System.out.print(" PARENT: " + Heap[Parent(i)]);
    System.out.print(" CURRENT: "+ Heap[i]);
    if(LeftChild(i) <=  10){
      System.out.print(" LEFT CHILD " + ": " +  Heap[LeftChild(i)]);
    } 
    if(RightChild(i) <= 10){
      System.out.print(" RIGHT CHILD "+ ": "+  Heap[RightChild(i)]);
      }
    System.out.println();
  }
}
 类似资料:
  • 我在[17,98,89,42,67,54,89,25,38]中有一个数字列表,从左到右插入到一个空堆中。生成的堆是什么?

  • 我只是想看看我是否理解教授和在线资源所说的话。 对于heapSort算法,第一个元素的索引从0开始。 对于最大堆,如果子堆大于父堆,则percolate down应将最大子堆与其父堆交换,例如(这是用于赋值,因此我尝试发布尽可能少的代码): 所以最后,最大元素应该在索引0处。 如果这是正确的,我不理解的是heapSort实现: 最大堆中的渗滤层不应该将最大的元素放在索引0处吗?在这种情况下,为什么

  • 我注意到一件非常奇怪的事情。 读完这节课后,我在C中实现了一些堆排序代码。 代码如下。 奇怪的是,对我来说,构建min堆-提取min(或在构建min堆后在根目录下执行min-heapify)应该按升序进行。然而,在执行此代码并打印出结果向量后,我得到: 在试图弄清楚发生了什么的时候,我改变了 到 最终选择较大(或最大)的父节点和子节点,得到的向量为: 我是否做错了什么,或者我对堆/堆排序的理解不清

  • 对于堆排序,如果我们想按升序对数组排序,那么应该在最大堆还是最小堆中转换堆?

  • 插入排序 """ 插入排序核心思想 将数组分成一个有序数组和一个无序数组 每次从无序数组中提一个元素出来 插入到 有序元素的合适位置 """ from typing import List def insert_sort(arr: List) -> List: """ 插入排序 :param arr: :return: """ target =

  • 我已经在链接中看到了(http://bigocheatsheet.com/)插入排序的复杂性与冒泡排序相同,堆排序也优于这两种排序。但是,当我创建一个示例程序并比较插入排序所花费的时间时,我感到难以置信。 类用于测试排序算法。 泡泡排序类 用于插入排序的类 堆排序类 用于创建数组的类 我尝试了所有的情况,比如最好的情况、最坏的情况和一般情况。但在所有情况下,插入排序都比冒泡排序和堆排序快得多。理论