使用ArrayList进行修改

时间:2018-05-10 08:06:33

标签: java arrays methods

我写了这个方法来测试我的优先级队列,它的参数是一个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(队列的新根)。这些方法是提取最大值 heapify 。我该如何解决?

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;
  }

这是IntegerComparator:

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);
  }

2 个答案:

答案 0 :(得分: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个元素

希望有所帮助!

答案 1 :(得分:1)

执行此操作时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()时,该平均索引不存在于队列中。