我正在寻找.Net 4.0中的分类键控数据结构,支持以下功能:
O(n log n)
时间O(log n)
时间O(log n)
时间内找到大于或等于给定参数的集合中的最小项(我们最有可能使用double
键入它)O(log n)
我快速查看了SortedDictionary
和SortedList
,但它们似乎没有从上面的列表中提供(3)和(4)。 SortedDictionary
似乎不支持(5),
我不确定SortedList
是否支持(6)。
不幸的是,我们仅限于.Net4
。
答案 0 :(得分:0)
您需要编写自己的收藏。从概念上讲,您想要的是基于树的结构,这就是SortedDictionary
的实现方式。底层结构具有完成所有这些任务的潜力,.NET实现根本不会公开它们,也不提供对足够的底层工具的访问来实现这些目标,迫使您从头开始。 / p>
幸运的是,构建这样的基于树的结构对于介绍性程序员来说是一项常见的任务,因此您可以找到大量开源的第三方实现,以实现您的目标,或作为一个开始地点。如果需要,您还可以考虑grabbing the source of SortedDictionary并重新编译自己的版本。
答案 1 :(得分:0)
我为你创建了一个排序字典。我希望它符合您的需求。
public class MyDictionary<TKey, TItem> : IDictionary<TKey, TItem>
where TKey : IComparable<TKey>
where TItem : IEquatable<TItem>
{
private readonly List<TKey> keys;
private readonly List<TItem> items;
private readonly ReadOnlyCollection<TKey> roKeys;
private readonly ReadOnlyCollection<TItem> roItems;
public MyDictionary()
{
keys = new List<TKey>();
items = new List<TItem>();
roKeys = new ReadOnlyCollection<TKey>(keys);
roItems = new ReadOnlyCollection<TItem>(items);
}
public MyDictionary(int capacity)
{
keys = new List<TKey>(capacity);
items = new List<TItem>(capacity);
roKeys = new ReadOnlyCollection<TKey>(keys);
roItems = new ReadOnlyCollection<TItem>(items);
}
public MyDictionary(TKey[] keys, TItem[] items)
{
if (keys == null)
throw new ArgumentNullException("keys");
if (items == null)
throw new ArgumentNullException("items");
if (keys.Length != items.Length)
throw new ArgumentException("Arrays lengths must be equal.");
TKey[] keysCopy = new TKey[keys.Length];
keys.CopyTo(keysCopy, 0);
TItem[] itemsCopy = new TItem[items.Length];
items.CopyTo(itemsCopy, 0);
Array.Sort(keysCopy, itemsCopy);
this.keys = new List<TKey>(keysCopy);
this.items = new List<TItem>(itemsCopy);
roKeys = new ReadOnlyCollection<TKey>(keys);
roItems = new ReadOnlyCollection<TItem>(items);
}
public int BinarySearch(TKey key)
{
return keys.BinarySearch(key);
}
public bool ContainsKey(TKey key)
{
return BinarySearch(key) >= 0;
}
public void Add(TKey key, TItem item)
{
int index = BinarySearch(key);
if (index >= 0)
throw new ArgumentException(String.Format("The key {0} already exists.", key), "key");
index = ~index;
keys.Insert(index, key);
items.Insert(index, item);
}
public void Add(KeyValuePair<TKey, TItem> item)
{
Add(item.Key, item.Value);
}
public bool Remove(TKey key)
{
int index = BinarySearch(key);
if (index < 0)
return false;
keys.RemoveAt(index);
items.RemoveAt(index);
return true;
}
public bool Remove(KeyValuePair<TKey, TItem> item)
{
int index = BinarySearch(item.Key);
if (index < 0)
return false;
index = ~index;
keys.RemoveAt(index);
items.RemoveAt(index);
return true;
}
public bool Contains(KeyValuePair<TKey, TItem> item)
{
int index = BinarySearch(item.Key);
if (index < 0)
return false;
index = ~index;
return items[index].Equals(item.Value);
}
public bool TryGetValue(TKey key, out TItem value)
{
int index = BinarySearch(key);
if (index < 0)
{
value = default(TItem);
return false;
}
value = items[index];
return true;
}
public TItem this[TKey key]
{
get
{
int index = BinarySearch(key);
if (index < 0)
throw new ArgumentException(String.Format("The key {0} not found.", key), "key");
return items[index];
}
set
{
int index = BinarySearch(key);
if (index < 0)
throw new ArgumentException(String.Format("The key {0} not found.", key), "key");
items[index] = value;
}
}
public ICollection<TKey> Keys
{
get { return roKeys; }
}
public ICollection<TItem> Values
{
get { return roItems; }
}
public IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()
{
return keys.Select((t, i) => new KeyValuePair<TKey, TItem>(t, items[i])).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Clear()
{
keys.Clear();
items.Clear();
}
public void CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)
{
Array.Copy(keys.Select((t, i) => new KeyValuePair<TKey, TItem>(t, items[i])).ToArray(), 0, array, arrayIndex, Count);
}
public int Count
{
get { return keys.Count; }
}
public int Capacity
{
get { return keys.Capacity; }
set
{
if (value < 0)
throw new ArgumentOutOfRangeException("value");
keys.Capacity = value;
items.Capacity = value;
}
}
public bool IsReadOnly
{
get { return false; }
}
public int GetSmallerOrEqualIndex(TKey key)
{
int index = BinarySearch(key);
if (index >= 0)
return index;
index = ~index;
return index - 1;
}
public int GetGreaterOrEqualIndex(TKey key)
{
int index = BinarySearch(key);
if (index >= 0)
return index;
index = ~index;
return index;
}
public KeyValuePair<TKey, TItem> GetItem(int index)
{
return new KeyValuePair<TKey, TItem>(keys[index], items[index]);
}
}
要求:
MyDictionary(TKey[] keys, TItem[] items)
构造函数初始化通常是O(n log n)操作,在最坏的情况下,它是O(n ^ 2)操作。添加单个项目是O(n)操作。 GetGreaterOrEqualIndex
方法)。 GetSmallerOrEqualIndex
方法)。