forked from enlightenment/efl
eina: add eina_inlist_sort (merge sort based on eina_list code).
SVN revision: 58540
This commit is contained in:
parent
733cfc629b
commit
ca83ca2ff4
|
@ -41,3 +41,7 @@
|
||||||
2011-04-06 Gustavo Sverzut Barbieri
|
2011-04-06 Gustavo Sverzut Barbieri
|
||||||
|
|
||||||
* Add Simple XML parser API.
|
* Add Simple XML parser API.
|
||||||
|
|
||||||
|
2011-05-11 Cedric Bail
|
||||||
|
|
||||||
|
* Add eina_inlist_sort.
|
||||||
|
|
|
@ -361,6 +361,53 @@ EAPI Eina_Iterator *eina_inlist_iterator_new(const Eina_Inlist *in_list) EINA_MA
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Accessor *eina_inlist_accessor_new(const Eina_Inlist *in_list) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
|
EAPI Eina_Accessor *eina_inlist_accessor_new(const Eina_Inlist *in_list) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sort a list according to the ordering func will return.
|
||||||
|
*
|
||||||
|
* @param list The list handle to sort.
|
||||||
|
* @param func A function pointer that can handle comparing the list data
|
||||||
|
* nodes.
|
||||||
|
* @return the new head of list.
|
||||||
|
*
|
||||||
|
* This function sorts all the elements of @p list. @p func is used to
|
||||||
|
* compare two elements of @p list. If @p list or @p func are @c NULL,
|
||||||
|
* this function returns @c NULL.
|
||||||
|
*
|
||||||
|
* @note @b in-place: this will change the given list, so you should
|
||||||
|
* now point to the new list head that is returned by this function.
|
||||||
|
*
|
||||||
|
* @note worst case is O(n * log2(n)) comparisons (calls to func()),
|
||||||
|
* O(n) comparisons average case. That means that for 1,000,000 list
|
||||||
|
* elements, sort will usually do 1,000,000 comparisons, but may do up
|
||||||
|
* to 20,000,000.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* @code
|
||||||
|
* typedef struct _Sort_Ex Sort_Ex;
|
||||||
|
* struct _Sort_Ex
|
||||||
|
* {
|
||||||
|
* INLIST;
|
||||||
|
* const char *text;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* int
|
||||||
|
* sort_cb(const Inlist *l1, const Inlist *l2)
|
||||||
|
* {
|
||||||
|
* const Sort_Ex *x1;
|
||||||
|
* const Sort_Ex *x2;
|
||||||
|
*
|
||||||
|
* x1 = EINA_INLIST_CONTAINER_GET(l1, Sort_Ex);
|
||||||
|
* x2 = EINA_INLIST_CONTAINER_GET(l2, Sort_Ex);
|
||||||
|
*
|
||||||
|
* return(strcmp(x1->text, x2->text));
|
||||||
|
* }
|
||||||
|
* extern Eina_Inlist *list;
|
||||||
|
*
|
||||||
|
* list = eina_inlist_sort(list, sort_cb);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
EAPI Eina_Inlist *eina_inlist_sort(Eina_Inlist *head, Eina_Compare_Cb func);
|
||||||
|
|
||||||
/* This two macros are helpers for the _FOREACH ones, don't use them */
|
/* This two macros are helpers for the _FOREACH ones, don't use them */
|
||||||
#define _EINA_INLIST_OFFSET(ref) ((char *)&(ref)->__in_list - (char *)(ref))
|
#define _EINA_INLIST_OFFSET(ref) ((char *)&(ref)->__in_list - (char *)(ref))
|
||||||
#define _EINA_INLIST_CONTAINER(ref, ptr) (void *)((char *)(ptr) - \
|
#define _EINA_INLIST_CONTAINER(ref, ptr) (void *)((char *)(ptr) - \
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
* @cond LOCAL
|
* @cond LOCAL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define EINA_INLIST_SORT_STACK_SIZE 32
|
||||||
|
|
||||||
typedef struct _Eina_Iterator_Inlist Eina_Iterator_Inlist;
|
typedef struct _Eina_Iterator_Inlist Eina_Iterator_Inlist;
|
||||||
typedef struct _Eina_Accessor_Inlist Eina_Accessor_Inlist;
|
typedef struct _Eina_Accessor_Inlist Eina_Accessor_Inlist;
|
||||||
|
|
||||||
|
@ -141,6 +143,41 @@ eina_inlist_accessor_free(Eina_Accessor_Inlist *it) {
|
||||||
free(it);
|
free(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Inlist *
|
||||||
|
eina_inlist_sort_merge(Eina_Inlist *a, Eina_Inlist *b, Eina_Compare_Cb func)
|
||||||
|
{
|
||||||
|
Eina_Inlist *first, *last;
|
||||||
|
|
||||||
|
if (func(a, b) < 0)
|
||||||
|
a = (last = first = a)->next;
|
||||||
|
else
|
||||||
|
b = (last = first = b)->next;
|
||||||
|
|
||||||
|
while (a && b)
|
||||||
|
if (func(a, b) < 0)
|
||||||
|
a = (last = last->next = a)->next;
|
||||||
|
else
|
||||||
|
b = (last = last->next = b)->next;
|
||||||
|
|
||||||
|
last->next = a ? a : b;
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Inlist *
|
||||||
|
eina_inlist_sort_rebuild_prev(Eina_Inlist *list)
|
||||||
|
{
|
||||||
|
Eina_Inlist *prev = NULL;
|
||||||
|
|
||||||
|
for (; list; list = list->next)
|
||||||
|
{
|
||||||
|
list->prev = prev;
|
||||||
|
prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @endcond
|
* @endcond
|
||||||
*/
|
*/
|
||||||
|
@ -385,6 +422,61 @@ eina_inlist_count(const Eina_Inlist *list)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Inlist *
|
||||||
|
eina_inlist_sort(Eina_Inlist *head, Eina_Compare_Cb func)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
unsigned int n = 0;
|
||||||
|
Eina_Inlist *tail = head;
|
||||||
|
Eina_Inlist *unsort = NULL;
|
||||||
|
Eina_Inlist *stack[EINA_INLIST_SORT_STACK_SIZE];
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(head, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(func, head);
|
||||||
|
|
||||||
|
while (tail)
|
||||||
|
{
|
||||||
|
unsigned int idx, tmp;
|
||||||
|
|
||||||
|
Eina_Inlist *a = tail;
|
||||||
|
Eina_Inlist *b = tail->next;
|
||||||
|
|
||||||
|
if (!b)
|
||||||
|
{
|
||||||
|
stack[i++] = a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tail = b->next;
|
||||||
|
|
||||||
|
if (func(a, b) < 0)
|
||||||
|
((stack[i++] = a)->next = b)->next = 0;
|
||||||
|
else
|
||||||
|
((stack[i++] = b)->next = a)->next = 0;
|
||||||
|
|
||||||
|
tmp = n++;
|
||||||
|
for (idx = n ^ tmp; idx &= idx - 1; i--)
|
||||||
|
stack[i - 2] = eina_inlist_sort_merge(stack[i - 2], stack[i - 1], func);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i-- > 1)
|
||||||
|
stack[i - 1] = eina_inlist_sort_merge(stack[i - 1], stack[i], func);
|
||||||
|
|
||||||
|
head = stack[0];
|
||||||
|
tail = eina_inlist_sort_rebuild_prev(head);
|
||||||
|
|
||||||
|
if (unsort)
|
||||||
|
{
|
||||||
|
tail->next = unsort;
|
||||||
|
unsort->prev = tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
head->last = tail;
|
||||||
|
|
||||||
|
return head;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
EAPI Eina_Iterator *
|
EAPI Eina_Iterator *
|
||||||
eina_inlist_iterator_new(const Eina_Inlist *list)
|
eina_inlist_iterator_new(const Eina_Inlist *list)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue