算法游戏

排序算法:随机法  分治法  贪心法

http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html

插入排序(根据元素找位置)
冒泡排序(两两比较)
快速排序 (中位数)
选择排序(根据位置找元素)

堆排序(左平衡二叉树)
桶排序(key是值 value是个数,循环获取)

归并算法排序(两两分成单个元素拼合成有序集)
基数排序(按位比较)
计数排序(统计元素个数,次第相加,由索引排位)
希尔排序(按照固定间隔取数,分成多个小组,然后合并,最后间隔必须是1) 
-------------------------------------------------------------------------------------------
查找算法:二分查找、顺序查找|循序搜寻法、插捕搜寻法(分布平均的数组高效)
其它算法:牛年求牛 分苹果 猴子代王 | 菱形 杨辉三角 | 斐波那契数列、线性表删除、汉诺塔算法
哈希算法:简单哈希 一致性哈希 拉链法哈希
字符处理:数据切分,出现次数,排列组合,数据组合 破解密码 字符相似 +数字转成汉字
内置函数:合并数组 字符查找 字符长度 字符翻转 字符删除/插入/截取 字符比较 字符复制 字符连接 字符编码解码/加密解密 字符替换 截取 

 */


一.使用:牛年求牛 分苹果 猴子代王 |  菱形 杨辉三角 | 斐波那契 线性表删除

//2.牛年求牛:有一母牛,到4岁可生育,每年一头,所生均是一样的母牛,到15岁绝育,不再能生,20岁死亡,问n年后有多少头牛


[php] view plaincopy

//静态变量,循环中数值不变 | 递归是在判断内实现的 |区分年份和数目

function niunum($n) {  

static $num = 1;  

for ($i = 1; $i <= $n; $i++) {  

   if ($i >= 4 && $i < 15) {  //生育期才计算

    $num++;  

    niunum($n - $i);            //抛去计算了生育期的牛

   }  

   if ($i == 20) $num--;  

}  

return $num;  

}  

echo niunum(10);  


2. 有5个人偷了一堆苹果,准备在第二天分赃。晚上,有一人遛出来,把所有菜果分成5份,但是多了一个,顺手把这个扔给树上的猴了,自己先拿1/5藏了。

   没想到其他四人也都是这么想的,都如第一个人一样分成5份把多的那一个扔给了猴,偷走了1/5。

   第二天,大家分赃,也是分成5份多一个扔给猴了。最后一人分了一份。问:共有多少苹果?

for($i=0;;$i++){

if($i%5 == 1){

$t = $i- round($i/5) -1;

if($t%5 ==1){

$s = $t - round($t/5) -1;


if($s%5 == 1){

$x = $s-round($s/5) -1;


if($x % 5 ==1){

$o = $x - round($x/5) -1;


if($o % 5 ==1){

$la = $o - round($o/5) -1;


if($la % 5 ==1){

echo $i;

break;

}

}


}

}

}

}

}


3.一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,

如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。


function king($n,$m) {


$monkeys = range(1,$n);


$i = 0;


while(count($monkeys) > 1) {        //每个循环要算一回


if(($i+1)%$m == 0) {    //与monkey共用的$i,所以要加1,保持monkey的索引i是从1开始的

unset($monkeys[$i]);


} else {

//不是,放尾部,从下一个开始循环,被踢的猴子会消失,等于位子没有变化,就是排序了

array_push($monkeys,$monkeys[$i]);


unset($monkeys[$i]);


}


$i++;


}

//获取当前猴子的位子

return current($monkeys);


}


$king = king(100,7);


print_r($king);


4. 用符号*画一个菱形图案.


for($i=0;$i<4;$i++){                    //行数


for($j=0;$j<3-$i;$j++){         //空格数


echo '&nbsp;';


}


for($k=0;$k<$i+1;$k++){         //星星数


echo '* ';


}


echo "<br/>";


}


for($i=0;$i<3;$i++){

for($j=0;$j<$i+1;$j++){

echo '&nbsp;';

}


for($k=0;$k<3-$i;$k++){

echo '* ';

}

echo '<br/>';

}


