Поскольку превосходное обсуждение этой темы имеет чтение эта статья от Sun.
Это входит во все преимущества включая способность ввести вмешивающиеся библиотеки. Больше детали о вставке может быть найдено в эта статья здесь .
Это полностью зависит от варианта использования. Вас больше волнует время, потраченное на копирование данных (и перераспределение массивов), или дополнительная память? Как долго прослужит массив? Если это не продлится долго, использование большего буфера вполне может быть хорошей идеей - штраф будет кратковременным. Если это будет продолжаться (например, в Java, переходя к старшим и старшим поколениям), это, очевидно, скорее штраф.
Не существует такой вещи, как «идеальный фактор роста». Это' s не только теоретически зависит от приложения, это определенно зависит от приложения.
2 - довольно распространенный фактор роста - я почти уверен, что это то, что ArrayList
и Список
в .NET. ArrayList
в Java использует 1.5.
РЕДАКТИРОВАТЬ: Как указывает Эрих, Dictionary <,>
в .NET использует «удвоить размер, затем увеличить до следующего простого числа. ", чтобы хеш-значения можно было разумно распределить между сегментами. (Я уверен, что недавно видел документацию, в которой говорится, что простые числа на самом деле не так хороши для распределения хэш-корзин, но это аргумент в пользу другого ответа.)
2 - довольно распространенный фактор роста - я почти уверен, что ArrayList
и List
используют в .NET. ArrayList
в Java использует 1.5.
РЕДАКТИРОВАТЬ: Как указывает Эрих, Dictionary <,>
в .NET использует «удвоить размер, затем увеличить до следующего простого числа. ", чтобы хеш-значения можно было разумно распределить между сегментами. (Я уверен, что недавно видел документацию, в которой говорится, что простые числа на самом деле не так хороши для распределения хэш-корзин, но это аргумент в пользу другого ответа.)
2 - довольно распространенный фактор роста - я почти уверен, что ArrayList
и List
используют в .NET. ArrayList
в Java использует 1.5.
РЕДАКТИРОВАТЬ: Как указывает Эрих, Dictionary <,>
в .NET использует «удвоить размер, затем увеличить до следующего простого числа. ", чтобы хеш-значения можно было разумно распределить между сегментами. (Я уверен, что недавно видел документацию, в которой говорится, что простые числа на самом деле не так хороши для распределения хэш-корзин, но это аргумент в пользу другого ответа.)
I remember reading many years ago why 1.5 is preferred over two, at least as applied to C++ (this probably doesn't apply to managed languages, where the runtime system can relocate objects at will).
The reasoning is this:
The idea is that, with a 2x expansion, there is no point in time that the resulting hole is ever going to be large enough to reuse for the next allocation. Using a 1.5x allocation, we have this instead:
One approach when answering questions like this is to just "cheat" and look at what popular libraries do, under the assumption that a widely used library is, at the very least, not doing something horrible.
So just checking very quickly, Ruby (1.9.1-p129) appears to use 1.5x when appending to an array, and Python (2.6.2) uses 1.125x plus a constant (in Objects/listobject.c
):
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
/* check for integer overflow */
if (new_allocated > PY_SIZE_MAX - newsize) {
PyErr_NoMemory();
return -1;
} else {
new_allocated += newsize;
}
newsize
above is the number of elements in the array. Note well that newsize
is added to new_allocated
, so the expression with the bitshifts and ternary operator is really just calculating the over-allocation.
I agree with Jon Skeet, even my theorycrafter friend insists that this can be proven to be O(1) when setting the factor to 2x.
The ratio between cpu time and memory is different on each machine, and so the factor will vary just as much. If you have a machine with gigabytes of ram, and a slow CPU, copying the elements to a new array is a lot more expensive than on a fast machine, which might in turn have less memory. It's a question that can be answered in theory, for a uniform computer, which in real scenarios doesnt help you at all.
It really depends. Some people analyze common usage cases to find the optimal number.
I've seen 1.5x 2.0x phi x, and power of 2 used before.
Если у вас есть распределение по длинам массивов, и у вас есть служебная функция, которая говорит, насколько вы любите тратить пространство против потери времени, тогда вы определенно можете выбрать оптимальную стратегию изменения размера (и начального изменения размера).
Причина, по которой используется простое постоянное кратное, очевидно, заключается в том, что каждое добавление имеет амортизированное постоянное время. Но это не означает, что вы не можете использовать другое (большее) соотношение для небольших размеров.
В Scala вы можете переопределить loadFactor для хеш-таблиц стандартной библиотеки с помощью функции, которая смотрит на текущий размер. Как ни странно, массивы с изменяемым размером просто удваиваются, что большинство людей и делает на практике.
Я не знаю ни одного массива с удвоением (или 1.5 * ing), который действительно перехватывает ошибки памяти и в этом случае становится меньше. Похоже, что если бы у вас был один огромный массив, вы бы захотели это сделать.
Я бы добавил, что если вы достаточно долго храните массивы с изменяемым размером и предпочитаете пространство с течением времени,