- 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:
Peter Wehrfritz 2007-02-01 19:22:35 +00:00
parent 64a72b8400
commit a398189939
4 changed files with 66 additions and 42 deletions

View File

@ -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)

View File

@ -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 */

View File

@ -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)

View File

@ -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;