使用 PHP 描述选择排序算法

基本思想:在要排序的一组数中,选出最小的一个数(要遍历一下)与第一个位置的数交换;
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

提示:在查找最小元素时,一定要记录下标的位置

<?php
function select(&$arr)
{
    for($i=0; $i<count($arr)-1; ++$i)
    {
        //假设下标为$i的元素就是最小的数
        $min = $arr[$i];
        $minIndex = $i;
        //取得最小的元素及其下标
        for($j=$i+1; $j<count($arr); ++$j)
        {
            if($min>$arr[$j])
            {
                $min = $arr[$j];
                $minIndex = $j;
            }
        }
        // 最后交换
        $temp = $arr[$i];
        $arr[$i] = $arr[$minIndex];
        $arr[$minIndex] = $temp;
    }
    return $arr;
};
$arr = array(12,5,33,78,96,16,8,57,62);
$res = select($arr);
print_r($res);

结果:Array ( [0] => 5 [1] => 8 [2] => 12 [3] => 16 [4] => 33 [5] => 57 [6] => 62 [7] => 78 [8] => 96 )

PHP读取大文件末尾N行的高效方法

小文件几兆以内大小,都可以通过 file() 函数,将文件按行读入数组,在用 array_pop 取得最后一行,就可以了。
但是对于很大的文本文件来说,机器内存不够大,或者 php 本身 memory_limit 有限制,这个办法就不适用了,即使强行不限制,效率也是非常低的。

没有办法了吗?当然有,不过没有现成的函数了,需要自己动手了。

这里需要用到文件指针,通俗的讲吧,PHP 中通过 fopen 打开一个文件,这时候还没有读取文件,这时候指向的是文件开头,指针位置也就是 0,当你通过 fgets 或者 fgetc 从文件中读取内容的时候,你读多少,指针也相应往前进多少,这也是

while(!feof($fp)){
$data.=fgets($fp,4096);
}

得以实现的原理,即 fgets 是从当前指针位置向后读取指定长度的字符串,直到遇见换行符为止。

那么可不可以控制指针的位置到倒数第 N 行位置呢?很遗憾,没有,但是可以将指针直接移动到末尾,并倒退 N 个位置,通过 fseek() 函数。

我们先将指针移动到末尾,并向后倒退 2 个位置,通过 fgetc 读取一个字符,判断这个字符是不是 "\n" 也就是换行符,如果不是换行符,那么继续倒退一个位置再次判断,直到我们倒退到上一行的结尾换行符为止,直接使用 fgets 将一整行都取出来即可。这里面用到两个 while 循环,外层循环控制需要取得的行数,内层循环控制 fseek 动作。

函数如下:

/**
 * 取文件最后$n行
 * @param string $filename 文件路径
 * @param int $n 最后几行
 * @return mixed false表示有错误,成功则返回字符串
 */
function FileLastLines($filename,$n){
    if(!$fp=fopen($filename,'r')){
        echo "打开文件失败,请检查文件路径是否正确,路径和文件名不要包含中文";
        return false;
    }
    $pos=-2;
    $eof="";
    $str="";
    while($n>0){
        while($eof!="\n"){
            if(!fseek($fp,$pos,SEEK_END)){
                $eof=fgetc($fp);
                $pos--;
            }else{
                break;
            }
        }
        $str.=fgets($fp);
        $eof="";
        $n--;
    }
    return $str;
}
echo nl2br(FileLastLines('sss.txt',4));

via: http://www.thinkphp.cn/topic/4127.html

约瑟夫环

是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

要求输入:n,k,m

输出:退出顺序

<?php
//$n 人数 $k 开始位置  $m 要数得数字
function array_f($n,$k,$m){
    for($i=1; $i <= $n ; $i++){
        $oldArr[] = $i;
    }    
    for ($i=0;$i<$k-1;$i++){
        $num = array_shift($oldArr);
        $oldArr[] = $num;
    }
    for($i=0;$i<$n;$i++){
        for($j=0;$j<$m-1;$j++){
            $num = array_shift($oldArr);
            $oldArr[] = $num;
        }
        $newArr[] = array_shift($oldArr);
    }
    var_dump($newArr);
}
array_f(6,2,3);

 

使用 PHP 实现冒泡排序,将数组 $a=array() 安装从小到大的方式进行排序

在要排序的一数组中,对当前还未排序好的范围内的全部数,自前向后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的数往上冒。

即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将他们互换。

<?php
$arr = [1,43,6,7,3,5,78];
function bubbleSort ($arr) {
    $num = count($arr);
    $temp;
    for ($i=0; $i<$num-1; $i++){
        for ($j=0; $j<$num-1-$i; $j++){
            if ($arr[$j] > $arr[$j+1]){
                $temp = $arr[$j];
                $arr[$j] = $arr[$j+1];
                $arr[$j+1] = $temp;
            }
        }
    }
    return $arr;
}
print_r (bubbleSort($arr));

 

使用 PHP 秒速快速排序算法

基本思想:选择一个基准元素,通常选择第一个元素,通过一趟扫描,将待排序列分为两个部分,一部分比基准元素小(做数组),一部分大于等于基准元素组(右数组),此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

可以看到,这种方法是把大问题转变为小问题的方法,使用递归实现。

image

<?php
//递归函数的特点有两个
//1.要有递归出口,应该放到递归函数的最前面
//2.要有递归调用
function quick sort ($arr) {
    //递归出口判断要放在最前面
    if (count($arr) <= 1){
        return $arr;
    }
    //把第一个元素从数组中弹出去放在一个变量中
    $key = array_shift($arr);
    //把刚才弹出的第一个元素(基准元素)存到一个数组中
    $key_arr = array($key);
    //定义两个空数组,给左边和右边的数组进行初始化。
    $left_arr = array();
    $right_arr = array();
    foreach ($arr as $value){
        if($value < $key){
            $left_arr[] = $value;
        }else{
            $right_arr[] = $value;
        }
    }
    //这里就是递归调用
    return array_merge(quick_sort($left_arr), $key_arr, quick_sort($right_arr));
}