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
,
86 g_sequence_new (GDestroyNotify data_destroy
)
88 GSequence
*seq
= g_new (GSequence
, 1);
89 seq
->data_destroy_notify
= data_destroy
;
91 seq
->node
= g_sequence_node_new (NULL
);
92 seq
->node
->is_end
= TRUE
;
93 seq
->node
->sequence
= seq
;
99 g_sequence_free (GSequence
*seq
)
101 g_return_if_fail (seq
!= NULL
);
103 g_sequence_node_free (seq
->node
, seq
->data_destroy_notify
);
110 flatten_nodes (GSequenceNode
*node
, GList
**list
)
112 g_print ("flatten %p\n", node
);
115 else if (g_sequence_node_is_singleton (node
))
116 *list
= g_list_prepend (*list
, node
);
120 GSequenceNode
*right
;
122 g_sequence_node_split (node
, &left
, &right
);
124 flatten_nodes (left
, list
);
125 flatten_nodes (right
, list
);
130 typedef struct SortInfo SortInfo
;
132 GCompareDataFunc cmp
;
137 node_compare (gconstpointer n1
, gconstpointer n2
, gpointer data
)
139 SortInfo
*info
= data
;
140 const GSequenceNode
*node1
= n1
;
141 const GSequenceNode
*node2
= n2
;
145 else if (node2
->is_end
)
148 return (* info
->cmp
) (node1
->data
, node2
->data
, info
->data
);
152 g_sequence_append (GSequence
*seq
,
155 GSequenceNode
*node
, *last
;
157 g_return_if_fail (seq
!= NULL
);
159 node
= g_sequence_node_new (data
);
160 node
->sequence
= seq
;
161 last
= g_sequence_node_find_last (seq
->node
);
162 g_sequence_node_insert_before (last
, node
);
166 g_sequence_prepend (GSequence
*seq
,
169 GSequenceNode
*node
, *second
;
171 g_return_if_fail (seq
!= NULL
);
173 node
= g_sequence_node_new (data
);
174 node
->sequence
= seq
;
175 second
= g_sequence_node_next (g_sequence_node_find_first (seq
->node
));
177 g_sequence_node_insert_before (second
, node
);
181 g_sequence_insert (GSequencePtr ptr
,
186 g_return_if_fail (ptr
!= NULL
);
188 node
= g_sequence_node_new (data
);
189 node
->sequence
= ptr
->sequence
;
191 g_sequence_node_insert_before (ptr
, node
);
195 g_sequence_unlink (GSequence
*seq
,
198 g_assert (!node
->is_end
);
200 seq
->node
= g_sequence_node_next (node
);
202 g_assert (seq
->node
);
203 g_assert (seq
->node
!= node
);
205 g_sequence_node_remove (node
);
209 g_sequence_remove (GSequencePtr ptr
)
213 g_return_if_fail (ptr
!= NULL
);
214 g_return_if_fail (!ptr
->is_end
);
216 seq
= g_sequence_node_get_sequence (ptr
);
217 g_sequence_unlink (seq
, ptr
);
218 g_sequence_node_free (ptr
, seq
->data_destroy_notify
);
222 g_sequence_sort (GSequence
*seq
,
223 GCompareDataFunc cmp_func
,
227 GSequenceNode
*begin
, *end
;
229 g_return_if_fail (seq
!= NULL
);
230 g_return_if_fail (cmp_func
!= NULL
);
232 begin
= g_sequence_get_begin_ptr (seq
);
233 end
= g_sequence_get_end_ptr (seq
);
235 g_sequence_remove_range (begin
, end
, &tmp
);
237 while (g_sequence_get_length (tmp
) > 0)
239 GSequenceNode
*node
= g_sequence_get_begin_ptr (tmp
);
240 g_sequence_unlink (tmp
, node
);
242 g_sequence_node_insert_sorted (seq
->node
, node
, cmp_func
, cmp_data
);
245 g_sequence_free (tmp
);
249 g_sequence_ptr_get_data (GSequencePtr ptr
)
251 g_return_val_if_fail (ptr
!= NULL
, NULL
);
252 g_return_val_if_fail (!ptr
->is_end
, NULL
);
258 g_sequence_insert_sorted (GSequence
*seq
,
260 GCompareDataFunc cmp_func
,
263 GSequenceNode
*new_node
= g_sequence_node_new (data
);
264 new_node
->sequence
= seq
;
265 g_sequence_node_insert_sorted (seq
->node
, new_node
, cmp_func
, cmp_data
);
270 g_sequence_insert_sequence (GSequencePtr ptr
,
271 GSequence
*other_seq
)
275 g_return_if_fail (other_seq
!= NULL
);
276 g_return_if_fail (ptr
!= NULL
);
278 last
= g_sequence_node_find_last (other_seq
->node
);
279 g_sequence_node_insert_before (ptr
, last
);
280 g_sequence_node_remove (last
);
281 g_sequence_node_free (last
, NULL
);
282 other_seq
->node
= NULL
;
283 g_sequence_free (other_seq
);
287 g_sequence_concatenate (GSequence
*seq1
,
292 g_return_if_fail (seq1
!= NULL
);
293 g_return_if_fail (seq2
!= NULL
);
295 last
= g_sequence_node_find_last (seq1
->node
);
296 g_sequence_insert_sequence (last
, seq2
);
300 * The new sequence inherits the destroy notify from the sequence that
301 * beign and end comes from
304 g_sequence_remove_range (GSequencePtr begin
,
309 GSequenceNode
*s1
, *s2
, *s3
;
311 seq
= g_sequence_node_get_sequence (begin
);
313 g_assert (end
!= NULL
);
315 g_return_if_fail (seq
== g_sequence_node_get_sequence (end
));
317 g_sequence_node_split (begin
, &s1
, &s2
);
318 g_sequence_node_split (end
, NULL
, &s3
);
321 g_sequence_node_insert_before (s3
, s1
);
327 *removed
= g_sequence_new (seq
->data_destroy_notify
);
328 g_sequence_node_insert_before ((*removed
)->node
, s2
);
332 g_sequence_node_free (s2
, seq
->data_destroy_notify
);
337 g_sequence_get_length (GSequence
*seq
)
339 return g_sequence_node_get_length (seq
->node
) - 1;
343 g_sequence_get_end_ptr (GSequence
*seq
)
345 g_return_val_if_fail (seq
!= NULL
, NULL
);
346 return g_sequence_node_find_last (seq
->node
);
350 g_sequence_get_begin_ptr (GSequence
*seq
)
352 g_return_val_if_fail (seq
!= NULL
, NULL
);
353 return g_sequence_node_find_first (seq
->node
);
357 * if pos > number of items or -1, will return end pointer
360 g_sequence_get_ptr_at_pos (GSequence
*seq
,
365 g_return_val_if_fail (seq
!= NULL
, NULL
);
367 len
= g_sequence_get_length (seq
);
369 if (pos
> len
|| pos
== -1)
372 return g_sequence_node_find_by_pos (seq
->node
, pos
);
378 g_sequence_ptr_is_end (GSequencePtr ptr
)
380 g_return_val_if_fail (ptr
!= NULL
, FALSE
);
385 g_sequence_ptr_is_begin (GSequencePtr ptr
)
387 return (g_sequence_node_prev (ptr
) == ptr
);
391 g_sequence_ptr_get_position (GSequencePtr ptr
)
393 g_return_val_if_fail (ptr
!= NULL
, -1);
395 return g_sequence_node_get_pos (ptr
);
399 g_sequence_ptr_next (GSequencePtr ptr
)
401 g_return_val_if_fail (ptr
!= NULL
, NULL
);
403 return g_sequence_node_next (ptr
);
407 g_sequence_ptr_prev (GSequencePtr ptr
)
409 g_return_val_if_fail (ptr
!= NULL
, NULL
);
411 return g_sequence_node_prev (ptr
);
415 g_sequence_ptr_move (GSequencePtr ptr
,
420 g_return_val_if_fail (ptr
!= NULL
, NULL
);
422 new_pos
= g_sequence_node_get_pos (ptr
) + delta
;
424 return g_sequence_node_find_by_pos (ptr
, new_pos
);
428 g_sequence_ptr_sort_changed (GSequencePtr ptr
,
429 GCompareDataFunc cmp_func
,
434 g_return_if_fail (!ptr
->is_end
);
436 seq
= g_sequence_node_get_sequence (ptr
);
437 g_sequence_unlink (seq
, ptr
);
438 g_sequence_node_insert_sorted (seq
->node
, ptr
, cmp_func
, cmp_data
);
443 * The only restriction on the search function is that it
444 * must not delete any nodes. It is permitted to insert new nodes,
445 * but the caller should "know what he is doing"
448 g_sequence_search (GSequence
*seq
,
449 GSequenceSearchFunc f
,
452 GQueue
*intervals
= g_queue_new ();
454 g_queue_push_tail (intervals
, g_sequence_node_find_first (seq
->node
));
455 g_queue_push_tail (intervals
, g_sequence_node_find_last (seq
->node
));
457 while (!g_queue_is_empty (intervals
))
459 GSequenceNode
*begin
= g_queue_pop_head (intervals
);
460 GSequenceNode
*end
= g_queue_pop_head (intervals
);
462 if (f (begin
, end
, data
))
464 gint begin_pos
= g_sequence_node_get_pos (begin
);
465 gint end_pos
= g_sequence_node_get_pos (end
);
467 if (end_pos
- begin_pos
> 1)
472 mid_pos
= begin_pos
+ (end_pos
- begin_pos
) / 2;
473 mid
= g_sequence_node_find_by_pos (begin
, mid_pos
);
475 g_queue_push_tail (intervals
, begin
);
476 g_queue_push_tail (intervals
, mid
);
478 g_queue_push_tail (intervals
, mid
);
479 g_queue_push_tail (intervals
, end
);
484 g_queue_free (intervals
);
492 g_sequence_add_aggregate (GSequence
*seq
,
493 const gchar
*aggregate
,
494 GSequenceAggregateFunc f
,
496 GDestroyNotify destroy
)
502 g_sequence_remove_aggregate (GSequence
*seq
,
503 const gchar aggregate
)
510 g_sequence_set_aggregate_data (GSequencePtr ptr
,
511 const gchar
*aggregate
,
519 g_sequence_get_aggregate_data (GSequencePtr begin
,
521 const gchar
*aggregate
)
523 g_assert_not_reached();
532 g_sequence_node_update_fields (GSequenceNode
*node
)
534 g_assert (node
!= NULL
);
539 node
->n_nodes
+= node
->left
->n_nodes
;
542 node
->n_nodes
+= node
->right
->n_nodes
;
545 if (node
->left
|| node
->right
)
546 g_assert (node
->n_nodes
> 1);
550 #define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
551 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
554 g_sequence_node_rotate (GSequenceNode
*node
)
556 GSequenceNode
*tmp
, *old
;
558 g_assert (node
->parent
);
559 g_assert (node
->parent
!= node
);
561 if (NODE_LEFT_CHILD (node
))
566 node
->right
= node
->parent
;
567 node
->parent
= node
->parent
->parent
;
570 if (node
->parent
->left
== node
->right
)
571 node
->parent
->left
= node
;
573 node
->parent
->right
= node
;
576 g_assert (node
->right
);
578 node
->right
->parent
= node
;
579 node
->right
->left
= tmp
;
581 if (node
->right
->left
)
582 node
->right
->left
->parent
= node
->right
;
591 node
->left
= node
->parent
;
592 node
->parent
= node
->parent
->parent
;
595 if (node
->parent
->right
== node
->left
)
596 node
->parent
->right
= node
;
598 node
->parent
->left
= node
;
601 g_assert (node
->left
);
603 node
->left
->parent
= node
;
604 node
->left
->right
= tmp
;
606 if (node
->left
->right
)
607 node
->left
->right
->parent
= node
->left
;
612 g_sequence_node_update_fields (old
);
613 g_sequence_node_update_fields (node
);
616 static GSequenceNode
*
617 splay (GSequenceNode
*node
)
621 if (!node
->parent
->parent
)
624 g_sequence_node_rotate (node
);
626 else if ((NODE_LEFT_CHILD (node
) && NODE_LEFT_CHILD (node
->parent
)) ||
627 (NODE_RIGHT_CHILD (node
) && NODE_RIGHT_CHILD (node
->parent
)))
630 g_sequence_node_rotate (node
->parent
);
631 g_sequence_node_rotate (node
);
636 g_sequence_node_rotate (node
);
637 g_sequence_node_rotate (node
);
644 static GSequenceNode
*
645 g_sequence_node_new (gpointer data
)
647 GSequenceNode
*node
= g_slice_new0 (GSequenceNode
);
654 node
->is_end
= FALSE
;
660 static GSequenceNode
*
661 find_min (GSequenceNode
*node
)
671 static GSequenceNode
*
672 find_max (GSequenceNode
*node
)
682 static GSequenceNode
*
683 g_sequence_node_find_first (GSequenceNode
*node
)
685 return splay (find_min (node
));
688 static GSequenceNode
*
689 g_sequence_node_find_last (GSequenceNode
*node
)
691 return splay (find_max (node
));
695 get_n_nodes (GSequenceNode
*node
)
698 return node
->n_nodes
;
703 static GSequenceNode
*
704 g_sequence_node_find_by_pos (GSequenceNode
*node
,
709 g_assert (node
!= NULL
);
713 while ((i
= get_n_nodes (node
->left
)) != pos
)
723 g_assert (node
->parent
!= NULL
);
730 static GSequenceNode
*
731 g_sequence_node_prev (GSequenceNode
*node
)
745 static GSequenceNode
*
746 g_sequence_node_next (GSequenceNode
*node
)
761 g_sequence_node_get_pos (GSequenceNode
*node
)
765 return get_n_nodes (node
->left
);
769 g_sequence_node_get_sequence (GSequenceNode
*node
)
773 return node
->sequence
;
776 static GSequenceNode
*
777 g_sequence_node_find_closest (GSequenceNode
*node
,
778 GSequenceNode
*other
,
779 GCompareDataFunc cmp
,
791 if ((c
= cmp (node
, other
, data
)) != 0)
799 while (c
!= 0 && node
!= NULL
);
805 g_sequence_node_free (GSequenceNode
*node
,
806 GDestroyNotify destroy
)
810 * This is to avoid excessively deep recursions. A splay tree is not necessarily
813 * I _think_ this is still linear in the number of nodes, but I'd like to
814 * do something more efficient.
821 node
= splay (find_min (node
));
826 if (destroy
&& !node
->is_end
)
827 destroy (node
->data
);
828 g_slice_free (GSequenceNode
, node
);
836 g_sequence_node_is_singleton (GSequenceNode
*node
)
840 if (node
->left
|| node
->right
)
848 g_sequence_node_split (GSequenceNode
*node
,
849 GSequenceNode
**left
,
850 GSequenceNode
**right
)
852 GSequenceNode
*left_tree
;
856 left_tree
= node
->left
;
859 left_tree
->parent
= NULL
;
860 g_sequence_node_update_fields (left_tree
);
864 g_sequence_node_update_fields (node
);
874 g_sequence_node_insert_before (GSequenceNode
*node
,
877 g_assert (node
!= NULL
);
878 g_assert (new != NULL
);
882 new = splay (find_min (new));
883 g_assert (new->left
== NULL
);
886 node
->left
->parent
= new;
888 new->left
= node
->left
;
893 g_sequence_node_update_fields (new);
894 g_sequence_node_update_fields (node
);
898 g_sequence_node_get_length (GSequenceNode
*node
)
900 g_assert (node
!= NULL
);
903 return node
->n_nodes
;
907 g_sequence_node_remove (GSequenceNode
*node
)
909 GSequenceNode
*right
, *left
;
916 node
->left
= node
->right
= NULL
;
920 right
->parent
= NULL
;
922 right
= g_sequence_node_find_first (right
);
923 g_assert (right
->left
== NULL
);
928 left
->parent
= right
;
929 g_sequence_node_update_fields (right
);
939 g_sequence_node_calc_height (GSequenceNode
*node
)
941 /* breadth first traversal */
943 GQueue
*nodes
= g_queue_new ();
945 g_queue_push_tail (nodes
, node
);
947 while (!g_queue_is_empty (nodes
))
949 GQueue
*tmp
= g_queue_new ();
952 while (!g_queue_is_empty (nodes
))
954 GSequenceNode
*node
= g_queue_pop_head (nodes
);
956 g_queue_push_tail (tmp
, node
->left
);
958 g_queue_push_tail (tmp
, node
->right
);
961 g_queue_free (nodes
);
965 g_queue_free (nodes
);
972 g_sequence_node_insert_sorted (GSequenceNode
*node
,
974 GCompareDataFunc cmp_func
,
978 GSequenceNode
*closest
;
980 info
.data
= cmp_data
;
983 g_sequence_node_find_closest (node
, new, node_compare
, &info
);
985 if (node_compare (new, closest
, &info
) > 0)
986 closest
= g_sequence_node_next (closest
);
988 /* this can never fail since we have a bigger-than-everything
991 g_assert (node_compare (new, closest
, &info
) <= 0);
992 g_sequence_node_insert_before (closest
, new);
996 g_sequence_node_calc_height (GSequenceNode
*node
)
1007 left_height
= g_sequence_node_calc_height (node
->left
);
1010 right_height
= g_sequence_node_calc_height (node
->right
);
1012 return MAX (left_height
, right_height
) + 1;
1019 g_sequence_calc_tree_height (GSequence
*seq
)
1021 GSequenceNode
*node
= seq
->node
;
1023 while (node
->parent
)
1024 node
= node
->parent
;
1028 r
= g_sequence_node_calc_height (node
->right
);
1029 l
= g_sequence_node_calc_height (node
->left
);
1031 return MAX (r
, l
) + 1;