Merge sort PHP implementation

Merge sort PHP implementation

After a short pause I am continuing my challenge to implement all sorting algorithms listed on Wikipedia in PHP. Merge sort is a bit more advanced than previous algorithms but once you figure it out it’s quite neat.

Personally, I hate recursion and try to avoid it as much as possible (speaking of recursion, check out my weblogs about Adjacency list model and Nested set model – which is in my opinion a better solution in most cases) – but sorting is one area where recursion is needed.

Merge sort was invented by John Von Neumann, a big name in computer science history. It is a divide and conquer algorithm. It sorts arrays by dividing them recursively into halves (divide) and then sorting and merging them back together (conquer).

The good thing about this algorithm is it preserves order of equal elements (if you have two 25s in an array, merge sort will place the one that came earlier in the original array on the left side).

Here is my PHP implementation consisting of two functions: divide and conquer:

Best way to understand how it works is to apply it to a smaller array and add a little debugging inside the functions so we can see what’s happening. After a little tweaking:

<?php

$arr=array(4,5,1,3,2);

$sortedArr= divide($arr);

var_dump($sortedArr);

function divide(array$arr){

if(1===count($arr)){

return$arr;

}

$left=$right=array();

$middle=round(count($arr)/2);

for($i=0;$i<$middle;++$i){

$left[]=$arr[$i];

}

for($i=$middle;$i<count($arr);++$i){

$right[]=$arr[$i];

}

$left= divide($left);

$right= divide($right);

echo"We are going to conquer these two arrays:narray(",

implode(", ",$left),")narray(",implode(", ",$right),")n";

$conquered= conquer($left,$right);

echo"After conquering we get: array(",implode(", ",$conquered),")nn";

return$conquered;

}

function conquer(array$left,array$right){

$result=array();

while(count($left)>0||count($right)>0){

if(count($left)>0&&count($right)>0){

$firstLeft=current($left);

$firstRight=current($right);

if($firstLeft<=$firstRight){

$result[]=array_shift($left);

}else{

$result[]=array_shift($right);

}

}elseif(count($left)>0){

$result[]=array_shift($left);

}elseif(count($right)>0){

$result[]=array_shift($right);

}

}

return$result;

}

Which will output a nice explanation of what’s happening, we can see what steps are being done and in what order:

We are going to conquer these two arrays:
array(4)
array(5)
After conquering we get: array(4, 5)
We are going to conquer these two arrays:
array(4, 5)
array(1)
After conquering we get: array(1, 4, 5)
We are going to conquer these two arrays:
array(3)
array(2)
After conquering we get: array(2, 3)
We are going to conquer these two arrays:
array(1, 4, 5)
array(2, 3)
After conquering we get: array(1, 2, 3, 4, 5)
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}