Skip to content

Commit 52b4668

Browse files
authored
PriorityQueue fix (#569)
1 parent 11506de commit 52b4668

File tree

2 files changed

+120
-23
lines changed

2 files changed

+120
-23
lines changed

Rx.NET/Source/src/System.Reactive/Internal/PriorityQueue.cs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,51 +29,38 @@ private bool IsHigherPriority(int left, int right)
2929
return _items[left].CompareTo(_items[right]) < 0;
3030
}
3131

32-
private void Percolate(int index)
32+
private int Percolate(int index)
3333
{
3434
if (index >= _size || index < 0)
35-
{
36-
return;
37-
}
38-
35+
return index;
3936
var parent = (index - 1) / 2;
4037
if (parent < 0 || parent == index)
41-
{
42-
return;
43-
}
38+
return index;
4439

4540
if (IsHigherPriority(index, parent))
4641
{
4742
var temp = _items[index];
4843
_items[index] = _items[parent];
4944
_items[parent] = temp;
50-
Percolate(parent);
45+
return Percolate(parent);
5146
}
52-
}
5347

54-
private void Heapify() => Heapify(index: 0);
48+
return index;
49+
}
5550

5651
private void Heapify(int index)
5752
{
5853
if (index >= _size || index < 0)
59-
{
6054
return;
61-
}
6255

6356
var left = 2 * index + 1;
6457
var right = 2 * index + 2;
6558
var first = index;
6659

6760
if (left < _size && IsHigherPriority(left, first))
68-
{
6961
first = left;
70-
}
71-
7262
if (right < _size && IsHigherPriority(right, first))
73-
{
7463
first = right;
75-
}
76-
7764
if (first != index)
7865
{
7966
var temp = _items[index];
@@ -98,7 +85,8 @@ private void RemoveAt(int index)
9885
_items[index] = _items[--_size];
9986
_items[_size] = default(IndexedItem);
10087

101-
Heapify();
88+
if (Percolate(index) == index)
89+
Heapify(index);
10290

10391
if (_size < _items.Length / 4)
10492
{
@@ -152,10 +140,7 @@ public int CompareTo(IndexedItem other)
152140
{
153141
var c = Value.CompareTo(other.Value);
154142
if (c == 0)
155-
{
156143
c = Id.CompareTo(other.Id);
157-
}
158-
159144
return c;
160145
}
161146
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System.Reactive;
2+
using Xunit;
3+
4+
namespace ReactiveTests.Tests
5+
{
6+
public class PriorityQueueTest
7+
{
8+
[Fact]
9+
public void Enqueue_dequeue()
10+
{
11+
var q = new PriorityQueue<int>();
12+
13+
for (var i = 0; i < 16; i++)
14+
{
15+
Assert.Equal(0, q.Count);
16+
17+
q.Enqueue(i);
18+
19+
Assert.Equal(1, q.Count);
20+
Assert.Equal(i, q.Peek());
21+
Assert.Equal(1, q.Count);
22+
Assert.Equal(i, q.Dequeue());
23+
Assert.Equal(0, q.Count);
24+
}
25+
}
26+
27+
[Fact]
28+
public void Enqueue_all_dequeue_all()
29+
{
30+
var q = new PriorityQueue<int>();
31+
32+
for (var i = 0; i < 33; i++)
33+
{
34+
q.Enqueue(i);
35+
Assert.Equal(i + 1, q.Count);
36+
}
37+
38+
Assert.Equal(33, q.Count);
39+
40+
for (var i = 0; i < 33; i++)
41+
{
42+
Assert.Equal(33 - i, q.Count);
43+
Assert.Equal(i, q.Peek());
44+
Assert.Equal(i, q.Dequeue());
45+
}
46+
47+
Assert.Equal(0, q.Count);
48+
}
49+
50+
[Fact]
51+
public void Reverse_Enqueue_all_dequeue_all()
52+
{
53+
var q = new PriorityQueue<int>();
54+
55+
for (var i = 32; i >= 0; i--)
56+
{
57+
q.Enqueue(i);
58+
Assert.Equal(33 - i, q.Count);
59+
}
60+
61+
Assert.Equal(33, q.Count);
62+
63+
for (var i = 0; i < 33; i++)
64+
{
65+
Assert.Equal(33 - i, q.Count);
66+
Assert.Equal(i, q.Peek());
67+
Assert.Equal(i, q.Dequeue());
68+
}
69+
70+
Assert.Equal(0, q.Count);
71+
}
72+
73+
[Fact]
74+
public void Remove_from_middle()
75+
{
76+
var q = new PriorityQueue<int>();
77+
78+
for (var i = 0; i < 33; i++)
79+
{
80+
q.Enqueue(i);
81+
}
82+
83+
q.Remove(16);
84+
85+
for (var i = 0; i < 16; i++)
86+
{
87+
Assert.Equal(i, q.Dequeue());
88+
}
89+
90+
for (var i = 16; i < 32; i++)
91+
{
92+
Assert.Equal(i + 1, q.Dequeue());
93+
}
94+
}
95+
96+
[Fact]
97+
public void Repro_329()
98+
{
99+
var queue = new PriorityQueue<int>();
100+
101+
queue.Enqueue(2);
102+
queue.Enqueue(1);
103+
queue.Enqueue(5);
104+
queue.Enqueue(2);
105+
106+
Assert.Equal(1, queue.Dequeue());
107+
Assert.Equal(2, queue.Dequeue());
108+
Assert.Equal(2, queue.Dequeue());
109+
Assert.Equal(5, queue.Dequeue());
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)