Существует два распространенных способа сериализации объектов, имеющих указатели на другие объекты.Первый - заменить указатель смещением в файле, второй - использовать простой индекс.Фактически, способ смещения в основном используется, когда данные используются непосредственно из файла (например, файлы базы данных), тогда как индексный способ больше используется для простого хранения.
Здесь простым способом было бы сохранитьузлов в файл рекурсивно, как left_node - right_node - main_node.Таким образом, когда вы сохраняете узел, вы уже знаете индекс в файле его левого и правого потомков.Тогда возможная реализация:
static size_t do_save(FILE *fd, struct Node *node, unsigned data_size, int curr) {
size_t left=0, right=0;
if (node->left != NULL) { // first left sub_hierarchy
left = do_save(fd, node->left, data_size, curr);
curr = left;
}
if (node->left != NULL) { // then right one
right = do_save(fd, node->right, data_size, curr);
curr = right;
}
fwrite(&left, sizeof(left), 1, fd); // store index of left child
fwrite(&right, sizeof(right), 1, fd); // then index of right child
fwrite(node->data, data_size, 1, fd); // then the data
return curr + 1; // and return current index
}
size_t save(FILE *fd, struct Node *root, unsigned data_size) {
size_t nb = do_save(fd, root, data_size, 0);
return nb;
}
Здесь индекс 0 означает нулевой указатель, а ненулевой индекс - это индекс на основе одного в файле
Для десериализации, как яПредположим, что вы хотите, чтобы каждый узел был выделен индивидуально, я бы использовал временный массив указателей, чтобы сохранить фактические адреса выделенных узлов:
struct Node* load(FILE *fd, unsigned data_size) {
size_t nb_elts, left, right;
fseek(fd, 0, SEEK_END); // computer number of nodes in the file
nb_elts = ftell(fd) / (data_size + 2*sizeof(size_t));
struct Node** ptx = malloc(nb_elts * sizeof(*ptx)); // allocate array of pointers
fseek(fd, 0, SEEK_SET);
for(size_t i=0; i<nb_elts; i++) { // loop reading nodes
ptx[i] = malloc(sizeof(struct Node)); // allocate node and data
ptx[i]->data = malloc(data_size);
fread(&left, sizeof(size_t), 1, fd); // extract child indices
fread(&right, sizeof(size_t), 1, fd);
fread(ptx[i]->data, data_size, 1, fd); // read data
ptx[i]->left = (left == 0) ? NULL : ptx[left - 1]; // convert indices to pointers
ptx[i]->right = (right == 0) ? NULL : ptx[right - 1];
}
struct Node *last = ptx[nb_elts - 1];
free(ptx); // free the temporary array
return last; // and return the root node
}