插入排序
1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前比较
3.如果该元素(已排序)大于新元素,将该元素移到下一位置
/**
* 插入排序
*/
public function Insert_sort($arr=array(5,2,7,1,3)){
$count=count($arr);
for($i=1;$i<$count;$i++){
$j=$i-1;
$temp=$arr[$i]; //临时比较元素
while($j>=0){ //从后往前逐个比较元素大小
if($arr[$j]>$temp){ //临时比较元素比较小则交换前后元素位置
$arr[$j+1]=$arr[$j];
$arr[$j]=$temp;
}
$j--;
}
var_dump($arr);echo "<br>";
}
return $arr;
}
简单选择排序
思想:
1)循环n次,每次找到最小的元素进行元素交换 。
/**
* 简单排序
* 循环n次,每次找到最小的元素进行元素交换
*/
public function Select($arr=array(2,16,8,6,3,19)){
$count=count($arr);
for($i=0;$i<=$count;$i++){
$min=$i;
for($j=$i+1;$j<$count;$j++){ //从未比较的元素开始循环
if($arr[$j]<$arr[$min]){
$min=$j; //比较到小元素则记录其下标
}
}
if($min!=$i){ //使用临时变量交换最小元素
$temp = $arr[$min];
$arr[$min] = $arr[$i];
$arr[$i] = $temp;
}
}
return $arr;
}
冒泡排序
思路:
1)第一次循环控制循环次数,数组长度n-1次(最坏的结果是比较n-1次才出结果)
2)第二次循环比较数组的每个元素,后一位元素比前一位元素小则交换位置(需要一个临时变量$tmp)
function bubbleSort($arr){
$count=count($arr);
#对于一个长度为N的数组,我们需要排序 N-1 轮,每 i 轮 要比较 N-i 次。对此我们可以用双重循环语句,外层循环控制循环轮次,内层循环控制每轮的比较次数。
for($i=1;$i<$count;$i++){
for($k=0;$k<$count-$i;$k++){
if($arr[$k]>$arr[$k+1]){
$tmp=$arr[$k+1];
$arr[$k+1]=$arr[$k];
$arr[$k]=$tmp;
}
}
}
return $arr;
}
快速排序
思路:
1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
2)通过一趟排序讲待排序的记录分割成独立的两个数组,其中小数组记录的元素值均比基准元素值小,大数组记录的 元素值比基准值大。
3)然后同样的方法递归大、小数组进行排序,直到整个序列有序。
4)最后合并小数组、基准元素、大数组。
/**
* 快速排序
*/
public function Quick_sort($arr = array(50, 43, 54, 62, 21, 66, 32, 78, 36, 76, 39,2)){
//判断参数是否是一个数组
if(!is_array($arr)) return false;
//递归出口:递归至数组长度为1,则返回数组
$length = count($arr);
if($length<=1) return $arr;
//数组元素有多个,则定义两个空数组
$left = array();
$right = array();
//使用for循环遍历数组
for($i=1; $i<$length; $i++) {
$value = $arr[0] ; //把 第一个元素 当做 比较对象
if($arr[$i] < $value){
$left[]=$arr[$i]; //小于 比较对象放入 $left 数组
}else{
$right[]=$arr[$i]; //大于 比较对象放入 $right 数组
}
}
//不断递归 $left、$right数组知道数组长度为1
$left = $this->Quick_sort($left);
$right = $this->Quick_sort($right);
//将所有的结果合并
return array_merge($left,$value,$right);
}
归并排序
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。
/**
* mergeSort 归并排序
* 是开始递归函数的一个驱动函数
* @param &$arr array 待排序的数组
*/
function mergeSort(&$arr) {
$len = count($arr);//求得数组长度
mSort($arr, 0, $len-1);
}
/**
* 实际实现归并排序的程序
* @param &$arr array 需要排序的数组
* @param $left int 子序列的左下标值
* @param $right int 子序列的右下标值
*/
function mSort(&$arr, $left, $right) {
if($left < $right) {
//说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
//计算拆分的位置,长度/2 去整
$center = floor(($left+$right) / 2);
//递归调用对左边进行再次排序:
mSort($arr, $left, $center);
//递归调用对右边进行再次排序
mSort($arr, $center+1, $right);
//合并排序结果
mergeArray($arr, $left, $center, $right);
}
}
/**
* 将两个有序数组合并成一个有序数组
* @param &$arr, 待排序的所有元素
* @param $left, 排序子数组A的开始下标
* @param $center, 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
* @param $right, 排序子数组B的结束下标(开始为$center+1)
*/
function mergeArray(&$arr, $left, $center, $right) {
//设置两个起始位置标记
$a_i = $left;
$b_i = $center+1;
while($a_i<=$center && $b_i<=$right) {
//当数组A和数组B都没有越界时
if($arr[$a_i] < $arr[$b_i]) {
$temp[] = $arr[$a_i++];
} else {
$temp[] = $arr[$b_i++];
}
}
//判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:
while($a_i <= $center) {
$temp[] = $arr[$a_i++];
}
//判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:
while($b_i <= $right) {
$temp[] = $arr[$b_i++];
}
//将$arrC内排序好的部分,写入到$arr内:
for($i=0, $len=count($temp); $i<$len; $i++) {
$arr[$left+$i] = $temp[$i];
}
}
//do some test:
$arr = array(4, 7, 6, 3, 9, 5, 8);
mergeSort($arr);
print_r($arr);
二分法查找
前提:查找数组必须是有序的
1)获取并记录数组上限、下限、中间下标;
2)用中间下标值与目标值进行比较,如果:
①目标值 < 中间值 ,上限减1,并改变对应中间下标;
②目标值 > 中间值 ,下限加1,并改变对应中间下标;
③目标值 = 中间值,匹配成功
/**
* 二分查找法
* 使用前提是有序数组
*/
public function binarySearch($value = 22, $arr = array(3, 4, 6, 7, 9, 16, 22) ){
$low = 0; //数组下限下标
$high = count($arr)-1; //数组上限下标
// 注意凡是使用到while的时候,一定要防备无限循环的时候,注意终止循环的判断。
while($low <= $high){
//获取中间比较的中间下标(强制整形)
$middle = intval(($low + $high)/2);
if($value < $arr[$middle]){ //目标值 < 中间值 ,上限减1
$high = $middle - 1;
}elseif ($value > $arr[$middle]){ //目标值 > 中间值 ,下限加1
$low = $middle + 1;
}else{
return $middle; //目标值 = 中间值,匹配成功返回下标值
}
}
return -1;
}