//6.杨辉三角


[php] view plaincopy


$n=10;

for($i=0;$i<$n;$i++){               //行

for($k=$n;$k>$i;$k--){                     //由多到少,递减,--

   echo '&nbsp;';

}


for($j=0;$j<=$i;$j++){//列

   

  

   if($j==0||$i==$j){   //两边都是 1


$arr[$i][$j]=1;


   }else {


$arr[$i][$j]=$arr[$i-1][$j]+$arr[$i-1][$j-1];//上一行的两个相邻数据相加算数


   }

   

echo $arr[$i][$j]."\t";

}


echo "<br>";


//6.实现斐波那契数列,格式为:1,1,2,3,5,8…即当前数字为前两个数字之和.

function feibolaqi($num) {

$arr = array();

for($i=0;$i<=$num;$i++) {

if($i == 1 || $i == 2) {

$arr[$i-1] = 1;

} else {

$arr[$i-1] = $arr[$i-2] + $arr[$i-3];

}

}

return $arr;

}

var_dump(feibolaqi(10));


//线性表的删除(数组中实现)  

function delete_array_element($array, $i) {  

$len = count($array);  

    for ($j=$i; $j<$len; $j++){  //直接从要找的点开始了

   @$array[$j] = $array[$j+1];  

}  

    array_pop($array); //删除最后空元素  

    return $array;  

}  

print_r(delete_array_element(array(1,2,3,4,5), 2));    


*

 * 

 */


/*

三.数组转化:数据切分,出现次数,排列组合,数据组合  +字符相似 用户密码  数字转成汉字


//8.把数组array(12,34,56,32) 转化为 array(1,2,3,4,5,6,3,2)


function changeArr($arr) {  

return str_split(implode('', $arr),1);  //str_split(str,num);

}  

print_r(changeArr(array(12,34,56,32)));  


//已知字符串 $string = "2dsjfh87HHfytasjdfldiuuidhfcjh";找出 $string 中出现次数最多的所有字符。


//1  

$string = "2dsjfh87HHfytasjdfldiuuidhfcjh";

$b = array_count_values(str_split($string));  //array_count_values

print_r(array_keys($b, max($b)));  

//2  暂时忽略

$re = count_chars($string, 1);  

print_r(array_map("chr", array_keys($re, max($re))));  

echo "<br />";  


1. 有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?


<?php

$num = 0;


for($i=1;$i<=4;$i++){

for($j=1;$j<=4;$j++){

for($k=1;$k<=4;$k++){

if($i!=$j && $i!=$k && $k!=$j)  //!=

$num++;

echo $i.$j.$k.'<br>';

}

}

}


echo $num;


?>


字符:0-9 或 a-z

长度:1

那就生成0,1,2,3,4,5,6,7,8,9 

长度:2,就会生成00-99


function echoStr($str,$n){

$len = strlen($str);

$string = '';

for($i=0;$i<$len;$i++){

for($j=1;$j<=$n;$j++){

$string .= $str[$i];

}

$string .= ',';

}

echo substr($string,0,-1);

}


$str = 'abcdefghi';

echoStr($str,3);


//顺序是从大到小排列的,cost是0就把左上角的拽下来,不然就比较i和j相邻的两个加1后的值,取小的,比较相同值,然后取最小值


                                        v0 v1

    G U M B O

  0 1 2 3 4 5

G 1 0 1 2 3 4

A 2 1 1 2 3 4

M 3 2 2 1 2 3

B 4 3 3 2 1 2

O 5 4 4 3 2 1

L 6 5 5 4 3 2


7.给两个字符串s1,s2,定义字符串之间的距离d(s1,s2)为通过如下操作使两个字符串一样的最少次数;

链接:http://blog.jobbole.com/80659/

1.替换其中一个字符

2.删除一个字符

3.插入一个字符

例如:kooxoo.com与kooxoo.cn的距离为2,12344与1244的距离为1,给出任意两个字符串,求其距离,要求给出算法并分析时间复杂度

echo levenshtein('kooxoo.com', 'kooxoo.cn');  

echo "<br />";  

function levdis($s,$t){  

    $n=strlen($s);  

    $m=strlen($t);  

    $matrix=array(range(0,$n+1),range(0,$m+1));  


    if ($n==0){  

        return $m;  

    }  

    elseif ($m==0){  

        return $n;  

    }  

    for ($i=0;$i<=$n;$i++) {  

        $matrix[$i][0]=$i;  //行

    }  


    for ($j=0;$j<=$m;$j++) {  

        $matrix[0][$j]=$j;  //列

    }  

                            


    for ($i=1;$i<=$n;$i++) {  

        for ($j=1;$j<=$m;$j++) {  

            if ($s[$i-1]==$t[$j-1]) {  

                $cost=0;  

            }else{  

                $cost=1;  

            }  

           $matrix[$i][$j]=min($matrix[$i-1][$j]+1, $matrix[$i][$j-1]+1, $matrix[$i-1][$j-1]+$cost);  


        }  

    }  

    return $matrix[$n][$m];  

}  

echo levdis('kooxoo.com', 'kooxoo.cn');  

 

//1. 用户密码六位数,数字值正则为[0-9],请用PHP写出有几种可能性,并做暴力破解;

  思想:二分查找

$start = 0;

$end = 999999;

function depwd($pwd,$start,$end){  depwd($pwd,$start,$end) 起始可循环

static $i = 0;

$half = ceil(($start+$end)/2);

if($pwd == $half){

echo $i.'<br>';

echo $pwd;

 }else if($pwd < $half){

 $i++;

depwd($pwd,0,$half);

 }else if ($pwd > $half){

 $i++;

depwd($pwd,$half,$end);

 }

}

depwd('345678',$start,$end);


//9.把数字1-1亿换成汉字表述,如:123->一百二十三


function num2char($num){

//正负数 

//整数(单位(0没单位 00没汉子 %4有单位,如是0换位))和小数(递归) 

error_reporting(0);

$cha = array('零','一','二','三','四','五','六','七','八','九',);

$dw = array('','十','百','千','','万','亿','兆',);

$prefix = '';

//正负数

if($num<0) {

$num=abs($num);

$prefix = '负';

}


//整数和小数

if($num>1){

$mode = true;//小数没有单位,

$pos = strpos($num,'.');

$int = substr($num,0,$pos);

$decimal = substr($num,$pos);

if(!empty($decimal)){

$dian = '点';

$rev = $dian.num2char($decimal);

}


$num = $int;

}

if($num !== ''){

if($num<1) 

{

$num = substr($num,strpos($decimal,'.')+1);

$mode = false;

}


$str = strrev($num);

$len = strlen($str);

for($i=0; $i<$len; $i++){

@$out[$i] = $cha[$str[$i]];


if($mode){  //单个0没单位  连续0没汉字  高位0有

$out[$i] .= ($str[$i]==0)?'':$dw[$i%4]; //单个0 没单位


if($str[$i]+$str[$i-1] == 0) $out[$i]=''; //连续0不显示 零


if($i%4 == 0){


if($str[$i] == 0)  //如果是0,那么单位在前面,


$out[$i] = $dw[floor($i/4)+4].$out[$i]; //万亿兆


else


$out[$i] .= $dw[floor($i/4)+4]; //万亿兆

}


}


}


var_dump($out);


$re = join('',array_reverse($out)).$rev;


}


return $prefix.$re;

}


$re = num2char('-203003.42343256');//负二亿 零万 三千零三点四二三四三


echo $re;


function num2char($num,$mode=true){


    $char = array('零','一','二','三','四','五','六','七','八','九');


    $dw = array('','十','百','千','','万','亿','兆');


    $dec = '点';  //$dec = '點';


    $retval = '';


    if($mode){


        preg_match_all('/^0*(\d*)\.?(\d*)/',$num, $ar);


    }else{


        preg_match_all('/(\d*)\.?(\d*)/',$num, $ar);


    }


    if($ar[2][0] != ''){


        $retval = $dec . num2char($ar[2][0],false); //如果有小数,先递归处理小数


    }


    if($ar[1][0] != ''){


        $str = strrev($ar[1][0]);


        for($i=0;$i<strlen($str);$i++) {


            $out[$i] = $char[$str[$i]];


            if($mode){


                @$out[$i] .= $str[$i] != '0'? $dw[$i%4] : '';


                if($str[$i]+$str[$i-1] == 0){


                    $out[$i] = '';


                }


                if($i%4 == 0){


                    $out[$i] .= $dw[4+floor($i/4)];


                }


            }


        }


        $retval = join('',array_reverse($out)) . $retval;


    }


    return $retval;


}


echo num2char(999999999999.945436369); 


//数据压缩和解压

function zipNum($str){

static $out;//静态,如果不是静态,递归只保留第一回的

    $len = strlen($str);


    for($i=0;$i<$len;$i++){

        if( $str[$i] != $str[$i+1]){


            $out .= $str[$i].($i+1);

            $str = substr($str,$i+1);

            zipNum($str);//递归

return $out; //回归


        }


    }


}


$str = 'ABCDDFF';


//echo zipNum($str);


function tarNum($str){


$len = strlen($str);

$out = '';


for($i=1;$i<$len;$i++){


if(is_int(intval($str[$i]))){


@$out .= str_repeat($str[$i-1],$str[$i]);


}

}


return $out;

}


$str = 'ABCDDFF';

$zip = zipNum($str);

echo $zip; //A1B1C1D2F2

$tar = tarNum($zip);

echo $tar; //ABCDDFF



*/

/*


// 四.PHP内置字符串函数实现  $str[$i],这种思想很重要的, 原理+算法+计数

合并数组  字符长度 字符翻转  字符删除/插入/截取/查找 字符比较 字符复制  字符连接 字符编码解码/加密解密 


//合并多个数组,不用array_merge(),思路:遍历每个数组,重新组成一个新数组。

function unionArray($a, $b) {  

$re = array();  

foreach ($a as $v) $re[] = $v;  

foreach ($b as $v) $re[] = $v;  

return $re;  

}  

print_r(unionArray(array(1,2,4,5,'s'), array(2,5,7,'c','d')));  


//字符串长度,每个计数 

function strlen ($str)  

{  

        if ($str == '' ) return 0;  

        $count =  0;  

        while (1){  

                if ( $str[$count] != NULL){  

                         $count++;  

                        continue;  

                }else{  

                        break;  

                }  

        }  

        return $count;  

}  


//字符串翻转  反向循环

function strrev($str)  

{  

        if ($str == '') return 0 ;  

        for ($i=(strlen($str)- 1); $i>=0; $i --){  

                $rev_str .= $str[$i];  

        }  

        return $rev_str;  

}  


//删除一段字符串  ,两端字符串连接 

function str_delete($str , $i, $j)  

{  

        for ( $c=0; $c<$i;  $c++){  

                $startstr .= $str [$c];  

        }  


        for ($c=( $i+$j); $c<strlen ($str); $c++){  

                $laststr  .= $str[$c];  

        }  

         $str = ($startstr . $laststr );  

        return $str;  

}  


//插入一段字符串 ,分段连接

function str_insert($str, $i , $substr)  

{  

        for($j=0 ; $j<$i; $j ++){  

                $startstr .= $str[$j ];  

        }  


        for ($j=$i; $j <strlen($str); $j ++){  

                $laststr .= $str[$j ];  

        }  


        $str = ($startstr . $substr  . $laststr);  

        return $str ;  

}  


//字符串比较 ,先比长度,后每个字符比较

function strcmp($s1,  $s2)  

{  

        if (strlen($s1) <  strlen($s2)) return -1 ;  

        if (strlen($s1) > strlen( $s2)) return -1;  

 

        for ($i =0; $i<strlen($s1 ); $i++){  

                if ($s1[$i] == $s2[$i]){  

                        continue;  

                }else{  

                        return false;  

                }  

        }  

        return  1;  

}  


//复制字符串  s1的逐个给s2,就相同了

function strcpy($s1, $s2 )  

{  

        if (strlen($s1)==NULL || !isset( $s2)) return;  

        for ($i=0 ; $i<strlen($s1);  $i++){  

                $s2[$i] = $s1 [$i];  

        }  

        return $s2;  

}  


//连接字符串  逐个连接 strlen

function strcat($s1 , $s2)  

{  

        if (!isset($s1) || !isset( $s2)) return;  

        $newstr = $s1 ;  

        for($i=0; $i <strlen($s2); $i++){  

                $newstr .= $s2[$i];  

        }  

        return $newstr;  

}  

echo strcat('abc' , 'def');  


//5.使用五种以上方式获取一个文件的扩展名.

return strrchr($file_name, ‘.’); //strrchr //找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。

return substr($file_name, strrpos($file_name, ‘.’)); //strrpos //查找字符串在另一个字符串中最后一次出现的位置。

array_pop(explode(‘.’, $file_name)); //array_pop //删除数组中的最后一个元素。 

pathinfo($file_name)['extension']; //pathinfo //以数组的形式返回文件路径的信息。

strrev(substr(strrev($file_name), 0, strpos(strrev($file_name), ‘.’))); //strrev //反转字符串  strpos //返回字符串在另一个字符串中第一次出现的位置。


//编码

//加密解密,就是数组对照替换的,

//简单加密函数(与php_decrypt函数对应)  

function php_encrypt($str)  

{  

         $encrypt_key = 'abcdefghijklmnopqrstuvwxyz1234567890';  

         $decrypt_key = 'ngzqtcobmuhelkpdawxfyivrsj2468021359';  

         if ( strlen($str) == 0) return  false;  

         for ($i=0;  $i<strlen($str); $i ++){  

                for ($j=0; $j <strlen($encrypt_key); $j ++){  

                        if ($str[$i] == $encrypt_key [$j]){  

                                $enstr .=  $decrypt_key[$j];  

                                break;  

                        }  

                }  

         }  

        return $enstr;  

}  


//简单解密函数(与php_encrypt函数对应)  

function php_decrypt($str)  

{  

        $encrypt_key = 'abcdefghijklmnopqrstuvwxyz1234567890';  

        $decrypt_key = 'ngzqtcobmuhelkpdawxfyivrsj2468021359';  

        if ( strlen($str) == 0) return  false;  

        for ($i=0;  $i<strlen($str); $i ++){  

                for ($j=0; $j <strlen($decrypt_key); $j ++){  

                        if ($str[$i] == $decrypt_key [$j]){  

                                $enstr .=  $encrypt_key[$j];  

                                break;  

                        }  

                }  

        }  

        return $enstr;  

}  


//编码 转码,与加密和解密相同,只不过加密是对照表,编码是码十六进制的一个值的对应的加减

//简单编码函数(与php_decode函数对应)  

function php_encode($str)  

{  

        if ( $str=='' && strlen( $str)>128) return false;  

        for( $i=0; $i<strlen ($str); $i++){  

                 $c = ord($str[$i ]);  

                if ($c>31 && $c <107) $c += 20 ;  

                if ($c>106 && $c <127) $c -= 75 ;  

                $word = chr($c );  

                $s .= $word;  

        }   

        return $s;   

}  


//简单解码函数(与php_encode函数对应)  

function php_decode($str)  

{  

        if ( $str=='' && strlen($str )>128) return false;  

        for( $i=0; $i<strlen ($str); $i++){  

                $c  = ord($word);  

                if ( $c>106 && $c<127 ) $c = $c-20;  

                if ($c>31 && $c< 107) $c = $c+75 ;  

                $word = chr( $c);  

                $s .= $word ;  

        }   

        return $s;   

}  


//查找字符串  substr

function  strstr($str, $substr)  

{  

        $m = strlen($str);  

        $n = strlen($substr );  

        if ($m < $n) return false ;  

        for ($i=0; $i <=($m-$n); $i ++){  

                $sub = substr( $str, $i, $n);  

                if ( strcmp($sub, $substr) ==  0)  return $i;  

        }  

        return false ;  

}


    //字符串替换  先删掉 再插入

    function str_replace($str,$sub,$newstr){


         $m = strlen($sub);

         if(strchr($str,$sub) == false) return false;

 

         $i = strpos($str,  $sub); //第一次出现的索引key

         $str = str_delete ($str, $i, $m);  

         $str = str_insert ($str,  $i, $newstr);  

         return $str;

    }


//顺序查找(数组里查找某个元素)  


function seq($arr,$n){

$num = count($arr);


for($i=0;$i<$num;$i++){


if($arr[$i] == $n){

return $i;

}

}

}


echo seq(array(1,2,3,4,45,5),4);

 

//截取子串  

start >=0 起始 

start <0  末尾倒数


length >=0 往后数几个

length < 0 末尾去掉几个


+

-

+ +

+ -

- +

- -

function substr2($str, $start,  $length=NULL)  


{  

                if ($length ==  NULL) $length = (strlen($str ) - $start); 


                //先判断起始个数

                $strlength = strlen($str);

                $substr = $realstr = '';

                if ($start >=  0){  

                        for ($i=$start; $i<$strlength ; $i++) {  

                                $substr .=  $str[$i];  

                        }  

                }  


                if ($start <  0){  

                        for ($i=$start+$strlength; $i<$strlength ; $i++) {  

                                $substr .=  $str[$i];  

                        }  

                }  

//后判断截取个数

$sublength = strlen($substr);

                if ($length  > 0){  

                        for ($i= 0; $i<$length; $i++) {  

                                $realstr  .= $substr[$i];  

                        }  

                }  

                 if ( $length < 0){  

if($start < $length  || $start>0){//有个数可去掉的

                            for ($i =0; $i<($sublength-abs($length)); $i++) {  //刨去

                                    $realstr .= $substr[$i];  

                            }  

}else{

$realstr = '';

}

        }

                return isset($realstr)?$realstr:$substr;  

}  


$str = 'addscdcd';

var_dump(substr($str,-6,2)).'<br>';  

var_dump(substr2($str,-6,2));


function hanoi($key, $a, $b, $c) {
 if(1 == $key) {
   echo "Move sheet {$key} from {$a} to {$c}" . "<br />";
 }else {
   hanoi($key-1, $a, $c, $b);
  echo "Move sheet {$key} from {$a} to {$c}" . "<br />";
  hanoi($key-1, $b, $a, $c);
 }
}
print_r(hanoi(3, "A", "B", "C" ));


桶排序

 $array = array(6,10,4,12,4,90,33,6);
 
    function mutong($max,$array)
    {

        $arr = array_fill(0, $max, 0);//有序空数组

        for($i = 0; $i<=count($array)-1 ; $i++){
            $arr[$array[$i]]++; //k=>v=>count 计数
        }
$filter = array_filter($arr);
var_dump($filter);

foreach($filter as $key=>$val){

if($val>1){
for($i=0;$i<$val;$i++){//循环出来
$mutong[] = $key;
}

}


$mutong[] = $key;
}
      return $mutong;
    }
 
    var_dump(mutong(90,$array));



//二叉树

$arr = array(

    'data' => 'A',

    'lChild' => array(

        'data' => 'B',

        'lChild' => array(

            'data' => 'C',

            'lChild' => array(),

            'rChild' => array(),

        ),

        'rChild' => array(

            'data' => 'D',

            'lChild' => array(

                'data' => 'E',

                'lChild' => array(),

                'rChild' => array(

                    'data' => 'G',

                    'lChild' => array(),

                    'rChild' => array(),

                ),

            ),

            'rChild' => array(

                'data' => 'F',

                'lChild' => array(),

                'rChild' => array(),

            ),

        ),

    ),

    'rChild' => array(),

);

echo '<pre>';

print_R($arr);


echo '前序遍历二叉树算法:';

PreOrderTraverse($arr);

echo '<Br>';

function PreOrderTraverse($node){

    if(empty($node)){

        return;

    }

    //输出值

    echo $node['data'];

    //左节点

    PreOrderTraverse($node['lChild']);

    //右节点

    PreOrderTraverse($node['rChild']);

}

 

echo '中序遍历二叉树算法:';

inOrderTraverse($arr);

echo '<Br>';

function inOrderTraverse($node){

    if(empty($node)){

        return;

    }

    //左节点

    inOrderTraverse($node['lChild']);

    //输出值

    echo $node['data'];

    //右节点

    inOrderTraverse($node['rChild']);

}

 

echo '后序遍历二叉树算法:';

postOrderTraverse($arr);

echo '<Br>';

function postOrderTraverse($node){

    if(empty($node)){

        return;

    }

    //左节点

    postOrderTraverse($node['lChild']);

    //右节点

    postOrderTraverse($node['rChild']);

    //输出值

    echo $node['data'];

}


        A

    B

  C   D

    E   F

     G

前序遍历二叉树算法:ABCDEGF

中序遍历二叉树算法:CBEGDFA

后序遍历二叉树算法:CGEFDBA





//堆排序

逻辑:每回遍历,父元素大于子元素,与左孩子优先交换,生成最大顶堆(顶端元素是最大的) ajustnode

      然后首尾两个元素互换,保证最后一个元素位置不动,重新生成最大顶堆,然后再交换首尾元素, $temp==>ajustnode

    

function heapSort(&$arr) {


         #初始化大顶堆

         initHeap($arr, 0, count($arr) - 1);

         


 //print_R($arr);

         #开始交换首尾节点,并每次减少一个末尾节点再调整堆,直到剩下一个元素

         for($end = count($arr) - 1; $end > 0; $end--) {  //最末元素是最大的,和最小的交换,然后保持最大的不变后,重新生成最大顶堆,然后再交换

             $temp = $arr[0];

             $arr[0] = $arr[$end];  //9和1对换

             $arr[$end] = $temp;


  // print_R($arr);

             ajustNodes($arr, 0, $end - 1);

         }

     }

     

     #初始化最大堆,从最左一个非叶子节点开始,最后一个非叶子节点编号为 数组长度/2 向下取整

     function initHeap(&$arr) {

         $len = count($arr);

         for($start = floor($len / 2) - 1; $start >= 0; $start--) { //$start=3

             ajustNodes($arr, $start, $len - 1);

// break;

         }

     }

     

     #调整节点

     #@param $arr    待调整数组

     #@param $start    调整的父节点坐标

     #@param $end    待调整数组结束节点坐标

     function ajustNodes(&$arr, $start, $end) {   //父元素大于子元素,与左孩子优先交换

         $maxInx = $start;  //3

         $len = $end + 1;    #待调整部分长度  9

         $leftChildInx = ($start + 1) * 2 - 1;    #左孩子坐标 7

         $rightChildInx = ($start + 1) * 2;    #右孩子坐标  8


         #如果待调整部分有左孩子

         if($leftChildInx + 1 <= $len) {

 

             #获取最小节点坐标

             if($arr[$maxInx] < $arr[$leftChildInx]) {

                 $maxInx = $leftChildInx;

             }

             

             #如果待调整部分有右子节点

             if($rightChildInx + 1 <= $len) {

                 if($arr[$maxInx] < $arr[$rightChildInx]) {

                     $maxInx = $rightChildInx;

                 }

             }

         }


 //echo $maxInx;exit; //8

         

         #交换父节点和最大节点

         if($start != $maxInx) { //3!=8

             $temp = $arr[$start];

             $arr[$start] = $arr[$maxInx];

             $arr[$maxInx] = $temp;

             

             #如果交换后的子节点还有子节点,继续调整

             if(($maxInx + 1) * 2 <= $len) {

                 ajustNodes($arr, $maxInx, $end);

             }

         }


 //print_r($arr);

     }

     

     $arr=array(1,8,7,2,3,4,6,5,9);

      

     heapSort($arr);

     var_dump($arr);

*//*

数组$arr的原形态结构如下:

             1

           /   

         8      7

       /         /

     2     3      4  6

    /

   5  9


1

           /  

         2      3

       /       / 

     4    5      6   7

    /

   8  9


 */



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值