一些有趣的排序 及优化 php

<?php


比较多全面   有点小bug  不喜勿喷 

/*
*1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。


/**
 * 冒泡排序
 **/
echo "冒泡排序";
echo "<br/>";
function main($array) {
$length = count($array);   //6       循环次数(n-1)^2

for ($i = 0; $i < $length; $i++) {
for ($j = 1; $j < $length - $i; $j++) {
if ($array[$j - 1] > $array[$j]) {
$temp = $array[$j - 1];
$array[$j - 1] = $array[$j];
$array[$j] = $temp;
}
}
}
return $array;
}
$array = array(1, 4, 3, 6, 2, 5);
print_r(main($array));
echo "<br/>";
/**
 * 优化的冒泡排序  
 **/
function main1($array) {
$length = count($array);
while ($length > 0) {
$p = $length;
$length = 0;
for ($j = 1; $j < $p; $j++) {
if ($array[$j - 1] > $array[$j]) {
$temp = $array[$j - 1];
$array[$j - 1] = $array[$j];
$array[$j] = $temp;
$length = $j;
}
}
}
return $array;
}
$array = array(1, 4, 3, 6, 2, 5);
print_r(main1($array)); 


// //冒泡排序(优化过的)  
// function maopao($arr)  
// {   
// $len = count($arr);   
// for($i=1; $i<$len; $i++)
// //最多做n-1趟排序  
//  {   
//   $flag = false;    
//   //本趟排序开始前,交换标志应为假    
//   for($j=$len-1;$j>=$i;$j--)    
//   {     
//   if($arr[$j]<$arr[$j-1])
//   //交换记录     
//   {
//   //如果是从大到小的话,只要在这里的判断改成
//   if($arr[$j]>$arr[$j-1])
//   //就可以了  


//   $x=$arr[$j];      
//   $arr[$j]=$arr[$j-1];      
//   $arr[$j-1]=$x;      
//   $flag = true;
//   //发生了交换,故将交换标志置为真     
//   }    
//   }    
//   if(!$flag)
//   //本趟排序未发生交换,提前终止算法(未交换就证明已经排序好了)    
//    return $arr;     
//     }  
// }  
// $shuz = array('2','4','1','8','5'); 
//  $bb = maopao($shuz); 
//   print_r($bb);
// echo "<hr/>";
// echo "选择排序";
// function swap(array &$arr, $a, $b){
//     $temp = $arr[$a];
//     $arr[$a] = $arr[$b];
//     $arr[$b] = $temp;
// }


// function selectSort(array &$arr){
//     $count = count($arr);
//     for ($i = 0; $i < $count; $i++){
//         $min = $i;
//         for ($j = $i + 1; $j < $count; $j++){
//             if ($arr[$min] > $arr[$j]){
//                 $min = $j;
//             }
//         }


//         if ($min != $j){
//             swap($arr, $min, $i);
//         }
//     }
// }


// $arr = array(9, 1, 5, 8, 3, 7, 4, 6, 2);
// selectSort($arr);
// echo "<pre>";
// print_r($arr);
// echo "</pre>";
function xrange()
{
    while (1) {


        $a = (yield '11'); //yield 表达式
        echo $a;
    }
}




$a = xrange();//返回一个生成器


echo $a->current();//返回当前产生的值


echo '<br>';


$a->send('33');//向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。


echo '<br>';


echo $a->current();


echo '<br>';


$a->send('22');


echo '<br>';


