| author | berghofe | 
| Sat, 15 Jan 2011 22:40:17 +0100 | |
| changeset 41584 | 2b07a4212d6d | 
| parent 41473 | 3717fc42ebe9 | 
| child 44334 | 605381e7c7c5 | 
| permissions | -rw-r--r-- | 
| 16464 | 1 | (* Title: Pure/General/ord_list.ML | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Ordered lists without duplicates -- a light-weight representation of | |
| 16497 | 5 | finite sets, all operations take linear time and economize heap usage. | 
| 16464 | 6 | *) | 
| 7 | ||
| 8 | signature ORD_LIST = | |
| 9 | sig | |
| 28354 | 10 | type 'a T = 'a list | 
| 28626 | 11 |   val make: ('a * 'a -> order) -> 'a list -> 'a T
 | 
| 28354 | 12 |   val member: ('b * 'a -> order) -> 'a T -> 'b -> bool
 | 
| 13 |   val insert: ('a * 'a -> order) -> 'a -> 'a T -> 'a T
 | |
| 14 |   val remove: ('b * 'a -> order) -> 'b -> 'a T -> 'a T
 | |
| 15 |   val subset: ('b * 'a -> order) -> 'b T * 'a T -> bool
 | |
| 16 |   val union: ('a * 'a -> order) -> 'a T -> 'a T -> 'a T
 | |
| 41473 | 17 |   val merge: ('a * 'a -> order) -> 'a T * 'a T -> 'a T
 | 
| 28354 | 18 |   val inter: ('b * 'a -> order) -> 'b T -> 'a T -> 'a T
 | 
| 19 |   val subtract: ('b * 'a -> order) -> 'b T -> 'a T -> 'a T
 | |
| 16464 | 20 | end; | 
| 21 | ||
| 39687 | 22 | structure Ord_List: ORD_LIST = | 
| 16464 | 23 | struct | 
| 24 | ||
| 28354 | 25 | type 'a T = 'a list; | 
| 28626 | 26 | fun make ord = sort_distinct ord; | 
| 28354 | 27 | |
| 16511 | 28 | |
| 29 | (* single elements *) | |
| 30 | ||
| 31 | fun find_index ord list x = | |
| 32 | let | |
| 16811 | 33 | fun find i [] = ~ i | 
| 16511 | 34 | | find i (y :: ys) = | 
| 35 | (case ord (x, y) of | |
| 16811 | 36 | LESS => ~ i | 
| 16511 | 37 | | EQUAL => i | 
| 38 | | GREATER => find (i + 1) ys); | |
| 16811 | 39 | in find 1 list end; | 
| 16497 | 40 | |
| 16811 | 41 | fun member ord list x = find_index ord list x > 0; | 
| 16464 | 42 | |
| 43 | fun insert ord x list = | |
| 44 | let | |
| 16811 | 45 | fun insrt 1 ys = x :: ys | 
| 16511 | 46 | | insrt i (y :: ys) = y :: insrt (i - 1) ys; | 
| 16811 | 47 | val idx = find_index ord list x; | 
| 48 | in if idx > 0 then list else insrt (~ idx) list end; | |
| 16464 | 49 | |
| 50 | fun remove ord x list = | |
| 51 | let | |
| 16811 | 52 | fun rmove 1 (_ :: ys) = ys | 
| 16511 | 53 | | rmove i (y :: ys) = y :: rmove (i - 1) ys; | 
| 16811 | 54 | val idx = find_index ord list x; | 
| 55 | in if idx > 0 then rmove idx list else list end; | |
| 16511 | 56 | |
| 57 | ||
| 58 | (* lists as sets *) | |
| 59 | ||
| 60 | fun subset ord (list1, list2) = | |
| 61 | let | |
| 62 | fun sub [] _ = true | |
| 63 | | sub _ [] = false | |
| 64 | | sub (lst1 as x :: xs) (y :: ys) = | |
| 16464 | 65 | (case ord (x, y) of | 
| 16511 | 66 | LESS => false | 
| 67 | | EQUAL => sub xs ys | |
| 68 | | GREATER => sub lst1 ys); | |
| 69 | in sub list1 list2 end; | |
| 70 | ||
| 71 | ||
| 72 | (* algebraic operations *) | |
| 73 | ||
| 74 | exception SAME; | |
| 75 | fun handle_same f x = f x handle SAME => x; | |
| 16464 | 76 | |
| 16497 | 77 | (*union: insert elements of first list into second list*) | 
| 78 | fun union ord list1 list2 = | |
| 79 | let | |
| 80 | fun unio [] _ = raise SAME | |
| 81 | | unio xs [] = xs | |
| 82 | | unio (lst1 as x :: xs) (lst2 as y :: ys) = | |
| 83 | (case ord (x, y) of | |
| 84 | LESS => x :: handle_same (unio xs) lst2 | |
| 85 | | EQUAL => y :: unio xs ys | |
| 86 | | GREATER => y :: unio lst1 ys); | |
| 30572 
8fbc355100f2
Library.merge/OrdList.union: optimize the important special case where the tables coincide -- NOTE: this changes both the operational behaviour and the result for non-standard eq/ord notion;
 wenzelm parents: 
29606diff
changeset | 87 | in if pointer_eq (list1, list2) then list1 else handle_same (unio list1) list2 end; | 
| 16464 | 88 | |
| 41473 | 89 | fun merge ord (list1, list2) = union ord list2 list1; | 
| 90 | ||
| 16497 | 91 | (*intersection: filter second list for elements present in first list*) | 
| 92 | fun inter ord list1 list2 = | |
| 93 | let | |
| 94 | fun intr _ [] = raise SAME | |
| 95 | | intr [] _ = [] | |
| 96 | | intr (lst1 as x :: xs) (lst2 as y :: ys) = | |
| 97 | (case ord (x, y) of | |
| 98 | LESS => intr xs lst2 | |
| 99 | | EQUAL => y :: intr xs ys | |
| 100 | | GREATER => handle_same (intr lst1) ys); | |
| 101 | in handle_same (intr list1) list2 end; | |
| 102 | ||
| 103 | (*subtraction: filter second list for elements NOT present in first list*) | |
| 104 | fun subtract ord list1 list2 = | |
| 105 | let | |
| 106 | fun subtr [] _ = raise SAME | |
| 107 | | subtr _ [] = raise SAME | |
| 108 | | subtr (lst1 as x :: xs) (lst2 as y :: ys) = | |
| 109 | (case ord (x, y) of | |
| 110 | LESS => subtr xs lst2 | |
| 111 | | EQUAL => handle_same (subtr xs) ys | |
| 112 | | GREATER => y :: subtr lst1 ys); | |
| 113 | in handle_same (subtr list1) list2 end; | |
| 16464 | 114 | |
| 115 | end; |