PHP排序常用算法汇总

标签: php
发布日期: 2024-01-05 10:02:10

在PHP中,排序算法用于将一组数据按照特定的顺序进行排列。常见的排序算法包括快速排序、插入排序、希尔排序、归并排序、堆排序、冒泡排序、计数排序、基数排序、桶排序、选择排序等。下面将介绍其中一些常用的PHP排序算法。

冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法,它重复地遍历待排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

以下是一个使用PHP实现冒泡排序的示例代码:

function maopao($arr){
        $count=count($arr);
        for($i=0;$i<$count;$i++){
            for($j=0;$j<$count-$i-1;$j++){
                if($arr[$j]<$arr[$j+1]){
                    $temp = $arr[$j];
                    $arr[$j] = $arr[$j+1];
                    $arr[$j+1] = $temp;
                }
            }
        }
        var_dump($arr);
    }

选择排序(Selection Sort)

选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。选择排序是不稳定的排序方法。

以下是一个使用PHP实现选择排序的示例代码:

function selectionSort($arr) {  
    $n = count($arr);  
    for ($i = 0; $i < $n - 1; $i++) {  
        $minIndex = $i;  
        for ($j = $i + 1; $j < $n; $j++) {  
            if ($arr[$j] < $arr[$minIndex]) {  
                $minIndex = $j;  
            }  
        }  
        // 交换元素  
        $temp = $arr[$i];  
        $arr[$i] = $arr[$minIndex];  
        $arr[$minIndex] = $temp;  
    }  
    return $arr;  
}

插入排序(Insertion Sort)

插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

以下是一个使用PHP实现插入排序的示例代码:

function insertionSort($arr) {  
    $n = count($arr);  
    for ($i = 1; $i < $n; $i++) {  
        $key = $arr[$i];  
        $j = $i - 1;  
        while ($j >= 0 && $arr[$j] > $key) {  
            $arr[$j + 1] = $arr[$j];  
            $j--;  
        }  
        $arr[$j + 1] = $key;  
    }  
    return $arr;  
}

快速排序

从1开始每个数和arr[0]比较,分别放进左右数组,递归,合并

function quicksort($arr) {
	if(count($arr) <=1) {
		return $arr;
	}
	$larr = [];
	$rarr = [];
	for ($i=1;$i<count($arr);$i++) {
		if($arr[$i] <= $arr[0]) {
			$larr[] = $arr[$i];
		} else {
			$rarr[] = $arr[$i];
		}
	}
	$left = quicksort($larr);
	$right = quicksort($rarr);
	return array_merge($left,array($arr[0]),$right);
}

希尔排序

带基数的插入排序

function shellsort($arr) {
	//初始化增量
	$increment = count($arr);
	while($increment > 1) {
		$increment = intval($increment/3) + 1;
		for ($i=$increment;$i<count($arr);$i++) {
			//待插入值
			$temp = $arr[$i];
			//待比较位置
			$j = $i - $increment;
			//降序排列
			while($j>=0&&$temp>$arr[$j]) {
				$arr[$j+$increment] = $arr[$j];
				$arr[$j] = $temp;
				$j = $j-$increment;
			}
			$arr[$j+$increment] = $temp;
		}
	}
	return $arr;
}

归并排序

把数组切割,直到不可分割,排序单个小数组,然后合并,递归执行

function merge_sort(&$arr) {
	$count = count($arr);
	if($count <= 1) {
		return $arr;
	}
	$mid = intval($count/2);
	$left = array_slice($arr, 0,$mid);
	$right = array_slice($arr, $mid);
	merge_sort($left);
	merge_sort($right);
	$merge=[];
	while(count($left)&&count($right)) {
		$merge[] = $left[0]<$right[0] ? array_shift($left):array_shift($right);
	}
	$arr = array_merge($merge,$left,$right);
	//    var_dump($arr);
}

堆排序

以最后一个父节点为起始节点,比较子节点,把最小值或最大值移动到父节点,遍历所有父节点后

