forked from enlightenment/efl
add ecore_list_mergesort() and ecore_list_heapsort()
SVN revision: 28139
This commit is contained in:
parent
0401faccc7
commit
64a72b8400
|
@ -117,6 +117,12 @@ extern "C" {
|
||||||
EAPI void *ecore_list_next(Ecore_List * list);
|
EAPI void *ecore_list_next(Ecore_List * list);
|
||||||
EAPI void *ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function,
|
EAPI void *ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function,
|
||||||
const void *user_data);
|
const void *user_data);
|
||||||
|
|
||||||
|
/* Sorting the list */
|
||||||
|
EAPI void ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||||
|
char order);
|
||||||
|
EAPI void ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||||
|
char order);
|
||||||
|
|
||||||
/* Check to see if there is any data in the list */
|
/* Check to see if there is any data in the list */
|
||||||
EAPI int ecore_list_is_empty(Ecore_List * list);
|
EAPI int ecore_list_is_empty(Ecore_List * list);
|
||||||
|
|
|
@ -22,12 +22,20 @@ static void *_ecore_list_goto_first(Ecore_List * list);
|
||||||
static void *_ecore_list_goto(Ecore_List * list, void *data);
|
static void *_ecore_list_goto(Ecore_List * list, void *data);
|
||||||
static void *_ecore_list_goto_index(Ecore_List *list, int index);
|
static void *_ecore_list_goto_index(Ecore_List *list, int index);
|
||||||
|
|
||||||
/* Iterative function */
|
/* Iterative functions */
|
||||||
static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function,
|
static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
static void *_ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function,
|
static void *_ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function,
|
||||||
const void *user_data);
|
const void *user_data);
|
||||||
|
|
||||||
|
/* Sorting functions */
|
||||||
|
static Ecore_List_Node *_ecore_list_node_mergesort(Ecore_List_Node *first,
|
||||||
|
int n, Ecore_Compare_Cb compare, int order);
|
||||||
|
static Ecore_List_Node *_ecore_list_node_merge(Ecore_List_Node *first,
|
||||||
|
Ecore_List_Node *second,
|
||||||
|
Ecore_Compare_Cb compare,
|
||||||
|
int order);
|
||||||
|
|
||||||
/* Private double linked list functions */
|
/* Private double linked list functions */
|
||||||
static void *_ecore_dlist_previous(Ecore_DList * list);
|
static void *_ecore_dlist_previous(Ecore_DList * list);
|
||||||
static void *_ecore_dlist_remove_first(Ecore_DList *list);
|
static void *_ecore_dlist_remove_first(Ecore_DList *list);
|
||||||
|
@ -1112,6 +1120,172 @@ _ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function, const void *user_d
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort data in @p list using the compare function @p func
|
||||||
|
* @param list The list.
|
||||||
|
* @param compare The function to compare the data of @p list
|
||||||
|
* @param order The sort direction
|
||||||
|
*
|
||||||
|
* Mergesort is a stable, in-place sorting algorithm
|
||||||
|
*/
|
||||||
|
EAPI void
|
||||||
|
ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
|
||||||
|
{
|
||||||
|
Ecore_List_Node *node;
|
||||||
|
|
||||||
|
CHECK_PARAM_POINTER("list", list);
|
||||||
|
if (!list || list->nodes < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (order == ECORE_SHEAP_MIN)
|
||||||
|
order = 1;
|
||||||
|
else
|
||||||
|
order = -1;
|
||||||
|
|
||||||
|
node = _ecore_list_node_mergesort(list->first, list->nodes, compare, order);
|
||||||
|
list->first = node;
|
||||||
|
|
||||||
|
/* maybe there is a better way to do that but our last node has changed */
|
||||||
|
while (node->next)
|
||||||
|
node = node->next;
|
||||||
|
list->last = node;
|
||||||
|
|
||||||
|
_ecore_list_goto_first(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is the internal recrusive function for the merge sort */
|
||||||
|
static Ecore_List_Node *
|
||||||
|
_ecore_list_node_mergesort(Ecore_List_Node *first, int n,
|
||||||
|
Ecore_Compare_Cb compare, int order)
|
||||||
|
{
|
||||||
|
Ecore_List_Node *middle;
|
||||||
|
Ecore_List_Node *premid;
|
||||||
|
int mid;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mid = n/2;
|
||||||
|
|
||||||
|
if (n < 2)
|
||||||
|
return first;
|
||||||
|
else if (n == 2)
|
||||||
|
{
|
||||||
|
if (compare(first->data, first->next->data) == order)
|
||||||
|
{
|
||||||
|
/* swap the data */
|
||||||
|
void *data;
|
||||||
|
data = first->next->data;
|
||||||
|
first->next->data = first->data;
|
||||||
|
first->data = data;
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first find the premiddle node*/
|
||||||
|
for (premid = first, i = 0; i < mid - 1; i++)
|
||||||
|
premid = premid->next;
|
||||||
|
|
||||||
|
/* split the list */
|
||||||
|
middle = premid->next;
|
||||||
|
premid->next = NULL;
|
||||||
|
|
||||||
|
/* sort the the partial lists */
|
||||||
|
first = _ecore_list_node_mergesort(first, mid, compare, order);
|
||||||
|
middle = _ecore_list_node_mergesort(middle, n - mid, compare, order);
|
||||||
|
|
||||||
|
return _ecore_list_node_merge(first, middle, compare, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this function is used to merge the partial sorted lists */
|
||||||
|
static Ecore_List_Node *
|
||||||
|
_ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
|
||||||
|
Ecore_Compare_Cb compare, int order)
|
||||||
|
{
|
||||||
|
Ecore_List_Node *list;
|
||||||
|
Ecore_List_Node *l;
|
||||||
|
|
||||||
|
/* select the first node outside the loop, because we need to keep
|
||||||
|
* a pointer to it */
|
||||||
|
if (compare(first->data, second->data) == order)
|
||||||
|
{
|
||||||
|
list = l = second;
|
||||||
|
second = second->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list = l = first;
|
||||||
|
first = first->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* and now start the merging */
|
||||||
|
while (first && second)
|
||||||
|
{
|
||||||
|
if (compare(first->data, second->data) == order)
|
||||||
|
{
|
||||||
|
l = l->next = second;
|
||||||
|
second = second->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l = l->next = first;
|
||||||
|
first = first->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append the rest or set it to NULL */
|
||||||
|
if (first)
|
||||||
|
l->next = first;
|
||||||
|
else if (second)
|
||||||
|
l->next = second;
|
||||||
|
else
|
||||||
|
l->next = NULL;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort data in @p list using the compare function @p func
|
||||||
|
* @param list The list.
|
||||||
|
* @param compare The function to compare the data of @p list
|
||||||
|
* @param order The sort direction
|
||||||
|
*
|
||||||
|
* Heapsort is a unstable sorting algorithm, it needs to allocate extra memomry,
|
||||||
|
* but there for it is for a great number of nodes faster than mergesort
|
||||||
|
*/
|
||||||
|
EAPI void
|
||||||
|
ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
|
||||||
|
{
|
||||||
|
Ecore_Sheap *heap;
|
||||||
|
Ecore_List_Node *node;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
CHECK_PARAM_POINTER("list", list);
|
||||||
|
/*
|
||||||
|
* Push the data into a heap.
|
||||||
|
*/
|
||||||
|
heap = ecore_sheap_new(compare, list->nodes);
|
||||||
|
ecore_sheap_set_order(heap, order);
|
||||||
|
_ecore_list_goto_first(list);
|
||||||
|
while ((data = _ecore_list_next(list)))
|
||||||
|
{
|
||||||
|
ecore_sheap_insert(heap, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract in sorted order.
|
||||||
|
*/
|
||||||
|
node = list->first;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
node->data = ecore_sheap_extract(heap);
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecore_sheap_destroy(heap);
|
||||||
|
|
||||||
|
_ecore_list_goto_first(list);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize a node to starting values */
|
/* Initialize a node to starting values */
|
||||||
EAPI int
|
EAPI int
|
||||||
ecore_list_node_init(Ecore_List_Node *node)
|
ecore_list_node_init(Ecore_List_Node *node)
|
||||||
|
|
Loading…
Reference in New Issue