array_ext.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 

class ARRAY_EXT{ELT}

class ARRAY_EXT{ELT} is delete_at(i:CARD, ar:ARRAY{ELT}):ARRAY{ELT} is --a::=ar.copy; --if i<a.size-1 then a.copy(i,a.size-1-i, i+1,a); end; --a:=a.resize(a.size-1); --return a; a:ARRAY{ELT}:=#(ar.size-1); if 0<i then a.copy(0,i,ar); end; if i<ar.size-1 then a.copy(i,ar.size-i-1,i+1,ar); end; return a; end; insert_at(i:CARD, ar:ARRAY{ELT}, e:ELT):ARRAY{ELT} pre (i<=ar.size) is if i=0 then res:ARRAY{ELT}:=#(ar.size+1); res[0]:=e; res.copy(1,ar); return res; elsif i=ar.size then return ar.append(|e|); else res:ARRAY{ELT}:=#(ar.size+1); res.copy(0,i,ar); res[i]:=e; res.copy(i+1,ar.size-i,i,ar); return res; end; end; insert_at(i:CARD,ar0:ARRAY{ELT},ar1:ARRAY{ELT}):ARRAY{ELT} pre (i<=ar0.size) is if i=0 then return ar1.append(ar0); elsif i=ar0.size then return ar0.append(ar1); else res:ARRAY{ELT}:=#(ar0.size+ar1.size); res.copy(0,i,ar0); res.copy(i,ar1); res.copy(i+ar1.size,ar0.size-i,i,ar0); return res; end; end; end;

class ARRAY_SORT{ELT}

