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++;
	        }
	      }
	 }
发布了12 篇原创文章 · 获赞 4 · 访问量 4350

猜你喜欢

转载自blog.csdn.net/u013083541/article/details/82771945