Я видел довольно много примеров реализаций C связанных списков на этом сайте, и большинство из них размещают следующий указатель в конце каждого узла следующим образом ...
struct intNode1 {
int data;
intNode1 *next;
};
Почему они реализуют их так, а не так?
struct node {
struct node *next;
};
struct intNode2 {
struct node node;
int data;
};
Последний способ реализации связанных списков позволяет вашему коду вставки и удаления работать на любом типе узла, а также позволяет создавать общий тип списка, тогда как первый способ заставляет вас создавать каждый вид списка с нуля.
Например, вот (неполная) реализация односвязного списка, использующего оба вида узлов:
struct intList {
struct intNode1 *head;
};
struct list {
struct node *head;
};
Теперь, очевидно, что любая операция в общем списке, которая должна сравнивать свои узлы, будет нуждаться в указателе функции на функцию сравнения, но ее часто можно скрыть при реализации менее общего интерфейса для списка. Например:
/* Returns zero if successful or nonzero otherwise */
int list-insertInt(struct list *list, int n) {
struct intNode2 * newNode;
if(!(newNode = malloc(sizeof *newNode)) {
return -1;
}
newNode->data = n;
return list-insertNode(list, (struct node *)newNode);
}
/* Assumes that the list contains only int nodes. */
int list-containsInt(struct list *list, int n) {
struct intNode2 *current = (intNode2 *)list->head;
while (current) {
if(current->data == n) {
return true;
}
current = current->next;
}
return false;
}
Конечно, вы можете free
список, не зная, какие у него узлы:
void list-free(struct list *list) {
struct node *current = list->head;
struct node *next;
while(current) {
next = current->next;
free(current);
current = next;
}
}
PS. Уже немного поздно (то есть рано утром, но я еще не спал), когда я пишу это. так что не стесняйтесь редактировать этот вопрос, чтобы быть более ясным.