1
/**************************************************************/
2
/* ********************************************************** */
6
/* * $Module: LIST * */
8
/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */
9
/* * MPI fuer Informatik * */
11
/* * This program is free software; you can redistribute * */
12
/* * it and/or modify it under the terms of the FreeBSD * */
15
/* * This program is distributed in the hope that it will * */
16
/* * be useful, but WITHOUT ANY WARRANTY; without even * */
17
/* * the implied warranty of MERCHANTABILITY or FITNESS * */
18
/* * FOR A PARTICULAR PURPOSE. See the LICENCE file * */
19
/* * for more details. * */
22
/* $Revision: 1.3 $ * */
24
/* $Date: 2010-02-22 14:09:58 $ * */
25
/* $Author: weidenb $ * */
28
/* * Christoph Weidenbach * */
29
/* * MPI fuer Informatik * */
30
/* * Stuhlsatzenhausweg 85 * */
31
/* * 66123 Saarbruecken * */
32
/* * Email: spass@mpi-inf.mpg.de * */
35
/* ********************************************************** */
36
/**************************************************************/
39
/* $RCSfile: list.c,v $ */
43
/**************************************************************/
44
/* ********************************************************** */
46
/* * MEMORY MANAGEMENT * */
48
/* ********************************************************** */
49
/**************************************************************/
51
LIST list_Copy(const LIST List)
52
/**************************************************************
54
RETURNS: The copy of the list.
55
CAUTION: The entries of the list are NOT copied !
56
the function needs time O(n), where <n> is the length
58
***************************************************************/
67
Copy = list_List(list_Car(List));
69
Scan2 = list_Cdr(List);
71
while (!list_Empty(Scan2)) {
72
list_Rplacd(Scan1, list_List(list_Car(Scan2)));
73
Scan1 = list_Cdr(Scan1);
74
Scan2 = list_Cdr(Scan2);
80
LIST list_CopyWithElement(const LIST List, POINTER (*CopyElement)(POINTER))
81
/**************************************************************
82
INPUT: A List and a copy function for the elements.
83
RETURNS: The copy of the list.
84
CAUTION: The entries of the list are NOT copied !
85
The function needs time O(n*c), where <n> is the length
86
of the list and <c> is the time for a call of the
87
element copy function.
88
***************************************************************/
96
Copy = list_List(CopyElement(list_Car(List)));
98
Scan2 = list_Cdr(List);
100
while (!list_Empty(Scan2)) {
101
list_Rplacd(Scan1, list_List(CopyElement(list_Car(Scan2))));
102
Scan1 = list_Cdr(Scan1);
103
Scan2 = list_Cdr(Scan2);
109
void list_InsertNext(LIST List, POINTER Pointer)
110
/**************************************************************
111
INPUT: A list and a pointer to anything.
112
RETURNS: A list with Pointer being added at the position that
114
SUMMARY: We enqueue the element at position list_Cdr(List);
115
The function needs time O(1).
116
***************************************************************/
119
if (Pointer == NULL) {
120
misc_StartErrorReport();
121
misc_ErrorReport("\n In list_InsertNext: NULL Pointer. ");
122
misc_FinishErrorReport();
126
list_Rplacd(List, list_Cons(Pointer, list_Cdr(List)));
130
void list_NMapCar(LIST List, POINTER (*ElementFunc)(POINTER))
131
/**************************************************************
132
INPUT: A List and a function for the elements.
133
RETURNS: The List where all elements are replaced by the result of
134
the function calls of <ElementFunc> to the elements
135
CAUTION: The List is not copied !
136
The function needs time O(n*f), where <n> is the length
137
of the list and <f> is the time for a call of the
139
***************************************************************/
143
for (Scan = List; !list_Empty(Scan); Scan = list_Cdr(Scan))
144
list_Rplaca(Scan, ElementFunc(list_Car(Scan)));
148
void list_Apply(void (*Function)(POINTER), LIST List)
149
/**************************************************************
150
INPUT: A non-resulting function and a list.
151
SUMMARY: Apply the function to all members of the list.
152
The function needs time O(n*f), where <n> is the length
153
of the list and <f> is the time for a call of the
155
***************************************************************/
157
while (!list_Empty(List)) {
158
Function(list_Car(List));
159
List = list_Cdr(List);
164
LIST list_Reverse(const LIST List)
165
/**************************************************************
167
RETURNS: A new list where the order of the elements is reversed.
168
EFFECT: The function needs time O(n), where <n> is the length
170
***************************************************************/
175
ReverseList = list_Nil();
177
for (Scan=List;!list_Empty(Scan);Scan=list_Cdr(Scan))
178
ReverseList = list_Cons(list_Car(Scan), ReverseList);
184
LIST list_NReverse(LIST List)
185
/**************************************************************
187
RETURNS: The same list with reversed order of items.
188
CAUTION: Destructive but the pointer <List> is also the pointer
190
The function needs time and space O(n), where n is the length
192
***************************************************************/
197
if (list_Empty(List) || list_Empty(list_Cdr(List)))
201
List = list_List(list_Car(List));
202
list_Rplacd(List,list_Cdr(Result));
204
ReverseList = list_Nil();
206
while (!list_Empty(List)) {
207
Scan = list_Cdr(List);
208
list_Rplacd(List, ReverseList);
213
list_Rplaca(Result,list_Car(ReverseList));
214
list_Rplacd(Result,list_Cdr(ReverseList));
215
list_Free(ReverseList);
221
static __inline__ BOOL list_PointerLower (POINTER A, POINTER B)
223
return (NAT) A < (NAT) B;
226
LIST list_PointerSort(LIST List)
227
/**************************************************************
229
RETURNS: The same list where the elements are sorted as pointers.
230
EFFECT: The function needs time O(n log n), where <n> is the length
232
CAUTION: Destructive.
233
***************************************************************/
235
return list_Sort(List, list_PointerLower);
239
BOOL list_SortedInOrder(LIST L, BOOL (*Test)(POINTER, POINTER))
240
/**************************************************************
241
INPUT: A list, and an ordering function.
242
RETURNS: TRUE, if the list is ordered with respect to the
243
ordering function, FALSE otherwise.
244
EFFECT: The function needs time O(n), where <n> is the
246
***************************************************************/
250
if (!(list_Empty(L) || list_Empty(list_Cdr(L)))) {
252
Scan2 = list_Cdr(Scan1);
256
/* If all elements are ordered, then every element */
257
/* is <= its successor with respect to the ordering */
259
/* We might have a strictly ordering Test function, */
260
/* which implements < instead of <=, so let's test */
261
/* for equality first. */
262
if (!Test(list_Car(Scan1), list_Car(Scan2)) &&
263
Test(list_Car(Scan2), list_Car(Scan1)))
264
/* It is really strictly greater, so return FALSE. */
267
Scan1 = list_Cdr(Scan1);
268
Scan2 = list_Cdr(Scan1);
269
} while (!list_Empty(Scan2));
276
LIST list_Merge(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER))
277
/**************************************************************
278
INPUT: Two sorted lists List1 and List2, and an ordering function.
279
RETURNS: The merged list ordered with respect to the ordering function.
280
EFFECT: The function needs time O(n), where <n> is the length of the list.
281
***************************************************************/
284
LIST Scan1, Scan2, Result, ResultStart;
287
if (!list_SortedInOrder(List1, Test)) {
288
/* print an error message and exit */
289
misc_StartErrorReport();
290
misc_ErrorReport("\n In list_Merge: First argument is not sorted.");
291
misc_FinishErrorReport();
293
else if (!list_SortedInOrder (List2, Test)) {
294
/* print an error message and exit */
295
misc_StartErrorReport();
296
misc_ErrorReport("\n In list_Merge: Second argument is not sorted.");
297
misc_FinishErrorReport();
301
if (list_Empty(List1))
304
if (list_Empty(List2))
307
/* This version is derived from list_NNumberMerge, but it doesn't need */
308
/* to allocate and deallocate memory, so it should be more efficient. */
310
/* Use the list with the least element as result list. */
311
if (Test(list_Car(List1), list_Car(List2))) {
313
Scan1 = list_Cdr(List1);
319
Scan2 = list_Cdr(List2);
322
/* Result is the last element of the merged list. */
324
Result = ResultStart;
326
while (!list_Empty(Scan1) && !list_Empty(Scan2)) {
327
/* This function doesn't implement stable merging. */
328
/* Add another test if you need it. */
330
if (Test(list_Car(Scan1), list_Car(Scan2))) {
331
list_Rplacd(Result,Scan1);
332
Scan1 = list_Cdr(Scan1);
335
list_Rplacd(Result,Scan2);
336
Scan2 = list_Cdr(Scan2);
338
Result = list_Cdr(Result);
341
if (list_Empty(Scan1))
342
list_Rplacd(Result, Scan2);
344
list_Rplacd(Result, Scan1);
350
void list_Split(LIST L, LIST *Half1, LIST *Half2)
351
/**************************************************************
352
INPUT: A list, and two pointers to lists.
354
EFFECT: The input list is split in two. <Half1> and
355
<Half2> point to the resulting halves.
356
The input list is destructively changed!
357
If the list length is odd, <Half2> is assigned the
359
The function needs time O(n), where <n> is the
360
length of the input list.
361
***************************************************************/
363
/* Adapted code from proofcheck ... MergeSort. */
365
LIST SingleStep, DoubleStep, Prev;
367
if (list_Empty(L) || list_Empty(list_Cdr(L))) {
372
/* divide list in two halves */
374
SingleStep = list_Cdr(L);
375
DoubleStep = list_Cdr(SingleStep);
377
while (!list_Empty(DoubleStep) && !list_Empty(list_Cdr(DoubleStep))) {
379
SingleStep = list_Cdr(SingleStep);
380
DoubleStep = list_Cdr(list_Cdr(DoubleStep));
385
list_Rplacd(Prev, list_Nil());
390
LIST list_MergeSort (LIST L, BOOL (*Test) (POINTER, POINTER))
391
/**************************************************************
392
INPUT: A list, and an ordering function.
393
RETURNS: The list sorted with respect to the ordering function.
394
EFFECT: The function needs time O((n log n) * t), where
395
<n> is the length of the input list and <t> is the
396
execution time of the ordering function.
397
***************************************************************/
403
originallength = list_Length(L);
406
/* Only sort if list has more than one element */
407
if (!list_Empty(L) && !list_Empty(list_Cdr(L))) {
412
LIST *greaterhalfptr;
414
lowerhalfptr = &lowerhalf;
415
greaterhalfptr = &greaterhalf;
417
list_Split(L, lowerhalfptr, greaterhalfptr);
420
if((list_Length(lowerhalf) + list_Length(greaterhalf))
422
/* output an error message and exit */
423
misc_StartErrorReport();
424
misc_ErrorReport("\n In list_MergeSort: Split lists' total sizes");
425
misc_ErrorReport("\n don't match original list's size.");
426
misc_FinishErrorReport();
430
lowerhalf = list_MergeSort(lowerhalf, Test);
432
greaterhalf = list_MergeSort(greaterhalf, Test);
435
if((list_Length(lowerhalf) + list_Length(greaterhalf))
437
/* output an error message and exit */
438
misc_StartErrorReport();
439
misc_ErrorReport("\n In list_MergeSort: Mergesorted lists' total sizes");
440
misc_ErrorReport("\n don't match original list's size.");
441
misc_FinishErrorReport();
445
Result = list_Merge(lowerhalf, greaterhalf, Test);
448
if(list_Length(Result) != originallength) {
449
/* output an error message and exit */
450
misc_StartErrorReport();
451
misc_ErrorReport("\n In list_MergeSort: Merged list's size doesn't match ");
452
misc_ErrorReport("\n original list's size.");
453
misc_FinishErrorReport();
466
LIST list_InsertionSort(LIST List, BOOL (*Test)(POINTER, POINTER))
467
/**************************************************************
468
INPUT: A list and a 'less' function on the elements.
469
RETURNS: The same list where the elements are sorted with
471
EFFECT: The function needs time O(n^2*t), where <n> is the
472
length of the list and <t> is the time for the test
474
CAUTION: Destructive.
475
***************************************************************/
477
LIST Scan1,Scan2,Min;
480
for (Scan1=List; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) {
482
for (Scan2 = list_Cdr(Scan1); !list_Empty(Scan2); Scan2 = list_Cdr(Scan2))
483
if (Test(list_Car(Scan2), list_Car(Min))) {
484
Exchange = list_Car(Min);
485
list_Rplaca(Min, list_Car(Scan2));
486
list_Rplaca(Scan2, Exchange);
494
LIST list_Sort(LIST List, BOOL (*Test)(POINTER, POINTER))
495
/**************************************************************
496
INPUT: A list and a 'less' function on the elements.
497
RETURNS: The same list where the elements are sorted with
499
EFFECT: The function needs time O((n log n) *t), where <n>
500
is the length of the list and <t> is the time for
502
CAUTION: Destructive.
503
***************************************************************/
510
originallength = list_Length(List);
513
Result = list_MergeSort(List, Test);
516
if (!list_SortedInOrder(Result, Test)) {
517
misc_StartErrorReport();
518
misc_ErrorReport("\n In list_Sort: list_MergeSort did not sort properly.");
519
misc_FinishErrorReport();
521
if (list_Length(Result) != originallength) {
522
misc_StartErrorReport();
523
misc_ErrorReport("\n In list_Sort: list_MergeSort lost elements. ");
524
misc_FinishErrorReport();
532
/* Help Variable used to store a pointer to the numbering function to use
533
in element comparisons.
535
static NAT (*NumberFunction)(POINTER) = NULL;
537
static __inline__ BOOL list_PointerNumberedLower(POINTER A, POINTER B)
539
return (BOOL) (NumberFunction(A) < NumberFunction(B));
542
static __inline__ BOOL list_PointerNumberedLowerOrEqual(POINTER A, POINTER B)
544
return (BOOL) (NumberFunction(A) <= NumberFunction(B));
547
static __inline__ BOOL list_PointerNumberedGreater(POINTER A, POINTER B)
549
return (BOOL) (NumberFunction(A) > NumberFunction(B));
552
LIST list_NumberSort(LIST List, NAT (*Number)(POINTER))
553
/**************************************************************
554
INPUT: A list and function mapping elements to numbers.
555
RETURNS: The same list where the elements are sorted with
556
respect to < and the Number function.
557
EFFECT: The function needs time O((n log n) * f), where <n>
558
is the length of the list and <f> is the time for a
559
call of the <Number> function.
560
CAUTION: Destructive.
561
***************************************************************/
563
/* Use number function as temporary variable. It is used as
564
an implicit parameter in list_PointerLower.
565
We can't make it an explicit parameter, because of the
566
prototype of list_Sort.
569
NumberFunction = Number;
571
return list_Sort(List, list_PointerNumberedLower);
576
LIST list_GreaterNumberSort(LIST List, NAT (*Number)(POINTER))
577
/**************************************************************
578
INPUT: A list and function mapping elements to numbers.
579
RETURNS: The same list where the elements are sorted with
580
respect to > and the Number function.
581
EFFECT: The function needs time O((n log n) * f), where <n>
582
is the length of the list and <f> is the time for a
583
call of the <Number> function.
584
CAUTION: Destructive.
585
***************************************************************/
587
/* Use number function as temporary variable. It is used as
588
an implicit parameter in list_PointerLower.
589
We can't make it an explicit parameter, because of the
590
prototype of list_Sort.
593
NumberFunction = Number;
595
return list_Sort(List, list_PointerNumberedGreater);
599
LIST list_NNumberMerge(LIST List1, LIST List2, NAT (*Number)(POINTER))
600
/**************************************************************
601
INPUT: Two sorted lists and function mapping elements to
603
RETURNS: The merge of the lists where the elements are sorted
604
with respect to < and the Number function.
605
CAUTION: Destructive on both lists.
606
***************************************************************/
608
NumberFunction = Number;
610
return list_Merge(List1, List2, list_PointerNumberedLowerOrEqual);
614
POINTER list_DequeueNext(LIST List)
615
/**************************************************************
617
RETURNS: A pointer to a dequeued element.
618
SUMMARY: We dequeue the element pointed to by list_Cdr(List).
619
The function needs time O(1).
620
***************************************************************/
625
if (list_Empty(List))
628
Memo = list_Cdr(List);
629
if (list_Empty(Memo))
632
Pointer = list_Car(Memo);
633
list_Rplacd(List, Memo->cdr);
639
POINTER list_NthElement(LIST List, NAT Number)
640
/**************************************************************
641
INPUT: A List and a natural number.
642
RETURNS: The <Number>th element of the list, NULL otherwise.
643
EFFECT: The function needs time O(Number).
644
***************************************************************/
646
while (!list_Empty(List) && --Number > 0)
647
List = list_Cdr(List);
649
if (list_Empty(List))
652
return list_Car(List);
656
void list_DeleteWithElement(LIST List, void (*ElementDelete)(POINTER))
657
/**************************************************************
658
INPUT: A list and a delete function for the elements.
660
EFFECT: The list and all its elements are deleted.
661
The function needs time O(n*d), where <n> is the length
662
of the list and <d> is the time for the delete function.
663
***************************************************************/
667
while (!list_Empty(List)) {
668
Scan = list_Cdr(List);
669
ElementDelete(list_Car(List));
676
NAT list_DeleteWithElementCount(LIST List, void (*ElementDelete)(POINTER))
677
/**************************************************************
678
INPUT: A List and a delete function for the elements.
679
RETURNS: The number of deleted elements.
680
EFFECT: The List and all its elements are deleted.
681
The function needs time O(n*d), where <n> is the length
682
of the list and <d> is the time for the delete function.
683
***************************************************************/
690
while (!list_Empty(List)) {
691
Scan = list_Cdr(List);
692
ElementDelete(list_Car(List));
702
LIST list_DeleteElement(LIST List, POINTER Element, BOOL (*Test)(POINTER, POINTER))
703
/**************************************************************
704
INPUT: A list, an element pointer, an equality test for
706
RETURNS: The list where Element is deleted from List with
708
EFFECTS: If List contains Element with respect to EqualityTest,
709
Element is deleted from List
710
CAUTION: Destructive. Be careful, the first element of a
711
list cannot be changed destructively by call by
713
***************************************************************/
717
while (!list_Empty(List) && Test(Element, list_Car(List))) {
718
Scan1 = list_Cdr(List);
723
if (list_Empty(List))
727
Scan1 = list_Cdr(List);
729
while (!list_Empty(Scan1)) {
730
if (Test(Element, list_Car(Scan1))) {
731
list_Rplacd(Scan2, list_Cdr(Scan1));
733
Scan1 = list_Cdr(Scan2);
737
Scan1 = list_Cdr(Scan1);
744
LIST list_DeleteElementIf(LIST List, BOOL (*Test)(POINTER))
745
/**************************************************************
746
INPUT: A list and a test for elements.
747
RETURNS: The list where an element is deleted if <Test> on it
749
CAUTION: Destructive. Be careful, the first element of a list
750
cannot be changed destructively by call by
752
***************************************************************/
756
while (!list_Empty(List) && Test(list_Car(List))) {
757
Scan1 = list_Cdr(List);
762
if (list_Empty(List))
766
Scan1 = list_Cdr(List);
768
while (!list_Empty(Scan1)) {
769
if (Test(list_Car(Scan1))) {
770
list_Rplacd(Scan2, list_Cdr(Scan1));
772
Scan1 = list_Cdr(Scan2);
776
Scan1 = list_Cdr(Scan1);
783
LIST list_DeleteElementIfFree(LIST List, BOOL (*Test)(POINTER),
784
void (*Delete)(POINTER))
785
/**************************************************************
786
INPUT: A list, a test for elements and a delete function
788
RETURNS: The list where an element is deleted if <Test> on it
790
The element is deleted with <Delete>.
791
CAUTION: Destructive. Be careful, the first element of a list
792
cannot be changed destructively by call by reference.
793
***************************************************************/
797
while (!list_Empty(List) && Test(list_Car(List))) {
798
Scan1 = list_Cdr(List);
799
Delete(list_Car(List));
804
if (list_Empty(List))
808
Scan1 = list_Cdr(List);
810
while (!list_Empty(Scan1)) {
811
if (Test(list_Car(Scan1))) {
812
Delete(list_Car(Scan1));
813
list_Rplacd(Scan2, list_Cdr(Scan1));
815
Scan1 = list_Cdr(Scan2);
819
Scan1 = list_Cdr(Scan1);
827
LIST list_DeleteElementFree(LIST List, POINTER Element,
828
BOOL (*Test)(POINTER, POINTER),
829
void (*Free)(POINTER))
830
/**************************************************************
831
INPUT: A list, an element pointer, an equality test for
832
elements and a free function for elements.
833
RETURNS: The list where Element is deleted from List with
835
EFFECTS: If the list contains <Element> with respect to <Test>,
836
<Element> is deleted from the list and freed.
837
CAUTION: Destructive. Be careful, the first element of a list
838
cannot be changed destructively by call by reference.
839
***************************************************************/
843
while (!list_Empty(List) && Test(Element, list_Car(List))) {
844
Scan1 = list_Cdr(List);
845
Free(list_Car(List));
850
if (list_Empty(List))
854
Scan1 = list_Cdr(List);
856
while (!list_Empty(Scan1)) {
857
if (Test(Element, list_Car(Scan1))) {
858
list_Rplacd(Scan2, list_Cdr(Scan1));
859
Free(list_Car(Scan1));
861
Scan1 = list_Cdr(Scan2);
865
Scan1 = list_Cdr(Scan1);
872
LIST list_DeleteOneElement(LIST List, POINTER Element, BOOL (*Test)(POINTER, POINTER))
873
/**************************************************************
874
INPUT: A list, an element pointer and an equality test for
876
RETURNS: The list where at most one element was deleted from
877
<List> if the Test between <Element> and the element
879
EFFECT: The function needs time O(n*t) in the worst case, and
880
time O(t) in the best case, where <n> is the length of
881
the list and t is the time for a call of the test function.
882
CAUTION: Destructive. Be careful, the first element of a list
883
cannot be changed destructively by call by
885
The memory of the deleted element is not freed.
886
***************************************************************/
890
if (list_Empty(List))
893
if (Test(Element, list_Car(List)))
894
return list_Pop(List);
897
for (scan2 = List, scan1 = list_Cdr(List); !list_Empty(scan1);
898
scan2 = scan1, scan1 = list_Cdr(scan1)) {
899
if (Test(Element, list_Car(scan1))) {
900
list_Rplacd(scan2, list_Cdr(scan1));
902
scan1 = list_Cdr(scan2);
910
LIST list_PointerDeleteElement(LIST List, POINTER Element)
911
/**************************************************************
912
INPUT: A list and an element pointer
913
RETURNS: The list where Element is deleted from List with respect to
915
EFFECTS: If <List> contains <Element> with respect to pointer equality,
916
<Element> is deleted from <List>.
917
This function needs time O(n), where <n> is the length of the list.
918
CAUTION: Destructive. Be careful, the first element of a list cannot
919
be changed destructively by call by reference.
920
***************************************************************/
924
while (!list_Empty(List) && Element == list_Car(List)) {
925
Scan1 = list_Cdr(List);
930
if (list_Empty(List))
934
Scan1 = list_Cdr(List);
936
while (!list_Empty(Scan1)) {
937
if (Element == list_Car(Scan1)) {
938
list_Rplacd(Scan2, list_Cdr(Scan1));
940
Scan1 = list_Cdr(Scan2);
944
Scan1 = list_Cdr(Scan1);
950
LIST list_PointerDeleteElementFree(LIST List, POINTER Element,
951
void (*Free)(POINTER))
952
/**************************************************************
953
INPUT: A list, an element pointer and a free function for
955
RETURNS: The list where Element is deleted from List with
956
respect to pointer equality and freed.
957
EFFECTS: If List contains Element with respect to pointer
958
equality, Element is deleted from List
959
CAUTION: Destructive. Be careful, the first element of a list
960
cannot be changed destructively by call by
962
***************************************************************/
966
while (!list_Empty(List) && Element == list_Car(List)) {
967
Scan1 = list_Cdr(List);
968
Free(list_Car(List));
973
if (list_Empty(List))
977
Scan1 = list_Cdr(List);
979
while (!list_Empty(Scan1)) {
980
if (Element == list_Car(Scan1)) {
981
list_Rplacd(Scan2, list_Cdr(Scan1));
982
Free(list_Car(Scan1));
984
Scan1 = list_Cdr(Scan2);
988
Scan1 = list_Cdr(Scan1);
995
LIST list_PointerDeleteOneElement(LIST List, POINTER Element)
996
/**************************************************************
997
INPUT: A list and an element pointer.
998
RETURNS: The list where one occurrence of Element is deleted from List
999
with respect to pointer equality.
1000
EFFECTS: If List contains Element with respect to pointer equality,
1001
Element is deleted from List.
1002
CAUTION: Destructive. Be careful, the first element of a list cannot
1003
be changed destructively by call by reference.
1004
***************************************************************/
1008
if (list_Empty(List))
1011
if (Element == list_Car(List))
1012
return list_Pop(List);
1016
Scan1 = list_Cdr(List);
1018
while (!list_Empty(Scan1)) {
1019
if (Element == list_Car(Scan1)) {
1020
list_Rplacd(Scan2, list_Cdr(Scan1));
1022
Scan1 = list_Cdr(Scan2);
1027
Scan1 = list_Cdr(Scan1);
1034
BOOL list_DeleteFromList(LIST* List, POINTER Element)
1035
/**************************************************************
1036
INPUT: A list and an element pointer
1037
RETURNS: TRUE, if Element was deleted; FALSE, otherwise.
1038
EFFECTS: If List contains Element with respect to pointer equality,
1039
all occurrences of Element are deleted from List.
1040
CAUTION: Destructive. Be careful, the first element of a list cannot
1041
be changed destructively by call by reference.
1042
***************************************************************/
1049
while (list_Exist(*List) && Element == list_Car(*List)) {
1050
Scan1 = list_Cdr(*List);
1056
if (list_Exist(*List)) {
1060
Scan1 = list_Cdr(*List);
1062
while (list_Exist(Scan1)) {
1063
if (Element == list_Car(Scan1)) {
1064
list_Rplacd(Scan2, list_Cdr(Scan1));
1066
Scan1 = list_Cdr(Scan2);
1070
Scan1 = list_Cdr(Scan1);
1079
BOOL list_DeleteOneFromList(LIST* List, POINTER Element)
1080
/**************************************************************
1081
INPUT: A list and an element pointer
1082
RETURNS: TRUE, if <Element> was deleted; FALSE, otherwise.
1083
EFFECTS: If <List> contains <Element> with respect to pointer equality,
1084
the first occurrence of <Element> is deleted from <List>.
1085
CAUTION: Destructive.
1086
***************************************************************/
1088
if (list_Exist(*List)) {
1091
/* special treatment for the first element */
1092
if (Element == list_Car(*List)) {
1093
Scan1 = list_Cdr(*List);
1100
for (Scan2 = *List, Scan1 = list_Cdr(*List); list_Exist(Scan1); ) {
1101
if (Element == list_Car(Scan1)) {
1102
list_Rplacd(Scan2, list_Cdr(Scan1));
1104
Scan1 = list_Cdr(Scan2);
1108
Scan1 = list_Cdr(Scan1);
1117
BOOL list_IsSetOfPointers(LIST L)
1118
/**************************************************************
1120
RETURNS: TRUE, if <L> is a set of pointers (without duplicates),
1122
EFFECT: The function needs n(n-1)/2 comparisons in the worst case,
1123
where n is the length of the list. So its time complexity
1125
***************************************************************/
1127
for ( ; !list_Empty(L); L = list_Cdr(L)) {
1128
if (list_PointerMember(list_Cdr(L), list_Car(L)))
1135
LIST list_DeleteDuplicates(LIST List, BOOL (*Test)(POINTER, POINTER))
1136
/**************************************************************
1137
INPUT: A list, an equality test for elements
1138
RETURNS: The list where multiple occurrences are deleted.
1139
CAUTION: Destructive.
1140
***************************************************************/
1146
while (!list_Empty(Scan)) {
1148
list_DeleteElement(list_Cdr(Scan), list_Car(Scan), Test));
1149
Scan = list_Cdr(Scan);
1155
LIST list_DeleteDuplicatesFree(LIST List, BOOL (*Test)(POINTER, POINTER),
1156
void (*Free)(POINTER))
1157
/**************************************************************
1158
INPUT: A list, an equality test for elements, and a free
1159
function for elements.
1160
RETURNS: The list where multiple occurrences are deleted.
1161
CAUTION: Destructive and frees all duplicates.
1162
***************************************************************/
1168
while (!list_Empty(Scan)) {
1169
list_Rplacd(Scan, list_DeleteElementFree(list_Cdr(Scan), list_Car(Scan), Test, Free));
1170
Scan = list_Cdr(Scan);
1176
LIST list_PointerDeleteDuplicates(LIST List)
1177
/**************************************************************
1179
RETURNS: The list where multiple occurrences are deleted.
1180
CAUTION: Destructive.
1181
EFFECT: The function needs
1182
***************************************************************/
1188
while (!list_Empty(Scan)) {
1189
list_Rplacd(Scan, list_PointerDeleteElement(list_Cdr(Scan),
1191
Scan = list_Cdr(Scan);
1197
LIST list_NPointerUnion(LIST List1, LIST List2)
1198
/**************************************************************
1200
RETURNS: Regarding both lists as sets, the union of the sets.
1201
CAUTION: Destructive.
1202
***************************************************************/
1204
return list_PointerDeleteDuplicates(list_Nconc(List1,List2));
1208
LIST list_NUnion(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER))
1209
/**************************************************************
1210
INPUT: Two lists and an equality test for the elements.
1211
RETURNS: Regarding both lists as sets, the union of the sets.
1212
CAUTION: Destructive.
1213
***************************************************************/
1215
return list_DeleteDuplicates(list_Nconc(List1,List2), Test);
1219
LIST list_NListTimes(LIST List1, LIST List2)
1220
/**************************************************************
1221
INPUT: Two lists of lists.
1222
RETURNS: The list of combinations of element lists.
1223
CAUTION: Destroys List1 and List2.
1224
***************************************************************/
1226
LIST Result, Scan1, Scan2;
1228
Result = list_Nil();
1230
if (!list_Empty(List2)) {
1231
for (Scan1=List1; !list_Empty(Scan1); Scan1=list_Cdr(Scan1))
1232
for (Scan2=List2; !list_Empty(Scan2); Scan2=list_Cdr(Scan2))
1233
Result = list_Cons(list_Append(((LIST)list_Car(Scan1)),
1234
list_Copy((LIST)list_Car(Scan2))),
1237
list_DeleteWithElement(List1, (void (*)(POINTER))list_Delete);
1238
list_DeleteWithElement(List2, (void (*)(POINTER))list_Delete);
1244
LIST list_NIntersect(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER))
1245
/**************************************************************
1246
INPUT: Two lists and an equality test for the elements.
1247
RETURNS: Regarding both lists as sets, the intersection of the sets.
1248
CAUTION: Destructive on List1
1249
***************************************************************/
1253
while (!list_Empty(List1) && !list_Member(List2, list_Car(List1), Test)) {
1254
Scan1 = list_Cdr(List1);
1259
if (list_Empty(List1))
1263
Scan2 = list_Cdr(List1);
1265
while (!list_Empty(Scan2)) {
1266
if (list_Member(List2, list_Car(Scan2), Test)) {
1267
Scan2 = list_Cdr(Scan2);
1268
Scan1 = list_Cdr(Scan1);
1271
list_Rplacd(Scan1, list_Cdr(Scan2));
1273
Scan2 = list_Cdr(Scan1);
1280
LIST list_NPointerIntersect(LIST List1, LIST List2)
1281
/**************************************************************
1283
RETURNS: Regarding both lists as sets, the intersection of the sets.
1284
CAUTION: Destructive on List1
1285
***************************************************************/
1289
while (!list_Empty(List1) && !list_PointerMember(List2, list_Car(List1))) {
1290
Scan1 = list_Cdr(List1);
1295
if (list_Empty(List1))
1299
Scan2 = list_Cdr(List1);
1301
while (!list_Empty(Scan2)) {
1302
if (list_PointerMember(List2, list_Car(Scan2))) {
1303
Scan2 = list_Cdr(Scan2);
1304
Scan1 = list_Cdr(Scan1);
1307
list_Rplacd(Scan1, list_Cdr(Scan2));
1309
Scan2 = list_Cdr(Scan1);
1315
/**************************************************************
1317
EFFECT: <List2> is concatenated after
1318
the last element of <List1>.
1319
RETURNS: Concatenated list.
1320
CAUTION: Destructive on List1.
1321
***************************************************************/
1322
LIST list_Nconc(LIST List1, LIST List2)
1326
if (list_Empty(List1))
1329
if (list_Empty(List2))
1333
for (List1 = Result; !list_Empty(list_Cdr(List1)); List1 = list_Cdr(List1))
1339
void list_NInsert(LIST List1, LIST List2)
1340
/**************************************************************
1341
INPUT: Two lists where <List1> must not be empty.
1342
EFFECT: <List2> is destructively concatenated after
1343
the first element of <List1>.
1345
CAUTION: Destructive on List1 and List2.
1346
***************************************************************/
1351
if (list_Empty(List1)) {
1352
misc_StartErrorReport();
1353
misc_ErrorReport("\n In list_NInsert: Empty list argument.");
1354
misc_FinishErrorReport();
1358
Help = list_Cdr(List1);
1359
list_Rplacd(List1,List2);
1362
while (!list_Empty(list_Cdr(List2)))
1363
List2 = list_Cdr(List2);
1365
list_Rplacd(List2,Help);
1369
BOOL list_HasIntersection(LIST List1, LIST List2)
1370
/**************************************************************
1372
RETURNS: TRUE iff List1 and List2 have a common element.
1373
EFFECT: The function needs time O(n*m), where n and m are the
1374
lengths of the lists.
1375
***************************************************************/
1379
if (!list_Empty(List2)) {
1380
for (Scan=List1; !list_Empty(Scan); Scan=list_Cdr(Scan))
1381
if (list_PointerMember(List2, list_Car(Scan)))
1388
LIST list_NPointerDifference(LIST List1, LIST List2)
1389
/**************************************************************
1391
RETURNS: The list List1-List2.
1392
CAUTION: Destructive on List1.
1393
***************************************************************/
1397
if (!list_Empty(List1)) {
1398
for (Scan=List2; !list_Empty(Scan); Scan=list_Cdr(Scan))
1399
List1 = list_PointerDeleteElement(List1, list_Car(Scan));
1405
LIST list_NDifference(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER))
1406
/**************************************************************
1407
INPUT: Two lists and an equality test for elements.
1408
RETURNS: The list List1-List2 wrt. <Test>.
1409
CAUTION: Destructive on List1.
1410
***************************************************************/
1414
if (!list_Empty(List1)) {
1415
for (Scan=List2; !list_Empty(Scan); Scan=list_Cdr(Scan))
1416
List1 = list_DeleteElement(List1, list_Car(Scan), Test);
1422
LIST list_NMultisetDifference(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER))
1423
/**************************************************************
1424
INPUT: Two lists representing multisets and an equality
1426
RETURNS: The multiset difference List1-List2 wrt. <Test>.
1427
CAUTION: Destructive on List1. The memory of deleted
1428
elements is not freed.
1429
***************************************************************/
1432
/* Delete equal arguments */
1433
if (!list_Empty(List1)) {
1434
for (scan = List2; !list_Empty(scan); scan = list_Cdr(scan))
1435
/* Delete at most one element from List1 equal to */
1436
/* the actual element of List2. */
1437
List1 = list_DeleteOneElement(List1, list_Car(scan), Test);
1443
BOOL list_PointerReplaceMember(LIST List, POINTER Old, POINTER New)
1444
/**************************************************************
1445
INPUT: A list, a pointer to an old element, a pointer to a new element
1446
RETURNS: TRUE iff <Old> was replaced.
1447
EFFECT: The first occurrence of <Old> in the list is replaced by <New>.
1448
***************************************************************/
1450
while (!list_Empty(List)) {
1451
if (Old == list_Car(List)) {
1452
list_Rplaca(List, New);
1455
List = list_Cdr(List);
1461
void list_DeleteAssocListWithValues(LIST List, void (*ValueDelete)(POINTER))
1462
/**************************************************************
1463
INPUT: An association list and a delete function for the values.
1465
EFFECT: The assoc list and its values are deleted.
1466
***************************************************************/
1470
for (Scan=List;!list_Empty(Scan);Scan = list_Cdr(Scan)) {
1471
ValueDelete(list_PairSecond(list_Car(Scan)));
1472
list_PairFree(list_Car(Scan));
1479
POINTER list_AssocListValue(LIST List, POINTER Key)
1480
/**************************************************************
1481
INPUT: An association list and a key.
1482
RETURNS: The value for <key> in the list. If <key> is not
1484
***************************************************************/
1488
for (Scan=List;!list_Empty(Scan);Scan = list_Cdr(Scan))
1489
if (Key == list_PairFirst(list_Car(Scan)))
1490
return list_PairSecond(list_Car(Scan));
1496
LIST list_AssocListPair(LIST List, POINTER Key)
1497
/**************************************************************
1498
INPUT: An association list and a key.
1499
RETURNS: The (<key>.<value) in the list. If <key> is not
1500
contained, the NULL pair.
1501
***************************************************************/
1505
for (Scan=List;!list_Empty(Scan);Scan = list_Cdr(Scan))
1506
if (Key == list_PairFirst(list_Car(Scan)))
1507
return list_Car(Scan);
1509
return list_PairNull();
1513
LIST list_MultisetDistribution(LIST Multiset)
1514
/**************************************************************
1515
INPUT: A list representing a multiset.
1516
RETURNS: The associative list of pairs (<element>.<occurrences>)
1517
representing the distribution of elements in the list.
1518
If the input multiset is empty, the NULL pair.
1519
***************************************************************/
1524
Distribution = list_PairNull();
1526
for (Scan = Multiset; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
1531
Element = list_Car(Scan);
1532
Count = list_AssocListPair(Distribution, Element);
1534
if (Count != list_PairNull()) {
1535
Occurences = (int) list_PairSecond(Count);
1536
list_PairRplacSecond(Count, (POINTER) (Occurences + 1));
1539
Distribution = list_AssocCons(Distribution, Element, (POINTER) 1);
1543
return Distribution;
1547
int list_CompareElementDistribution(LIST LeftPair, LIST RightPair)
1548
/**************************************************************
1549
INPUT: Two lists, representing single element frequency
1551
RETURNS: 1 if left > right, -1 if left < right, 0 otherwise.
1552
EFFECT: Compares two element frequencies.
1553
***************************************************************/
1555
if ((int) list_PairSecond(LeftPair) < (int) list_PairSecond(RightPair)) {
1558
else if ((int) list_PairSecond(LeftPair) > (int) list_PairSecond(RightPair)) {
1566
BOOL list_CompareElementDistributionLEQ(LIST LeftPair, LIST RightPair) {
1567
/**************************************************************
1568
INPUT: Two lists, representing single element frequency
1570
RETURNS: TRUE if left <= right, FALSE otherwise.
1571
EFFECT: Compares two element frequencies.
1572
***************************************************************/
1573
return (list_CompareElementDistribution(LeftPair, RightPair) <= 0);
1577
static int list_CompareDistributions(LIST Left, LIST Right)
1578
/**************************************************************
1579
INPUT: Two lists, representing element distributions.
1580
RETURNS: 1 if left > right, -1 if left < right, 0 otherwise.
1581
EFFECT: Compares the two distributions by comparing the
1582
element frequencies from left to right.
1583
CAUTION: Expects the distributions to be sorted.
1584
***************************************************************/
1594
/* Compare distributions. */
1596
while ( !(list_Empty(scan) || list_Empty(scan2))) {
1597
result = list_CompareElementDistribution(list_Car(scan), list_Car(scan2));
1602
scan = list_Cdr(scan);
1603
scan2 = list_Cdr(scan2);
1606
/* If the result is 0, and a distribution still
1607
has elements left, it is declared to be greater.
1610
if (list_Empty(scan) && !list_Empty(scan2))
1612
else if (!list_Empty(scan) && list_Empty(scan2))
1620
int list_CompareMultisetsByElementDistribution(LIST Left, LIST Right)
1621
/**************************************************************
1622
INPUT: Two lists, representing multisets.
1623
RETURNS: 1 if left > right, -1 if left < right, 0 otherwise.
1624
EFFECT: Compares two multisets by counting their element
1625
frequencies, sorting them, and comparing the
1626
resulting multisets over natural numbers.
1627
***************************************************************/
1629
LIST lmsd, rmsd; /* multiset distributions. */
1632
/* Convert multiset of elements into a
1633
multiset of pairs (element, occurrences).
1636
lmsd = list_MultisetDistribution(Left);
1637
rmsd = list_MultisetDistribution(Right);
1639
/* Sort multiset distributions in order
1640
to make them comparable.
1643
lmsd = list_Sort(lmsd, (BOOL (*) (POINTER, POINTER)) list_CompareElementDistributionLEQ);
1644
rmsd = list_Sort(rmsd, (BOOL (*) (POINTER, POINTER)) list_CompareElementDistributionLEQ);
1646
result = list_CompareDistributions(lmsd, rmsd);
1648
list_DeleteDistribution(lmsd);
1649
list_DeleteDistribution(rmsd);
1655
NAT list_Length(LIST List)
1656
/**************************************************************
1658
RETURNS: The number of elements..
1659
EFFECT: The function needs time O(n), where <n> is the length
1661
***************************************************************/
1667
while (!list_Empty(List)) {
1669
List = list_Cdr(List);
1676
NAT list_Bytes(LIST List)
1677
/**************************************************************
1679
RETURNS: The number of Bytes occupied by the list structure of <List>
1680
EFFECT: the function needs time O(n), where <n> is the length
1682
***************************************************************/
1684
return (list_Length(List)*sizeof(LIST_NODE));