class ARRAY_SORT{ELT} is check_range(ar:ARRAY{ELT}, l,u:CARD):BOOL is if void(ar) then return false; end; return (l<=u)and(u<ar.size) end ; swap(inout ar:ARRAY{ELT}, i1,i2:CARD) is t:ELT:=ar[i1]; ar[i1]:=ar[i2]; ar[i2]:=t; end; is_sorted(ar:ARRAY{ELT}, l,u:CARD, lt:ROUT{ELT,ELT}:BOOL):BOOL is -- true if and only if "ar" is sorted as determined by "lt". if ~check_range(ar,l,u) then return false; end; loop i:CARD:=(l+1).upto!(u); if lt.call(ar[i],ar[i-1]) then return false; end; end; return true; end; is_sorted(ar:ARRAY{ELT}, lt:ROUT{ELT,ELT}:BOOL):BOOL is if ar.size=0 then return true; end; return is_sorted(ar,0,ar.size-1,lt); end; count(ar:ARRAY{ELT},lt:ROUT{ELT,ELT}:BOOL):CARD is -- count different (partial) ordered element in the sense of "lt". if ar.size<=1 then return ar.size; end; c::=1; i::=1; loop until!(i>=ar.size); if lt.call(ar[i],ar[i-1]) /= lt.call(ar[i-1],ar[i]) then c:=c+1; end; i:=i+1; end; return c; end; search(ar:ARRAY{ELT}, e:ELT, lt:ROUT{ELT,ELT}:BOOL):CARD is -- assume "ar" is sorted by increasing order "<"(with lt). -- binary search i1:CARD:=ar.size; if i1=0 then return i1; end; i0:CARD:=0; loop until!(i0+1=i1); -- binary search i2::=(i0+i1)/2; if lt.call(e,ar[i2]) then i1:=i2; else i0:=i2; end; end; if lt.call(e,ar[i0]) then i1:=i0; end; return i1; end; sorted_insert(ar:ARRAY{ELT}, e:ELT):ARRAY{ELT} is -- assume ar is sorted by increasing order "<". lt:ROUT{ELT,ELT}:BOOL:=bind(_.is_lt(_)); return sorted_insert(ar,e,lt); end; sorted_insert(ar:ARRAY{ELT}, e:ELT, lt:ROUT{ELT,ELT}:BOOL):ARRAY{ELT} is -- assume ar is sorted by increasing order "<"(with lt). if ar.size=0 then return |e|; end; i:CARD:=search(ar,e,lt); res:ARRAY{ELT}:=ARRAY_EXT{ELT}::insert_at(i,ar,e); return res; end; merge(ar1,ar2:ARRAY{ELT}, lt:ROUT{ELT,ELT}:BOOL):ARRAY{ELT} is -- merge sort: Assume that ar1, ar2 are sorted. res:ARRAY{ELT}:=#(ar1.size+ar2.size); if ar1.size=0 then loop res.set!(ar2.elt!); end; return res; end; if ar2.size=0 then loop res.set!(ar1.elt!); end; return res; end; i1::=0; i2::=0; i3::=0; e:ELT; loop until!(i3>=res.size); if i1>=ar1.size then e:=ar2[i2]; i2:=i2+1; elsif i2>=ar2.size then e:=ar1[i1]; i1:=i1+1; elsif lt.call(ar2[i2],ar1[i1]) then e:=ar2[i2]; i2:=i2+1; else e:=ar1[i1]; i1:=i1+1; end; res[i3]:=e; i3:=i3+1; end; return res; end; lt_rev(a,b:ELT,lt:ROUT{ELT,ELT}:BOOL):BOOL is -- ">" with respect to lt(<). return lt.call(b,a); end; sorted_rev_insert(ar:ARRAY{ELT}, e:ELT):ARRAY{ELT} is -- assume ar is sorted by decreasing order ">". lt:ROUT{ELT,ELT}:BOOL:=bind(_.is_lt(_)); ltr:ROUT{ELT,ELT}:BOOL:=bind(lt_rev(_,_,lt)); return sorted_insert(ar,e,ltr); end; sorted_rev_insert(ar:ARRAY{ELT}, e:ELT, lt:ROUT{ELT,ELT}:BOOL):ARRAY{ELT} is ltr:ROUT{ELT,ELT}:BOOL:=bind(lt_rev(_,_,lt)); return sorted_insert(ar,e,ltr); end; insertion_sort(inout ar:ARRAY{ELT}) post ar.is_sorted is -- stable sort. if ar.size>1 then insertion_sort_range(inout ar,0,ar.size-1); end; end; insertion_sort(inout ar:ARRAY{ELT},lt:ROUT{ELT,ELT}:BOOL) is -- stable sort. if ar.size>1 then insertion_sort_range(inout ar,0,ar.size-1,lt); end; end; insertion_sort_range(inout ar:ARRAY{ELT},l,u:CARD) is lt:ROUT{ELT,ELT}:BOOL:=bind(_.is_lt(_)); insertion_sort_range(inout ar,l,u, lt); end; insertion_sort_range(inout ar:ARRAY{ELT},l,u:CARD, lt:ROUT{ELT,ELT}:BOOL) is -- sort by increasing order "<" with respect to `lt'. i0,i1:CARD; loop i::=(l+1).upto!(u); e:ELT:=ar[i]; i1:=i-1; if lt.call(e,ar[i1]) then ; -- is_lt if lt.call(e,ar[l]) then i1:=l; -- is_lt else i0:=l; loop until!(i0+1=i1); i2::=(i0+i1)/2; -- binary search if lt.call(e,ar[i2]) then i1:=i2; else i0:=i2; end; -- is_lt end; end; loop j::=i.downto!(i1+1); ar[j]:=ar[j-1]; end; ar[i1]:=e; --insertion end; end; end; private const quicksort_limit:CARD:=20; -- When to stop the quicksort recursion and switch to insertion sort. quicksort_range(inout ar:ARRAY{ELT},l,u:CARD) is lt:ROUT{ELT,ELT}:BOOL:=bind(_.is_lt(_)); quicksort_range(inout ar,l,u,lt); end; quicksort_range(inout ar:ARRAY{ELT}, l, u:CARD, lt:ROUT{ELT,ELT}:BOOL) pre check_range(ar,l,u) is -- Use quicksort to sort the elements of self from `l' to `u' if u>l+quicksort_limit then r::=RANDOM::card(l+1,u-1); swap(inout ar, l,r); t:ELT:=ar[l]; m::=l; loop i::=(l+1).upto!(u); if lt.call(ar[i],t) then m:=m+1; swap(inout ar,m,i); end; end; swap(inout ar,l,m); if l+1 < m then quicksort_range(inout ar,l,m-1,lt); end; if m+1 < u then quicksort_range(inout ar,m+1,u,lt); end; else insertion_sort_range(inout ar, l,u,lt); end; end; quick_sort(inout ar:ARRAY{ELT}, lt:ROUT{ELT,ELT}:BOOL) post ar.is_sorted_by(lt) is -- Use quicksort to permute the elements of self so that -- it is sorted by increasing order "<" with respect to `lt'. Self may be void. if ar.size>1 then quicksort_range(inout ar, 0,ar.size-1,lt); end; end; quick_sort(inout ar:ARRAY{ELT}) is -- Use quicksort to permute the elements of self so that -- it is sorted by increasing order "<" with respect to `elt_lt'. Self may be void. quick_sort(inout ar,bind(_.is_lt(_))); end; end;

