Производительность memmove()
и realloc()
может быть увеличена путем разделения данных. Под разделением данных я подразумеваю использование нескольких массивов, а не одного большого массива.
Помимо memmove()
, я обнаружил, что обмен памятью является эффективным способом. Но есть и недостаток. Порядок массива может быть изменен следующим образом.
int remove_element(int*from, int total, int index) {
if(index != (total-1))
from[index] = from[total-1];
return total-1; // return the number of elements
}
Интересно, что массив произвольно доступен по индексу. И случайное удаление элемента может повлиять на индексы других элементов. Если это удаление выполняется в цикле обхода массива, то переупорядочение может привести к неожиданным результатам.
Один из способов исправить это - использовать массив масок is_blank
и отложить удаление.
int remove_element(int*from, int total, int*is_valid, int index) {
is_blank[index] = 1;
return total; // **DO NOT DECREASE** the total here
}
Может создать разреженный массив. Но его также можно заполнить, когда в пустые позиции добавляются новые элементы.
Опять же, можно сделать массив компактным в следующем эффективном алгоритме подкачки.
int sparse_to_compact(int*arr, int total, int*is_valid) {
int i = 0;
int last = total - 1;
// trim the last blank elements
for(; last >= 0 && is_blank[last]; last--); // trim blank elements from last
// now we keep swapping the blank with last valid element
for(i=0; i < last; i++) {
if(!is_blank[i])
continue;
arr[i] = arr[last]; // swap blank with the last valid
last--;
for(; last >= 0 && is_blank[last]; last--); // trim blank elements
}
return last+1; // return the compact length of the array
}
Обратите внимание, что вышеприведенный алгоритм использует swap, и он меняет порядок элементов. Может быть предпочтительным / безопасным для использования вне некоторой операции цикла в массиве. И если индексы элементов где-то сохранены, их также необходимо обновить / перестроить.