Индекс по набору данных?
От: Sinix  
Дата: 25.01.11 04:40
Оценка:
В очередной раз припёрло.
Надо переизобрести как можно более шустрый велосипед с вот таким вот интерфейсом:
  interface IStorageIndex<T> // для всех T есть EqualityComparer, для большей части - ещё и Comparer<T>
  {
    // index изменяться не будет, value - не уникальное. Распределение заранее неизвестно.
    void AddIndex(T value, int index);
    void RemoveIndex(T value, int index);

    int[] IndexesOf(T value); // обязательно O(1).
  }


Подозреваю, что много не выжать — индекс на ~5 млн элементов уже сейчас строится за секунду-две. На практике коллекции будут в пару-тройку тысяч элементов, но зато их будет несколько десятков и изменяться они будут достаточно часто.

Все реализации "в лоб" идут нос к носу — надо копать в сторону алгоритмической сложности. Как пример:
  internal class StorageIndex<T>: IStorageIndex<T>
  {
    private Dictionary<T, SortedSet<int>> valueIndexes;
    private SortedSet<int> nullValueIndexes;

    public StorageIndex(IEqualityComparer<T> valueComparer)
    {
      this.valueIndexes = new Dictionary<T, SortedSet<int>>(valueComparer);
      this.nullValueIndexes = new SortedSet<int>();
    }

    private bool TryGetIndexes(T value, out SortedSet<int> indexes)
    {
      bool result;
      if (value == null)
      {
        indexes = nullValueIndexes;
        result = true;
      }
      else
      {
        result = valueIndexes.TryGetValue(value, out indexes);
      }
      return result;
    }

    public void AddIndex(T value, int index)
    {
      //EnumerableCode.ValidIndex(index, "index");
      SortedSet<int> indexes;
      if (TryGetIndexes(value, out indexes))
      {
        if (!indexes.Add(index))
        {
          //Code.Bug(@"Indexing already indexed value.");
        }
      }
      else
      {
        indexes = new SortedSet<int>() { index };
        valueIndexes.Add(value, indexes);
      }
    }

    public void RemoveIndex(T value, int index)
    {
      //EnumerableCode.ValidIndex(index, "index");
      SortedSet<int> indexes;

      bool removed = false;
      if (TryGetIndexes(value, out indexes))
      {
        removed = indexes.Remove(index);
      }
      if (!removed)
      {
        //Code.Bug(@"Removing index on non-indexed value.");
      }

      if (value != null && indexes.Count == 0)
      {
        valueIndexes.Remove(value);
      }
    }

    public int[] IndexesOf(T value)
    {
      SortedSet<int> indexes;
      return TryGetIndexes(value, out indexes) ?
        indexes.ToArray() :
        new int[0];
    }
  }


Может, на RB tree поменять?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.