排序数据结构

时间:2014-03-19 16:10:04

标签: c# .net dictionary sortedlist sorteddictionary

我正在寻找.Net 4.0中的分类键控数据结构,支持以下功能:

  1. O(n log n)时间
  2. 中创建结构
  3. O(log n)时间
  4. 中按键获取项目
  5. O(log n)时间内找到大于或等于给定参数的集合中的最小项(我们最有可能使用double键入它)
  6. O(log n)
  7. 中找到小于给定参数的最大项目
  8. 对于集合中的给定项目,获取下一个和上一个项目
  9. 密钥在集合中必须是唯一的
  10. 我快速查看了SortedDictionarySortedList,但它们似乎没有从上面的列表中提供(3)和(4)。 SortedDictionary似乎不支持(5), 我不确定SortedList是否支持(6)。

    不幸的是,我们仅限于.Net4

2 个答案:

答案 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]);
    }
}

要求:

  1. 不满意(我正在努力)。目前,通过MyDictionary(TKey[] keys, TItem[] items)构造函数初始化通常是O(n log n)操作,在最坏的情况下,它是O(n ^ 2)操作。添加单个项目是O(n)操作。
  2. 满意。
  3. 满意(GetGreaterOrEqualIndex方法)。
  4. 满意(GetSmallerOrEqualIndex方法)。
  5. 如果我正确理解“给定项目”,则不直接满意,但对项目索引感到满意。
  6. 满意。