Skip to content

Commit 8a9c522

Browse files
Introduced fixed min heap for Top
1 parent 12d74ce commit 8a9c522

File tree

4 files changed

+351
-0
lines changed

4 files changed

+351
-0
lines changed

src/Tests/Test_CFixedMinHeap.java

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package Tests;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.stream.Collectors;
6+
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
10+
import YASL.Collectors.Heap.CFixedMinHeap;
11+
import YASL.Collectors.Heap.CprSimple;
12+
13+
public class Test_CFixedMinHeap {
14+
15+
@Test
16+
public void addSingleItem() {
17+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(3);
18+
queue.add(new CItem("test", 2));
19+
Assert.assertEquals( //
20+
"test 2", //
21+
queue.print() //
22+
);
23+
}
24+
25+
@Test
26+
public void lowerPriorityBubbleUp() {
27+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
28+
queue.add(new CItem("test", 2));
29+
queue.add(new CItem("lower", 1));
30+
Assert.assertTrue( //
31+
queue.print(), //
32+
queue.print().startsWith("lower 1") //
33+
);
34+
queue.add(new CItem("not lowest", 2));
35+
Assert.assertTrue( //
36+
queue.print(), //
37+
queue.print().startsWith("lower 1") //
38+
);
39+
40+
queue.add(new CItem("lowest", 0));
41+
Assert.assertTrue( //
42+
queue.print(), //
43+
queue.print().startsWith("lowest 0") //
44+
);
45+
}
46+
47+
@Test
48+
public void getByKey() {
49+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
50+
for (int i = 0; i < 5; i++) {
51+
queue.add(new CItem("item" + i, i));
52+
}
53+
for (int i = 0; i < 5; i++) {
54+
Assert.assertEquals(i, queue.get("item" + i).Priority());
55+
}
56+
}
57+
58+
@Test
59+
public void getNotExisted() {
60+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
61+
Assert.assertEquals(null, queue.get("item"));
62+
}
63+
64+
@Test
65+
public void returnLowest() {
66+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
67+
for (int i = 5; 0 < i; i--) {
68+
queue.add(new CItem("item" + i, i));
69+
Assert.assertEquals(i, queue.lowest().Priority());
70+
}
71+
}
72+
73+
@Test
74+
public void pollLowest() {
75+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
76+
for (int i = 0; i < 5; i++)
77+
queue.add(new CItem("item" + i, i));
78+
79+
for (int i = 1; i < 5; i++) {
80+
queue.poll();
81+
Assert.assertTrue( //
82+
queue.print(), //
83+
queue.print().startsWith("item" + i) //
84+
);
85+
}
86+
}
87+
88+
@Test
89+
public void increasePriority() {
90+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
91+
for (int i = 0; i < 5; i++) {
92+
queue.add(new CItem("item" + i, i));
93+
}
94+
final CItem item = queue.get("item3");
95+
item.setPriority(6); // top
96+
queue.update(item.value);
97+
98+
Assert.assertEquals( //
99+
"item0 0 | item1 1 | item2 2 | item3 6 | item4 4", //
100+
queue.print() //
101+
);
102+
}
103+
104+
@Test
105+
public void decreasePriority() {
106+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(5);
107+
for (int i = 0; i <= 4; i++) {
108+
queue.add(new CItem("item" + i, i));
109+
}
110+
final CItem item = queue.get("item3");
111+
item.setPriority(-1);
112+
queue.update(item.value);
113+
114+
Assert.assertEquals(item.value, queue.lowest().value);
115+
}
116+
117+
@Test
118+
public void pollMustEraseItem() {
119+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(4);
120+
queue.add(new CItem("item", 0));
121+
queue.poll();
122+
Assert.assertEquals(null, queue.get("item"));
123+
}
124+
125+
@Test
126+
public void storeOnlyMaximalItem() {
127+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(1);
128+
for (int i = 0; i <= 5; i++) {
129+
queue.add(new CItem("item" + i, i));
130+
}
131+
Assert.assertEquals( //
132+
"item5 5", //
133+
queue.print() //
134+
);
135+
}
136+
137+
@Test
138+
public void rejectItemSmallerThanLowest() {
139+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(2);
140+
queue.add(new CItem("A", 6));
141+
queue.add(new CItem("B", 7));
142+
for (int i = 0; i <= 5; i++)
143+
queue.add(new CItem("item" + i, i));
144+
145+
Assert.assertEquals( //
146+
"A 6 | B 7", //
147+
queue.print() //
148+
);
149+
}
150+
151+
@Test
152+
public void returnOrderedItems() {
153+
CFixedMinHeap<CItem, String> queue = new CFixedMinHeap<>(3);
154+
for (int i = 5; 0 < i; i--) {
155+
queue.add(new CItem("item" + i, i));
156+
}
157+
158+
final List<String> items = queue.items().stream() //
159+
.map(x -> x.value)//
160+
.collect(Collectors.toList()); //
161+
162+
Assert.assertEquals( //
163+
Arrays.asList("item5", "item4", "item3"), //
164+
items //
165+
);
166+
}
167+
}
168+
169+
class CItem extends CprSimple<String> implements Comparable<CItem> {
170+
public CItem(String value, int priority) {
171+
super(value, priority);
172+
}
173+
174+
public void setPriority(int i) {
175+
_priority = i;
176+
}
177+
178+
@Override
179+
public String toString() {
180+
return value.toString() + " " + Priority();
181+
}
182+
183+
@Override
184+
public int compareTo(CItem o) {
185+
final int diff = o._priority - _priority;
186+
if (0 != diff)
187+
return diff;
188+
return o.value.compareTo(value);
189+
}
190+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package YASL.Collectors.Heap;
2+
3+
import java.lang.reflect.Array;
4+
import java.util.ArrayList;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
public class CFixedMinHeap<T extends IPrioritizedItem<TKey>, TKey> {
10+
private final CbhItem<T>[] _items;
11+
private final Map<TKey, CbhItem<T>> _byValue;
12+
private int _count = 0;
13+
14+
@SuppressWarnings("unchecked")
15+
public CFixedMinHeap(int size) {
16+
_items = (CbhItem[]) Array.newInstance(CbhItem.class, size);
17+
_byValue = new HashMap<>();
18+
}
19+
20+
public T poll() {
21+
final T res = lowest();
22+
_count--;
23+
swap(_items[_count], _items[0]);
24+
_items[_count] = null;
25+
_byValue.remove(res.Value());
26+
if (0 < _count)
27+
bubbleDown(_items[0]);
28+
return res;
29+
}
30+
31+
public T lowest() {
32+
return _items[0].Item;
33+
}
34+
35+
public void update(TKey key) {
36+
final CbhItem<T> item = _byValue.get(key);
37+
bubbleUp(item);
38+
bubbleDown(item);
39+
}
40+
41+
public void add(T item) {
42+
if (_count == _items.length) {
43+
if (item.Priority() < lowest().Priority())
44+
return;
45+
poll();
46+
}
47+
48+
final CbhItem<T> node = new CbhItem<T>(item, _count);
49+
_items[_count] = node;
50+
_byValue.put(item.Value(), node);
51+
bubbleUp(node);
52+
_count++;
53+
}
54+
55+
public T get(TKey key) {
56+
final CbhItem<T> item = _byValue.get(key);
57+
return (null == item) ? null : item.Item;
58+
}
59+
60+
public String print() {
61+
final StringBuilder res = new StringBuilder();
62+
String sepp = "";
63+
for (int i = 0; i < _count; i++) {
64+
final CbhItem<T> item = _items[i];
65+
res.append(sepp);
66+
res.append(item.Item.toString());
67+
sepp = " | ";
68+
}
69+
return res.toString();
70+
}
71+
72+
private void swap(CbhItem<T> first, CbhItem<T> second) {
73+
final int oldIndex = second.Index;
74+
second.Index = first.Index;
75+
first.Index = oldIndex;
76+
77+
_items[first.Index] = first;
78+
_items[second.Index] = second;
79+
}
80+
81+
private void bubbleDown(CbhItem<T> node) {
82+
while (true) {
83+
CbhItem<T> best = node;
84+
85+
for (int childID = 0; childID < 2; childID++) {
86+
final int ind = (node.Index << 1) + 1 + childID;
87+
if (ind < _count) {
88+
final CbhItem<T> child = _items[ind];
89+
if (isBigger(best, child)) {
90+
best = child;
91+
}
92+
}
93+
}
94+
95+
if (best.Index == node.Index)
96+
break;
97+
swap(best, node);
98+
}
99+
}
100+
101+
private void bubbleUp(CbhItem<T> node) {
102+
while (0 < node.Index) {
103+
final CbhItem<T> parent = _items[(node.Index - 1) >> 1];
104+
if (isBigger(node, parent))
105+
break;
106+
swap(parent, node);
107+
}
108+
}
109+
110+
private boolean isBigger(CbhItem<T> first, CbhItem<T> second) {
111+
final int diff = first.Item.Priority() - second.Item.Priority();
112+
return 0 < diff;
113+
}
114+
115+
public List<T> items() {
116+
List<T> res = new ArrayList<>(_count);
117+
for (int i = 0; i < _count; i++) {
118+
res.add(_items[i].Item);
119+
}
120+
res.sort(null);
121+
return res;
122+
}
123+
124+
125+
private static class CbhItem<T> {
126+
public final T Item;
127+
public int Index;
128+
129+
public CbhItem(T item, int index) {
130+
Item = item;
131+
Index = index;
132+
}
133+
}
134+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package YASL.Collectors.Heap;
2+
3+
public class CprSimple<T> implements IPrioritizedItem<T> {
4+
public final T value;
5+
protected int _priority;
6+
7+
public CprSimple(T value, int priority) {
8+
this.value = value;
9+
_priority = priority;
10+
}
11+
12+
@Override
13+
public int Priority() {
14+
return _priority;
15+
}
16+
17+
@Override
18+
public T Value() {
19+
return value;
20+
}
21+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package YASL.Collectors.Heap;
2+
3+
public interface IPrioritizedItem<T> {
4+
public int Priority();
5+
public T Value();
6+
}

0 commit comments

Comments
 (0)