实现堆:经过一次筛选后变得不准确

huangapple go评论58阅读模式
英文:

Implementing a heap: becomes inaccurate after one sift

问题

以下是翻译好的代码部分:

public void makeHeap(int[] arr)
{
    for(int i = 0; i <= arr.length; i++)//对数组中的每个元素,检查其子节点并将其向下移动以构建堆
    {
        siftDown(arr, i);
    }
}

//将新的根插入到正确的位置,通过比较顶部元素并与其较大的子节点交换
public void siftDown(int[] heap, int i)
{
    int c = i * 2; //获取当前索引位置的子节点

    if(c == 0) // 0*2等于0,因此将其加1以将第一个节点的父节点计入
    {
        c+=1;
    }

   if(c >= heap.length || c+1 >= heap.length) // 防止数组越界
    {
        return;
    }

    if(heap[c] < heap[c + 1]) //子节点1是否小于子节点2?
    {
        c += 1; //如果是,将c设为较大的子节点,以便最终向上移动
    }

    if(heap[i] < heap[c])//如果刚获取的父节点小于上一次循环定义的子节点,则交换两者。然后再次调用siftDown以比较子节点和父节点。
    {
        heap = swap(heap, i, c);//交换值
        siftDown(heap, c);//再次调用以比较新根与其子节点。
    }

}

//以下是swap方法
public int[] swap(int[] heap, int i, int c)
{
    //将两个值存入变量中
    int ele1 = heap[i];
    int ele2 = heap[c];
    
    heap[i] = ele2;//将heap[i]更改为heap[c]
    heap[c] = ele1;//将heap[c]更改为heap[i]
    
    return heap;
}

起始数字为:4,7,9,6,3,1,5。期望的输出是:9,7,5,6,3,1,4,但实际上我只能得到:9,7,4,6,3,1,5。似乎一旦4在被9替换后下移一次,算法就会出错,它会认为3和1是它的子节点,而实际上应该是1,5。

谢谢您的帮助!

英文:

I am currently trying to write a program that takes an array and makes it into a heap.
I am trying to implement a siftDown method that will take the elements of the array and make them into a heap but i am just not getting the correct output i want and im not sure why:

public void makeHeap(int[] arr)
{
for(int i = 0; i &lt;= arr.length; i++)//for each element in the array, we we check its children and sift it down
{
siftDown(arr, i);
}
}
//insert a new root in the correct position. Byu comparing the top element and swapping it with its largest child.
public void siftDown(int[]heap, int i)
{
int c = i * 2; //grab the children of the current index we are at.
if(c == 0) // 0*2 is 0 so we make it 1 so it will register the first nodes parents
{
c+=1;
}
if(c &gt;= heap.length || c+1 &gt;= heap.length) // so we dont go off the end of the array
{
return;
}
if(heap[c] &lt; heap[c + 1]) //Is child 1 less than child 2? 
{
c += 1; //if it is we want c to be the greater child to eventually move upwards
}
if(heap[i] &lt; heap[c])//If the parent we have just gotten is smaller than the child defined last loop, then we swap the two. We then call sift down again to compare child and parent.
{
heap = swap(heap,i,c);//swap the values
siftDown(heap, c);//call again to compare the new root with its children.
}
}

Here is my swap method:

 public int[] swap(int[]heap, int i, int c)
{
//capture the two values in variables
int ele1 = heap[i];
int ele2 = heap[c];
heap[i] = ele2;//change heap i to heap c
heap[c] = ele1;//change heap c to heap i
return heap;
}

The starting numbers are: 4,7,9,6,3,1,5
. The output i want to get is 9,7,5,6,3,1,4 but i seem to only be able to get 9,7,4,6,3,1,5. It seems once 4 gets sifted down once after being replaced by 9, the algorithm goes out of wack and it believes that 3 and 1 are its children when 1,5 should be.
Thank you or your help!

答案1

得分: 2

    int c = i * 2; // 获取当前索引的子节点。
if(c == 0) // 0*2 等于 0,所以将其加一,以便注册第一个节点的父节点
{
c+=1;
}

这段代码看起来有问题。
堆中子节点的索引应该使用适用于所有情况的通用公式。

对于基于0的数组,给定父索引parentIdx,
左子索引leftChildIdx = parentIdx * 2 + 1
右子索引rightChildIdx = parentIdx * 2 + 2

这意味着索引为0的节点的子节点是1和2,索引为1的节点的子节点是3和4,索引为2的节点的子节点是5和6,依此类推。这是正确的。

而你的代码将索引为1的节点的子节点放在了2和3处,显然是错误的。

英文:
    int c = i * 2; //grab the children of the current index we are at.
if(c == 0) // 0*2 is 0 so we make it 1 so it will register the first nodes parents
{
c+=1;
}

This looks wrong to me.
The heap indices for children should be a general formula that works for all cases.

Given parentIdx in 0-based array,
leftChildIdx = parentIdx * 2 + 1
rightChildIdx = parentIdx * 2 + 2

This means children of 0 are 1 and 2, children of 1 are 3 and 4, children of 2 are 5 and 6, etc. It works.

Your code places children of 1 at 2 and 3, which is clearly wrong.

huangapple
  • 本文由 发表于 2020年8月18日 08:28:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63460254.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定