【发布时间】:2019-09-24 04:52:17
【问题描述】:
我正在尝试实现一个优先级队列,它的功能与普通优先级队列有点不同。这里的想法是支持快速插入,但对最高优先级项目的访问速度较慢。在这种情况下,Insert 方法将新项目放在方便的地方;因此,remove 和 peek 方法必须在整个队列中搜索最高优先级的项目。
public class MinPriorityQueue {
/** Constructs a new MinPriorityQueue with capacity cap and size 0.
*
* @param cap Capacity of the new queue.
*/
public MinPriorityQueue(int cap) {
this.queue = (Comparable []) new Comparable[cap];
this.size = 0;
this.cap = cap;
}
int size() {
return this.size;
}
int capacity() {
return this.cap;
}
boolean isEmpty() {
return this.size==0;
}
boolean isFull() {
return this.size == cap;
}
void insert(Comparable e) {
if (this.size == cap) {
throw new IllegalStateException();
}
queue[size] = e;
size++;
Comparable remove() {
if (this.size == 0) {
throw new IllegalStateException();
}
int maxIndex = 0;
for (int i=1; i<size; i++) {
if (queue[i].compareTo (queue[maxIndex]) < 0) {
maxIndex = i;
}
}
Comparable result = queue[maxIndex];
size--;
queue[maxIndex] = queue[size];
return result;
}
/** Returns, but does not remove, the lowest-priority item in the
* queue.
*
* Complexity: O(n)
* @return Lowest priority item.
* @throws IllegalStateException if the queue is empty.
*/
Comparable top() {
if (this.size == 0) {
throw new IllegalStateException();
}
/* int i;
for (i=0; i < size; i++) {
if (queue[i].compareTo (size-1) < 0) {
break;
}
}
return queue[size - 1];*/
return queue[size-1];
}
Comparable[] queue; // Contents of the queue
private int cap;
private int size;
}
//// 测试文件
/**
* Test of remove method, of class MinPriorityQueue.
*/
@Test
public void testRemove() {
System.out.println("remove");
MinPriorityQueue q = new MinPriorityQueue(10);
boolean throws_exception = false;
try {
q.remove();
} catch (IllegalStateException e) {
throws_exception = true;
} catch (Throwable e) {
}
assertTrue("remove throws an exception when empty", throws_exception);
// Permutation of 0...9
int[] input = {0, 5, 9, 2, 3, 1, 6, 8, 7, 4};
for (int i : input) {
q.insert(i);
}
assertTrue(q.isFull());
for (int i = 10; i > 0; --i) {
assertEquals(q.size(), i);
Integer x = (Integer) q.remove();
assertEquals(x, new Integer(10 - i)); // Items are removed in correct order
}
assertTrue(q.isEmpty());
}
/**
* Test of top method, of class MinPriorityQueue.
*/
@Test
public void testTop() {
System.out.println("top");
MinPriorityQueue q = new MinPriorityQueue(10);
boolean throws_exception = false;
try {
q.top();
} catch (IllegalStateException x) {
throws_exception = true;
} catch (Throwable x) {
}
assertTrue("top throws an exception when empty", throws_exception);
int[] input = {0, 5, 9, 2, 3, 1, 6, 8, 7, 4};
int smallest = 10;
for (int i : input) {
q.insert(i);
if (i < smallest) {
smallest = i;
}
assertEquals(q.top(), smallest);
}
for (int i = 0; i < 10; ++i) {
assertEquals(q.top(), i);
q.remove();
}
}
我已经能够实现除 remove 和 peek 之外的所有方法,因为我无法获得实现这些方法的逻辑权。我无法弄清楚我们如何搜索整个队列以找到最高优先级的项目。对于这个,我相信应该使用 for 循环,但只是没有得到正确的逻辑
编辑:我能够为 remove() 方法获得正确的逻辑,只需要让 pop() 方法工作
【问题讨论】:
-
使用 remove 你只是在减小数组的大小,即使要删除的项目不在数组的末尾
-
是的。我正在尝试不同的东西来使逻辑正确。你能指导我如何使它正确吗。谢谢
-
@Scary Wombat 。我想出了 remove 方法的逻辑并更新了我的帖子。只需要让 pop() 方法工作
-
旁注:演员
(Comparable []) new Comparable[cap];是不必要的。queue[maxIndex] = queue[size];应该在size--之前发生,否则你会复制下一个元素并“删除”最后一个元素。 -
另一个:只使用
Comparable很危险,因为您可能会添加不兼容的类型(例如,尝试比较字符串和日期)。除此之外,这些元素没有 priority,因此您可能希望使用泛型来使用更具体的类型,或者与数据一起提供优先级并为元素使用专门的类.
标签: java priority-queue