- 冒泡排序
冒泡排序大概的意思是依次比较相邻的两个数,然后根据大小做出排序,直至最后两位数。由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。但其实在实际过程中也可以根据自己需要反过来用,大数往前放,小数往后放。
<?php
/**
* 冒泡排序
* @param $arr
* @return mixed
*/
function bubbleSort($arr)
{
$len = count($arr);
if ($len <= 1) {
return $arr;
}
// 第一层可以理解为从数组中键为0开始循环到最后一个
for ($i = 0; $i < $len ; $i++) {
// 第二层为从$i+1的地方循环到数组最后
for ($j = $i+1; $j < $len; $j++) {
// 比较数组中两个相邻值的大小
if ($arr[$i] > $arr[$j]) {
$temp = $arr[$i]; // 这里临时变量,存贮$i的值
$arr[$i] = $arr[$j]; // 第一次更换位置
$arr[$j] = $temp; // 完成位置互换
}
}
}
return $arr;
}
$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];
$arr = bubbleSort($arr);
print_r($arr);
输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )
- 插入排序
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。就像抓扑克牌,抓一张,然后再手里已经部分已经排好序的手牌的找到位置插进去。
$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];
//插入排序是一种逻辑上非常好理解的排序方式,整个排序的核心就是不断在当前已经排好部分数据的数组里,
//找到合适的位置插入新数据。就像抓扑克牌,抓一张,然后再手里已经部分已经排好序的手牌的找到位置插进去。
/**
* 插入排序
* @param $arr
* @return mixed
*/
function insertSort($arr)
{
//获取数组单元个数
$len = count($arr);
if ($len <= 1) {
return $arr;
}
//外层循环用于从未排序区域中取出待排序元素
for ($i = 1; $i < $len; $i++) {
//获取当前需要插入已排序区域的元素值
$temp = $arr[$i];
//内层循环用于从已排序区域寻找待排序元素的插入位置
for ($j = $i - 1; $j >= 0; $j--) {
//如果$arr[$i]比已排序区域的$arr[$j]小,就后移$arr[$j]
if ($temp < $arr[$j]) {
$arr[$j + 1] = $arr[$j];
$arr[$j] = $temp;
} else {
//如果$arr[$i]不小于$arr[$j],则对已排序区无需再排序
break;
}
}
}
return $arr;
}
$arr = insertSort($arr);
print_r($arr);
输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )
- 选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];
/**
* 选择排序
* @param $arr
* @return mixed
*/
function selectSort($arr)
{
//获取数组单元个数
$len = count($arr);
if ($len <= 1) {
return $arr;
}
for ($i = 0; $i < $len - 1; $i++) {
// 当前值的位置
$key = $i;
for ($j = $i + 1; $j < $len; $j++) {
// 相邻值进行比较,条件成立替换当前值
if ($arr[$key] > $arr[$j]) {
$key = $j;
}
}
if ($key != $i) {
// 交换位置
$temp = $arr[$key];
$arr[$key] = $arr[$i];
$arr[$i] = $temp;
}
}
return $arr;
}
$arr = selectSort($arr);
print_r($arr);
输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )
- 归并排序
假设当前需要从小到大进行排序,归并排序的核心思路是,把大的数组,不停地拆成小的数组,直到拆得最小,然后再把小数组两两排序合并,再将结果不停地进行一次次排序的合并。
算法描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];
/**
* mergeSort 归并排序
* 是开始递归函数的一个驱动函数
* @param &$arr array 待排序的数组
*/
function mergeSort(&$arr)
{
$len = count($arr);//求得数组长度
mSort($arr, 0, $len - 1);
}
/**
* 实际实现归并排序的程序
* @param &$arr array 需要排序的数组
* @param $left int 子序列的左下标值
* @param $right int 子序列的右下标值
*/
function mSort(&$arr, $left, $right)
{
if ($left < $right) {
//说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
//计算拆分的位置,长度/2 去整
$center = floor(($left + $right) / 2);
//递归调用对左边进行再次排序:
mSort($arr, $left, $center);
//递归调用对右边进行再次排序
mSort($arr, $center + 1, $right);
//合并排序结果
mergeArray($arr, $left, $center, $right);
}
}
/**
* 将两个有序数组合并成一个有序数组
* @param &$arr , 待排序的所有元素
* @param $left , 排序子数组A的开始下标
* @param $center , 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
* @param $right , 排序子数组B的结束下标(开始为$center+1)
*/
function mergeArray(&$arr, $left, $center, $right)
{
//设置两个起始位置标记
$a_i = $left;
$b_i = $center + 1;
while ($a_i <= $center && $b_i <= $right) {
//当数组A和数组B都没有越界时
if ($arr[$a_i] < $arr[$b_i]) {
$temp[] = $arr[$a_i++];
} else {
$temp[] = $arr[$b_i++];
}
}
//判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:
while ($a_i <= $center) {
$temp[] = $arr[$a_i++];
}
//判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:
while ($b_i <= $right) {
$temp[] = $arr[$b_i++];
}
//将$arrC内排序好的部分,写入到$arr内:
for ($i = 0, $len = count($temp); $i < $len; $i++) {
$arr[$left + $i] = $temp[$i];
}
}
mergeSort($arr);
- 快速排序
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];
function quickSort($arr)
{
$count = count($arr);
if ($count < 2) {
return $arr;
}
$leftArray = $rightArray = array();
$middle = $arr[0];// 基准值
for ($i = 1; $i < $count; $i++) {
// 小于基准值,存入左边;大于基准值,存入右边
if ($arr[$i] < $middle) {
$leftArray[] = $arr[$i];
} else {
$rightArray[] = $arr[$i];
}
}
$leftArray = quickSort($leftArray);
$rightArray = quickSort($rightArray);
return array_merge($leftArray, array($middle), $rightArray);
// 倒序
// return array_merge($rightArray, array($middle), $leftArray);
}
$arr = quickSort($arr);
print_r($arr);
注:快速排序在常规排序里综合排名最高的排序算法。 快速排序在工程实践中应用较多,比如 PHP 数组的 sort
函数底层就是基于快速排序来实现的