PHP幾個基本的排序算法

/**修改版冒泡排序法
*/

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++;
	        }
	      }
	 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章