浅谈容器扩容参数

2021-10-02  本文已影响0人  太刀
美女

在编码时我们经常使用各种容器来做基本的数据结构,比如 C++ STL 中的 vector, C# 的 List 和 Dictionary 等,这篇文章我们简单聊一下这些容器在发生扩容时的扩容系数选择的话题

1. 什么是容器的扩容

虽然容器的使用方法和特点各异,但整体来说底层的存储结构基本上都是基于数组,例如 C++ 中的 vector、C# 中的 List 底层都是使用数组来存放数据,那么容器中的数组长度如何确定呢?

2. 容器扩容的时机

那么容器的扩容发生在什么时候呢?

3. 容器扩容的系数选择逻辑

扩容时分配多大的新空间比较合适呢?(此处综合考虑到普遍情况下的内存分配、元素复制消耗、扩容次数等),假设当前容量是x,那么新分配的容量为 n*x,对于不同容器,不同的版本实现,此处的 n 不尽相同

3.1 C++ STL vector 的扩容系数

3.2 C# List 的扩容系数

查看 List源码可知,C# List 的扩容系数是 2,扩容是分配 2 倍新空间

对于 vector 和 List 来说,1.5 的扩容系数是比 2 更好的选择。使用扩容系数 2 时产生的问题在于,每次新分配的空间必然刚好大于之前分配的空间之和,之前分配的空间无法复用,使用1.5 是一个更好的选择,便于复用之前分配过的空间,详情可以参考 MiloYip的回答

3.3 C# Dictionary 的扩容系数

和列表不同,Dictionary 由于底层哈希桶数组的存在,添加元素时需要考虑元素哈希值冲突,扩容应该能够尽量避免哈希冲突的产生,所以 Dictionary 的扩容方法是,取小于 2*x的最小质数,为什么要取质数呢?这是因为哈希桶的长度为质数时,能够使得哈希值分配更均匀,最大程度的减少哈希冲突的发生,理论依据简单概括:

陷入以质数做除数,得到的结果的可能性更多,也就说明了质数能够使数据分配的更均匀,达到了减少哈希冲突的目的。

上一篇 下一篇

猜你喜欢

热点阅读