插入排序
思想:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。
function insertSort($arr){ $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--; } } return $arr; }
希尔排序
思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
function shellSort($arr){ $count=count($arr); $step=floor($count/2); while($step>=1){ for($i=$step;$i<$count;$i++){ $temp=$arr[$i]; $j=$i-$step; while($j>=0 && $arr[$j]>$temp){ $arr[$j+$step]=$arr[$j]; $j-=$step; } $arr[$j+$step]=$temp; } $step=floor($step/2); } return $arr; }
简单选择排序
思想:在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
function selectSort($arr){ $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; }
冒泡排序
思路:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
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)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
function quickSort($arr) { //先判断是否需要继续进行 $count = count($arr); if($count <= 1) { return $arr; } //选择第一个元素作为基准 $base_num = $arr[0]; //遍历除了标尺外的所有元素,按照大小关系放入两个数组内 //初始化两个数组 $left_array = array(); //小于基准的 $right_array = array(); //大于基准的 for($i=1; $i<$count; $i++) { if($base_num > $arr[$i]) { //放入左边数组 $left_array[] = $arr[$i]; } else { //放入右边 $right_array[] = $arr[$i]; } } //再分别对左边和右边的数组进行相同的排序处理方式递归调用这个函数 $left_array = quickSort($left_array); $right_array = quickSort($right_array); //合并 return array_merge($left_array, array($base_num), $right_array); }
归并排序
归并(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);
二分法查找
前提:查找数组必须是有序的
function bsearch($v, $arr){ $low = 0; $high = count($arr)-1;// 使用下标,注意减去1 // 注意凡是使用到while的时候,一定要防备无限循环的时候,注意终止循环的判断。 while($low <= $high){// 比如$low<=$high,这个等于号必须有。 $i = intval(($high + $low)/2); if ($arr[$i] > $v){ $high = $i-1; } else if ($arr[$i] < $v){ $low = $i+1; } else { return $i; } } return -1;// 找不到的时候返回-1 } echo bsearch(13, $arr);// 5