SortedSet.Remove()不会删除任何内容

van*_*zen 2 c# graph dijkstra sortedset

我目前正在实现Dijkstra的算法,我使用C#SortedSet作为优先级队列.但是,为了跟踪我已经访问过的顶点,我想从优先级队列中删除第一个项目.

这是我的代码:

static int shortestPath(int start, int target)
    {
        SortedSet<int> PQ = new SortedSet<int>(new compareByVertEstimate());
        for (int i = 0; i < n; i++)
        {
            if (i == start - 1)
                vertices[i].estimate = 0;
            else
                vertices[i].estimate = int.MaxValue;

            PQ.Add(i);
        }

        int noOfVisited = 0;
        while (noOfVisited < n)
        {
            int u = PQ.First();
            noOfVisited++;

            foreach (Edge e in vertices[u].neighbours)
            {
                if (vertices[e.target.Item1].estimate > vertices[u].estimate + e.length)
                {
                    vertices[e.target.Item1].estimate = vertices[u].estimate + e.length;
                }
            }

            PQ.Remove(u);
        }
        return vertices[target - 1].estimate;
    }
Run Code Online (Sandbox Code Playgroud)

这是比较器:

public class compareByVertEstimate : IComparer<int>
{
    public int Compare(int a, int b)
    {

        if (Program.vertices[a].estimate >= Program.vertices[b].estimate) return 1;
        else return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的优先级队列没有显式保存顶点,而是我有一个顶点数组,优先级队列保存索引.因此,优先级队列基于每个顶点所包含的"估计"整数进行排序.

现在我的问题是,我可以使用.First()或.Min轻松地从SortedSet中检索第一个元素,但是当我尝试使用.Remove()删除该元素时,该方法返回false,并且不会删除任何内容.SortedSet保持不变.

有想法该怎么解决这个吗?

提前致谢!

编辑 我将Comparer更改为:

public class compareByVertEstimate : IComparer<int>
{
    public int Compare(int a, int b)
    {

        if (Program.vertices[a].estimate == Program.vertices[b].estimate) return 0;
        else if (Program.vertices[a].estimate >= Program.vertices[b].estimate) return 1;
        else return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

但现在优先级队列不再包含所有正确的元素.(注意,优先级队列将包含指向具有相同估计值的顶点的指针)

nvo*_*igt 6

您的比较函数从不将两个元素比较为equal(return 0;).

您的集合将无法删除与其包含的任何元素不相等的元素.

例:

public class compareByVertEstimate : IComparer<int>
{
    public int Compare(int a, int b)
    {

        if (a == b) return 0;

        if (Program.vertices[a].estimate >= Program.vertices[b].estimate) return 1;

        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

@hvd当然是正确的,虽然上面的版本有效,但它很破碎.一个更好的比较者可能是:

public class compareByVertEstimate : IComparer<int>
{
    public int Compare(int a, int b)
    {
        var ae = Program.vertices[a].estimate;
        var be = Program.vertices[b].estimate; 

        var result = ae.CompareTo(be);

        if (result == 0) return a.CompareTo(b);

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)