ПРЕДУПРЕЖДЕНИЕ : Следующее является наиболее вероятным излишним для того, что вы хотите сделать. Но я расстроен, пытаясь отследить тонкий, но неприятный баг и мне нужно отвлечься.
Если я могу предложить несколько предложений ...
Прежде всего, в IMO проще вставлять элементы в список, чтобы отсортировать неупорядоченный список; я хотел бы создать функцию insertInOrder, которая берет заголовок списка, добавляемый новый элемент и предикат (указатель на функцию), который сравнивает записи и возвращает новый заголовок списка:
Rec *insertInOrder(Rec *head, Rec *new, int (*cmp)(Rec *, Rec *))
{
if (head == NULL)
{
return new;
}
else if (cmp(new, head) < 0) // new is "less than" head
{
new->nextRec = head;
return new; // new becomes the new head of the list
}
else
{
Rec *tmp = head;
/**
* Find the first element in the list that is not "less than" new
*/
while (tmp->nextRec != NULL && cmp(new, tmp->nextRec) > 0)
{
tmp = tmp->nextRec;
}
if (tmp->nextRec == NULL)
{
// insert new at end of list
tmp->nextRec = new;
new->nextRec = NULL;
}
else
{
// insert new before tmp->nextRec
new->nextRec = tmp->nextRec;
tmp->nextRec = new;
}
// keep the current list head
return head;
}
}
Теперь вы можете заказать список на основе различных критериев. Аргумент cmp
указывает на функцию, которая берет два указателя записи и сравнивает их, возвращая -1, если первый аргумент «меньше» второго, 1, если первый аргумент «больше» второго, и 0, если они сравнить равных. Например, если вы хотите отсортировать по именам, определите функцию, например
int compareNames(Rec *e1, Rec *e2)
{
int r = strcmp(e1->name, e2->name);
if (r < 0) return -1;
if (r > 0) return 1;
return 0;
}
и вызовите insertInOrder как
head = insertInOrder(head, new, compareNames);
Чтобы отсортировать список по заданному предикату: начиная с заголовка, удаляйте по одному элементу за раз из существующего списка и добавляйте его в новый список, используя указанный предикат:
Rec *sortLinkedList(Rec *head, int (*cmp)(Rec *, Rec *))
{
Rec *newList = NULL;
while (head)
{
Rec *tmp = head;
head = head->nextRec;
tmp->nextRec = NULL;
newList = insertInOrder(newList, tmp, cmp);
}
return newList;
}
...
head = sortLinkedList(head, compareNr);
...
head = sortLinkdeList(head, compareNames);
...
head = sortLinkedList(head, compareSomethingElse);
Как и Нил, мне не очень нравятся определения типов для типов указателей; опыт показал мне, что они вызывают больше проблем, чем стоят.