Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带比较器的java heapify方法_Java_Algorithm_Data Structures_Heap_Priority Queue - Fatal编程技术网

带比较器的java heapify方法

带比较器的java heapify方法,java,algorithm,data-structures,heap,priority-queue,Java,Algorithm,Data Structures,Heap,Priority Queue,我正在尝试编写一个类HeapQueue。我将根的左子级存储在2*indexOfRoot+1索引中,右子级存储在2*indexOfRoot+2中 public class HeapQueue implements PriorityQueue, BinaryHeap { public List<Task> queue; public Comparator comparator; public HeapQueue() { queue = new ArrayList(); }

我正在尝试编写一个类
HeapQueue
。我将根的左子级存储在
2*indexOfRoot+1
索引中,右子级存储在
2*indexOfRoot+2

public class HeapQueue implements PriorityQueue, BinaryHeap {

public List<Task> queue;
public Comparator comparator;

public HeapQueue() {
    queue = new ArrayList();
}

public void setComparator(Comparator comparator) {
    this.comparator = comparator;
    heapify(0);
}

public Comparator getComparator() {
    return comparator;
}

public void offer(Task task) {
    int currentElement, previousElement;
    queue.add(task);
    currentElement = queue.size() - 1;
    previousElement = (currentElement - 1) / 2;
    while (previousElement >= 0 && 
             getComparator().compare(queue.get(currentElement), queue.get(previousElement)) > 0) {
        swap(currentElement, previousElement);
        currentElement = previousElement;
        previousElement = (currentElement - 1) / 2;
    }
}

private void swap(int i, int j) {
    Task t1 = queue.get(i);
    Task t2 = queue.get(j);
    Task t3 = t1;
    queue.set(i, t2);
    queue.set(j, t3);
}
}
我在
HeapQueue
中有一个方法
heapify()

public void heapify(int root) {
    int leftChild, rightChild;
    leftChild = 2 * root + 1;
    if (leftChild < queue.size()) {
        rightChild = leftChild + 1;
        if ((rightChild < queue.size())
                && getComparator().compare(queue.get(rightChild), queue.get(leftChild)) > 0) {
            leftChild = rightChild;
        }
        if (getComparator().compare(queue.get(leftChild), queue.get(root)) > 0) {
            swap(root, leftChild);
            heapify(leftChild);
        }
    }

}
例如,其他比较器可以是:

public class otherComparator{
    public int compare(Task t1, Task t2) {
        if (t1.getPriority() == t2.getPriority()) {
            return 0;
        } else if (t1.getPriority() < t2.getPriority()) {
            return 1;
        } else {
            return -1; 
        } //sorting min
    }
 }
结果是:

[d priority = 4, c  priority = 3, b priority = 2, a priority = 1]

    4
   / \
  3   2
 /
1 
没错。但是当我将
比较器
更改为
其他比较器
时:

otherComparator newComparator = new otherComparator();
heap.setComparator(newComparator);
System.out.println(heap.queue.toString());
结果是:

[b priority = 2, c  priority = 3, d priority = 4, a priority = 1]

    2
   / \
  3   4
 /
1 
这是错误的。正确答案是这样的:

[a priority = 1, b priority = 2, c  priority = 3, d priority = 4]

    1
   / \
  2   3
 /
4 

我想我的
heapify()
函数有问题。但我找不到错误。有人能帮忙吗?

您只需将最大堆更改为最小堆,这破坏了整个堆结构

问题是,当您更改比较器时,调用
heapify(0)
是不够的,因为,例如,此结构:

             4
            / \
           3   2
          /
         1
heapify
之后,1不会向上移动,因为在
heapify(0)
之后,程序会跳转到右侧的子级,即2,从该子级我们无法到达1

您可以创建另一个堆


您可以看到,基本上,在更改比较器时,您刚刚破坏了堆结构

您需要做的不仅仅是heapify down(正如您在heapify中所做的--将节点推到树下)或heapify up(正如您在offer方法中所做的--将节点拉到树上)。这些仅适用于分别在删除或添加时修复单个节点。堆的其余部分必须遵守堆规则

你需要彻底改变结构。这可以在线性时间内完成,从结构的底部开始,将每个根向下推到正确的子树。可以将其看作是为每个节点运行heapify down,子节点从完整树的末尾开始

rehapify arraynodes:
    for i from arraynodes.length / 2:
      heapifydown( arraynodes, i )
其中heapifydown是heapify函数。

我通过创建函数
rebuild()
来解决问题:
private void rebuild(){
HeapQueue reHeap=新HeapQueue();
reHeap.setComparator(比较仪);
对于(int i=0;i
你也可以共享你的交换函数吗?@PhamTung它就在那里。嗯,你如何将
其他比较器设置为堆的比较器?它没有实现相同的接口?@PhamTrung通过任务比较器可以更改堆,通过setComparator(),我可以更改比较器并通过heapify()重新构建堆。但是它不起作用。我明白了,好吧,我现在可以重现这个bug:)@AlexeySharov是的,原因是我的树结构不同,所以幸运的是它运行正确,但正如我上面指出的那样,
heapify(0)
还不够!如果这样做:
heap.offer(t1)
heap.offer(t2)
heap.offer(t3)
heap.offer(t4)你会遇到我的问题。我不能忘记heapify,因为我在
setComparator()
中有
heapify()
。为什么
heapify(0)
setComparator()
中还不够?这必须足够了。@AlexeySharov,不,冷静点,伙计:),请重新阅读我的解释,因为heapify是基于堆中的结构是正确的这一事实,但在这个堆中,当你从max更改为min heap时,所有条件都被违反了,所以你不能再指望heapify了。这不是我的问题。“也就是说,如果我保持数组不变,当我将一个元素附加到内部数组时会发生什么?”但我想在更改comparator并添加新元素后更改堆。对于每个
heapifyDown
,我看到它需要从上到下移动O(logn),这基本上是O(nlogn),但是,这不是一个严格的界限,你能提供一个数学证明这是O(n)吗?你的时间复杂度是log(n)+log(n-1)+…+日志1=log(n*(n-1)*(n-2)…)=log(n!)~O(n日志n)。更重要的是,它看起来只是那样,但每次通过都会越来越多地对树进行排序。
[a priority = 1, b priority = 2, c  priority = 3, d priority = 4]

    1
   / \
  2   3
 /
4 
             4
            / \
           3   2
          /
         1
rehapify arraynodes:
    for i from arraynodes.length / 2:
      heapifydown( arraynodes, i )
private void rebuild() {
    HeapQueue reHeap = new HeapQueue();
    reHeap.setComparator(comparator);
    for (int i = 0; i < queue.size(); i++) {
        reHeap.offer(queue.get(i));
    }
    queue = reHeap.queue;
}