# HG changeset patch # User wenzelm # Date 1342447041 -7200 # Node ID b28defd0b5a5d59ad022411719ef6859b97b7d64 # Parent 9cfd3e7ad5c8a0f51d19171ec5bd490c98ddc031 replaced quicksort by mergesort, which might be a bit more efficient for key operations like Ord_List.make, Sorts.minimize_sort; diff -r 9cfd3e7ad5c8 -r b28defd0b5a5 src/Pure/library.ML --- a/src/Pure/library.ML Mon Jul 16 15:55:21 2012 +0200 +++ b/src/Pure/library.ML Mon Jul 16 15:57:21 2012 +0200 @@ -932,29 +932,55 @@ (* sorting *) -(*quicksort -- stable, i.e. does not reorder equal elements*) -fun quicksort unique ord = +(*stable mergesort -- preserves order of equal elements*) +fun mergesort unique ord = let - fun qsort [] = [] - | qsort (xs as [_]) = xs - | qsort (xs as [x, y]) = + fun merge (xs as x :: xs') (ys as y :: ys') = + (case ord (x, y) of + LESS => x :: merge xs' ys + | EQUAL => + if unique then merge xs ys' + else x :: merge xs' ys + | GREATER => y :: merge xs ys') + | merge [] ys = ys + | merge xs [] = xs; + + fun merge_all [xs] = xs + | merge_all xss = merge_all (merge_pairs xss) + and merge_pairs (xs :: ys :: xss) = merge xs ys :: merge_pairs xss + | merge_pairs xss = xss; + + fun runs (x :: y :: xs) = (case ord (x, y) of - LESS => xs - | EQUAL => if unique then [x] else xs - | GREATER => [y, x]) - | qsort xs = - let val (lts, eqs, gts) = part (nth xs (length xs div 2)) xs - in qsort lts @ eqs @ qsort gts end - and part _ [] = ([], [], []) - | part pivot (x :: xs) = add (ord (x, pivot)) x (part pivot xs) - and add LESS x (lts, eqs, gts) = (x :: lts, eqs, gts) - | add EQUAL x (lts, [], gts) = (lts, [x], gts) - | add EQUAL x (res as (lts, eqs, gts)) = if unique then res else (lts, x :: eqs, gts) - | add GREATER x (lts, eqs, gts) = (lts, eqs, x :: gts); - in qsort end; + LESS => ascending y [x] xs + | EQUAL => + if unique then runs (x :: xs) + else ascending y [x] xs + | GREATER => descending y [x] xs) + | runs xs = [xs] -fun sort ord = quicksort false ord; -fun sort_distinct ord = quicksort true ord; + and ascending x xs (zs as y :: ys) = + (case ord (x, y) of + LESS => ascending y (x :: xs) ys + | EQUAL => + if unique then ascending x xs ys + else ascending y (x :: xs) ys + | GREATER => rev (x :: xs) :: runs zs) + | ascending x xs [] = [rev (x :: xs)] + + and descending x xs (zs as y :: ys) = + (case ord (x, y) of + GREATER => descending y (x :: xs) ys + | EQUAL => + if unique then descending x xs ys + else (x :: xs) :: runs zs + | LESS => (x :: xs) :: runs zs) + | descending x xs [] = [x :: xs]; + + in merge_all o runs end; + +fun sort ord = mergesort false ord; +fun sort_distinct ord = mergesort true ord; val sort_strings = sort string_ord; fun sort_wrt key xs = sort (string_ord o pairself key) xs;