timsort: Add gtk_tim_sort_set_already_sorted()

... and use it in Tim1SortModel
This commit is contained in:
Benjamin Otte
2020-07-11 06:02:58 +02:00
parent 2bd6e20883
commit d67df53f17
4 changed files with 36 additions and 13 deletions

View File

@@ -175,13 +175,22 @@ sort_func (gconstpointer a,
}
static void
gtk_tim1_sort_model_resort (GtkTim1SortModel *self)
gtk_tim1_sort_model_resort (GtkTim1SortModel *self,
guint already_sorted)
{
gtk_tim_sort (sort_array_get_data (&self->items),
sort_array_get_size (&self->items),
sizeof (SortItem),
sort_func,
self->sorter);
GtkTimSort sort;
gtk_tim_sort_init (&sort,
sort_array_get_data (&self->items),
sort_array_get_size (&self->items),
sizeof (SortItem),
sort_func,
self->sorter);
gtk_tim_sort_set_already_sorted (&sort, already_sorted);
while (gtk_tim_sort_step (&sort));
gtk_tim_sort_finish (&sort);
}
static void
@@ -252,7 +261,7 @@ gtk_tim1_sort_model_items_changed_cb (GListModel *model,
{
sort_array_append (&self->items, &(SortItem) { g_list_model_get_item (self->model, i), i });
}
gtk_tim1_sort_model_resort (self);
gtk_tim1_sort_model_resort (self, sort_array_get_size (&self->items) - added);
for (i = 0; i < start; i++)
{
@@ -339,7 +348,7 @@ gtk_tim1_sort_model_sorter_changed_cb (GtkSorter *sorter,
else if (sort_array_is_empty (&self->items))
gtk_tim1_sort_model_create_items (self);
gtk_tim1_sort_model_resort (self);
gtk_tim1_sort_model_resort (self, 0);
n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
if (n_items > 1)
@@ -476,7 +485,7 @@ gtk_tim1_sort_model_set_model (GtkTim1SortModel *self,
added = g_list_model_get_n_items (model);
gtk_tim1_sort_model_create_items (self);
gtk_tim1_sort_model_resort (self);
gtk_tim1_sort_model_resort (self, 0);
}
else
added = 0;

View File

@@ -215,10 +215,6 @@ gtk_tim_sort(merge_append) (GtkTimSort *self)
/* Push run onto pending-run stack, and maybe merge */
gtk_tim_sort_push_run (self, self->base, run_len);
/* Advance to find next run */
self->base = ELEM (self->base, run_len);
self->size -= run_len;
return TRUE;
}

View File

@@ -129,6 +129,10 @@ gtk_tim_sort_push_run (GtkTimSort *self,
self->run[self->pending_runs].base = base;
self->run[self->pending_runs].len = len;
self->pending_runs++;
/* Advance to find next run */
self->base = ((char *) self->base) + len * self->element_size;
self->size -= len;
}
/**
@@ -167,6 +171,18 @@ gtk_tim_sort_ensure_capacity (GtkTimSort *self,
return self->tmp;
}
void
gtk_tim_sort_set_already_sorted (GtkTimSort *self,
gsize already_sorted)
{
g_assert (self);
g_assert (self->pending_runs == 0);
g_assert (already_sorted <= self->size);
if (already_sorted > 1)
gtk_tim_sort_push_run (self, self->base, already_sorted);
}
#if 1
#define WIDTH 4
#include "gtktimsort-impl.c"

View File

@@ -95,6 +95,8 @@ void gtk_tim_sort_init (GtkTimSort
gpointer data);
void gtk_tim_sort_finish (GtkTimSort *self);
void gtk_tim_sort_set_already_sorted (GtkTimSort *self,
gsize already_sorted);
gboolean gtk_tim_sort_step (GtkTimSort *self);
void gtk_tim_sort (gpointer base,