class TEST_ARRAY_EXT

class TEST_ARRAY_EXT is check_time1(n:INT, ar0:ARRAY{INT}) is timer:TIMER:=#; f1,f2,f3,f4:ELAPSED; ite:CARD:=4; loop ite.times!; ar1::=ar0.copy; ar2::=ar0.copy; ar3::=ar0.copy; ar4::=ar0.copy; timer.clear; ar1.sort; f1:=f1+timer.elapsed; timer.clear; ARRAY_SORT{INT}::quick_sort(inout ar2); f2:=f2+timer.elapsed; --t1.mark; ar3.stable_sort; f3:=f3+t1.elapsed; --t1.mark; ARRAY_SORT{INT}::insertion_sort(inout ar4); f4:=f4+t1.elapsed; assert ar1.is_sorted; assert ar2.is_sorted; --assert ar3.is_sorted; assert ar4.is_sorted; end; f1:=f1/ite; f2:=f2/ite; --f3:=f3/#FLTD(ite); f4:=f4/#FLTD(ite); #OUT+"sort="+f1.full_str+", quick/ext="+f2.full_str -- +", stable_sort="+f3.str +", insertion/ext="+f4.str +"\n"; end; check_time(n:INT) is #OUT+"n="+n.str+"\n"; #OUT.flush; ar0:ARRAY{INT}; rnd::=#RANDOM; ar0:=#(n.card); -- randum loop i::=ar0.ind!; ar0[i]:=rnd.int(0.int,n); end; check_time1(n,ar0); -- iterated sorted loop i::=0.upto!(ar0.size/2); j::=1.up!; ar0[i]:=j.int; end; loop i::=(ar0.size/2+1).upto!(ar0.size-1);j::=1.up!; ar0[i]:=j.int; end; check_time1(n,ar0); -- randum with many duplication loop i::=ar0.ind!; ar0[i]:=rnd.int(0.int,n.sqrt); end; check_time1(n,ar0); -- same --loop i::=ar0.ind!; ar0[i]:=1; end; --check_time1(n,ar0); end; check_sorting_speed is n:INT; --n:=10; check_time(n); --n:=20; check_time(n); --n:=100; check_time(n); n:=1000; check_time(n); n:=10000; check_time(n); --n:=100000; check_time(n); --n:=1000000; check_time(n); end; check_sorted_insert is rnd::=#RANDOM; n::=10; ar:ARRAY{INT}; loop 100.times!; ar:=#; loop i::=1.upto!(n); ar:=ARRAY_SORT{INT}::sorted_insert(ar,rnd.int(0.int,n.int)); --#OUT+ar.str+"\n"; end; assert ar.is_sorted; end; loop 100.times!; ar:=#; loop i::=1.upto!(n); ar:=ARRAY_SORT{INT}::sorted_rev_insert(ar,rnd.int(0.int,n.int)); --#OUT+ar.str+"\n"; end; ar:=ar.reverse; assert ar.is_sorted; end; end; main is check_sorting_speed; check_sorted_insert; end; end;