echo $a->current();
echo '<br>';
function one($number)
{
for($i=0;$i<$number;$i++){
    //生成器yield关键字不是返回值,他的专业术语叫产出值,只是生成一个值
        yield time();
    }
}


     
  header("content-type:text/html;charset=utf-8");    
    $arr = array(3,5,8,7,4,9,9,6,6,1,7,2);    
    echo implode(" ",$arr)."<br/>";    
    //---------------------------------------    
    //       常用排序算法    
    //---------------------------------------    
    //冒泡      
    function BubbleSort($arr)      
    {        
      $len=count($arr);      
      //设置一个空数组 用来接收冒出来的泡      
      //该层循环控制 需要冒泡的轮数      
      for($i=1;$i<$len;$i++)      
      { //该层循环用来控制每轮 冒出一个数 需要比较的次数      
        for($k=0;$k<$len-$i;$k++)      
        {      
           if($arr[$k]>$arr[$k+1])      
            {      
                $tmp=$arr[$k+1];      
                $arr[$k+1]=$arr[$k];      
                $arr[$k]=$tmp;      
            }      
        }      
      }      
      return $arr;      
    }       
    echo '冒泡排序:';    
    echo implode(' ',BubbleSort($arr))."<br/>";    
         
    //快速排序    
    function QSort($arr) {      
        //先判断是否需要继续进行      
        $length = count($arr);      
        if($length <= 1) {      
            return $arr;      
        }      
        //如果没有返回,说明数组内的元素个数 多余1个,需要排序      
        //选择一个标尺      
        //选择第一个元素      
        $base_num = $arr[0];      
        //遍历 除了标尺外的所有元素,按照大小关系放入两个数组内      
        //初始化两个数组      
        $left_array = array();//小于标尺的      
        $right_array = array();//大于标尺的      
        for($i=1; $i<$length; $i++) {      
            if($base_num > $arr[$i]) {      
                //放入左边数组      
                $left_array[] = $arr[$i];      
            } else {      
                //放入右边      
                $right_array[] = $arr[$i];      
            }      
        }      
        //再分别对 左边 和 右边的数组进行相同的排序处理方式      
        //递归调用这个函数,并记录结果      
        $left_array = QSort($left_array);      
        $right_array = QSort($right_array);      
        //合并左边 标尺 右边      
        return array_merge($left_array, array($base_num), $right_array);      
    }      
    echo "快速排序:";    
    echo implode(' ',QSort($arr))."<br/>";    
         
    //选择排序    
    function SelectSort($arr) {      
    //实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数      
        //$i 当前最小值的位置, 需要参与比较的元素      
        for($i=0, $len=count($arr); $i<$len-1; $i++) {      
            //先假设最小的值的位置      
            $p = $i;      
            //$j 当前都需要和哪些元素比较,$i 后边的。      
            for($j=$i+1; $j<$len; $j++) {      
                //$arr[$p] 是 当前已知的最小值      
                if($arr[$p] > $arr[$j]) {      
         //比较,发现更小的,记录下最小值的位置;并且在下次比较时,      
     // 应该采用已知的最小值进行比较。      
                    $p = $j;      
                }      
            }      
            //已经确定了当前的最小值的位置,保存到$p中。      
     //如果发现 最小值的位置与当前假设的位置$i不同,则位置互换即可      
            if($p != $i) {      
                $tmp = $arr[$p];      
                $arr[$p] = $arr[$i];      
                $arr[$i] = $tmp;      
            }      
        }      
        //返回最终结果      
        return $arr;      
    }      
    echo "选择排序:";    
    echo implode(' ',SelectSort($arr))."<br/>";    
         
    //插入排序    
    function InsertSort($arr) {      
        //区分 哪部分是已经排序好的      
        //哪部分是没有排序的      
        //找到其中一个需要排序的元素      
        //这个元素 就是从第二个元素开始,到最后一个元素都是这个需要排序的元素      
        //利用循环就可以标志出来      
        //i循环控制 每次需要插入的元素,一旦需要插入的元素控制好了,      
        //间接已经将数组分成了2部分,下标小于当前的(左边的),是排序好的序列      
        for($i=1, $len=count($arr); $i<$len; $i++) {      
            //获得当前需要比较的元素值。      
            $tmp = $arr[$i];      
            //内层循环控制 比较 并 插入      
            for($j=$i-1;$j>=0;$j--) {      
       //$arr[$i];//需要插入的元素; $arr[$j];//需要比较的元素      
                if($tmp < $arr[$j]) {      
                    //发现插入的元素要小,交换位置      
                    //将后边的元素与前面的元素互换      
                    $arr[$j+1] = $arr[$j];      
                    //将前面的数设置为 当前需要交换的数      
                    $arr[$j] = $tmp;      
                } else {      
                    //如果碰到不需要移动的元素      
               //由于是已经排序好是数组,则前面的就不需要再次比较了。      
                    break;      
                }      
            }      
        }      
        //将这个元素 插入到已经排序好的序列内。      
        //返回      
        return $arr;      
    }      
    //var_dump(InsertSort($arr));    
    echo '插入排序:';    
    echo implode(' ',InsertSort($arr))."<br/>"; 
    /**基数排序**/


