/**修改版冒泡排序法
*/
function bubbleSort(&$arr) :void
{
$swapped = false;
$bound = count($arr) - 1;
for ($i = 0, $c = count($arr); $i < $c; $i++) {
for ($j = 0; $j < $bound; $j++) {
if ($arr[$j + 1] < $arr[$j]) {
list($arr[$j], $arr[$j + 1]) = array($arr[$j + 1], $arr[$j]);
//list()在PHP5和PHP7的效果不一樣
$swapped = true;
$newBound = $j;
}
}
$bound = $newBound;
if (!$swapped) break; //沒有發生交換,算法結束
}
}
/*
選擇排序每次找到最小(最大)的與之互換位置
*/
function selectionSort(&$arr)
{
$count = count($arr);
//重複元素個數-1次
for ($j = 0; $j <= $count - 1; $j++) {
//把第一個沒有排過序的元素設置爲最小值
$min = $arr[$j];
//遍歷每一個沒有排過序的元素
for ($i = $j + 1; $i < $count; $i++) {
//如果這個值小於最小值
if ($arr[$i] < $min) {
//把這個元素設置爲最小值
$min = $arr[$i];
//把最小值的位置設置爲這個元素的位置
$minPos = $i;
}
}
//內循環結束把最小值和沒有排過序的元素交換
list($arr[$j], $arr[$minPos]) = [$min, $arr[$j]];
}
}
/*
插入排序的工作原理是將數字插入到已排序列表的正確位置。
它從數組的第二項開始,並判斷該項是否小於當前值。如果是這樣,它將項目轉移,並將較小的項目存儲在其正確的位置。
然後,它移動到下一項,並且相同的原理繼續下去,直到整個數組被排序。
*/
function insertionSort(array &$arr)
{
$len = count($arr);
for ($i = 1; $i < $len; $i++) {
$key = $arr[$i];
$j = $i - 1;
while ($j >= 0 && $arr[$j] > $key) {
$arr[$j + 1] = $arr[$j];
$j--;
}
$arr[$j + 1] = $key;
}
}
/**
* 歸併排序
* 核心:兩個有序子序列的歸併(function merge)
* 時間複雜度任何情況下都是 O(nlogn)
* 空間複雜度 O(n)
* 發明人: 約翰·馮·諾伊曼
* 速度僅次於快速排序,爲穩定排序算法,一般用於對總體無序,但是各子項相對有序的數列
* 一般不用於內(內存)排序,一般用於外排序
*/
function mergeSort($arr)
{
$lenght = count($arr);
if ($lenght == 1) return $arr;
$mid = (int)($lenght / 2);
//把待排序數組分割成兩半
$left = mergeSort(array_slice($arr, 0, $mid));
$right = mergeSort(array_slice($arr, $mid));
return merge($left, $right);
}
function merge(array $left, array $right)
{
//初始化兩個指針
$leftIndex = $rightIndex = 0;
$leftLength = count($left);
$rightLength = count($right);
//臨時空間
$combine = [];
//比較兩個指針所在的元素
while ($leftIndex < $leftLength && $rightIndex < $rightLength) {
//如果左邊的元素大於右邊的元素,就將右邊的元素放在單獨的數組,並將右指針向後移動
if ($left[$leftIndex] > $right[$rightIndex]) {
$combine[] = $right[$rightIndex];
$rightIndex++;
} else {
//如果右邊的元素大於左邊的元素,就將左邊的元素放在單獨的數組,並將左指針向後移動
$combine[] = $left[$leftIndex];
$leftIndex++;
}
}
//右邊的數組全部都放入到了返回的數組,然後把左邊數組的值放入返回的數組
while ($leftIndex < $leftLength) {
$combine[] = $left[$leftIndex];
$leftIndex++;
}
//左邊的數組全部都放入到了返回的數組,然後把右邊數組的值放入返回的數組
while ($rightIndex < $rightLength) {
$combine[] = $right[$rightIndex];
$rightIndex++;
}
return $combine;
}
//快速排序
function qSort(array &$arr, int $p, int $r)
{
if ($p < $r) {
$q = partition($arr, $p, $r);
qSort($arr, $p, $q);
qSort($arr, $q + 1, $r);
}
}
function partition(array &$arr, int $p, int $r)
{
$pivot = $arr[$p];
$i = $p - 1;
$j = $r + 1;
while (true) {
do {
$i++;
} while ($arr[$i] < $pivot);
do {
$j--;
} while ($arr[$j] > $pivot);
if ($i < $j) {
list($arr[$i], $arr[$j]) = [$arr[$j], $arr[$i]];
} else {
return $j;
}
}
}
/**
* 桶排序
* 不是一種基於比較的排序
* T(N, M) = O(M + N) N是帶排序的數據的個數,M是數據值的數量
* 當 M >> N 時,需要考慮使用基數排序
*/
function bucketSort(array &$data)
{
$bucketLen = max($data) - min($data) + 1;
$bucket = array_fill(0, $bucketLen, []);
for ($i = 0; $i < count($data); $i++) {
array_push($bucket[$data[$i] - min($data)], $data[$i]);
}
$k = 0;
for ($i = 0; $i < $bucketLen; $i++) {
$currentBucketLen = count($bucket[$i]);
for ($j = 0; $j < $currentBucketLen; $j++) {
$data[$k] = $bucket[$i][$j];
$k++;
}
}
}
PHP幾個基本的排序算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.