Ваш код сортировки неверен: вы меняете поле content
, но не content_size
.Ожидается, что вы отсортируете элементы списка, обновив их next
членов и обновив аргумент *head
.
Ваш метод имеет квадратичную сложность, если не хуже.Вместо этого вы должны использовать сортировку слиянием, которая имеет гораздо меньшую временную сложность O (N.log (N)) .
Вот пример (сортировка слиянием сверху вниз):
/* return the comparison status: 0 for equal, <0 if a < b, >0 if a>b */
int compare_ascii(t_list *a, t_list *b) {
return ft_strcmp(((t_dir *)a->content)->pathname, ((t_dir *)b->content)->pathname);
}
t_list *merge(t_list *a, t_list *b, int (*cmp)(t_list *a, t_list *b)) {
t_list *head = NULL; /* head of the merged list */
t_list **r = &head; /* pointer to the node link */
if (a && b) {
for (;;) {
if ((*cmp)(a, b) <= 0) {
/* link the head node of list a */
*r = a;
r = &a->next;
a = a->next;
if (!a)
break;
} else {
/* link the head node of list b */
*r = b;
r = &b->next;
b = b->next;
if (!b)
break;
}
}
}
/* link the remaining part of a or b if any */
*r = (a == NULL) ? b : a;
return head;
}
t_list *mergesort(t_list *p, int (*cmp)(t_list *a, t_list *b)) {
t_list *a, *b, *last = NULL;
/* find the middle with 2 finger method: a moves twice as fast as b */
for (a = b = p; a && a->next; a = a->next->next, b = b->next)
last = b;
if (last == NULL) {
/* empty list or single element */
return p;
}
/* split in the middle (before b) */
last->next = NULL;
/* sort each half and merge the sorted sublists */
return merge(mergesort(p, cmp), mergesort(b, cmp), cmp);
}
void sort_ascii(t_list **head) {
*head = mergesort(*head, compare_ascii);
}
Как прокомментировал rcgldr , сортировка по принципу слияния снизу обычно выполняется быстрее, потому что не нужно сканировать списки, чтобы найти средний элемент, что может быть дорого из-за несоответствия кеша.С другой стороны, он может выполнять больше сравнений, но все еще с временной сложностью O (N.log (N)) и не является рекурсивной.
Вот версия mergesort
используя сортировку слиянием снизу вверх:
t_list *mergesort(t_list *head, int (*cmp)(t_list *a, t_list *b)) {
t_list *array[32]; // sorted sublists: array[i] has 2**i length if not null
t_list *result = head;
int i, top = 0;
// merge nodes into array
while (result != NULL) {
t_list *next = result->next;
result->next = NULL;
// merge sorted sublists by increasing power of 2 sizes
for (i = 0; i < top && array[i] != NULL; i++) {
result = merge(array[i], result, cmp);
array[i] = NULL;
}
// store the merged list, update top, do not go past end of array
if (i == top) {
if (top < 32)
top++;
else
i--;
}
array[i] = result;
result = next;
}
// merge all sorted sublists into single list
result = NULL;
for (i = 0; i < top; i++) {
result = merge(array[i], result, cmp);
}
return result;
}