2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,11 +1,25 @@
{{Sorting Algorithm}}[[Category:Recursion]]The '''merge sort''' is a recursive sort of order n*log(n).
It is notable for having a worst case and average complexity of ''O(n*log(n))'', and a best case complexity of ''O(n)'' (for pre-sorted input).
The basic idea is to split the collection into smaller groups by halving it until the groups only have one element or no elements (which are both entirely sorted groups).
Then merge the groups back together so that their elements are in order.
This is how the algorithm gets its "divide and conquer" description.
{{Sorting Algorithm}}
[[Category:Recursion]]
The &nbsp; '''merge sort''' &nbsp; is a recursive sort of order &nbsp; <big> n*log(n). </big>
It is notable for having a worst case and average complexity of &nbsp; <big> ''O(n*log(n))'', </big> &nbsp; and a best case complexity of &nbsp; <big> ''O(n)'' &nbsp; </big> (for pre-sorted input).
The basic idea is to split the collection into smaller groups by halving it until the groups only have one element or no elements &nbsp; (which are both entirely sorted groups).
Then merge the groups back together so that their elements are in order.
This is how the algorithm gets its &nbsp; ''divide and conquer'' &nbsp; description.
;Task:
Write a function to sort a collection of integers using the merge sort.
The merge sort algorithm comes in two parts: a sort function and a merge function.
The merge sort algorithm comes in two parts:
a sort function and
a merge function
The functions in pseudocode look like this:
'''function''' ''mergesort''(m)
'''var''' list left, right, result
@ -40,6 +54,10 @@ The functions in pseudocode look like this:
'''append''' rest(right) '''to''' result
'''return''' result
For more information see [[wp:Merge_sort|Wikipedia]]
Note: better performance can be expected if, rather than recursing until length(m) ≤ 1, an insertion sort is used for length(m) smaller than some threshold larger than 1. However, this complicates example code, so is not shown here.
;See also:
* &nbsp; the Wikipedia entry: &nbsp; [[wp:Merge_sort| merge sort]]
Note: &nbsp; better performance can be expected if, rather than recursing until &nbsp; <big> length(m) ≤ 1, </big> &nbsp; an insertion sort is used for &nbsp; <big> length(m) </big> &nbsp; smaller than some threshold larger than &nbsp; '''1'''. &nbsp; However, this complicates the example code, so it is not shown here.
<br><br>

View file

