我将通过列表[[a]]
列出项目中的矩阵这是一个好主意还是我应该更好地使用数组?
如何使用索引(i,j)
答案 0 :(得分:9)
当然,基于列表的解决方案永远不会像优化的紧密阵列那样快,因为必要的间接性以及所有缓存局部性问题。然而,这只是一个恒定的开销因素(可能很大,但大约为100)。
然而,有趣的是,对矩阵的嵌套列表方法并不像看起来那么糟糕:列表仍然是以传统的纯功能方式最自然地处理的数据结构。正如millimoose所说,你不能只是以纯粹的方式就地改变一个元素,你必须用一个元素改变整个事物的副本*。对于 n ✕ n 紧密阵列矩阵,这是 O ( n 2 ) - 对于较大的 n 几乎不可接受。
虽然长度 m 的列表中的随机访问已经 O ( m ),因此比数组更糟糕,对于更复杂的操作,它不会变得更糟。您可以“修改” O ( m )中的列表,您可以访问 n ✕ n 嵌套列表在 O ( n )中,您可以在 O ( n )中修改它!因此,如果您想对大型矩阵进行无损更新,[[a]]
实际上比Array a i
更快。
哦,这是如何工作的 - 好吧,像
type Matrix a = [[a]]
updateMatrixAt :: (Int,Int) -> (a->a) -> Matrix a -> Matrix a
updateMatrixAt(i,j) f mat
| (upperRows, thisRow : lowerRows ) <- splitAt i mat
, (leftCells, thisCell: rightCells) <- splitAt j thisRow
= upperRows
++ (leftCells ++ (f thisCell): rightCells)
: lowerRows
| otherwise = error "Tried to index matrix outside range"
会做到这一点。
*有have been attempts to avoid this,但我担心这已被证明是死路一条。如果你想要真正的高性能,你应该在ST
monad中使用破坏性更新,它没有任何问题,虽然它可能不太好。
答案 1 :(得分:5)
如何使用自己的数据类型包裹Map (Int,Int) a
?更改元素是微不足道的,特别是对于稀疏矩阵,您可以节省大量内存。
答案 2 :(得分:0)
如何使用索引(i,j)更改场所元素?
一般来说,你不能。您必须创建一个更改了一个元素的新矩阵。 (使用Array
代替列表会使the //
operator稍微容易一些。)看起来您可以使用MArray
进行就地更改,但几乎所有代码都会必须使用IO
。