Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PriorityQueue<TElement, TPriority>.Remove method violates min-heap invariant #107292

Closed
adetunji-david opened this issue Sep 3, 2024 · 3 comments · Fixed by #107550
Closed

PriorityQueue<TElement, TPriority>.Remove method violates min-heap invariant #107292

adetunji-david opened this issue Sep 3, 2024 · 3 comments · Fixed by #107550
Assignees
Labels
area-System.Collections in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@adetunji-david
Copy link

adetunji-david commented Sep 3, 2024

Description

The newly added Remove method in PriorityQueue<TElement, TPriority> violates the invariant of the internal min-heap structure. The current implementation pops the last element and performs a sift-down operation from the index of the removed element. However, it fails to handle scenarios where the last element should be sifted upwards, resulting in incorrect ordering in the priority queue.

Reproduction Steps

var q = new PriorityQueue<int, int>();
for (var i = 19; i >= 0; i--)
{
    q.Enqueue(i, i);
}

q.Remove(10, out var _, out var _);

while (q.Count > 0)
{
    Console.WriteLine(q.Dequeue());
}

Expected behavior

The code should print numbers from 0 to 19 in ascending order, except for 10.

Actual behavior

It prints 2 between 8 and 9
0
1
3
4
5
6
7
8
2
9
11
12
13
14
15
16
17
18
19

Regression?

No response

Known Workarounds

No response

Configuration

.NET version: 9.0 preview

Other information

No response

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Sep 3, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-collections
See info in area-owners.md if you want to be subscribed.

@jeffhandley jeffhandley added this to the 9.0.0 milestone Sep 3, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Sep 3, 2024
@jeffhandley
Copy link
Member

@krwq can you investigate this issue this week? We should target RC2 snap for this.

Thank you for finding and reporting this with a minimal repro, @adetunji-david!

@ocoanet
Copy link

ocoanet commented Sep 5, 2024

It seems that Remove assumes that the priority of lastNode is always greater than the priority of the removed node, which is not the case. If the priority of lastNode is lower than the priority of the removed node, it should probably be moved up:

if (_comparer == null)
{
    if (Comparer<TPriority>.Default.Compare(priority, lastNode.Priority) < 0)
        MoveDownDefaultComparer(lastNode, index);
    else
        MoveUpDefaultComparer(lastNode, index);
}
else
{
    if (_comparer.Compare(priority, lastNode.Priority) < 0)
        MoveDownCustomComparer(lastNode, index);
    else
        MoveUpCustomComparer(lastNode, index);
}

@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Sep 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Collections in-pr There is an active PR which will close this issue when it is merged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants