Home > Software engineering >  Merge sort implementation JavaScript
Merge sort implementation JavaScript

Time:10-30

I was trying to implement merge sort algorithm in JavaScript without built in methods like slice(), splice(), etc. It doesn’t work exactly I wish. Can you help me to figure out where is bug hidden? Getting output [3, 5, 5, 3, 7] instead of [3, 5, 5, 7, 8].

// Merge Sort implementation

// sort implementation
function sort(arr, start, mid, end) {

  // Creation and filling the temp arrays
  let lArray = [];
  let rArray = [];

  for (let i = 0; i <= mid - start; i  ) {
    lArray[i] = arr[start   i];
  }

  for (let j = 0; j <= end - mid - 1; j  ) {
    rArray[j] = arr[mid   1   j];
  }


  // Sorting and updating current array
  let i = 0;
  let j = 0;
  let k = start;

  while (i < lArray.length && j < rArray.length) {
    if (lArray[i] < rArray[j]) {
      arr[k] = lArray[i];
      i  ;
      k  ;
    } else {
      arr[k] = rArray[j];
      j  ;
      k  ;
    }
  }

  // Handling last element in lArray or rArray

  i < lArray.length ? arr[k] = lArray[i] : arr[k] = rArray[j];
}

// Recursive Merge Sort 
function recursiveMergeSort(arr, start, end) {
  if (start < end) {
    let mid = Math.floor(((end)   start) / 2);
    //console.log(start, end, mid);
    recursiveMergeSort(arr, start, mid);
    recursiveMergeSort(arr, mid   1, end);
    sort(arr, start, mid, end);
  }
}

function mergeSort(arr) {

  let start = 0;
  let end = arr.length - 1;

  recursiveMergeSort(arr, start, end);
  return (arr)
}

console.log(mergeSort([5, 8, 3, 7, 5]));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

// Handling last element in lArray or rArray is not correct.

After merging arrays you have to check the rests and copy untreated tail if it does exist

 while (i < lArray.length) {
     arr[k] = lArray[i];
     i  ;
     k  ;
 }
 while (j < rArray.length) {
     arr[k] = rArray[j];
     j  ;
     k  ;
 }

Replacing ternary operator by this code gives correct results for given data

CodePudding user response:

Example of a somewhat optimized version of top down merge sort. It does a one time allocation of a working array and uses a pair of mutually recursive functions to change the direction of merge for each level of recursion. Takes about 1/4 second to sort 1 million pseudo-random integers on my system:

// merge sort top down

function merge(a, b, bgn, mid, end) {
  var i = bgn                           // left:  a[bgn,mid)
  var j = mid                           // right: a[mid,end)
  var k = bgn                           // index for b[]
  while(true){
    if(a[i] <= a[j]){                   // if left <= right
      b[k  ] = a[i  ]                   //   copy left
      if(i < mid)                       //   if not end of left
        continue                        //     continue back to while
      do                                //   else copy rest of right
        b[k  ] = a[j  ]
      while(j < end)
      break                             //     and break
    } else {                            // else left > right
      b[k  ] = a[j  ]                   //   copy right
      if(j < end)                       //   if not end of right
        continue                        //     continue back to while
      do                                //   else copy rest of left
        b[k  ] = a[i  ]
      while(i < mid)
      break                             //     and break
    }
  }
}

function sortatob(a, b, bgn, end) {     // sort a to b
  if ((end-bgn) < 2){
    b[bgn] = a[bgn]
    return
  }
  var mid = Math.floor(bgn   (end - bgn) / 2)
  sortatoa(a, b, bgn, mid)
  sortatoa(a, b, mid, end)
  merge(a, b, bgn, mid, end)
}

function sortatoa(a, b, bgn, end) {     // sort a to a
  if ((end-bgn) < 2)
    return
  var mid = Math.floor(bgn   (end - bgn) / 2)
  sortatob(a, b, bgn, mid)
  sortatob(a, b, mid, end)
  merge(b, a, bgn, mid, end)
}

function mergesort(a) {                 // entry function
  if(a.length < 2)
      return
  var b = new Array(a.length)           // allocate temp array
  sortatoa(a, b, 0, a.length)           // start with sort a to a
}

var a = new Array(1000000)
for (i = 0; i < a.length; i  ) {
  a[i] = parseInt(Math.random() * 1000000000)
}
console.time('measure')
mergesort(a)
console.timeEnd('measure')
for (i = 1; i < a.length; i  ) {
  if(a[i-1] > a[i]){
    console.log('error')
    break
  }
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related