- add ecore_list_sort() a wrapper for ecore_list_mergesort and ecore_list_heapsort
- change the API for the sort functions to return an int on success - change ECORE_SHEAP_MIN/MAX to ECORE_SORT_MIN/MAX (*API break*) - use ecore_list_sort() in ecore_file_ls() SVN revision: 28188
This commit is contained in:
parent
64a72b8400
commit
a398189939
|
@ -40,6 +40,9 @@ extern "C" {
|
|||
|
||||
EAPI extern const unsigned int ecore_prime_table[];
|
||||
|
||||
# define ECORE_SORT_MIN 0
|
||||
# define ECORE_SORT_MAX 1
|
||||
|
||||
typedef void (*Ecore_For_Each) (void *value, void *user_data);
|
||||
# define ECORE_FOR_EACH(function) ((Ecore_For_Each)function)
|
||||
|
||||
|
@ -119,9 +122,11 @@ extern "C" {
|
|||
const void *user_data);
|
||||
|
||||
/* Sorting the list */
|
||||
EAPI void ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||
EAPI int ecore_list_sort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||
char order);
|
||||
EAPI void ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||
EAPI int ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||
char order);
|
||||
EAPI int ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare,
|
||||
char order);
|
||||
|
||||
/* Check to see if there is any data in the list */
|
||||
|
@ -327,9 +332,6 @@ extern "C" {
|
|||
EAPI Ecore_List *ecore_plugin_get_available(int group_id);
|
||||
|
||||
|
||||
# define ECORE_SHEAP_MIN 0
|
||||
# define ECORE_SHEAP_MAX 1
|
||||
|
||||
typedef struct _ecore_heap Ecore_Sheap;
|
||||
# define ECORE_HEAP(heap) ((Ecore_Sheap *)heap)
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
#include "Ecore.h"
|
||||
#include "Ecore_Data.h"
|
||||
|
||||
/* Some tests showed that beyond that value heap sort is faster than merge sort
|
||||
* (in this implementation). This value has to be changed or at least review
|
||||
* if someone is changing the implementation. */
|
||||
#define ECORE_MERGESORT_LIMIT 40000
|
||||
|
||||
/* Return information about the list */
|
||||
static void *_ecore_list_current(Ecore_List * list);
|
||||
|
||||
|
@ -1121,24 +1126,51 @@ _ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function, const void *user_d
|
|||
}
|
||||
|
||||
/**
|
||||
* Sort data in @p list using the compare function @p func
|
||||
* Sort data in @p list using the compare function @p compare
|
||||
* @param list The list.
|
||||
* @param compare The function to compare the data of @p list
|
||||
* @param order The sort direction
|
||||
*
|
||||
* @return true on success
|
||||
*
|
||||
* This is a wrapper function for mergesort and heapsort. It
|
||||
* tries to choose the fastest algorithm depending on the
|
||||
* number of notes. Note: The sort may be unstable.
|
||||
*/
|
||||
EAPI int
|
||||
ecore_list_sort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
|
||||
{
|
||||
CHECK_PARAM_POINTER_RETURN("list", list, 0);
|
||||
|
||||
if (list->nodes < 2)
|
||||
return 1;
|
||||
if (list->nodes < ECORE_MERGESORT_LIMIT)
|
||||
return ecore_list_mergesort(list, compare, order);
|
||||
if (!ecore_list_heapsort(list, compare, order))
|
||||
return ecore_list_mergesort(list, compare, order);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* Sort data in @p list using the compare function @p compare
|
||||
* @param list The list.
|
||||
* @param compare The function to compare the data of @p list
|
||||
* @param order The sort direction
|
||||
*
|
||||
* @return true on success
|
||||
*
|
||||
* Mergesort is a stable, in-place sorting algorithm
|
||||
*/
|
||||
EAPI void
|
||||
EAPI int
|
||||
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)
|
||||
CHECK_PARAM_POINTER_RETURN("list", list, 0);
|
||||
if (list->nodes < 2)
|
||||
return 1;
|
||||
|
||||
if (order == ECORE_SORT_MIN)
|
||||
order = 1;
|
||||
else
|
||||
order = -1;
|
||||
|
@ -1152,6 +1184,8 @@ ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
|
|||
list->last = node;
|
||||
|
||||
_ecore_list_goto_first(list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* this is the internal recrusive function for the merge sort */
|
||||
|
@ -1170,7 +1204,7 @@ _ecore_list_node_mergesort(Ecore_List_Node *first, int n,
|
|||
return first;
|
||||
else if (n == 2)
|
||||
{
|
||||
if (compare(first->data, first->next->data) == order)
|
||||
if (compare(first->data, first->next->data) * order > 0)
|
||||
{
|
||||
/* swap the data */
|
||||
void *data;
|
||||
|
@ -1206,7 +1240,7 @@ _ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
|
|||
|
||||
/* select the first node outside the loop, because we need to keep
|
||||
* a pointer to it */
|
||||
if (compare(first->data, second->data) == order)
|
||||
if (compare(first->data, second->data) * order > 0)
|
||||
{
|
||||
list = l = second;
|
||||
second = second->next;
|
||||
|
@ -1220,7 +1254,7 @@ _ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
|
|||
/* and now start the merging */
|
||||
while (first && second)
|
||||
{
|
||||
if (compare(first->data, second->data) == order)
|
||||
if (compare(first->data, second->data) * order > 0)
|
||||
{
|
||||
l = l->next = second;
|
||||
second = second->next;
|
||||
|
@ -1244,26 +1278,31 @@ _ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
|
|||
}
|
||||
|
||||
/**
|
||||
* Sort data in @p list using the compare function @p func
|
||||
* Sort data in @p list using the compare function @p compare
|
||||
* @param list The list.
|
||||
* @param compare The function to compare the data of @p list
|
||||
* @param order The sort direction
|
||||
*
|
||||
* @return true on success
|
||||
*
|
||||
* 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
|
||||
EAPI int
|
||||
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);
|
||||
CHECK_PARAM_POINTER_RETURN("list", list, 0);
|
||||
/*
|
||||
* Push the data into a heap.
|
||||
*/
|
||||
heap = ecore_sheap_new(compare, list->nodes);
|
||||
if (!heap)
|
||||
return 0;
|
||||
|
||||
ecore_sheap_set_order(heap, order);
|
||||
_ecore_list_goto_first(list);
|
||||
while ((data = _ecore_list_next(list)))
|
||||
|
@ -1284,6 +1323,7 @@ ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
|
|||
ecore_sheap_destroy(heap);
|
||||
|
||||
_ecore_list_goto_first(list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize a node to starting values */
|
||||
|
|
|
@ -54,7 +54,7 @@ ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size)
|
|||
heap->compare = ecore_direct_compare;
|
||||
else
|
||||
heap->compare = compare;
|
||||
heap->order = ECORE_SHEAP_MIN;
|
||||
heap->order = ECORE_SORT_MIN;
|
||||
|
||||
heap->data = (void **)malloc(heap->space * sizeof(void *));
|
||||
if (!heap->data)
|
||||
|
@ -149,7 +149,7 @@ ecore_sheap_insert(Ecore_Sheap *heap, void *data)
|
|||
* data. The loop is placed inside the if statement to reduce the
|
||||
* number of branching decisions that must be predicted.
|
||||
*/
|
||||
if (heap->order == ECORE_SHEAP_MIN)
|
||||
if (heap->order == ECORE_SORT_MIN)
|
||||
{
|
||||
while ((position > 0) && heap->compare(heap->data[parent],
|
||||
heap->data[position]) > 0)
|
||||
|
@ -383,7 +383,7 @@ _ecore_sheap_heapify(Ecore_Sheap *heap, int i)
|
|||
int left = LEFT(i);
|
||||
int right = RIGHT(i);
|
||||
|
||||
if (heap->order == ECORE_SHEAP_MIN)
|
||||
if (heap->order == ECORE_SORT_MIN)
|
||||
{
|
||||
if (left <= heap->size && heap->compare(heap->data[left - 1],
|
||||
heap->data[i - 1]) < 0)
|
||||
|
|
|
@ -298,7 +298,6 @@ ecore_file_ls(const char *dir)
|
|||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
Ecore_List *list;
|
||||
Ecore_Sheap *heap;
|
||||
|
||||
dirp = opendir(dir);
|
||||
if (!dirp) return NULL;
|
||||
|
@ -315,25 +314,8 @@ ecore_file_ls(const char *dir)
|
|||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
/*
|
||||
* Push the data into a heap.
|
||||
*/
|
||||
heap = ecore_sheap_new(ECORE_COMPARE_CB(strcasecmp), ecore_list_nodes(list));
|
||||
while ((f = ecore_list_remove_first(list)))
|
||||
{
|
||||
ecore_sheap_insert(heap, f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract in sorted order.
|
||||
*/
|
||||
while ((f = ecore_sheap_extract(heap)))
|
||||
{
|
||||
ecore_list_append(list, f);
|
||||
}
|
||||
|
||||
ecore_sheap_destroy(heap);
|
||||
|
||||
ecore_list_sort(list, ECORE_COMPARE_CB(strcasecmp), ECORE_SORT_MIN);
|
||||
|
||||
ecore_list_goto_first(list);
|
||||
return list;
|
||||
|
|
Loading…
Reference in New Issue