我正在尝试编写一个小型F#线性代数库(对于具有小矩阵的应用程序,因此内存不是问题),我想知道哪个数据结构在元素查找时间方面具有最佳性能特征,因为我需要它来定义矩阵运算?
答案 0 :(得分:9)
我有点不清楚被问到了什么。
阵列当然是O(1),所以我希望它们是正确的答案。 (Brian的经验法则:如果你想要快速的东西,那么每种语言的答案都是一样的 - 使用一组结构。)
如果你需要更稀疏的东西,那就是.NET Dictionary
和HashSet
类(使用散列),以及F#Map
和Set
类型(使用树) /比较)。 Dictionary
可能是次佳尝试。
但是我当然希望这要么取决于细节(密度,地点/访问模式......),要么根本不重要(其他因素压倒它)。
在一天结束时,就像每个表现问题一样:衡量。
答案 1 :(得分:9)
如果“小”是2维或3维,那么结构。对于略大的“小”,请使用具有显式组件的引用类型。如果元素的数量超过大约30,那么使用单个数组并自己i + n*j
。避免使用.NET的2D数组,因为它们比必要的慢几倍。真的避免使用F#的Matrix
类型进行逐元素操作,因为它会像动态调度一样疯狂(速度慢一个数量级)。数组数组很好,但自己编制索引可以对索引进行更多的JIT优化。
答案 2 :(得分:2)
最有效的表示可能是一个可变数组(二维应该可以很好地工作)。索引的查找是O(1),因此它可以获得最高效率。即使数组是可变的,您仍然可以使用它来开发不可变(功能)矩阵类型 - 您需要做的就是避免变异数组。编译器不会检查这一点,但数据结构对于用户来说可以是纯粹的功能。
这样的事情可能是一个很好的起点:
// Constructor takes the data of the matrix
type Matrix(data:float[,]) =
// Expose data only for private purposes (cannot be mutated by the user!)
member private x.Data = data
// All operations create new array as the result
static member (+) (a:Matrix, b:Matrix) =
// TODO: Check that arrays have the same size
let res = Array2D.init (a.Data.GetLength(0)) (a.Data.GetLength(1))
(fun i j -> a.Data.[i, j] + a.Data.[i, j])
new Matrix<_>(res)