冒泡排序
<?php
$arr1 = array(5,9,2,6,4,7,365,69,5,62,1); //数组共有10个元素
for($j=0,$lenght=count($arr1);$j<$lenght;$j++) {
for ($i = 0, $lenght = count($arr1); $i < $lenght-1-$j; $i++) {
//因为是向高一位比较,所以比较进行到第九个元素,即下标为8
//随着比较次数的增加,每次需要比较的元素减少一个
if ($arr1[$i] > $arr1[$i + 1]) { //比较左右两数字的大小
$value = $arr1[$i + 1]; //如果左边的数字更大,交换两数字
$arr1[$i + 1] = $arr1[$i];
$arr1[$i] = $value;
}
}
}
echo '<pre>';
print_r ($arr1);
选择排序:(相较于冒泡交换次数更少)
假设第一个元素为最小元素,保存下标
寻找右侧元素,如果有更小的元素,重新保存其下标
如果下标改变,则交换两元素
标记下一个元素,继续执行以上步骤,直至最后一个元素
<?php
$arr1 = array(7,8,9,6,5,4,1,2,3);
//1、首先确定需要交换多少次,即数组长度
for($i=0,$lenght=count($arr1);$i<$lenght;$i++){
//2、假设第一个元素就是最小的
$min=$i;
//3、寻找是否有更小的元素
for($j=$i+1;$j<$lenght;$j++){
//4、比较当前元素和最小的元素
if($arr1[$j]<$arr1[$min]){
//说明当前的值不合适
$min=$j;
}
}
//5、交换起初值和实际最小值
if($min!= $i){ //判断当前下标是否发生改变
$value=$arr1[$min];
$arr1[$min]=$arr1[$i];
$arr1[$i]=$value;
}
}
echo '<pre>';
print_r ($arr1);
插入排序
把一个数据插入到已经排好序的有序数据中,从而得到一个新的(元素个数加一的)数据。
1、认定第一个元素已经排好序;
2、假定取出第二个元素,作为待插入数据;
3、与已经排好序的数组的最右侧元素开始进行比较
4、如果后面的小于前面的,说明前面已经排好序的数组元素不在对的位置(向后移一位),然后让新的元素填充进去,继续向前比。
5、重复前面的步骤,直到当前元素插入到正确位置。
6、重复以上步骤,直到所有的数组元素都插入到正确位置。
<?php
//插入排序
$arr = array(2,5,8,9,6,3);
//1、确定要插入多少回(假设一个数组一次性插入到对的位置,同时第一个位置是假设对的。
for($i=1,$lenght=count($arr);$i<$lenght;$i++){
//2、取出当前要插入的元素的值
$temp=$arr[$i];
$change=false;//标记是否需要换位
//3、让该数据与前面已经排好序的数组元素比较(挨个比较),直到对的位置
for($j=$i-1;$j>=0;$j--){
//4、比较
if($arr[$j]>$temp){ //说明当前要插入的元素,比已经排好序的数列的最后一个元素小,交换位置
$arr[$j+1]=$arr[$j];
//插入元素小于前面元素才会执行,则需要换位,打开change
$change=true;//$arr[$j]=$temp;
}
else{ //说明当前待插入元素比前面的元素大,不需要换位
break;
}
}
if($change){
$arr[$j+1]=$temp;//j-1判断失败后才会进入这一步,所以需要j+1获得原值
}
}
echo '<pre>';
print_r($arr);
快速排序:
对冒泡排序的改进,利用递归函数
1、从数组中选出第一个元素,作为参照对象;
2、将数组中剩余元素与参照对象进行比较,更小的放在一个数组,更大的放在另外一个数组;
3、将剩余数组多次重复进行以上操作;
4、回溯最小数组(数组中仅有一个元素)。
<?php
//快速排序
$arr1= array(5,4,7,8,5,2,3,6,9,8,7,4,5,6,3,2,1);
function quickSort($arr){
$len = count($arr);
if($len <=1){
return $arr;
}
$left=$right= array();
for($i=1;$i<$len;$i++){ //第一个元素作为比较,所以从第二个元素开始
if($arr[$i]<$arr[0]){
$left[] =$arr[$i];
}
else{
$right[]=$arr[$i];
}
}
//排序$left和$right; 递归点
$left = quickSort($left);
$right = quickSort($right);
//合并三个数组
return array_merge($left,(array)$arr[0],$right);
}
echo '<pre>';
print_r(quickSort($arr1));
归并排序
采用分治法,将已有序的子序列合并,得到完全有序的序列。
即先使每个子序列(仅含有1-2个元素)有序,再使子序列段间有序。
将两个有序数列合并成一个有序数列,成为二路归并:
<?php
//PHP二路归并
$arr1 = array(1,4,7);
$arr2 = array(2,5,8);
$arr3 = array(); 事先开辟一个空数列用于归并空间
while(count($arr1) && count($arr2)){ //判断两组数列是否为空,若某一组为空,则跳出循环
$arr3[]= $arr1[0]<$arr2[0] ? array_shift($arr1) : array_shift($arr2);
//三目运算,如果数组一中首位元素更小,则从数组中取出,否则取出数组二首位元素
}
//合并三组数列
print_r($arr3,$arr1,$arr2); //此时两组数列谁在前已经无关紧要,因为其中一组必为空数列
思路:
1、将数组拆分成两个数组
2、重复步骤1,把数组拆分成最小单元
3、申请空间,作为合并空间
4、利用二路归并
<?php
//归并排序
$arrTest=array(98,98,7,89,4,84,64,56,4654,65,42,1,21,3);
function arraySort($arr){
$len = count($arr); //获取数列长度
if ($len<=1){return $arr;}
//把数组分开
$middle = floor($len/2);
$left = array_slice($arr,0,$middle);
$right = array_slice($arr,$middle);
//递归点:此时可能数列还不是单个元素的数列
$left = arraySort($left);
$right = arraySort($right);
//假设此时都已经是有序数列,进行二路归并
$m = array(); //为最终序列开辟空间存放
while(count($left) && count($right)){ //判断两个数列中是否有空数列
$m[] = $left[0] < $right[0] ? array_shift($left) : array_shift($right);
}
return array_merge($m,$left,$right);
}
echo '<pre>';
print_r(arraySort($arrTest));