@ -0,0 +1,164 @@
* Merge sort 19/06/2016
MAIN CSECT
STM R14,R12,12(R13) save caller's registers
LR R12,R15 set R12 as base register
USING MAIN,R12 notify assembler
LA R11,SAVEXA get the address of my savearea
ST R13,4(R11) save caller's save area pointer
ST R11,8(R13) save my save area pointer
LR R13,R11 set R13 to point to my save area
LA R1,1 1
LA R2,NN hbound(a)
BAL R14,SPLIT call split(1,hbound(a))
LA RPGI,PG pgi=0
LA RI,1 i=1
DO WHILE=(C,RI,LE,=A(NN)) do i=1 to hbound(a)
LR R1,RI i
SLA R1,2 .
L R2,A-4(R1) a(i)
XDECO R2,XDEC edit a(i)
MVC 0(4,RPGI),XDEC+8 output a(i)
LA RPGI,4(RPGI) pgi=pgi+4
LA RI,1(RI) i=i+1
ENDDO , end do
XPRNT PG,80 print buffer
L R13,SAVEXA+4 restore caller's savearea address
LM R14,R12,12(R13) restore caller's registers
XR R15,R15 set return code to 0
BR R14 return to caller
* split(istart,iend) ------recursive---------------------
SPLIT STM R14,R12,12(R13) save all registers
LR R9,R1 save R1
LA R1,72 amount of storage required
GETMAIN RU,LV=(R1) allocate storage for stack
USING STACK,R10 make storage addressable
LR R10,R1 establish stack addressability
LA R11,SAVEXB get the address of my savearea
ST R13,4(R11) save caller's save area pointer
ST R11,8(R13) save my save area pointer
LR R13,R11 set R13 to point to my save area
LR R1,R9 restore R1
LR RSTART,R1 istart=R1
LR REND,R2 iend=R2
IF CR,REND,EQ,RSTART THEN if iend=istart
B RETURN return
ENDIF , end if
BCTR R2,0 iend-1
IF C,R2,EQ,RSTART THEN if iend-istart=1
LR R1,REND iend
SLA R1,2 .
L R2,A-4(R1) a(iend)
LR R1,RSTART istart
SLA R1,2 .
L R3,A-4(R1) a(istart)
IF CR,R2,LT,R3 THEN if a(iend)<a(istart)
LR R1,RSTART istart
SLA R1,2 .
LA R2,A-4(R1) @a(istart)
LR R1,REND iend
SLA R1,2 .
LA R3,A-4(R1) @a(iend)
MVC TEMP,0(R2) temp=a(istart)
MVC 0(4,R2),0(R3) a(istart)=a(iend)
MVC 0(4,R3),TEMP a(iend)=temp
ENDIF , end if
B RETURN return
ENDIF , end if
LR RMIDDL,REND iend
SR RMIDDL,RSTART iend-istart
SRA RMIDDL,1 (iend-istart)/2
AR RMIDDL,RSTART imiddl=istart+(iend-istart)/2
LR R1,RSTART istart
LR R2,RMIDDL imiddl
BAL R14,SPLIT call split(istart,imiddl)
LA R1,1(RMIDDL) imiddl+1
LR R2,REND iend
BAL R14,SPLIT call split(imiddl+1,iend)
LR R1,RSTART istart
LR R2,RMIDDL imiddl
LR R3,REND iend
BAL R14,MERGE call merge(istart,imiddl,iend)
RETURN L R13,SAVEXB+4 restore caller's savearea address
XR R15,R15 set return code to 0
LA R0,72 amount of storage to free
FREEMAIN A=(R10),LV=(R0) free allocated storage
L R14,12(R13) restore caller's return address
LM R2,R12,28(R13) restore registers R2 to R12
BR R14 return to caller
DROP R10 base no longer needed
* merge(jstart,jmiddl,jend) ------------------------------------
MERGE STM R1,R3,JSTART jstart=r1,jmiddl=r2,jend=r3
SR R2,R1 jmiddl-jstart
LA RBS,2(R2) bs=jmiddl-jstart+2
LA RI,1 i=1
LR R3,RBS bs
BCTR R3,0 bs-1
DO WHILE=(CR,RI,LE,R3) do i=0 to bs-1
L R2,JSTART jstart
AR R2,RI jstart+i
SLA R2,2 .
L R2,A-8(R2) a(jstart+i-1)
LR R1,RI i
SLA R1,2 .
ST R2,B-4(R1) b(i)=a(jstart+i-1)
LA RI,1(RI) i=i+1
ENDDO , end do
LA RI,1 i=1
L RJ,JMIDDL j=jmiddl
LA RJ,1(RJ) j=jmiddl+1
L RK,JSTART k=jstart
DO UNTIL=(CR,RI,EQ,RBS,OR, do until i=bs or X
C,RJ,GT,JEND) j>jend
LR R1,RI i
SLA R1,2 .
L R4,B-4(R1) r4=b(i)
LR R1,RJ j
SLA R1,2 .
L R3,A-4(R1) r3=a(j)
LR R9,RK k
SLA R9,2 r9 for a(k)
IF CR,R4,LE,R3 THEN if b(i)<=a(j)
ST R4,A-4(R9) a(k)=b(i)
LA RI,1(RI) i=i+1
ELSE , else
ST R3,A-4(R9) a(k)=a(j)
LA RJ,1(RJ) j=j+1
ENDIF , end if
LA RK,1(RK) k=k+1
ENDDO , end do
DO WHILE=(CR,RI,LT,RBS) do while i<bs
LR R1,RI i
SLA R1,2 .
L R2,B-4(R1) b(i)
LR R1,RK k
SLA R1,2 .
ST R2,A-4(R1) a(k)=b(i)
LA RI,1(RI) i=i+1
LA RK,1(RK) k=k+1
ENDDO , end do
BR R14 return to caller
* ------- ------------------ ------------------------------------
LTORG
SAVEXA DS 18F savearea of main
NN EQU ((B-A)/L'A) number of items
A DC F'4',F'65',F'2',F'-31',F'0',F'99',F'2',F'83',F'782',F'1'
DC F'45',F'82',F'69',F'82',F'104',F'58',F'88',F'112',F'89',F'74'
B DS (NN/2+1)F merge sort static storage
TEMP DS F for swap
JSTART DS F jstart
JMIDDL DS F jmiddl
JEND DS F jend
PG DC CL80' ' buffer
XDEC DS CL12 for edit
STACK DSECT dynamic area
SAVEXB DS 18F " savearea of mergsort (72 bytes)
YREGS
RI EQU 6 i
RJ EQU 7 j
RK EQU 8 k
RSTART EQU 6 istart
REND EQU 7 i
RMIDDL EQU 8 i
RPGI EQU 3 pgi
RBS EQU 0 bs
END MAIN

View file

@ -1,14 +1,13 @@
(defn merge* [left right]
(defn merge [left right]
(cond (nil? left) right
(nil? right) left
true (let [[l & *left] left
[r & *right] right]
(if (<= l r) (cons l (merge* *left right))
(cons r (merge* left *right))))))
:else (let [[l & *left] left
[r & *right] right]
(if (<= l r) (cons l (merge *left right))
(cons r (merge left *right))))))
(defn merge-sort [L]
(let [[l & *L] L]
(if (nil? *L)
L
(let [[left right] (split-at (/ (count L) 2) L)]
(merge* (merge-sort left) (merge-sort right))))))
(defn merge-sort [list]
(if (< (count list) 2)
list
(let [[left right] (split-at (/ (count list) 2) list)]
(merge (merge-sort left) (merge-sort right)))))

