多种排序算法(php实现)
1.冒泡排序算法
function maopaosort($data){
for ($i = 0; $i < count($data); $i++) {
//对待排序序列进行冒泡排序
//相邻两个数比较,将最大的放到最后面,下一轮循环就不需要循环最后一个最大的数据
for ($j = 0; $j + 1 < count($data) - $i; $j++) {
//相邻元素进行比较,当顺序不正确时,交换位置
if ($data[$j] > $data[$j + 1]) {
$tmp = $data[$j];
$data[$j] = $data[$j + 1];
$data[$j + 1] = $tmp;
}
}
}
return $data;
}
//与第一种相反
function maopaosort($data){
//$data = ['9','4','8','6','5','3',];
//获取data的长度
$len = count($data);
//与上面相反,将最小的放到最前面,下一次循环的时候跳过最小的一个
for($i=0;$i<$len;$i++){
//索引从大的向小的方向,筛选最小的放到最前面
for($j=$len-1;$j-1 >= $i;$j--){
if($data[$j] < $data[$j-1]){
$tmp = $data[$j];
$data[$j] = $data[$j-1];
$data[$j-1] = $tmp;
}
}
}
}
//这个和第一种类似
function maopaosort($data){
$len = count($data);
for ($i = $len-1; $i > 0 ; $i--) {
//索引从小的向大的方向,筛选最大的放到最后面,下次循环跳过最大的数值
for ($j = 0; $j + 1 <= $i; $j++) {
//相邻元素进行比较,当顺序不正确时,交换位置
if ($data[$j] > $data[$j + 1]) {
$tmp = $data[$j];
$data[$j] = $data[$j + 1];
$data[$j + 1] = $tmp;
}
}
}
return $data;
}
2选择排序算法
function ChoiceSort($arr){
//大循环,控制轮数
for ($i=0; $i < count($arr); $i++) {
//定义一个索引锁定为最小值,即为最小值索引
$k = $i;
//从后面的索引里面找到最小的值
for ($j=$i+1; $j < count($arr); $j++) {
if ($arr[$k] > $arr[$j]) {
//如果当前索引的值比后面索引的值大,更换索引
$k = $j;
}
}
//如果索引与最初索引不同,说明最小值已变化,原先的最小索引已变化,最小值另有其值,
//更换最小值与第一个值 ,即将最小值放在第一个位置,之后继续下一次循环
if ($k != $i) {
$tmp = $arr[$i];
$arr[$i] = $arr[$k];
$arr[$k] = $tmp;
}
}
return $arr;
}
3 插入排序算法
function insert($arr){
//插入排序
$arr = array(4,2,6,8,9,5);
//1 确定要插入多少回,(假设一个数组一次性插入到对的位置,同时第一个位置假设是对的)
$len=count($arr);
for($i=1;$i<$len;$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];
//$arr[$j] = $temp;
//说明前面顺序的数组元素有不合适的位置
$change = true;
}else{
//说明当前待插入元素比前面的元素要大,说明位置正确
break;
}
}
//判断位置需要变动,
if($change){
//有数据移动,站错位置了
$arr[$j+1] = $temp;
}
}
}
4 归并排序算法
<?php
$arr1 = array(1,3,5);
$arr2 = array(2,4,6);
$arr3 = array();
dump(array_merge($arr3,$arr2,$arr1));
print_r(merge_sort(array_merge($arr3,$arr2,$arr1)));
function merge_sort($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和$right都没有排好序,而且可能是多个元素的数组
$left = merge_sort($left);
$right = merge_sort($right);
//假设左边和右边已经排好序,二路归并
$m = array();
while (count($left) && count($right)) {
//只要$arr1和$arr2里面还有元素,就进行循环,取出每个数组的第一个元素:进行比较
$m[] = $left[0] < $right[0]?array_shift($left):array_shift($right);
}
//返回结果
return array_merge($m,$left,$right);
}
?>
5 顺序查找算法
//查找算法,顺序查找
//$arr = array(1,3,6,8,23,45,68,100);
function check_order($arr,$num){
//全部匹配
/* $len = count($arr);
for($i = 0;$i<$len;$i++){
//判断
if($arr[$i] == $num){
return $i;
}
}
return false; */
}
6 二分查找算法
$arr = array(1,3,6,8,23,45,68,100);
$res = 100;
var_dump(check_break($arr,$res));
(int)$i = check_break($arr,$res);
dd($i,$arr[$i-1]);
function check_break($arr,$res){
//二分查找算法
//1 得到数组边界
$right = count($arr);
$left = 0;
//2 循环匹配
while ($left <= $right) {
$middle = floor(($right+$left)/2);
if($arr[$middle] == $res){
return $middle+1;
}
if($arr[$middle] < $res){
$left = $middle+1;
}else{
$right = $middle -1;
}
}
return false;
}
7快速排序算法
<?php
$arr = ['6','4','2','5','3','9','7'];
print_r(quick_sort($arr));
//快速排序 ,原理:以第一个为基准数,第一轮从最后向前走,若数据比基准数小,则将数值放到基准数的位置,再从前面往后走,若数据比基准数大,则将数值放到后面基准数的位置,以此类推,直到索引相等或大于,找到基准数的位置,后面的轮循以此类推。
function quick_sort($arr){
//递归出口
$len = count($arr);
if($len <= 1)
return $arr;
//取出某个元素,然后将剩余的数组元素分散到两个不同的数组中
$left = $right = array();
for($i = 1;$i < $len;$i++){
//第一个元素作为比较元素
//比较:小的放left中,大的放right中
if($arr[$i] < $arr[0]){
$left[] = $arr[$i];
}else{
$right[] = $arr[$i];
}
}
//$left和$right 数组元素没有排好序,递归点
$left = quick_sort($left);
$right = quick_sort($right);
//合并三个数组
return array_merge($left,(array)$arr[0],$right);
}
?>
8. 微信红包的随机算法
function randBonus($bonus_total=0, $bonus_count=3, $bonus_type=1){
// $bonus_total 红包总金额
// $bonus_count 红包个数
// $bonus_type 红包类型 1=拼手气红包 0=普通红包
// 将要瓜分的结果
$bonus_items = array();
// 每次分完之后的余额
$bonus_balance = $bonus_total;
//dd($bonus_balance);
// 平均每个红包多少钱
$bonus_avg = number_format($bonus_total/$bonus_count, 2);
$i = 0;
while($i<$bonus_count){
if($i<$bonus_count-1){
// 根据红包类型计算当前红包的金额
$r = mt_rand(0.01, $bonus_balance*100-1)/100;
$rand = $bonus_type?$r:$bonus_avg;
$bonus_items[] = $rand;
$bonus_balance -= $rand;
dump($bonus_items);
echo $bonus_balance.'-------';
echo PHP_EOL;
}else{
// 最后一个红包直接承包最后所有的金额,保证发出的总金额正确
$bonus_items[] = $bonus_balance;
}
$i++;
}
return $bonus_items;
}