Реализация Dictionary на основе списка или вектора
Задание: реализовать свой обобщенный Dictionary на основе списка или массива.
Вопрос: список или массив лучше выбрать за основу? На сколько знаю, если брать список то поиск будет O(n), если отсортированный - O(log n), но в Dictionary должен же быть O(1). Знаю что в .net Dictionary написан на хеш-таблице, возможно ли написать хеш-таблицу на основе массива или списка? Подскажите какой выбор будет оптимальней?
Ответы (1 шт):
Автор решения: juliion
→ Ссылка
В итоге сделала на двухсвязном списке. Вот если кому-то интересно. Буду рада любым комментариям.
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly DoublyLinkedList<KeyValuePair<TKey, TValue>> _items;
public TValue this[TKey key]
{
get => _items.FirstOrDefault(item => item.Key.Equals(key)).Value;
set => Add(key, value);
}
public ICollection<TKey> Keys => (ICollection<TKey>)_items.Select(item => item.Key);
public ICollection<TValue> Values => (ICollection<TValue>)_items.Select(item => item.Value);
public int Count => _items.Count;
public bool IsReadOnly => false;
public Dictionary()
{
_items = new DoublyLinkedList<KeyValuePair<TKey, TValue>>();
}
public void Add(TKey key, TValue value)
{
if (key == null)
throw new ArgumentException(nameof(key));
if (value == null)
throw new ArgumentException(nameof(value));
Add(new KeyValuePair<TKey, TValue>(key, value));
}
public void Add(KeyValuePair<TKey, TValue> item)
{
if (ContainsKey(item.Key))
throw new ArgumentException($"The dictionary already contains a value with key {item.Key}", nameof(item));
_items.Add(item);
}
public void Clear()
{
_items.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _items.Contains(item);
}
public bool ContainsKey(TKey key)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
return _items.Any(item => item.Key.Equals(key));
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
{
_items.CopyTo(array, index);
}
public bool Remove(TKey key)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
return Remove(_items.FirstOrDefault(item => item.Key.Equals(key)));
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
if(!ContainsKey(item.Key))
return false;
return _items.Remove(item);
}
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
if (!ContainsKey(key))
{
value = default(TValue);
return false;
}
value = this[key];
return true;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var item in _items)
{
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this).GetEnumerator();
}