| author | wenzelm | 
| Thu, 12 Oct 2023 20:58:15 +0200 | |
| changeset 78767 | aa67309a7960 | 
| parent 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
 | |
| 44334 | 17 |   val unions: ('a * 'a -> order) -> 'a T list -> 'a T
 | 
| 41473 | 18 |   val merge: ('a * 'a -> order) -> 'a T * 'a T -> 'a T
 | 
| 28354 | 19 |   val inter: ('b * 'a -> order) -> 'b T -> 'a T -> 'a T
 | 
| 20 |   val subtract: ('b * 'a -> order) -> 'b T -> 'a T -> 'a T
 | |
| 16464 | 21 | end; | 
| 22 | ||
| 39687 | 23 | structure Ord_List: ORD_LIST = | 
| 16464 | 24 | struct | 
| 25 | ||
| 28354 | 26 | type 'a T = 'a list; | 
| 28626 | 27 | fun make ord = sort_distinct ord; | 
| 28354 | 28 | |
| 16511 | 29 | |
| 30 | (* single elements *) | |
| 31 | ||
| 32 | fun find_index ord list x = | |
| 33 | let | |
| 16811 | 34 | fun find i [] = ~ i | 
| 16511 | 35 | | find i (y :: ys) = | 
| 36 | (case ord (x, y) of | |
| 16811 | 37 | LESS => ~ i | 
| 16511 | 38 | | EQUAL => i | 
| 39 | | GREATER => find (i + 1) ys); | |
| 16811 | 40 | in find 1 list end; | 
| 16497 | 41 | |
| 16811 | 42 | fun member ord list x = find_index ord list x > 0; | 
| 16464 | 43 | |
| 44 | fun insert ord x list = | |
| 45 | let | |
| 16811 | 46 | fun insrt 1 ys = x :: ys | 
| 16511 | 47 | | insrt i (y :: ys) = y :: insrt (i - 1) ys; | 
| 16811 | 48 | val idx = find_index ord list x; | 
| 49 | in if idx > 0 then list else insrt (~ idx) list end; | |
| 16464 | 50 | |
| 51 | fun remove ord x list = | |
| 52 | let | |
| 16811 | 53 | fun rmove 1 (_ :: ys) = ys | 
| 16511 | 54 | | rmove i (y :: ys) = y :: rmove (i - 1) ys; | 
| 16811 | 55 | val idx = find_index ord list x; | 
| 56 | in if idx > 0 then rmove idx list else list end; | |
| 16511 | 57 | |
| 58 | ||
| 59 | (* lists as sets *) | |
| 60 | ||
| 61 | fun subset ord (list1, list2) = | |
| 62 | let | |
| 63 | fun sub [] _ = true | |
| 64 | | sub _ [] = false | |
| 65 | | sub (lst1 as x :: xs) (y :: ys) = | |
| 16464 | 66 | (case ord (x, y) of | 
| 16511 | 67 | LESS => false | 
| 68 | | EQUAL => sub xs ys | |
| 69 | | GREATER => sub lst1 ys); | |
| 70 | in sub list1 list2 end; | |
| 71 | ||
| 72 | ||
| 73 | (* algebraic operations *) | |
| 74 | ||
| 75 | exception SAME; | |
| 76 | fun handle_same f x = f x handle SAME => x; | |
| 16464 | 77 | |
| 16497 | 78 | (*union: insert elements of first list into second list*) | 
| 79 | fun union ord list1 list2 = | |
| 80 | let | |
| 81 | fun unio [] _ = raise SAME | |
| 82 | | unio xs [] = xs | |
| 83 | | unio (lst1 as x :: xs) (lst2 as y :: ys) = | |
| 84 | (case ord (x, y) of | |
| 85 | LESS => x :: handle_same (unio xs) lst2 | |
| 86 | | EQUAL => y :: unio xs ys | |
| 87 | | 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 | 88 | in if pointer_eq (list1, list2) then list1 else handle_same (unio list1) list2 end; | 
| 16464 | 89 | |
| 44334 | 90 | fun unions ord lists = | 
| 91 | let | |
| 92 | fun unios (xs :: ys :: rest) acc = unios rest (union ord xs ys :: acc) | |
| 93 | | unios [xs] (ys :: acc) = unios (union ord xs ys :: acc) [] | |
| 94 | | unios [xs] [] = xs | |
| 95 | | unios [] [] = [] | |
| 96 | | unios [] acc = unios acc []; | |
| 97 | in unios lists [] end; | |
| 98 | ||
| 41473 | 99 | fun merge ord (list1, list2) = union ord list2 list1; | 
| 100 | ||
| 16497 | 101 | (*intersection: filter second list for elements present in first list*) | 
| 102 | fun inter ord list1 list2 = | |
| 103 | let | |
| 104 | fun intr _ [] = raise SAME | |
| 105 | | intr [] _ = [] | |
| 106 | | intr (lst1 as x :: xs) (lst2 as y :: ys) = | |
| 107 | (case ord (x, y) of | |
| 108 | LESS => intr xs lst2 | |
| 109 | | EQUAL => y :: intr xs ys | |
| 110 | | GREATER => handle_same (intr lst1) ys); | |
| 111 | in handle_same (intr list1) list2 end; | |
| 112 | ||
| 113 | (*subtraction: filter second list for elements NOT present in first list*) | |
| 114 | fun subtract ord list1 list2 = | |
| 115 | let | |
| 116 | fun subtr [] _ = raise SAME | |
| 117 | | subtr _ [] = raise SAME | |
| 118 | | subtr (lst1 as x :: xs) (lst2 as y :: ys) = | |
| 119 | (case ord (x, y) of | |
| 120 | LESS => subtr xs lst2 | |
| 121 | | EQUAL => handle_same (subtr xs) ys | |
| 122 | | GREATER => y :: subtr lst1 ys); | |
| 123 | in handle_same (subtr list1) list2 end; | |
| 16464 | 124 | |
| 125 | end; |