【问题标题】:Heapify with ArrayList使用 ArrayList 进行堆放
【发布时间】:2018-05-10 08:06:32
【问题描述】:

我编写了这个方法来测试我的优先级队列,它有一个 ArrayList 和一个 Comparator 作为参数:

@Test
  public void testPriorityQueue_ExtractMax() {
    PriorityQueue queue = new PriorityQueue(new IntegerComparator());
    Integer[] arrayExp={14, 9};
    queue.insert(16);
    queue.insert(9);
    queue.insert(14);
    queue.extractMax();
    assertArrayEquals(arrayExp, queue.getArray().toArray());
  }

现在,如果我执行它,它会说我的结果中的第一个元素是 9,但我必须是 14(我的队列的新根)。这些是 extract maxheapify 方法。我该如何解决?

public void heapify(int index) {
    int largest = index;
    int leftIndex = 2 * index + 1;
    int rightIndex = 2 * index + 2;

    if (leftIndex < queue.size() && c.compare(queue.get(index), (queue.get(leftIndex))) < 0)
      largest = leftIndex;

    if (rightIndex < queue.size() && c.compare(queue.get(largest), queue.get(rightIndex)) < 0)
      largest = rightIndex;

    if (largest != index) {
      swap(index, largest);
      heapify(largest);
    }
  }

  public T extractMax() {
    if (queue.size() == 0) return null;

    T min = queue.get(0);
    queue.remove(0);
    queue.set(0, queue.get(queue.size() - 1));
    heapify(0);
    return min;
  }

这是整数比较器:

public class IntegerComparator implements Comparator<Integer>{
  @Override
  public int compare(Integer l1, Integer l2) {
    int result = l1.compareTo(l2);
    if(result != 0)
      return result;
    return -1;
   }
}

EDIT_2:这是我的插入方法,会不会是问题:

public void insert(T elem) {
    int i = queue.size();
    int parentIndex = (i - 1) / 2;
    while (i > 0 && c.compare(elem, queue.get(parentIndex)) == 1) {
      queue.set(i, queue.get(parentIndex));
      i = parentIndex;
      parentIndex = (i - 1) / 2;
    }
    queue.add(i, elem);
  }

【问题讨论】:

  • 这取决于IntegerComparator 如何对元素进行排序(最小堆或最大堆)。检查它是如何实现的。
  • 我在问题中添加了它。

标签: java arrays methods


【解决方案1】:

作为建议,考虑在索引 0 处添加一个未使用的元素,以便更直观地访问每个节点的父/子。

示例

考虑堆heap = [-1, 6, 4, 5, 2, 1, 4, 3],其中根定义为heap[1],堆的数据位于从index = 1 到堆大小的位置。

要访问index 的节点的子节点,可以直观地说左子节点定义为heap[2 * index],右子节点定义为heap[2 * index + 1]。同样,要访问index 节点的父节点,可以使用int 截断来访问父节点:

int parentInd = (int)(index/2);
T parent = heap[parentInd];

解决方案

正如 raul1ro 所指出的,您正在丢失索引 0 中您不打算删除的数据。

extractMax():

T min = queue.get(0);
queue.remove(0);
queue.set(0, queue.get(queue.size() - 1));

应该是:

T min = queue.get(0); //Get min
T temp = queue.get(queue.size() - 1); //Get the last element in heap as temp
queue.remove(queue.size - 1); //Remove the last element
queue.set(0, temp); //Set the root to the temp value so that you can heapify

这将使您在 extractMax() 时只丢失 1 个元素

希望有帮助!

【讨论】:

  • 请查看我的编辑以了解替代方法,否则 raul1ro 的解决方案会很好!
  • 我认为问题是由插入方法给出的。请检查一下好吗?
  • 请上传源代码,以便我调试。然后我会带你解决这个问题。
【解决方案2】:

当您这样做时queue.remove(i); 会自动将索引 i 之后的所有元素向左移动一个位置。

https://www.tutorialspoint.com/java/util/arraylist_remove.htm

而使用queue.set(0, queue.get(queue.size() - 1));,您只需将队列中最后一个索引的值设置为索引 0 并从索引 0 中丢失值,但它仍保留在最后一个位置。

读后插入方法

queue.set(i, queue.get(parentIndex));,如果i = queue.size() 在第一步中,则意味着队列中不存在索引。

【讨论】:

  • 我应该改变什么?
  • 您可以检查队列中是否存在索引 i,如果不存在,请使用添加。 if(i &gt;= size) { queue.add(...) } else ... P.S.:并建议修复 extractMax()
  • queue.add(i, obj); - i 的范围 - [0,queue.size()] 并且如果在 i 索引处已经存在某些东西,将是从 iqueue.size() 的所有元素向右移动一个位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
  • 2018-10-16
  • 2016-02-24
  • 1970-01-01
相关资源
最近更新 更多