合并Java时间复杂度排序

时间:2019-10-13 05:43:39

标签: sorting data-structures time-complexity slice mergesort

在Java中实现合并排序时,许多代码都使用slice来分割数组。 这样会不会增加时间复杂度?

切片是否具有时间复杂度,或者在计算中忽略了这一点?

1 个答案:

答案 0 :(得分:1)

示例自上而下合并排序。使用一对相互递归的函数(sortatob,sortatoa)根据递归级别更改合并方向。

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
  }
}


示例自底向上合并排序。函数merge()与上面的相同。通过交换对数组的引用来更改每次通过时的合并方向。

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 getpasscount(n)                // return # passes
{
  var i = 0
  for(var s = 1; s < n; s <<= 1)
    i += 1
  return(i)
}

function mergesort(a)
{
  var n = a.length
  if(n < 2)                             // if size < 2 return
    return
  var b = new Array(n)                  // allocate temp array
  var s = 1                             // default run size to 1
  if(0 != (1&getpasscount(n))){         //  if odd # passes swap in place
    for(var i = 1; i < n; i += 2){
      if(a[i-1] > a[i]){
        var t = a[i-1]
        a[i-1] = a[i]
        a[i] = t
      }
    }
    s = 2                               // change run size to 2
  }
  while(s < n){                         // while not done
    var ee = 0                          // reset end index
    while(ee < n){                      // merge pairs of runs
      var ll = ee                       // ll = start of left  run
      var rr = ll+s                     // rr = start of right run
      if(rr >= n){                      // if only left run
        do                              //   copy it
          b[ll] = a[ll]
        while(++ll < n)
        break                           //   end of pass
      }
      ee = rr+s                         // ee = end of right run
      if(ee > n)
        ee = n
      merge(a, b, ll, rr, ee)           // merge a[left],a[right] to b[]
    }
    var t = a                           // swap array references
    a = b
    b = t
    s <<= 1                             // double the run size
  }
}

var a = new Array(1000000)
for (var i = 0; i < a.length; i++) {
  a[i] = parseInt(Math.random() * 1000000000)
}
console.time('measure')
mergesort(a)
console.timeEnd('measure')
for (var i = 1; i < a.length; i++) {
  if(a[i-1] > a[i]){
    console.log('error')
    break
  }
}