Во-первых, вы обязательно должны использовать Dictionary<TKey, TValue>
вместо Hashtable
- если вы используете BigInteger
из .NET 4, нет причин не использовать универсальные коллекции везде , которые вы можете использовать. Скорее всего, по большей части вы не увидите никакой разницы в том, как он используется - просто создайте его с помощью:
Dictionary<BigInteger, BigInteger> map =
new Dictionary<BigInteger, BigInteger>();
для начала. Следует обратить внимание на то, что индексатор выдаст исключение, если ключ отсутствует на карте - используйте TryGetValue
, чтобы получить значение, если оно существует, и bool
, чтобы сказать, или нет существовал .
Что касается поиска ключа по значению - нет способа сделать это эффективно из Dictionary
. Вы можете искать все записи, что проще всего сделать с помощью LINQ:
var key = map.Where(pair => pair.Value == value)
.Select(pair => pair.Key)
.First();
но он будет перебирать весь словарь, пока не найдет совпадение, поэтому это операция O (n).
Если вы хотите сделать это эффективно, вам следует сохранить два словаря - один от a
до a^j
и один от a^j
до a
. Когда вы добавляете запись, добавьте ее в обе стороны. Где-то в переполнении стека у меня есть пример кода класса, который делает это для вас, но я сомневаюсь, что смогу найти его легко. РЕДАКТИРОВАТЬ: есть один, который справляется с несколькими сопоставлениями здесь ; версия «с одним отображением» находится в ответе под этим.
В любом случае, если у вас есть два словаря, по одному в каждом направлении, это легко - очевидно, вы просто посмотрите a^m
как ключ во втором словаре, чтобы найти исходное значение, которое его создало.
Обратите внимание, что вам нужно подумать, возможно ли, чтобы два исходных ключа имели одно и то же значение - в этот момент вы, очевидно, не сможете иметь оба отображения в одном обратном словаре (если это не было Dictionary<BigInteger, List<BigInteger>>
или что-то подобное).