PHP 常用例子

归并排序是一种分而治之的算法。它基于以下思想:将未排序的数组划分为多个子数组,直到每个子数组由单个元素组成,然后以产生排序数组的方式合并这些子数组。归并排序的过程步骤可以概括如下:

  • 划分: 将未排序的数组划分为多个子数组,直到每个子数组只包含单个元素。
  • 合并:将子数组合并为有序数组,然后合并直至获得原始数组。
  • 合并技术: 考虑并比较两个子数组的第一个元素。对于升序排序,从子数组中取出值较小的元素,并成为排序数组的新元素。重复此过程,直到两个子数组都被清空并且合并后的数组成为排序数组。

示例:

为了理解归并排序,让我们考虑一个未排序的数组[4, 9, -4](下图中第 11 个过程后创建的右侧数组)并讨论按升序对数组进行排序所采取的每个步骤。

在第一步,将数组[4, 9, -4]分为两个子数组。第一个子数组包含 [4, 9],第二个子数组包含 [-4]。由于第一个子数组中的元素数量大于1,因此将其进一步分为分别由元素[4][9]组成的子数组。由于所有子数组的元素个数都是1,因此无法对数组进行进一步的划分。

在合并过程中,将上一步形成的子数组合并在一起,使用上面提到的过程形成一个排序数组。首先,将[4][9]子数组合并在一起,形成排序子数组[4, 9]。然后将[4, 9][-4]子数组合并在一起形成最终的排序数组[-4, 4, 9]

PHP 程序 归并排序

归并排序的实现

<?php
// 归并排序函数 - 分割数组
//并调用merge函数对数组进行排序和合并
//归并排序是一个递归函数
function mergesort(&$Array, $left, $right) {
  if ($left < $right) { 
    $mid = $left + (int)(($right - $left)/2);
    mergesort($Array, $left, $mid);
    mergesort($Array, $mid+1, $right);
    merge($Array, $left, $mid, $right);
  }
}

//合并函数执行排序和合并操作
//用于归并排序函数
function merge(&$Array, $left, $mid, $right) {
  // 创建两个临时数组来保存 split
  //主数组的元素
  $n1 = $mid - $left + 1; //LeftArray 中的元素数量
  $n2 = $right - $mid;     //RightArray 中的元素数量
  $LeftArray = array_fill(0, $n1, 0); 
  $RightArray = array_fill(0, $n2, 0);
  for($i=0; $i < $n1; $i++) { 
    $LeftArray[$i] = $Array[$left + $i];
  }
  for($i=0; $i < $n2; $i++) { 
    $RightArray[$i] = $Array[$mid + $i + 1];
  }

  //下面的x,y,z代表索引号
  //分别为LeftArray、RightArray和Array
  $x=0; $y=0; $z=$left;
  while($x < $n1 && $y < $n2) {
    if($LeftArray[$x] < $RightArray[$y]) { 
      $Array[$z] = $LeftArray[$x]; 
      $x++; 
    }
    else { 
      $Array[$z] = $RightArray[$y];  
      $y++; 
    }
    $z++;
  }

  //复制LeftArray的剩余元素
  while($x < $n1) { 
     $Array[$z] = $LeftArray[$x];  
     $x++;  
     $z++;
  }

  //复制RightArray的剩余元素
  while($y < $n2) { 
    $Array[$z] = $RightArray[$y]; 
    $y++;  
    $z++; 
  }
}

//打印数组的函数
function PrintArray($Array, $n) { 
  for ($i = 0; $i < $n; $i++) 
    echo $Array[$i]." "; 
  echo "\n";
} 

//测试代码
$MyArray = array(10, 1, 23, 50, 4, 9, -4);
$n = sizeof($MyArray); 
echo "原始数组\n";
PrintArray($MyArray, $n);

mergesort($MyArray, 0, $n-1);
echo "\n排序数组\n";
PrintArray($MyArray, $n);
?> 

上面的代码将给出以下输出:

原始数组
10 1 23 50 4 9 -4 

排序数组
-4 1 4 9 10 23 50 

时间复杂度:

在所有情况下(最差、平均和最佳),归并排序始终划分数组,直到所有子数组都包含单个元素,并花费线性时间来合并这些子数组。划分过程的时间复杂度为θ(logN),合并过程的时间复杂度为θ(N)。因此,在所有情况下,归并排序的时间复杂度都是θ(NlogN)