Если большинство ваших элементов нулевые, то, возможно, вам вообще не нужно создавать массив.
Джон предлагает один подход, который будет работать - реализация разреженного массива с использованием связанных списков. Вот еще один:
public struct CellLocation
{
int Row;
int Column;
}
public class Element
{
public Element(int row, int column)
{
Location = new CellLocation {Row = row, Column=column};
}
public readonly Location { get; private set; }
// your class's other properties and methods go here
}
Теперь вы можете хранить Element
объектов в Dictionary<CellLocation, Element>
. Фактически, я бы поместил этот словарь в собственный класс, чтобы он мог реализовывать такие методы, как:
public IEnumerable<Element> AdjacentElements(Element elm)
{
for (int row = -1; row <= 1; row++)
{
for (int column = -1; column <= 1; column++)
{
// elm isn't adjacent to itself
if (row == 0 && column == 0)
{
continue;
}
CellLocation key = new CellLocation {
Row=elm.Location.Row + row,
Column=elm.Location.Column + column
};
if (!Cells.ContainsKey(key))
{
continue;
}
yield return Cells[key];
}
}
}
Существуют операции, для которых это может быть быстрее, чем разреженный массив. Чтобы найти элемент в одной строке и столбце, разреженному массиву все еще необходимо выполнить линейный поиск, чтобы найти строку, а затем другой линейный поиск, чтобы найти столбец в этой строке, тогда как этот метод может найти элемент с одним поиском в хеш-таблица.
Есть также обстоятельства, при которых это будет существенно медленнее. Чтобы найти все элементы в строке, требуется столько же поисков в хеш-таблицах, сколько в строке есть ячеек, в то время как выполнение этого с разреженным массивом влечет за собой обход связанного списка.