View file

@ -0,0 +1,20 @@
merge_sort(List) -> m(List, erlang:system_info(schedulers)).
m([L],_) -> [L];
m(L, N) when N > 1 ->
{L1,L2} = lists:split(length(L) div 2, L),
{Parent, Ref} = {self(), make_ref()},
spawn(fun()-> Parent ! {l1, Ref, m(L1, N-2)} end),
spawn(fun()-> Parent ! {l2, Ref, m(L2, N-2)} end),
{L1R, L2R} = receive_results(Ref, undefined, undefined),
lists:merge(L1R, L2R);
m(L, _) -> {L1,L2} = lists:split(length(L) div 2, L), lists:merge(m(L1, 0), m(L2, 0)).
receive_results(Ref, L1, L2) ->
receive
{l1, Ref, L1R} when L2 == undefined -> receive_results(Ref, L1R, L2);
{l2, Ref, L2R} when L1 == undefined -> receive_results(Ref, L1, L2R);
{l1, Ref, L1R} -> {L1R, L2};
{l2, Ref, L2R} -> {L1, L2R}
after 5000 -> receive_results(Ref, L1, L2)
end.

View file

@ -12,21 +12,19 @@ function merge(left, right, arr) {
}
}
function mSort(arr, tmp, len) {
function mergeSort(arr) {
var len = arr.length;
if (len === 1) { return; }
var m = Math.floor(len / 2),
tmp_l = tmp.slice(0, m),
tmp_r = tmp.slice(m);
var mid = Math.floor(len / 2),
left = arr.slice(0, mid),
right = arr.slice(mid);
mSort(tmp_l, arr.slice(0, m), m);
mSort(tmp_r, arr.slice(m), len - m);
merge(tmp_l, tmp_r, arr);
}
function merge_sort(arr) {
mSort(arr, arr.slice(), arr.length);
mergeSort(left);
mergeSort(right);
merge(left, right, arr);
}
var arr = [1, 5, 2, 7, 3, 9, 4, 6, 8];
merge_sort(arr); // arr will now: 1, 2, 3, 4, 5, 6, 7, 8, 9
mergeSort(arr); // arr will now: 1, 2, 3, 4, 5, 6, 7, 8, 9

View file

@ -0,0 +1,50 @@
fun mergeSort(list: List<Int>): List<Int> {
if (list.size <= 1) {
return list
}
val left = mutableListOf<Int>()
val right = mutableListOf<Int>()
val middle = list.size / 2
list.forEachIndexed { index, number ->
if (index < middle) {
left.add(number)
} else {
right.add(number)
}
}
fun merge(left: List<Int>, right: List<Int>): List<Int> = mutableListOf<Int>().apply {
var indexLeft = 0
var indexRight = 0
while (indexLeft < left.size && indexRight < right.size) {
if (left[indexLeft] <= right[indexRight]) {
add(left[indexLeft])
indexLeft++
} else {
add(right[indexRight])
indexRight++
}
}
while (indexLeft < left.size) {
add(left[indexLeft])
indexLeft++
}
while (indexRight < right.size) {
add(right[indexRight])
indexRight++
}
}
return merge(mergeSort(left), mergeSort(right))
}
fun main(args: Array<String>) {
val numbers = listOf(5, 2, 3, 17, 12, 1, 8, 3, 4, 9, 7)
println("Unsorted: $numbers")
println("Sorted: ${mergeSort(numbers)}")
}

View file

@ -0,0 +1,22 @@
function getLower(a,b)
local i,j=1,1
return function()
if not b[j] or a[i] and a[i]<b[j] then
i=i+1; return a[i-1]
else
j=j+1; return b[j-1]
end
end
end
function merge(a,b)
local res={}
for v in getLower(a,b) do res[#res+1]=v end
return res
end
function mergesort(list)
if #list<=1 then return list end
local s=math.floor(#list/2)
return merge(mergesort{unpack(list,1,s)}, mergesort{unpack(list,s+1)})
end

View file

@ -10,8 +10,8 @@ def merge(left, right):
result.append(right[right_idx])
right_idx += 1
if left:
if left_idx < len(left):
result.extend(left[left_idx:])
if right:
if right_idx < len(right):
result.extend(right[right_idx:])
return result

View file

@ -1,57 +1,38 @@
/*REXX program sorts a (stemmed) array using the merge─sort algorithm.*/
call gen@; w=length(#) /*generate an array (@.) of items*/
call show@ 'before sort' /*show the before array elements.*/
call mergeSort # /*invoke the merge sort for array*/
call show@ ' after sort' /*show the after array elements.*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────GEN@ subroutine─────────────────────*/
gen@: @. = /*assign default value for @ stem*/
@.1 = '---The seven deadly sins---' /*pick a favorite.*/
@.2 = '==========================='
@.3 = 'pride'
@.4 = 'avarice'
@.5 = 'wrath'
@.6 = 'envy'
@.7 = 'gluttony'
@.8 = 'sloth'
@.9 = 'lust'
do #=1 while @.#\==''; end; #=#-1 /*find the number of entries in @*/
return
/*──────────────────────────────────MERGESORT subroutine────────────────*/
mergeSort: procedure expose @.; call mergeTo@ 1,arg(1); return
/*──────────────────────────────────MERGETO@ subroutine─────────────────*/
mergeTo@: procedure expose @. !.; parse arg L,n ; if n==1 then return
if n==2 then do; h=L+1 /*handle special case of 2 items.*/
if @.L>@.h then do; _=@.h; @.h=@.L; @.L=_; end
return
end
m=n%2 /*cut N in half (integer div.)*/
call mergeTo@ L+m,n-m /*divide items to the left ···*/
call mergeTo! L,m,1 /* " " " " right ···*/
i=1; j=L+m; do k=L while k<j /*whilst items on right···*/
if j==L+n | !.i<=@.j then do; @.k=!.i; i=i+1; end
else do; @.k=@.j; j=j+1; end
end /*k*/
return
/*──────────────────────────────────MERGETO! subroutine─────────────────*/
mergeTo!: procedure expose @. !.; parse arg L,n,_
if n==1 then do; !._=@.L; return; end /*handle special case of 1 item. */
if n==2 then do /* " " " " 2 items.*/
h=L+1; q=1+_
if @.L>@.h then do; q=_; _=q+1; end
!._=@.L; !.q=@.h
return /*done with special case of N=2.*/
end
m=n%2 /*cut N in half (integer div).*/
call mergeTo@ L,m /*divide items to the left ···*/
call mergeTo! L+m,n-m,m+_ /* " " " " right ···*/
i=L; j=m+_; do k=_ while k<j /*whilst items on left ···*/
if j==_+n | @.i<=!.j then do; !.k=@.i; i=i+1; end
else do; !.k=!.j; j=j+1; end
end /*k*/
return
/*──────────────────────────────────SHOW@ subroutine────────────────────*/
show@: say copies('',70); do j=1 for #; pad=left('',10) /*indent.*/
say pad 'element' right(j,w) arg(1)':' @.j
end /*j*/
return
/*REXX program sorts a stemmed array (numbers or chars) using the merge─sort algorithm.*/
@.=; @.1 = '---The seven deadly sins---'
@.2 = '===========================' ; @.6 = "envy"
@.3 = 'pride' ; @.7 = "gluttony"
@.4 = 'avarice' ; @.8 = "sloth"
@.5 = 'wrath' ; @.9 = "lust"
do #=1 while @.#\==''; end; #=#-1; w=length(#) /*#≡number of entries in @*/
call show@ 'before sort' /*show the "before" array elements. */
say copies('', 70) /*display a separator line to the term.*/
call mergeSort # /*invoke the merge sort for the array*/
call show@ ' after sort' /*show the "after" array elements. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
mergeSort: procedure expose @.; call mergeTo@ 1,arg(1); return
/*──────────────────────────────────────────────────────────────────────────────────────*/
mergeTo@: procedure expose @. !.; parse arg L,n; if n==1 then return; h=L+1
if n==2 then do; if @.L>@.h then do; _=@.h; @.h=@.L; @.L=_; end; return; end
m=n%2 /* [↑] handle case of two items.*/
call mergeTo@ L+m,n-m /*divide items to the left ···*/
call mergeTo! L,m,1 /* " " " " right ···*/
i=1; j=L+m; do k=L while k<j /*whilst items on right exist ···*/
if j==L+n | !.i<=@.j then do; @.k=!.i; i=i+1; end
else do; @.k=@.j; j=j+1; end
end /*k*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
mergeTo!: procedure expose @. !.; parse arg L,n,T; if n==1 then do; !.T=@.L; return; end
if n==2 then do; h=L+1; q=T+1; !.q=@.L; !.T=@.h; return; end
m=n%2 /* [↑] handle case of two items.*/
call mergeTo@ L,m /*divide items to the left ···*/
call mergeTo! L+m,n-m,m+T /* " " " " right ···*/
i=L; j=m+T; do k=T while k<j /*whilst items on left exist ···*/
if j==T+n | @.i<=!.j then do; !.k=@.i; i=i+1; end
else do; !.k=!.j; j=j+1; end
end /*k*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
show@: do j=1 for #; say right('element',17) right(j,w) arg(1)":" @.j; end; return

View file

@ -0,0 +1,23 @@
fn merge<T: Copy + PartialOrd>(x1: &[T], x2: &[T], y: &mut [T]) {
assert_eq!(x1.len() + x2.len(), y.len());
let mut i = 0;
let mut j = 0;
let mut k = 0;
while i < x1.len() && j < x2.len() {
if x1[i] < x2[j] {
y[k] = x1[i];
k += 1;
i += 1;
} else {
y[k] = x2[j];
k += 1;
j += 1;
}
}
if i < x1.len() {
y[k..].copy_from_slice(&x1[i..]);
}
if j < x2.len() {
y[k..].copy_from_slice(&x2[j..]);
}
}

View file

@ -0,0 +1,17 @@
fn merge_sort_rec<T: Copy + Ord>(x: &mut [T]) {
let n = x.len();
let m = n / 2;
if n <= 1 {
return;
}
merge_sort_rec(&mut x[0..m]);
merge_sort_rec(&mut x[m..n]);
let mut y: Vec<T> = x.to_vec();
merge(&x[0..m], &x[m..n], &mut y[..]);
x.copy_from_slice(&y);
}

View file

@ -0,0 +1,35 @@
fn merge_sort<T: Copy + PartialOrd>(x: &mut [T]) {
let n = x.len();
let mut y = x.to_vec();
let mut len = 1;
while len < n {
let mut i = 0;
while i < n {
if i + len >= n {
y[i..].copy_from_slice(&x[i..]);
} else if i + 2 * len > n {
merge(&x[i..i+len], &x[i+len..], &mut y[i..]);
} else {
merge(&x[i..i+len], &x[i+len..i+2*len], &mut y[i..i+2*len]);
}
i += 2 * len;
}
len *= 2;
if len >= n {
x.copy_from_slice(&y);
return;
}
i = 0;
while i < n {
if i + len >= n {
x[i..].copy_from_slice(&y[i..]);
} else if i + 2 * len > n {
merge(&y[i..i+len], &y[i+len..], &mut x[i..]);
} else {
merge(&y[i..i+len], &y[i+len..i+2*len], &mut x[i..i+2*len]);
}
i += 2 * len;
}
len *= 2;
}
}