Edit file File name : listfuns.sl Content :% Copyright (C) 2012-2017,2018 John E. Davis % % This file is part of the S-Lang Library and may be distributed under the % terms of the GNU General Public License. See the file COPYING for % more information. %--------------------------------------------------------------------------- require ("arrayfuns"); private define user_sort_cmp (cd, i, j) { variable list = cd.list; return (@cd.cmp) (list[i], list[j]); } private define default_sort_cmp (list, i, j) { if (list[i] > list[j]) return 1; if (list[i] == list[j]) return 0; return -1; } define list_sort (list) { variable dir = qualifier ("dir", 1); variable cmp = qualifier ("cmp"); variable n = length (list); variable i; if (cmp == NULL) i = array_sort (list, &default_sort_cmp, n; dir=dir); else i = array_sort (struct {list=list, cmp=cmp}, &user_sort_cmp, n; dir=dir); variable inplace = qualifier ("inplace", 0); if (inplace == 0) return i; rearrange (list, i); } % Heap Implementation private define heap_length (h) { return length (h.list); } private define upheap (list, k, cmp) { variable obj = list[k]; variable k2 = (k-1)/2; while (k && (@cmp)(obj,list[k2]) > 0) { list[k] = list[k2]; k = k2; k2 = (k-1)/2; } list[k] = obj; } private define downheap (list, k, cmp) { variable obj = list[k]; variable n = length(list), n2 = n/2; n--; % 0 % 1 2 % 3 4 5 6 % 7 8 9 10 11 12 13 14 while (k < n2) { variable j = 2*k + 1; if ((j < n) && ((@cmp)(list[j], list[j+1]) < 0)) j++; if ((@cmp)(obj, list[j]) >= 0) break; list[k] = list[j]; k = j; } list[k] = obj; } private define heap_add (h, obj) { variable list = h.list; list_append (list, obj); upheap (list, length(list)-1, h.cmp); } private define heap_pop (h) { variable list = h.list; variable obj = list[0]; variable last = list_pop(list, -1); if (length (list)) { list[0] = last; downheap (list, 0, h.cmp); } return obj; } private define heap_peek (h) { return h.list[0]; } private define default_heap_cmp (a, b) { if (a > b) return 1; if (a < b) return -1; return 0; } private define default_heap_cmp_rev (a, b) { if (a > b) return -1; if (a < b) return 1; return 0; } define heap_new () { if (_NARGS == 0) usage (` h = new_heap (list; cmp=&cmpfun, dir=val); len = h.length(); h.add (item); top = h.remove(); top = h.peek (); ` ); variable list = (); variable cmp = qualifier ("cmp"); variable dir = qualifier ("dir", -1); % The conventional interpretation of a heap is that the largest % element is at the root, and smaller ones below. For this reason, % dir=-1 (ascending order) is the default for sorting. list_sort (list; cmp=cmp, dir=dir, inplace); if (cmp == NULL) { cmp = (dir <= 0) ? &default_heap_cmp : &default_heap_cmp_rev; } variable h = struct { list = list, cmp = cmp, length = &heap_length, add = &heap_add, remove = &heap_pop, peek = &heap_peek, }; return h; } Save