冒泡排序
思路分析:在未排序的数组中,从前往后对相邻的两个数一次对比,较大的数往下沉,较小的往上冒。
即,从左到右,数组中相邻的两个元素进行比较,将较大的放到后面。
function bubbleSort($arr) {
if(empty($arr)) return $arr;
$len = count($arr);
//该层循环控制 需要冒泡的轮数
for($i=0; $i< $len; $i++) {
//该层循环用来控制每轮 冒出一个数 需要比较的次数
for($j=0; $j<($len-1-$i); $j++) {
if($arr[$j] > $arr[$j+1]){
$tmp = $arr[$j];
$arr[$j] = $arr[$j+1];
$arr[$j+1]= $tmp;
}
}
}
return $arr;
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(bubbleSort($arr));
选择排序
思路分析:在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
即,从第一个位置开始比较,找出最小的,和第一个位置互换,开始下一轮。
function selectSort($arr) {
if (empty($arr)) return $arr;
$len = count($arr);
//双重循环完成,外层控制轮数,内层控制比较次数
for($i=0; $i<$len-1; $i++) {
//先假设最小的值的位置
$min = $i;
for($j=$i+1; $j<$len; $j++){
if($arr[$min] > $arr[$j]){
$min = $j;
}
if ($min != $i) {
$tmp = $arr[$min];
$arr[$min] = $arr[$i];
$arr[$i] = $tmp;
}
}
}
return $arr;
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(selectSort($arr));
快速排序
思路分析:选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。
此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
function quickSort($arr) {
$len = count($arr);
if ($len <= 1) return $arr;
//选择第一个元素作为标准
$baseTmp = $arr[0];
$leftArr = [];
$rightArr = [];
//遍历,按照大小关系放入两个数组内。注意从1开始
for($i=1; $i<$len; $i++) {
if ($arr[$i] < $baseTmp) {
$leftArr[] = $arr[$i];
} else {
$rightArr[] = $arr[$i];
}
}
$leftArr = quickSort($leftArr);
$rightArr = quickSort($rightArr);
return array_merge($leftArr, [$baseTmp], $rightArr);
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(quickSort($arr));
插入排序
思路分析:在要排序的一组数中,假设前面的数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。
第n个数与前面n-1个数分别依次作比较,如果比前面的数小就交换位置,否则就终止循环,如此反复循环,直到全部排好顺序。
function insertSoet($arr) {
if (empty($arr)) return $arr;
$len = count($arr);
for($i=1; $i< $len; $i++) {
//要插入的数
$tmp = $arr[$i];
//依次与前面的每个数作比较,$tmp小就互换位置,否则终止循环;
for($j=$i-1; $j>=0; $j--) {
if ($tmp < $arr[$j]) {
//发现插入的元素要小,交换位置,将后边的元素与前面的元素互换
$arr[$j+1] = $arr[$j];
$arr[$j] = $tmp;
} else {
//如果碰到不需要移动的元素,由于是已经排序好是数组,则前面的就不需要再次比较了。
break;
}
}
}
return $arr;
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(insertSoet($arr));
二分查找
思路分析:折半算法,先找到中间节点,用K与中间节点的关键词比较,中间节点把线性表分为两个子表,直到查找到或查找结束。
注:针对已经排好序的数组
//递归方法
function binSch($arr, $k, $start=0, $end=0) {
if ($start > $end) return -1;
if (count($arr) !== 0 && $end ==0) {//判断是否为第一次调用
$end = count($arr);
}
$mid = floor(($start + $end) / 2);
if ($k == $arr[$mid]) {
return $mid;
} elseif ($k < $arr[$mid]) {
$newStart = $start;
$newEnd = $mid -1;
return binSch($arr, $k, $newStart, $newEnd);
} else {
$newStart = $mid + 1;
$newEnd = $end;
return binSch($arr, $k, $newStart, $newEnd);
}
}
$arr = array(1,2,4,6,10,40,50,80,100,110);
echo bin_search($arr,80);
//循环方法:
function bin_search($arr,$key) {
$high = count($arr);
if($high <= 0)
return 0;
$low = 0;
while($low <= $high) {
//当前查找区间arr[low..high]非空
$mid=intval(($low + $high) / 2);
if($arr[$mid] == $key)
return $mid; //查找成功返回
if($arr[$mid] > $key)
$high = $mid - 1; //继续在arr[low..mid-1]中查找
else
$low = $mid + 1; //继续在arr[mid+1..high]中查找
}
return 0; //当low>high时表示查找区间为空,查找失败
}
$arr = array(1,2,4,6,10,40,50,80,100,110);
echo bin_search($arr,80);