【发布时间】:2021-04-18 16:43:02
【问题描述】:
我想首先说我的代码按预期工作,并且相当快。不管如何分析它,大部分时间都花在一个非常具体的部分上,这让我问:有没有普遍接受的更好的解决方案?
这是我的实现:
var cellDistance = new double[cells.Count];
cellDistance.SetAll(idx => idx == startCellIndex ? 0 : double.PositiveInfinity);
var visitedCells = new HashSet<int>();
do
{
// current cell is the smallest unvisited tentative distance cell
var currentCell = cells[cellDistance.Select((d, idx) => (d, idx)).OrderBy(x => x.d).First(x => !visitedCells.Contains(cells[x.idx].Index)).idx];
foreach (var neighbourCell in currentCell.Neighbours)
if (!visitedCells.Contains(neighbourCell.Index))
{
var distanceThroughCurrentCell = cellDistance[currentCell.Index] + neighbourCell.Value;
if (cellDistance[neighbourCell.Index] > distanceThroughCurrentCell)
{
cellDistance[neighbourCell.Index] = distanceThroughCurrentCell;
prevCell[neighbourCell] = currentCell;
}
}
visitedCells.Add(currentCell.Index);
} while (visitedCells.Count != cells.Count && !visitedCells.Contains(endCell.Index));
大部分时间都花在了这一行上,它取的是未访问过的具有最低部分成本的节点:
var currentCell = cells[cellDistance.Select((d, idx) => (d, idx)).OrderBy(x => x.d).First(x => !visitedCells.Contains(cells[x.idx].Index)).idx];
更具体地说,在最后一个 lambda 中,不是那种(我觉得非常令人惊讶):
x => !visitedCells.Contains(cells[x.idx].Index)
由于visitedCells 已经是HashSet,仅使用内置数据结构我无法改进,所以我的问题是:是否有不同的方式来存储部分成本,使其具体化查询(即具有最低部分成本的未访问节点)明显更快?
我正在考虑某种排序字典,但我需要一个按值排序的字典,因为如果它按键排序,我必须将部分成本设为键,这使得更新它的成本很高,然后构成关于我如何将此结构映射到我的成本数组的问题,这仍然不能解决我的visitedCells 查找问题。
【问题讨论】: