C#常用集合的实现原理(SortedList)

SortedList 有序线性表

SortedList集合类是有序线性表,本质上是一颗二分查找树。

Add操作是通过二分查找到它应该被插入的下标,再通过Insert进行添加。

       public void Add(TKey key, TValue value) {
            if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
            int i = Array.BinarySearch<TKey>(keys, 0, _size, key, comparer);
            if (i >= 0)
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
            Insert(~i, key, value);
        }


        private void Insert(int index, TKey key, TValue value) {
            if (_size == keys.Length) EnsureCapacity(_size + 1);
            if (index < _size) {
                Array.Copy(keys, index, keys, index + 1, _size - index);
                Array.Copy(values, index, values, index + 1, _size - index);
            }
            keys[index] = key;
            values[index] = value;
            _size++;
            version++;
        }

通过Array.BinarySearch查找到当前元素应该插入的位置下标,再调用Insert方法添加到指定的位置。

    bool System.Collections.IDictionary.Contains(Object key) {
            if( IsCompatibleKey(key)) {
                return ContainsKey((TKey) key);
            }
            return false;
        }
 
        // Checks if this sorted list contains an entry with the given key.
        // 
        public bool ContainsKey(TKey key) {
            return IndexOfKey(key) >= 0;
        }
    
        // Checks if this sorted list contains an entry with the given value. The
        // values of the entries of the sorted list are compared to the given value
        // using the Object.Equals method. This method performs a linear
        // search and is substantially slower than the Contains
        // method.
        // 
        public bool ContainsValue(TValue value) {
            return IndexOfValue(value) >= 0;
        }
    

其Contains方法与Containskey方法通过二分查找检索元素,复杂度是O(lg n),ContainsValue方法是使用线性查找元素,复杂度是O(n)。

     public int IndexOfKey(TKey key) {
            if (key == null) 
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
            int ret = Array.BinarySearch<TKey>(keys, 0, _size, key, comparer);
            return ret >=0 ? ret : -1;
        }
    
     
        public int IndexOfValue(TValue value) {
            return Array.IndexOf(values, value, 0, _size);
        }

TryGetValue与索引器通过二分查找检索到指定的key的下标,再借此返回指定的value。

    public bool TryGetValue(TKey key, out TValue value) {
            int i = IndexOfKey(key);
            if (i >= 0) {
                value =values[i]; 
                return true;
            }
 
            value = default(TValue);
            return false;
        }

     public TValue this[TKey key] {
            get {
                int i = IndexOfKey(key);
                if (i >= 0)
                    return values[i];
 
                ThrowHelper.ThrowKeyNotFoundException();
                return default(TValue);
            }
        }

        // Removes the entry at the given index. The size of the sorted list is
        // decreased by one.
        // 
        public void RemoveAt(int index) {
            if (index < 0 || index >= _size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
            _size--;
            if (index < _size) {
                Array.Copy(keys, index + 1, keys, index, _size - index);
                Array.Copy(values, index + 1, values, index, _size - index);
            }
            keys[_size] = default(TKey);
            values[_size] = default(TValue);
            version++;
        }
    
        // Removes an entry from this sorted list. If an entry with the specified
        // key exists in the sorted list, it is removed. An ArgumentException is
        // thrown if the key is null.
        // 
        public bool Remove(TKey key) {
            int i = IndexOfKey(key);
            if (i >= 0) 
                RemoveAt(i);
            return i >= 0;
        }

        void System.Collections.IDictionary.Remove(Object key) {
            if( IsCompatibleKey(key)) {
                Remove((TKey) key);
            }
        }

如果是Remove需要先通过二分查找检索到指定的key的下标,然后再调用RemoveAt方法删除指定的元素。

   public TValue this[TKey key] {
            set {
                if (((Object) key) == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
                int i = Array.BinarySearch<TKey>(keys, 0, _size, key, comparer);
                if (i >= 0) {
                    values[i] = value;
                    version++;
                    return;
                }
                Insert(~i, key, value);
            }
        }

二分查找到下标设置值。

本身就是一颗二叉查找树,自身有序,所以无需排序。

关于二叉查找树的更多内容可以查看我之前的文章:

二分搜索树_漫漫无期的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值