function heep_sort($arr) {
	//获取数组的长度
	$arrsize = count($arr);
	while($arrsize > 0) {
		//遍历每个节点,和子节点比较得到最小值
		for ($i = intval($arrsize/2)-1;$i>=0;$i--) {
			//起初认定当前节点最小
			$min = $i;
			//如果存在左节点
			if($i*2+1 < $arrsize) {
				//比较和左节点的大小,如果左节点的值更小,那么进行交换
				if($arr[$i] > $arr[$i*2+1]) {
					$temp = $arr[$i];
					$arr[$i] = $arr[$i*2+1];
					$arr[$i*2+1] = $temp;
				}
			}
			//如果存在又节点
			if($i*2+2 < $arrsize) {
				//比较和右节点的大小,如果右节点的值更小,那么进行交换
				if($arr[$i] > $arr[$i*2+2]) {
					$temp = $arr[$i];
					$arr[$i] = $arr[$i*2+2];
					$arr[$i*2+2] = $temp;
				}
			}
			//执行完一次遍历,跳到下一个非叶子节点
		}
		//成功找到第一个最小值,使数组长度减一
		//首尾交换,保存最小值
		$temp = $arr[0];
		$arr[0] = $arr[$arrsize-1];
		$arr[$arrsize-1] = $temp;
		$arrsize--;
	}
	return $arr;
}

计数排序

时间复杂度O(n+k),n为排序的数的个数,k为要排序的数的最大值,消耗空间来达到快捷,空间换时间,

计算数组的最大和最小值,创建一个键从min到max的数组,计数排序数组的每个值的个数,然后向一个新数组填充入栈

步骤:

找出待排序的数组中最大和最小的元素

统计数组中每个值为i的元素出现的次数,存入数组C的第i项

对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)

反向填充目标数组:将每个元素i放在新数组的第C[i]项,每放一个元素就将C[i]减去1

function countsort($arr) {
	$count = count($arr);
	$carr = [];
	$min = $arr[0];
	$max = $arr[0];
	//找最大值和最小值
	for ($i=1;$i<$count;$i++) {
		if($arr[$i]<$min) {
			$min = $arr[$i];
		}
		if($arr[$i]>$max) {
			$max = $arr[$i];
		}
	}
	for ($i=$min;$i<=$max;$i++) {
		$carr[$i] = 0;
	}
	for ($i=1;$i<$count;$i++) {
		$carr[$arr[$i]]++;
	}
	$newarr = [];
	for ($i=$max;$i>=$min;$i--) {
		while($carr[$i]>0) {
			$newarr[]=$i;
			$carr[$i]--;
		}
	}
	var_dump($newarr);
}

基数排序

//默认降序
function radixSort($arr, $desc=true) {
	if (count($arr) <= 1) {
		return $arr;
	}
	$max = $arr[0];
	for ($i=1;$i<count($arr);$i++) {
		if ($arr[$i] > $max) {
			$max = $arr[$i];
		}
	}
	$n = 0;
	//记录最大数的位数
	while($max > 1) {
		$max = $max/10;
		$n++;
	}
	for ($j=1;$j<=$n;$j++) {
		$tmp_arr = [];
		for ($k=0;$k<count($arr);$k++) {
			$r = pow(10,$j-1);
			$num = $arr[$k] > $r ? intval($arr[$k]/$r)%10 : 0;
			$tmp_arr[$num][] = $arr[$k];
		}
		$arr=[];
		if ($desc) {
			for ($m=9;$m>=0;$m--) {
				if (!empty($tmp_arr[$m])) {
					for ($p=0;$p<count($tmp_arr[$m]);$p++) {
						$arr[] = $tmp_arr[$m][$p];
					}
				}
			}
		} else {
			for ($m=0;$m<=9;$m++) {
				if (!empty($tmp_arr[$m])) {
					for ($p=0;$p<count($tmp_arr[$m]);$p++) {
						$arr[] = $tmp_arr[$m][$p];
					}
				}
			}
		}
	}
	return $arr;
}

桶排序

function bucketSort($arr, $bucketSize = 5) {
	if (count($arr) === 0) {
		return $arr;
	}
	$minValue = $arr[0];
	$maxValue = $arr[0];
	for ($i = 1; $i < count($arr); $i++) {
		if ($arr[$i] < $minValue) {
			$minValue = $arr[$i];
		} else if ($arr[$i] > $maxValue) {
			$maxValue = $arr[$i];
		}
	}
	$bucketCount = floor(($maxValue - $minValue) / $bucketSize) + 1;
	$buckets = array();
	for ($i = 0; $i < $bucketCount; $i++) {
		$buckets[$i] = [];
	}
	for ($i = 0; $i < count($arr); $i++) {
		$buckets[floor(($arr[$i] - $minValue) / $bucketSize)][] = $arr[$i];
	}
	$arr = array();
	for ($i = 0; $i < count($buckets); $i++) {
		$bucketTmp = $buckets[$i];
		sort($bucketTmp);
		for ($j = 0; $j < count($bucketTmp); $j++) {
			$arr[] = $bucketTmp[$j];
		}
	}
	return $arr;
}