Sorting algorithms/Merge sort: Difference between revisions
(add CL, E, and Haskell examples; promote from <5 to <10) |
(+D) |
||
Line 46: | Line 46: | ||
> (merge-sort 'list (list 1 3 5 7 9 8 6 4 2) #'<) |
> (merge-sort 'list (list 1 3 5 7 9 8 6 4 2) #'<) |
||
(1 2 3 4 5 6 7 8 9) |
(1 2 3 4 5 6 7 8 9) |
||
=={{header|D}}== |
|||
<pre>module mergesort ; |
|||
version(Tango) { |
|||
import tango.io.Stdout ; |
|||
import tango.util.collection.LinkSeq ; |
|||
alias LinkSeq!(int) LNK ; |
|||
</pre> |
|||
<pre style="background-color:#ffe"> // Tango LinkSeq version |
|||
void mergesort1(T)(T m) { |
|||
if (m.length <= 1) |
|||
return m ; |
|||
int mid = m.length / 2 ; |
|||
T left = m.subset(0, mid) ; |
|||
T right = m.subset(mid, m.length - mid) ; |
|||
mergesort1(left) ; |
|||
mergesort1(right) ; |
|||
merge1(m, left, right) ; |
|||
} |
|||
void merge1(T)(T m, T left, T right) { |
|||
m.clear ; |
|||
while(left.length > 0 && right.length > 0) |
|||
if (left.head < right.head) |
|||
m.append(left.take()) ; |
|||
else |
|||
m.append(right.take()) ; |
|||
while(left.length > 0) |
|||
m.append(left.take()) ; |
|||
while(right.length > 0) |
|||
m.append(right.take()) ; |
|||
}</pre> |
|||
<pre> |
|||
alias Stdout print ; |
|||
} else { // not Version Tango |
|||
import std.stdio ; |
|||
alias writef print ; |
|||
} |
|||
</pre> |
|||
<pre style="background-color:#ffe">// D array version |
|||
T[] mergesort2(T)(inout T[] m) { |
|||
if (m.length <= 1) |
|||
return m ; |
|||
int mid = m.length / 2 ; |
|||
T[] left, right; |
|||
left = m[0..mid] ; |
|||
right = m[mid..$] ; |
|||
left.mergesort2() ; |
|||
right.mergesort2() ; |
|||
m.merge2(left, right) ; |
|||
return m ; |
|||
} |
|||
void merge2(T)(inout T[] merged, inout T[] left, inout T[] right) { |
|||
T[] m = new T[left.length + right.length]; |
|||
int headL = 0 ; |
|||
int headR = 0 ; |
|||
int tailM = 0 ; |
|||
while (headL < left.length && headR < right.length) |
|||
if(left[headL] < right[headR]) |
|||
m[tailM++] = left[headL++] ; |
|||
else |
|||
m[tailM++] = right[headR++] ; |
|||
if (headL < left.length) |
|||
m[tailM..$] = left[headL..$] ; |
|||
else if (headR < right.length) |
|||
m[tailM..$] = right[headR..$] ; |
|||
merged = m ; |
|||
}</pre> |
|||
<pre>void dump(T)(T l) { |
|||
foreach(e ; l) |
|||
print(e," ") ; |
|||
print("\n") ; |
|||
} |
|||
void main() { |
|||
int[] arr = [8,6,4,2,1,3,5,7,9] ; |
|||
version(Tango) { |
|||
LNK lnk = new LNK ; |
|||
foreach(e;arr) |
|||
lnk.append(e); |
|||
dump(lnk) ; |
|||
mergesort1(lnk) ; |
|||
dump(lnk) ; |
|||
} |
|||
dump(arr) ; |
|||
mergesort2(arr) ; |
|||
dump(arr) ; |
|||
}</pre> |
|||
{{works with|Tango}}(part of the codes) |
|||
=={{header|E}}== |
=={{header|E}}== |
||
Revision as of 09:33, 27 February 2008
You are encouraged to solve this task according to the task description, using any language you may know.
Sorting Algorithm
This is a sorting algorithm. It may be applied to a set of data in order to sort it.
For comparing various sorts, see compare sorts.
For other sorting algorithms, see sorting algorithms, or:
Heap sort | Merge sort | Patience sort | Quick sort
O(n log2n) sorts
Shell Sort
O(n2) sorts
Bubble sort |
Cocktail sort |
Cocktail sort with shifting bounds |
Comb sort |
Cycle sort |
Gnome sort |
Insertion sort |
Selection sort |
Strand sort
other sorts
Bead sort |
Bogo sort |
Common sorted list |
Composite structures sort |
Custom comparator sort |
Counting sort |
Disjoint sublist sort |
External sort |
Jort sort |
Lexicographical sort |
Natural sorting |
Order by pair comparisons |
Order disjoint list items |
Order two numerical lists |
Object identifier (OID) sort |
Pancake sort |
Quickselect |
Permutation sort |
Radix sort |
Ranking methods |
Remove duplicate elements |
Sleep sort |
Stooge sort |
[Sort letters of a string] |
Three variable sort |
Topological sort |
Tree sort
The merge sort is a recursive sort of order n*log(n) (technically n*lg(n)--lg is log base 2) sort. It is notable for having no worst case. It is always O(n*log(n)). 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 is "divide and conquer" description.
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 functions in pseudocode look like this:
function mergesort(m) var list left, right, result if length(m) ≤ 1 return m else var middle = length(m) / 2 for each x in m up to middle - 1 add x to left for each x in m at and after middle add x to right left = mergesort(left) right = mergesort(right) result = merge(left, right) return result
function merge(left,right) var list result while length(left) > 0 and length(right) > 0 if first(left) ≤ first(right) append first(left) to result left = rest(left) else append first(right) to result right = rest(right) if length(left) > 0 append rest(left) to result if length(right) > 0 append rest(right) to result return result
Common Lisp
(defun merge-sort (result-type sequence predicate) (let ((split (floor (length sequence) 2))) (if (zerop split) (copy-seq sequence) (merge result-type (merge-sort result-type (subseq sequence 0 split) predicate) (merge-sort result-type (subseq sequence split) predicate) predicate))))
merge
is a standard Common Lisp function.
> (merge-sort 'list (list 1 3 5 7 9 8 6 4 2) #'<) (1 2 3 4 5 6 7 8 9)
D
module mergesort ; version(Tango) { import tango.io.Stdout ; import tango.util.collection.LinkSeq ; alias LinkSeq!(int) LNK ;
// Tango LinkSeq version void mergesort1(T)(T m) { if (m.length <= 1) return m ; int mid = m.length / 2 ; T left = m.subset(0, mid) ; T right = m.subset(mid, m.length - mid) ; mergesort1(left) ; mergesort1(right) ; merge1(m, left, right) ; } void merge1(T)(T m, T left, T right) { m.clear ; while(left.length > 0 && right.length > 0) if (left.head < right.head) m.append(left.take()) ; else m.append(right.take()) ; while(left.length > 0) m.append(left.take()) ; while(right.length > 0) m.append(right.take()) ; }
alias Stdout print ; } else { // not Version Tango import std.stdio ; alias writef print ; }
// D array version T[] mergesort2(T)(inout T[] m) { if (m.length <= 1) return m ; int mid = m.length / 2 ; T[] left, right; left = m[0..mid] ; right = m[mid..$] ; left.mergesort2() ; right.mergesort2() ; m.merge2(left, right) ; return m ; } void merge2(T)(inout T[] merged, inout T[] left, inout T[] right) { T[] m = new T[left.length + right.length]; int headL = 0 ; int headR = 0 ; int tailM = 0 ; while (headL < left.length && headR < right.length) if(left[headL] < right[headR]) m[tailM++] = left[headL++] ; else m[tailM++] = right[headR++] ; if (headL < left.length) m[tailM..$] = left[headL..$] ; else if (headR < right.length) m[tailM..$] = right[headR..$] ; merged = m ; }
void dump(T)(T l) { foreach(e ; l) print(e," ") ; print("\n") ; } void main() { int[] arr = [8,6,4,2,1,3,5,7,9] ; version(Tango) { LNK lnk = new LNK ; foreach(e;arr) lnk.append(e); dump(lnk) ; mergesort1(lnk) ; dump(lnk) ; } dump(arr) ; mergesort2(arr) ; dump(arr) ; }
(part of the codes)
E
def merge(var xs :List, var ys :List) { var result := [] while (xs =~ [x] + xr && ys =~ [y] + yr) { if (x < y) { result with= x xs := xr } else { result with= y ys := yr } } return result + xs + ys } def sort(list :List) { if (list.size() <= 1) { return list } def split := list.size() // 2 return merge(sort(list.run(0, split)), sort(list.run(split))) }
Haskell
merge [] ys = ys merge xs [] = xs merge xs@(x:xs') ys@(y:ys') | x < y = x : merge xs' ys | otherwise = y : merge xs ys'
mergeSort [] = [] mergeSort [x] = [x] mergeSort xs = merge (mergeSort $ take n xs) (mergeSort $ drop n xs) where n = length xs `div` 2
Java
import java.util.LinkedList; public class Merge{ public static LinkedList<Integer> mergeSort(LinkedList<Integer> m){ LinkedList<Integer> left = new LinkedList<Integer>(); LinkedList<Integer> right = new LinkedList<Integer>(); LinkedList<Integer> result = new LinkedList<Integer>(); if (m.size() <= 1) return m; int middle = m.size() / 2; for(int i = 0; i < middle; i++) left.add(m.get(i)); for(int i = middle; i < m.size(); i++) right.add(m.get(i)); right = mergeSort(right); left = mergeSort(left); result = merge(left, right); return result; } public static LinkedList<Integer> merge(LinkedList<Integer> left, LinkedList<Integer> right){ LinkedList<Integer> result = new LinkedList<Integer>(); while (left.size() > 0 && right.size() > 0){ //change the direction of this comparison to change the direction of the sort if (left.peek() <= right.peek()) result.add(left.remove()); else result.add(right.remove()); } if (left.size() > 0) result.addAll(left); if (right.size() > 0) result.addAll(right); return result; } }
Scheme
(define (merge-sort l gt?) (letrec ( (merge (lambda (left right) (cond ((null? left) right) ((null? right) left) ((gt? (car left) (car right)) (cons (car right) (merge left (cdr right)))) (else (cons (car left) (merge (cdr left) right)))))) (take (lambda (l num) (if (zero? num) (list) (cons (car l) (take (cdr l) (- num 1)))))) (half (quotient (length l) 2))) (if (zero? half) l (merge (merge-sort (take l half) gt?) (merge-sort (list-tail l half) gt?)))))
(merge-sort (list 1 3 5 7 9 8 6 4 2) >)