Два способы реализации связанного списка: что лучше?

Я обычно знаю два способа разработать общую структуру данных связанного списка на C. И мне интересно, какой из них лучше. Прежде чем задать вопрос, я кратко расскажу об обоих методах:

Один из методов - построить функции вокруг структуры, подобной следующей:

struct list_element {
    struct list_element *prev;
    struct list_element *next;
    void *data;
};

Очевидно, указатель данных указывает на полезную нагрузку. Структура элемента списка находится за пределами полезной нагрузки. Это например как glib спроектировал свое средство двойных связанных списков: http://library.gnome.org/devel/glib/2.26/glib-Doubly-Linked-Lists.html

Другой метод - это то, как это делается в ядро Linux: http://isis.poly.edu/kulesh/stuff/src/klist/ . В структуре элемента списка нет пустого указателя на полезную нагрузку. Вместо этого структура элемента списка включается в структуру полезной нагрузки:

struct list_element {
    struct list_element *prev;
    struct list_element *next;
};

struct person {
    char name[20];
    unsigned int age;
    struct list_element list_entry;
};

Специальный макрос используется для получения указателя на структуру полезной нагрузки с учетом указателя на list_entry, ее имени в структуре полезной нагрузки и типа структуры полезной нагрузки ( list_entry () macro).

Наконец, вот вопрос: В чем преимущество последнего из двух методов построения связного списка? Несколько раз я слышал, как люди говорят, что второе более «общее», чем первое, но почему? Я бы даже сказал, что первый метод является более общим, потому что структуры полезной нагрузки не зависят от реализации списка, что не относится ко второму методу.
Еще одним недостатком второго метода является то, что если вы хотите разместить полезную нагрузку более чем в одном списке, вам следует указать член struct list_element для каждого списка в структуре полезной нагрузки.

Изменить: Подводя итог, я увидел два важных для меня ответа:

  • Первый метод: удаление полезной нагрузки из списка включает в себя цикл по полному списку, пока не будет найден элемент списка, указывающий на полезную нагрузку. При втором способе этого делать не нужно. (Ответ Патрика)
  • В первом методе вы должны выполнить две функции malloc () для каждого элемента: одну для полезной нагрузки и одну для структуры элемента списка. Во втором методе достаточно одного malloc (). (Ответ Родди)

9
задан Bart 1 December 2010 в 12:29
поделиться