- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在尝试编写一个递归的heapify方法,该方法将整数数组变成最小堆。 Main和Heap类如下所示。 Main中显示的大多数数组已经是最小堆,但是子树[11、4、5]不是最小堆。但是,heapify函数似乎未到达该子树。我不知道问题出在哪里,任何帮助将不胜感激。
public class Heap {
public Heap(int[] array) {
heap = array;
}
public void heapify() {
heapifyHelper(0);
}
public void heapifyHelper(int rootIndex) {
if(isLeafIndex(rootIndex)) {
return;
}
else {
int leftChildIndex = getLeftChildIndex(rootIndex);
int rightChildIndex = getRightChildIndex(rootIndex);
int leftChildValue = heap[leftChildIndex];
int rightChildValue = heap[rightChildIndex];
int rootValue = heap[rootIndex];
if(leftChildValue < rootValue && leftChildValue < rightChildValue) {
swap(rootIndex, leftChildIndex);
heapifyHelper(leftChildIndex);
heapifyHelper(rightChildIndex);
}
else if(rightChildValue < rootValue && rightChildValue < leftChildValue) {
swap(rootIndex, rightChildIndex);
heapifyHelper(leftChildIndex);
heapifyHelper(rightChildIndex);
}
}
}
public int getLeftChildIndex(int parentIndex) {
return 2 * parentIndex + 1;
}
public int getRightChildIndex(int parentIndex) {
return 2 * parentIndex + 2;
}
public int getParentIndex(int childIndex) {
if(childIndex == 0) {
throw new IllegalArgumentException("Cannot get the parent index of the root.");
}
else {
return (childIndex / 2) - 1;
}
}
public boolean isLeafIndex(int index) {
int leftIndex = getLeftChildIndex(index);
int rightIndex = getRightChildIndex(index);
if(leftIndex >= heap.length && rightIndex >= heap.length) {
return true;
}
else {
return false;
}
}
public void swap(int index1, int index2) {
int temp = heap[index1];
heap[index1] = heap[index2];
heap[index2] = temp;
}
public void printHeap() {
System.out.println(Arrays.toString(heap));
}
int[] heap;
}
public class Main {
public static void main(String[] args) {
int[] x = {0, 5, 2, 9, 11, 6, 12, 21, 32, 4, 5};
Heap heap = new Heap(x);
heap.printHeap();
heap.heapify();
heap.printHeap();
}
}
最佳答案
您的heapifyHelper
中有几个问题:
public void heapifyHelper(int rootIndex) {
if(isLeafIndex(rootIndex)) {
return;
}
else {
int leftChildIndex = getLeftChildIndex(rootIndex);
int rightChildIndex = getRightChildIndex(rootIndex);
int leftChildValue = heap[leftChildIndex];
int rightChildValue = heap[rightChildIndex];
leftChildIndex == heap.length - 1
怎么办?然后
rightChildValue
将导致
ArrayIndexOutOfBoundsException
。
int rootValue = heap[rootIndex];
if(leftChildValue < rootValue && leftChildValue < rightChildValue) {
swap(rootIndex, leftChildIndex);
heapifyHelper(leftChildIndex);
heapifyHelper(rightChildIndex);
}
else if(rightChildValue < rootValue && rightChildValue < leftChildValue) {
swap(rootIndex, rightChildIndex);
heapifyHelper(leftChildIndex);
heapifyHelper(rightChildIndex);
}
}
}
[11, 4, 5]
的原因是,如果子节点之一小于父节点,则只为子节点调用
heapifyHelper
,而当您调用
heapifyHelper(1)
时,节点<的两个子节点< cc>是
5
和
9
,均大于根值。 (实际上,您甚至都没有呼叫
11
,因为
heapifyHelper(1)
已经小于其两个子对象。)
heap[0]
正确。如果从根到叶递归,则每个值最多可以冒充一个级别。您必须从叶子移到根(1),并且需要将值完全向下筛选,而不仅仅是向下筛选。
7
/ \
/ \
2 6
/ \ / \
1 3 4 5
heapify
和
2
,得到
2
/ \
/ \
7 6
/ \ / \
1 3 4 5
2
/ \
/ \
1 4
/ \ / \
7 3 6 5
7
(在这种情况下,仅为一个级别)。
6
/ \
4 5
4
/ \
6 5
2
/ \
1 3
1
/ \
2 3
7
/ \
/ \
1 4
/ \ / \
2 3 6 5
1
和
7
交换,产生
1
/ \
/ \
7 4
/ \ / \
2 3 6 5
1
。
7
方法(和/或
siftDown
方法),该方法可以根据需要向下(向上)筛选值。
private void siftDown(int index) {
int leftChildIndex = getLeftChildIndex(index);
if (leftChildIndex >= heap.length) {
// a leaf, no further sifting down possible
return;
}
int rightChildIndex = getRightChildIndex(index);
if ((heap[leftChildIndex] < heap[index])
&& (rightChildIndex >= heap.length || heap[rightChildIndex] >= heap[leftChildIndex)) {
// left child is smallest or only, and smaller than parent
swap(index, leftChildIndex);
siftDown(leftChildIndex);
} else
// left child not smaller than parent, or right child exists and is smaller than parent
if (rightChildIndex < heap.length && heap[rightChildIndex] < heap[index]) {
swap(index, rightChildIndex);
siftDown(rightChildIndex);
}
// otherwise, this one has no smaller child, so no more sifting needed
}
siftUp
将是
public void heapify() {
// last index that has a child:
int lastNonLeafIndex = heap.length/2 - 1;
for(int index = lastNonLeafIndex; index >= 0; --index) {
siftDown(index);
}
}
heapify
中处理的每个索引,以该索引为根的子树将变为最小堆。
heapify
:
private void siftUp(int index) {
if (index == 0) return; // root, nothing to do
int parentIndex = getParentIndex(index); // see Note below
if (heap[index] < heap[parentIndex]) {
swap(index, parentIndex);
siftUp(parentIndex);
}
}
public void heapify() {
for(int index = 1; index < heap.length; ++index) {
siftUp(index);
}
}
siftUp
的代码比
siftUp
的代码短得多,因为此处仅涉及两个节点,因此无需检查是否有任何子索引落在数组之外。但是
siftDown
的效率较低(请参阅脚注(1))。
heapify
是用于将新值插入堆的方法。因此,通过将所有值(根值除外)插入到现有的最小堆中(当调用
siftUp
时,
siftUp(index)
之前的数组部分已经是最小堆),从而构建一个堆。
index
不正确,
return (childIndex / 2) - 1;
getParentIndex
的父级是
1
,索引
-1
的父级是
3
,正确的是
return (childIndex - 1) / 2;
0
级别具有
k
值,可能需要使
2^k
级别起泡,这为构建堆增加了
k
的复杂性。如果从[父级]树叶开始向上操作,则可能具有
O(n*log n)
值,可能需要降低
2^(log n - 1 - k)
级别,这为构建堆提供了
k
的复杂性。
关于java - Heapify功能不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14902679/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!