Обычно, если я хочу выделить массив с нулевой инициализацией, я бы сделал что-то вроде этого:
int size = 1000;
int* i = (int*)calloc(sizeof int, size));
И позже мой код может сделать это, чтобы проверить, был ли инициализирован элемент в массиве:
if(!i[10]) {
// i[10] has not been initialized
}
Однако в этом случае я не хочу платить первоначальные затраты на нулевую инициализацию массива, потому что массив может быть довольно большим (например, концерты). Но в этом случае я могу позволить себе использовать столько памяти, сколько хочу памяти.
Кажется, я помню, что существует метод отслеживания элементов в массиве, которые были инициализированы, без каких-либо предварительных затрат, который также допускает стоимость O (1) (не амортизируется с помощью хеш-таблица). Насколько я помню, этот метод требует дополнительного массива того же размера.
Я думаю, это было что-то вроде этого:
int size = 1000;
int* i = (int*)malloc(size*sizeof int));
int* i_markers = (int*)malloc(size*sizeof int));
Если используется запись в массиве, она записывается следующим образом:
i_markers[10] = &i[10];
И затем его использование можно проверить позже следующим образом:
if(i_markers[10] != &i[10]) {
// i[10] has not been initialized
}
Конечно, это не совсем правильно, потому что i_markers[10]
могло быть случайным образом установлено на &i[10]
.
Может кто напомнит технику?
Благодарю вас!
Кажется, я это запомнил. Это правильно? Есть ли лучший способ или есть варианты? Спасибо еще раз. (Это было обновлено, чтобы быть правильным ответом)
struct lazy_array {
int size;
int* values;
int* used;
int* back_references;
int num_used;
};
struct lazy_array* create_lazy_array(int size) {
struct lazy_array* lazy = (struct lazy_array*)malloc(sizeof(lazy_array));
lazy->size = 1000;
lazy->values = (int*)malloc(size*sizeof int));
lazy->used = (int*)malloc(size*sizeof int));
lazy->back_references = (int*)malloc(size*sizeof int));
lazy->num_used = 0;
return lazy;
}
void use_index(struct lazy_array* lazy, int index, int value) {
lazy->values[index] = value;
if(is_index_used(lazy, index))
return;
lazy->used[index] = lazy->used;
lazy->back_references[lazy->used[index]] = index;
++lazy->used;
}
int is_index_used(struct lazy_array* lazy, int index) {
return lazy->used[index] < lazy->num_used &&
lazy->back_references[lazy->used[index]] == index);
}
calloc
в современной операционной системе должно превзойти ленивый массив. - person user3386109   schedule 02.10.2015calloc
равен или быстрее, чем большойmalloc
, потому что ОС в любом случае предоставляет виртуальные страницы, уже обнуленные. Так что отложите преждевременную оптимизацию, если только вы не продемонстрировали необходимость в тестировании! - person M.M   schedule 02.10.2015i_markers[10] = &i[10];
- это проблема, назначение указателя наint
. Почему бы не использоватьint** i_markers
? - person chux - Reinstate Monica   schedule 02.10.2015