1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 2002 Soeren Sandmann (sandmann@daimi.au.dk)
4 * arch-tag: Implementation of GSequence - a fast ordered-sequence
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
23 #include "gsequence.h"
26 #define g_slice_new0(a) g_new0(a, 1)
27 #define g_slice_free(a, b) g_free(b)
30 typedef struct _GSequenceNode GSequenceNode
;
33 GSequenceNode
*node
; /* does not necessarily point to the root.
34 * You can splay it if you want it to
36 GDestroyNotify data_destroy_notify
;
39 struct _GSequenceNode
{
41 gint n_nodes
: 31; /* number of nodes below this node,
44 GSequenceNode
*parent
;
53 static GSequenceNode
*g_sequence_node_new (gpointer data
);
54 static GSequenceNode
*g_sequence_node_find_first (GSequenceNode
*node
);
55 static GSequenceNode
*g_sequence_node_find_last (GSequenceNode
*node
);
56 static GSequenceNode
*g_sequence_node_find_by_pos (GSequenceNode
*node
,
58 static GSequenceNode
*g_sequence_node_prev (GSequenceNode
*node
);
59 static GSequenceNode
*g_sequence_node_next (GSequenceNode
*node
);
60 static gint
g_sequence_node_get_pos (GSequenceNode
*node
);
61 static GSequence
*g_sequence_node_get_sequence (GSequenceNode
*node
);
62 static GSequenceNode
*g_sequence_node_find_closest (GSequenceNode
*node
,
66 static gint
g_sequence_node_get_length (GSequenceNode
*node
);
67 static void g_sequence_node_free (GSequenceNode
*node
,
68 GDestroyNotify destroy
);
70 static gboolean
g_sequence_node_is_singleton (GSequenceNode
*node
);
72 static void g_sequence_node_split (GSequenceNode
*node
,
74 GSequenceNode
**right
);
75 static void g_sequence_node_insert_before (GSequenceNode
*node
,
77 static void g_sequence_node_remove (GSequenceNode
*node
);
78 static void g_sequence_node_insert_sorted (GSequenceNode
*node
,
80 GCompareDataFunc cmp_func
,
85 g_sequence_new (GDestroyNotify data_destroy
)
87 GSequence
*seq
= g_new (GSequence
, 1);
88 seq
->data_destroy_notify
= data_destroy
;
90 seq
->node
= g_sequence_node_new (NULL
);
91 seq
->node
->is_end
= TRUE
;
92 seq
->node
->sequence
= seq
;
98 g_sequence_free (GSequence
*seq
)
100 g_return_if_fail (seq
!= NULL
);
102 g_sequence_node_free (seq
->node
, seq
->data_destroy_notify
);
109 flatten_nodes (GSequenceNode
*node
, GList
**list
)
111 g_print ("flatten %p\n", node
);
114 else if (g_sequence_node_is_singleton (node
))
115 *list
= g_list_prepend (*list
, node
);
119 GSequenceNode
*right
;
121 g_sequence_node_split (node
, &left
, &right
);
123 flatten_nodes (left
, list
);
124 flatten_nodes (right
, list
);
129 typedef struct SortInfo SortInfo
;
131 GCompareDataFunc cmp
;
136 node_compare (gconstpointer n1
, gconstpointer n2
, gpointer data
)
138 SortInfo
*info
= data
;
139 const GSequenceNode
*node1
= n1
;
140 const GSequenceNode
*node2
= n2
;
144 else if (node2
->is_end
)
147 return (* info
->cmp
) (node1
->data
, node2
->data
, info
->data
);
151 g_sequence_append (GSequence
*seq
,
154 GSequenceNode
*node
, *last
;
156 g_return_if_fail (seq
!= NULL
);
158 node
= g_sequence_node_new (data
);
159 node
->sequence
= seq
;
160 last
= g_sequence_node_find_last (seq
->node
);
161 g_sequence_node_insert_before (last
, node
);
165 g_sequence_prepend (GSequence
*seq
,
168 GSequenceNode
*node
, *second
;
170 g_return_if_fail (seq
!= NULL
);
172 node
= g_sequence_node_new (data
);
173 node
->sequence
= seq
;
174 second
= g_sequence_node_next (g_sequence_node_find_first (seq
->node
));
176 g_sequence_node_insert_before (second
, node
);
180 g_sequence_insert (GSequencePtr ptr
,
185 g_return_if_fail (ptr
!= NULL
);
187 node
= g_sequence_node_new (data
);
188 node
->sequence
= ptr
->sequence
;
190 g_sequence_node_insert_before (ptr
, node
);
194 g_sequence_unlink (GSequence
*seq
,
197 g_assert (!node
->is_end
);
199 seq
->node
= g_sequence_node_next (node
);
201 g_assert (seq
->node
);
202 g_assert (seq
->node
!= node
);
204 g_sequence_node_remove (node
);
208 g_sequence_remove (GSequencePtr ptr
)
212 g_return_if_fail (ptr
!= NULL
);
213 g_return_if_fail (!ptr
->is_end
);
215 seq
= g_sequence_node_get_sequence (ptr
);
216 g_sequence_unlink (seq
, ptr
);
217 g_sequence_node_free (ptr
, seq
->data_destroy_notify
);
221 g_sequence_sort (GSequence
*seq
,
222 GCompareDataFunc cmp_func
,
226 GSequenceNode
*begin
, *end
;
228 g_return_if_fail (seq
!= NULL
);
229 g_return_if_fail (cmp_func
!= NULL
);
231 begin
= g_sequence_get_begin_ptr (seq
);
232 end
= g_sequence_get_end_ptr (seq
);
234 g_sequence_remove_range (begin
, end
, &tmp
);
236 while (g_sequence_get_length (tmp
) > 0)
238 GSequenceNode
*node
= g_sequence_get_begin_ptr (tmp
);
239 g_sequence_unlink (tmp
, node
);
241 g_sequence_node_insert_sorted (seq
->node
, node
, cmp_func
, cmp_data
);
244 g_sequence_free (tmp
);
248 g_sequence_ptr_get_data (GSequencePtr ptr
)
250 g_return_val_if_fail (ptr
!= NULL
, NULL
);
251 g_return_val_if_fail (!ptr
->is_end
, NULL
);
257 g_sequence_insert_sorted (GSequence
*seq
,
259 GCompareDataFunc cmp_func
,
262 GSequenceNode
*new_node
= g_sequence_node_new (data
);
263 new_node
->sequence
= seq
;
264 g_sequence_node_insert_sorted (seq
->node
, new_node
, cmp_func
, cmp_data
);
269 g_sequence_insert_sequence (GSequencePtr ptr
,
270 GSequence
*other_seq
)
274 g_return_if_fail (other_seq
!= NULL
);
275 g_return_if_fail (ptr
!= NULL
);
277 last
= g_sequence_node_find_last (other_seq
->node
);
278 g_sequence_node_insert_before (ptr
, last
);
279 g_sequence_node_remove (last
);
280 g_sequence_node_free (last
, NULL
);
281 other_seq
->node
= NULL
;
282 g_sequence_free (other_seq
);
286 g_sequence_concatenate (GSequence
*seq1
,
291 g_return_if_fail (seq1
!= NULL
);
292 g_return_if_fail (seq2
!= NULL
);
294 last
= g_sequence_node_find_last (seq1
->node
);
295 g_sequence_insert_sequence (last
, seq2
);
299 * The new sequence inherits the destroy notify from the sequence that
300 * beign and end comes from
303 g_sequence_remove_range (GSequencePtr begin
,
308 GSequenceNode
*s1
, *s2
, *s3
;
310 seq
= g_sequence_node_get_sequence (begin
);
312 g_assert (end
!= NULL
);
314 g_return_if_fail (seq
== g_sequence_node_get_sequence (end
));
316 g_sequence_node_split (begin
, &s1
, &s2
);
317 g_sequence_node_split (end
, NULL
, &s3
);
320 g_sequence_node_insert_before (s3
, s1
);
326 *removed
= g_sequence_new (seq
->data_destroy_notify
);
327 g_sequence_node_insert_before ((*removed
)->node
, s2
);
331 g_sequence_node_free (s2
, seq
->data_destroy_notify
);
336 g_sequence_get_length (GSequence
*seq
)
338 return g_sequence_node_get_length (seq
->node
) - 1;
342 g_sequence_get_end_ptr (GSequence
*seq
)
344 g_return_val_if_fail (seq
!= NULL
, NULL
);
345 return g_sequence_node_find_last (seq
->node
);
349 g_sequence_get_begin_ptr (GSequence
*seq
)
351 g_return_val_if_fail (seq
!= NULL
, NULL
);
352 return g_sequence_node_find_first (seq
->node
);
356 * if pos > number of items or -1, will return end pointer
359 g_sequence_get_ptr_at_pos (GSequence
*seq
,
364 g_return_val_if_fail (seq
!= NULL
, NULL
);
366 len
= g_sequence_get_length (seq
);
368 if (pos
> len
|| pos
== -1)
371 return g_sequence_node_find_by_pos (seq
->node
, pos
);
376 g_sequence_ptr_is_end (GSequencePtr ptr
)
378 g_return_val_if_fail (ptr
!= NULL
, FALSE
);
383 g_sequence_ptr_is_begin (GSequencePtr ptr
)
385 return (g_sequence_node_prev (ptr
) == ptr
);
389 g_sequence_ptr_get_position (GSequencePtr ptr
)
391 g_return_val_if_fail (ptr
!= NULL
, -1);
393 return g_sequence_node_get_pos (ptr
);
397 g_sequence_ptr_next (GSequencePtr ptr
)
399 g_return_val_if_fail (ptr
!= NULL
, NULL
);
401 return g_sequence_node_next (ptr
);
405 g_sequence_ptr_prev (GSequencePtr ptr
)
407 g_return_val_if_fail (ptr
!= NULL
, NULL
);
409 return g_sequence_node_prev (ptr
);
413 g_sequence_ptr_move (GSequencePtr ptr
,
418 g_return_val_if_fail (ptr
!= NULL
, NULL
);
420 new_pos
= g_sequence_node_get_pos (ptr
) + delta
;
422 return g_sequence_node_find_by_pos (ptr
, new_pos
);
426 g_sequence_ptr_sort_changed (GSequencePtr ptr
,
427 GCompareDataFunc cmp_func
,
432 g_return_if_fail (!ptr
->is_end
);
434 seq
= g_sequence_node_get_sequence (ptr
);
435 g_sequence_unlink (seq
, ptr
);
436 g_sequence_node_insert_sorted (seq
->node
, ptr
, cmp_func
, cmp_data
);
441 * The only restriction on the search function is that it
442 * must not delete any nodes. It is permitted to insert new nodes,
443 * but the caller should "know what he is doing"
446 g_sequence_search (GSequence
*seq
,
447 GSequenceSearchFunc f
,
450 GQueue
*intervals
= g_queue_new ();
452 g_queue_push_tail (intervals
, g_sequence_node_find_first (seq
->node
));
453 g_queue_push_tail (intervals
, g_sequence_node_find_last (seq
->node
));
455 while (!g_queue_is_empty (intervals
))
457 GSequenceNode
*begin
= g_queue_pop_head (intervals
);
458 GSequenceNode
*end
= g_queue_pop_head (intervals
);
460 if (f (begin
, end
, data
))
462 gint begin_pos
= g_sequence_node_get_pos (begin
);
463 gint end_pos
= g_sequence_node_get_pos (end
);
465 if (end_pos
- begin_pos
> 1)
470 mid_pos
= begin_pos
+ (end_pos
- begin_pos
) / 2;
471 mid
= g_sequence_node_find_by_pos (begin
, mid_pos
);
473 g_queue_push_tail (intervals
, begin
);
474 g_queue_push_tail (intervals
, mid
);
476 g_queue_push_tail (intervals
, mid
);
477 g_queue_push_tail (intervals
, end
);
482 g_queue_free (intervals
);
488 g_sequence_add_aggregate (GSequence
*seq
,
489 const gchar
*aggregate
,
490 GSequenceAggregateFunc f
,
492 GDestroyNotify destroy
)
498 g_sequence_remove_aggregate (GSequence
*seq
,
499 const gchar aggregate
)
506 g_sequence_set_aggregate_data (GSequencePtr ptr
,
507 const gchar
*aggregate
,
515 g_sequence_get_aggregate_data (GSequencePtr begin
,
517 const gchar
*aggregate
)
519 g_assert_not_reached();
527 g_sequence_node_update_fields (GSequenceNode
*node
)
529 g_assert (node
!= NULL
);
534 node
->n_nodes
+= node
->left
->n_nodes
;
537 node
->n_nodes
+= node
->right
->n_nodes
;
540 if (node
->left
|| node
->right
)
541 g_assert (node
->n_nodes
> 1);
545 #define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
546 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
549 g_sequence_node_rotate (GSequenceNode
*node
)
551 GSequenceNode
*tmp
, *old
;
553 g_assert (node
->parent
);
554 g_assert (node
->parent
!= node
);
556 if (NODE_LEFT_CHILD (node
))
561 node
->right
= node
->parent
;
562 node
->parent
= node
->parent
->parent
;
565 if (node
->parent
->left
== node
->right
)
566 node
->parent
->left
= node
;
568 node
->parent
->right
= node
;
571 g_assert (node
->right
);
573 node
->right
->parent
= node
;
574 node
->right
->left
= tmp
;
576 if (node
->right
->left
)
577 node
->right
->left
->parent
= node
->right
;
586 node
->left
= node
->parent
;
587 node
->parent
= node
->parent
->parent
;
590 if (node
->parent
->right
== node
->left
)
591 node
->parent
->right
= node
;
593 node
->parent
->left
= node
;
596 g_assert (node
->left
);
598 node
->left
->parent
= node
;
599 node
->left
->right
= tmp
;
601 if (node
->left
->right
)
602 node
->left
->right
->parent
= node
->left
;
607 g_sequence_node_update_fields (old
);
608 g_sequence_node_update_fields (node
);
611 static GSequenceNode
*
612 splay (GSequenceNode
*node
)
616 if (!node
->parent
->parent
)
619 g_sequence_node_rotate (node
);
621 else if ((NODE_LEFT_CHILD (node
) && NODE_LEFT_CHILD (node
->parent
)) ||
622 (NODE_RIGHT_CHILD (node
) && NODE_RIGHT_CHILD (node
->parent
)))
625 g_sequence_node_rotate (node
->parent
);
626 g_sequence_node_rotate (node
);
631 g_sequence_node_rotate (node
);
632 g_sequence_node_rotate (node
);
639 static GSequenceNode
*
640 g_sequence_node_new (gpointer data
)
642 GSequenceNode
*node
= g_slice_new0 (GSequenceNode
);
649 node
->is_end
= FALSE
;
655 static GSequenceNode
*
656 find_min (GSequenceNode
*node
)
666 static GSequenceNode
*
667 find_max (GSequenceNode
*node
)
677 static GSequenceNode
*
678 g_sequence_node_find_first (GSequenceNode
*node
)
680 return splay (find_min (node
));
683 static GSequenceNode
*
684 g_sequence_node_find_last (GSequenceNode
*node
)
686 return splay (find_max (node
));
690 get_n_nodes (GSequenceNode
*node
)
693 return node
->n_nodes
;
698 static GSequenceNode
*
699 g_sequence_node_find_by_pos (GSequenceNode
*node
,
704 g_assert (node
!= NULL
);
708 while ((i
= get_n_nodes (node
->left
)) != pos
)
718 g_assert (node
->parent
!= NULL
);
725 static GSequenceNode
*
726 g_sequence_node_prev (GSequenceNode
*node
)
740 static GSequenceNode
*
741 g_sequence_node_next (GSequenceNode
*node
)
756 g_sequence_node_get_pos (GSequenceNode
*node
)
760 return get_n_nodes (node
->left
);
764 g_sequence_node_get_sequence (GSequenceNode
*node
)
768 return node
->sequence
;
771 static GSequenceNode
*
772 g_sequence_node_find_closest (GSequenceNode
*node
,
773 GSequenceNode
*other
,
774 GCompareDataFunc cmp
,
786 if ((c
= cmp (node
, other
, data
)) != 0)
794 while (c
!= 0 && node
!= NULL
);
800 g_sequence_node_free (GSequenceNode
*node
,
801 GDestroyNotify destroy
)
805 * This is to avoid excessively deep recursions. A splay tree is not necessarily
808 * I _think_ this is still linear in the number of nodes, but I'd like to
809 * do something more efficient.
816 node
= splay (find_min (node
));
821 if (destroy
&& !node
->is_end
)
822 destroy (node
->data
);
823 g_slice_free (GSequenceNode
, node
);
831 g_sequence_node_is_singleton (GSequenceNode
*node
)
835 if (node
->left
|| node
->right
)
843 g_sequence_node_split (GSequenceNode
*node
,
844 GSequenceNode
**left
,
845 GSequenceNode
**right
)
847 GSequenceNode
*left_tree
;
851 left_tree
= node
->left
;
854 left_tree
->parent
= NULL
;
855 g_sequence_node_update_fields (left_tree
);
859 g_sequence_node_update_fields (node
);
869 g_sequence_node_insert_before (GSequenceNode
*node
,
872 g_assert (node
!= NULL
);
873 g_assert (new != NULL
);
877 new = splay (find_min (new));
878 g_assert (new->left
== NULL
);
881 node
->left
->parent
= new;
883 new->left
= node
->left
;
888 g_sequence_node_update_fields (new);
889 g_sequence_node_update_fields (node
);
893 g_sequence_node_get_length (GSequenceNode
*node
)
895 g_assert (node
!= NULL
);
898 return node
->n_nodes
;
902 g_sequence_node_remove (GSequenceNode
*node
)
904 GSequenceNode
*right
, *left
;
911 node
->left
= node
->right
= NULL
;
915 right
->parent
= NULL
;
917 right
= g_sequence_node_find_first (right
);
918 g_assert (right
->left
== NULL
);
923 left
->parent
= right
;
924 g_sequence_node_update_fields (right
);
934 g_sequence_node_calc_height (GSequenceNode
*node
)
936 /* breadth first traversal */
938 GQueue
*nodes
= g_queue_new ();
940 g_queue_push_tail (nodes
, node
);
942 while (!g_queue_is_empty (nodes
))
944 GQueue
*tmp
= g_queue_new ();
947 while (!g_queue_is_empty (nodes
))
949 GSequenceNode
*node
= g_queue_pop_head (nodes
);
951 g_queue_push_tail (tmp
, node
->left
);
953 g_queue_push_tail (tmp
, node
->right
);
956 g_queue_free (nodes
);
960 g_queue_free (nodes
);
967 g_sequence_node_insert_sorted (GSequenceNode
*node
,
969 GCompareDataFunc cmp_func
,
973 GSequenceNode
*closest
;
975 info
.data
= cmp_data
;
978 g_sequence_node_find_closest (node
, new, node_compare
, &info
);
980 if (node_compare (new, closest
, &info
) > 0)
981 closest
= g_sequence_node_next (closest
);
983 /* this can never fail since we have a bigger-than-everything
986 g_assert (node_compare (new, closest
, &info
) <= 0);
987 g_sequence_node_insert_before (closest
, new);
991 g_sequence_node_calc_height (GSequenceNode
*node
)
1002 left_height
= g_sequence_node_calc_height (node
->left
);
1005 right_height
= g_sequence_node_calc_height (node
->right
);
1007 return MAX (left_height
, right_height
) + 1;
1014 g_sequence_calc_tree_height (GSequence
*seq
)
1016 GSequenceNode
*node
= seq
->node
;
1018 while (node
->parent
)
1019 node
= node
->parent
;
1023 r
= g_sequence_node_calc_height (node
->right
);
1024 l
= g_sequence_node_calc_height (node
->left
);
1026 return MAX (r
, l
) + 1;