/*
* 获取第几位上的数字
*
*百位数 = 2345%1000/100
*/
function getN($num,$N){
    $value = 10;
    for($i=1;$i<$N;$i++){
        $value = $value * 10; 
    }


    $M = (int)(($num % $value /($value/10)));
    return $M;
}
/*
*/
function paixu($arr)
{
    $flag = 1;//该次位数上是否全为0标志位,全为0 flag=0
    for($M=1;$flag!=0;$M++)
    {
        $flag = 0;


        if($M > 1){
            $m = 0; 
            for($j=0;$j<10;$j++){
                for($k=0;$k<count($b[$j]);$k++){
                    if($b[$j][$k]!=0)
                    $arr[$m++] = $b[$j][$k];//将容器中的数按序取出,进行下一次排序
                }


            }
            $b = array();//再给b附新值前要清空数组中原有的数据
        }


        for($i=0;$i<count($arr);$i++)
        {
            $thisNum = getN($arr[$i],$M);
            if($thisNum!=0) $flag = 1;
            $b[$thisNum][] = $arr[$i];//将数组中的数放入容器中


        }


    }
    //print_r($arr);
    return $arr;
    //var_dump($b);


}
//print_r(paixu(array(65,3,45,6,7,8,31,100,1000,1234)));
    echo '基数排序:';    
    echo implode(' ',paixu($arr))."<br/>"; 
/**基数排序**结束**/ 




//堆排序(对简单选择排序的改进)


function swap(array &$arr,$a,$b){
    $temp = $arr[$a];
    $arr[$a] = $arr[$b];
    $arr[$b] = $temp;
}


//调整 $arr[$start]的关键字,使$arr[$start]、$arr[$start+1]、、、$arr[$end]成为一个大根堆(根节点最大的完全二叉树)
//注意这里节点 s 的左右孩子是 2*s + 1 和 2*s+2 (数组开始下标为 0 时)
function HeapAdjust(array &$arr,$start,$end){
    $temp = $arr[$start];
    //沿关键字较大的孩子节点向下筛选
    //左右孩子计算(我这里数组开始下标识 0)
    //左孩子2 * $start + 1,右孩子2 * $start + 2
    for($j = 2 * $start + 1;$j <= $end;$j = 2 * $j + 1){
        if($j != $end && $arr[$j] < $arr[$j + 1]){
            $j ++; //转化为右孩子
        }
        if($temp >= $arr[$j]){
            break;  //已经满足大根堆
        }
        //将根节点设置为子节点的较大值
        $arr[$start] = $arr[$j];
        //继续往下
        $start = $j;
    }
    $arr[$start] = $temp;
}


function HeapSort(array &$arr){
    $count = count($arr);
    //先将数组构造成大根堆(由于是完全二叉树,所以这里用floor($count/2)-1,下标小于或等于这数的节点都是有孩子的节点)
    for($i = floor($count / 2) - 1;$i >= 0;$i --){
        HeapAdjust($arr,$i,$count);
    }
    for($i = $count - 1;$i >= 0;$i --){
        //将堆顶元素与最后一个元素交换,获取到最大元素(交换后的最后一个元素),将最大元素放到数组末尾
        swap($arr,0,$i);  
        //经过交换,将最后一个元素(最大元素)脱离大根堆,并将未经排序的新树($arr[0...$i-1])重新调整为大根堆
        HeapAdjust($arr,0,$i - 1);
    }
}


$arr = array(4,1,5,9,8,5,4,6,33,5,2,6);
HeapSort($arr);
var_dump($arr);


?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值