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

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

Implementing a heap: becomes inaccurate after one sift

问题

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

  1. public void makeHeap(int[] arr)
  2. {
  3. for(int i = 0; i <= arr.length; i++)//对数组中的每个元素,检查其子节点并将其向下移动以构建堆
  4. {
  5. siftDown(arr, i);
  6. }
  7. }
  8. //将新的根插入到正确的位置,通过比较顶部元素并与其较大的子节点交换
  9. public void siftDown(int[] heap, int i)
  10. {
  11. int c = i * 2; //获取当前索引位置的子节点
  12. if(c == 0) // 0*2等于0,因此将其加1以将第一个节点的父节点计入
  13. {
  14. c+=1;
  15. }
  16. if(c >= heap.length || c+1 >= heap.length) // 防止数组越界
  17. {
  18. return;
  19. }
  20. if(heap[c] < heap[c + 1]) //子节点1是否小于子节点2?
  21. {
  22. c += 1; //如果是,将c设为较大的子节点,以便最终向上移动
  23. }
  24. if(heap[i] < heap[c])//如果刚获取的父节点小于上一次循环定义的子节点,则交换两者。然后再次调用siftDown以比较子节点和父节点。
  25. {
  26. heap = swap(heap, i, c);//交换值
  27. siftDown(heap, c);//再次调用以比较新根与其子节点。
  28. }
  29. }
  30. //以下是swap方法
  31. public int[] swap(int[] heap, int i, int c)
  32. {
  33. //将两个值存入变量中
  34. int ele1 = heap[i];
  35. int ele2 = heap[c];
  36. heap[i] = ele2;//将heap[i]更改为heap[c]
  37. heap[c] = ele1;//将heap[c]更改为heap[i]
  38. return heap;
  39. }

起始数字为: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:

  1. public void makeHeap(int[] arr)
  2. {
  3. for(int i = 0; i &lt;= arr.length; i++)//for each element in the array, we we check its children and sift it down
  4. {
  5. siftDown(arr, i);
  6. }
  7. }
  8. //insert a new root in the correct position. Byu comparing the top element and swapping it with its largest child.
  9. public void siftDown(int[]heap, int i)
  10. {
  11. int c = i * 2; //grab the children of the current index we are at.
  12. if(c == 0) // 0*2 is 0 so we make it 1 so it will register the first nodes parents
  13. {
  14. c+=1;
  15. }
  16. if(c &gt;= heap.length || c+1 &gt;= heap.length) // so we dont go off the end of the array
  17. {
  18. return;
  19. }
  20. if(heap[c] &lt; heap[c + 1]) //Is child 1 less than child 2?
  21. {
  22. c += 1; //if it is we want c to be the greater child to eventually move upwards
  23. }
  24. 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.
  25. {
  26. heap = swap(heap,i,c);//swap the values
  27. siftDown(heap, c);//call again to compare the new root with its children.
  28. }
  29. }

Here is my swap method:

  1. public int[] swap(int[]heap, int i, int c)
  2. {
  3. //capture the two values in variables
  4. int ele1 = heap[i];
  5. int ele2 = heap[c];
  6. heap[i] = ele2;//change heap i to heap c
  7. heap[c] = ele1;//change heap c to heap i
  8. return heap;
  9. }

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

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

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

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

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

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

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

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

  1. Given parentIdx in 0-based array,
  2. leftChildIdx = parentIdx * 2 + 1
  3. 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:

确定