In an implementation of a doubly linked list I am using the typical structure:
struct node
{
void *data;
struct node *prev;
struct node *next;
};
I will also insert at the end of the list in O(1) time, so I have another struct storing the head and the tail:
struct linklist
{
struct node *head;
struct node *tail;
size_t size;
};
The program works as expected for all insert and delete operations, but I have a problem with the sort function, I am using the merge-sort algorithm, as I understand it is the most effective or one of the most effective to sort lists, the algorithm works well:
static struct node *split(struct node *head)
{
struct node *fast = head;
struct node *slow = head;
while ((fast->next != NULL) && (fast->next->next != NULL))
{
fast = fast->next->next;
slow = slow->next;
}
struct node *temp = slow->next;
slow->next = NULL;
return temp;
}
static struct node *merge(struct node *first, struct node *second, int (*comp)(const void *, const void *))
{
if (first == NULL)
{
return second;
}
if (second == NULL)
{
return first;
}
if (comp(first->data, second->data) < 0)
{
first->next = merge(first->next, second, comp);
first->next->prev = first;
first->prev = NULL;
return first;
}
else
{
second->next = merge(first, second->next, comp);
second->next->prev = second;
second->prev = NULL;
return second;
}
}
static struct node *merge_sort(struct node *head, int (*comp)(const void *, const void *))
{
if ((head == NULL) || (head->next == NULL))
{
return head;
}
struct node *second = split(head);
head = merge_sort(head, comp);
second = merge_sort(second, comp);
return merge(head, second, comp);
}
but I have no idea how to keep the address of list->tail updated:
void linklist_sort(struct linklist *list, int (*comp)(const void *, const void *))
{
list->head = merge_sort(list->head, comp);
// list->tail is no longer valid at this point
}
Sure I can walk the whole list after ordering and update list->tail by brute force, but I'd like to know if there's a fancier way to do it.
I managed to solve the problem using a circular list, but I would like to avoid changing the structure of the program.