導航:首頁 > 源碼編譯 > php演算法場景

php演算法場景

發布時間:2023-01-24 10:30:36

1. php實現常見的排序演算法

註:為方便描述,下面的排序全為正序(從小到大排序)

假設有一個數組[a,b,c,d]
冒泡排序依次比較相鄰的兩個元素,如果前面的元素大於後面的元素,則兩元素交換位置;否則,位置不變。具體步驟:
1,比較a,b這兩個元素,如果a>b,則交換位置,數組變為:[b,a,c,d]
2,比較a,c這兩個元素,如果a<c,則位置不變,數組變為:[b,a,c,d]
3,比較c,d這兩個元素,如果c>d,則交換位置,數組變為:[b,a,d,c]
完成第一輪比較後,可以發現最大的數c已經排(冒)在最後面了,接著再進行第二輪比較,但第二輪比較不必比較最後一個元素了,因為最後一個元素已經是最大的了。
第二輪比較結束後,第二大的數也會冒到倒數第二的位置。
依次類推,再進行第三輪,,,
就這樣最大的數一直往後排(冒),最後完成排序。所以我們稱這種排序演算法為冒泡排序。

選擇排序是一種直觀的演算法,每一輪會選出列中最小的值,把最小值排到前面。具體步驟如下:

插入排序步驟大致如下:

快速排序是由東尼·霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個項目要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(n log n) 演算法更快,因為它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來,且在大部分真實世界的數據,可以決定設計的選擇,減少所需時間的二次方項之可能性。

步驟:
從數列中挑出一個元素,稱為 「基準」(pivot),
重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作。
遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

2. 常見的php排序演算法

常見的php排序演算法

本文匯總了常見的php排序演算法,在進行演算法設計的時候有不錯的借鑒價值。現分享給大家供參考之用。具體如下:

一、插入排序

用文字簡單的描述,比如說$arr = array(4,2,4,6,3,6,1,7,9); 這樣的一組數字進行順序排序:

那麼,首先,拿數組的第二個元素和第一元素比較,假如第一個元素大於第二元素,那麼就讓兩者位置互換,接下來,拿數組的第三個元素,分別和第二個,第一個元素比較,假如第三個元素小,那麼就互換。依次類推。這就是插入排序,它的時間頻度是:1+2+...+(n-1)=(n^2)/2。則它的時間復雜度為O(n^2).

php實現代碼如下:

<?phpfunction Sort($arr){ $count = count($arr); if($count<2){ return $arr; } for($i=1;$i<$count;$i++){ tmp="$arr[$i];" j="">=0&&$arr[$j]<$arr[$i]){ return="">

二、選擇排序

選擇排序用語言描述的話,可以這樣,如:$arr = array(4,3,5,2,1);

首先,拿第一個和後面所有的比,找出最小的那個數字,然後和第一個數組互換(當然,如果是第一個最小,那麼就不用互換了),接著循環,即:拿第二個和後面的比較,找出最小的數字,然後和第二個數字互換,依次類推,也就是說每次都是找出剩餘最小的值。 可得到:第一次,時間頻度 是n, (第一個和後面的n-1個比較,找到最小的,再看是不是第一個,不是第一個的話進行互換) 在往後,依次是 減一 。 它的時間復雜度,也是O(n^2);

php實現代碼如下:

<?phpfunction selectSort($arr){ $count = count($arr); if($count<2){ return $arr; } for($i=0;$i<$count;$i++){ $min=$i; for(j=$i+1;$j<$count;$j++){>$arr[$j]){ $min = $j; //找到最小的那個元素的下標 } } if($min!=$i){//如果下標不是$i 則互換。 $tmp= $arr[$i]; $arr[$i] = $arr[$min]; $arr[$min] = $tmp; } } return $arr; }?>

三、冒泡排序

冒泡排序其實上是和選擇排序相比,並無明顯差別。都是找到最小的,放到最左端。依次循環解決問題。差別在於冒泡排序的交換位置的次數較多,而選擇排序則是找到最小的元素的下標,然後直接和最左端的交換位置。

php實現代碼如下:

<?phpfunction selectSort($arr){ $count = count($arr); if($count<2){ return $arr; } for($i=0;$i<$count;$i++){ for(j=$i+1;$j<$count;$j++){>$arr[$j]){ $tmp= $arr[$i]; $arr[$i] = $arr[$i]; $arr[$i] = $tmp; } } } return $arr; }?>

四、快速排序

快速排序,用語言來形容的話,從數組中選擇一個值$a,然後和其餘元素進行比較,比$a大的放到數組right中,反之,放到數組left中。然後將left right 分別進行遞歸調用,即:再細分left right ,最後進行數組的合並。

php實現快速排序:

<?phpfunction mySort($arr){ $count = count($arr); if($count<2){ return $arr; } $key = $arr[0];//選擇第一個元素作為比較元素,可選其他 $left = array(); $right = array(); for($i=1;$i<$count;$i++){ key="">=$arr[$i]){ $left[] = $arr[$i]; }else{ $right[] = $arr[$i]; } } $left = mySort($left); $right = mySort($right); $result = array_merge($left,$right); return $result; }?>

五、歸並排序

其實歸並排序是一種拆分,合並的思想。和快速排序思想有共通之處,左邊一堆,右邊一堆,然後進行合並。通過遞歸實現排序。 區別之處呢? 他們的區別也是思想上本質的區別,快速排序的拆分,是選擇了特定的值進行大小比較,從而分為left 和 right 。也就是小的一堆放入left,大的一堆放入right。而後,小的left 再細分為left1 right1。。。。通過進行類似的遞歸完成排序。也就是說,一直細分下去,遞歸最末尾的left1就是最小值。

而歸並排序,是從幾何上的左右切分,一直遞歸切分成2或者1的'最小粒度的數組,然後才開始進行比較大小,然後合並。此處的比較大小是:兒子left的元素 和兒子的right元素 進行比較,而後進行排序合並成為父親left或者right。在此,直到拿到各自排序合並完成最後兩個數組:最起初的left 和right,也僅僅直到他們各自的順序,並不能確認整個數組的順序,還是需要通過最終的left right 比較後合並才能完成真正意義上的排序。

<?phpfunction gbSort($arr){ if(count($arr)<=1){return min="floor(count($arr)/2);//取中間數字進行拆分" left="gbSort($left);" right="gbSort($right);" return="" function="">$right[0] ? array_shift($right) : array_shift($left); //進行比較,小的移除,並且放入到數組$m中。 } return arr_merge($m,$left,$right);//進行合並(由於不知道left right 哪個會為空,所以進行統一合並)}?>

六、堆排序

本例中fixDown函數實現對某一個節點的向下調整,這里默認的是起始節點為1,方便計算父子節點關系

注:

起始節點為1的父子關系: 父節點k, 子節點為2K、2k+1 子節點j, 父節點為 floor(j/2) floor為向下取整

起始節點為0的父子關系: 父節點k, 子節點為2K+1, 2k+2 子節點j, 父節點為 floor((j-1)/2)

參數$k為調整點位置, $lenth為數組長度,也就是從1起始到最後一個節點的坐標.

<?phpfunction fixDown(&$arr, $k, $lenth){while(2*$k<=$lenth) { //只要當前節點有子節點, 就需要繼續該循環 $j = $k*2; if ($j<$lenth && $arr[$j]<$arr[$j+1]) $j++; // 只要子節點有右節點,且右節點比左節點大,那麼切換到右節點操作。 if ($arr[$j] < $arr[$k]) break; // 如果子節點都沒有父節點大, 那麼調整結束。 exch($arr[$j], $arr[$k]); $k = $j; }}function exch(&$a, &$b) { $tmp = $a; $a = $b; $b = $tmp;}function headSort(&$arr){ $len = count($arr); array_unshift($arr, NULL); for($i=$len/2;$i>=1;$i--) { fixDown($arr, $i, $len); } while($len>1) { exch($arr[1], $arr[$len]); fixDown($arr, 1, --$len); } array_shift($arr);}$arr = array(4,6,4,9,2,3);headSort($arr);?>

希望本文所述排序演算法實例對大家的php程序設計有所幫助。

;

3. php現在有哪些常用的演算法

<?
//--------------------
// 基本數據結構演算法
//--------------------
//二分查找(數組里查找某個元素)
function bin_sch($array, $low, $high, $k){
if ( $low <= $high){
$mid = intval(($low+$high)/2 );
if ($array[$mid] == $k){
return $mid;
}elseif ( $k < $array[$mid]){
return bin_sch($array, $low, $mid-1, $k);
}else{
return bin_sch($array, $mid+ 1, $high, $k);
}
}
return -1;
}
//順序查找(數組里查找某個元素)
function seq_sch($array, $n, $k){
$array[$n] = $k;
for($i=0; $i<$n; $i++){
if( $array[$i]==$k){
break;
}
}
if ($i<$n){
return $i;
}else{
return -1;
}
}
//線性表的刪除(數組中實現)
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 ;
}
//冒泡排序(數組排序)
function bubble_sort( $array)
{
$count = count( $array);
if ($count <= 0 ) return false;
for($i=0 ; $i<$count; $i ++){
for($j=$count-1 ; $j>$i; $j--){
if ($array[$j] < $array [$j-1]){
$tmp = $array[$j];
$array[$j] = $array[ $j-1];
$array [$j-1] = $tmp;
}
}
}
return $array;
}
//快速排序(數組排序)
function quick_sort($array ) {
if (count($array) <= 1) return $array;
$key = $array [0];
$left_arr = array();
$right_arr = array();
for ($i= 1; $i<count($array ); $i++){
if ($array[ $i] <= $key)
$left_arr [] = $array[$i];
else
$right_arr[] = $array[$i ];
}
$left_arr = quick_sort($left_arr );
$right_arr = quick_sort( $right_arr);
return array_merge($left_arr , array($key), $right_arr);
}

//------------------------
// PHP內置字元串函數實現
//------------------------
//字元串長度
function strlen ($str)
{
if ($str == '' ) return 0;
$count = 0;
while (1){
if ( $str[$count] != NULL){
$count++;
continue;
}else{
break;
}
}
return $count;
}
//截取子串
function substr($str, $start, $length=NULL)
{
if ($str== '' || $start>strlen($str )) return;
if (($length!=NULL) && ( $start>0) && ($length> strlen($str)-$start)) return;
if (( $length!=NULL) && ($start< 0) && ($length>strlen($str )+$start)) return;
if ($length == NULL) $length = (strlen($str ) - $start);

if ($start < 0){
for ($i=(strlen( $str)+$start); $i<(strlen ($str)+$start+$length ); $i++) {
$substr .= $str[$i];
}
}
if ($length > 0){
for ($i= $start; $i<($start+$length ); $i++) {
$substr .= $str[$i];
}
}
if ( $length < 0){
for ($i =$start; $i<(strlen( $str)+$length); $i++) {
$substr .= $str[$i ];
}
}
return $substr;
}
//字元串翻轉
function strrev($str)
{
if ($str == '') return 0 ;
for ($i=(strlen($str)- 1); $i>=0; $i --){
$rev_str .= $str[$i ];
}
return $rev_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 0;
}

//查找字元串
function strstr($str, $substr)
{
$m = strlen($str);
$n = strlen($substr );
if ($m < $n) return false ;
for ($i=0; $i <=($m-$n+1); $i ++){
$sub = substr( $str, $i, $n);
if ( strcmp($sub, $substr) == 0) return $i;
}
return false ;
}
//字元串替換
function str_replace($substr , $newsubstr, $str)
{
$m = strlen($str);
$n = strlen($substr );
$x = strlen($newsubstr );
if (strchr($str, $substr ) == false) return false;
for ( $i=0; $i<=($m- $n+1); $i++){
$i = strchr($str, $substr);
$str = str_delete ($str, $i, $n);
$str = str_insert($str, $i, $newstr);
}
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 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 strcpy($s1, $s2 )
{
if (strlen($s1)==NULL || !isset( $s2)) return;
for ($i=0 ; $i<strlen($s1); $i++){
$s2[] = $s1 [$i];
}
return $s2;
}
//連接字元串
function strcat($s1 , $s2)
{
if (!isset($s1) || !isset( $s2)) return;
$newstr = $s1 ;
for($i=0; $i <count($s); $i ++){
$newstr .= $st[$i ];
}
return $newsstr;
}
//簡單編碼函數(與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;
}
//簡單加密函數(與php_decrypt函數對應)
function php_encrypt($str)
{
$encrypt_key = '';
$decrypt_key = '';
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 = '';
$decrypt_key = '';
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;
}
?>

4. php 簡單演算法

$int = 100;// $int 要計算的數字
$n = 3; //$n 是歸屬的最大值
/* 下面的代碼生成歸屬描述數組 */
$array = array();
for ($i = 0; $i < n; $i ++) {
$array[$i+1] = pow(3, $i);
}
//現在$array為array(1 => 1, 2 => 3, 3 => 9)
$limit = 0; //當前范圍
$is = 0; //歸屬
foreach ($array as $key => $value) {
$limit += $value;
if ($limit>= $int) {
break;
}
}
echo $is;//這個就是結果了

5. PHP對稱加密-AES

對稱加解密演算法中,當前最為安全的是 AES 加密演算法(以前應該是是 DES 加密演算法),PHP 提供了兩個可以用於 AES 加密演算法的函數簇: Mcrypt OpenSSL

其中 Mcrypt 在 PHP 7.1.0 中被棄用(The Function Mycrypt is Deprecated),在 PHP 7.2.0 中被移除,所以即可起你應該使用 OpenSSL 來實現 AES 的數據加解密。

在一些場景下,我們不能保證兩套通信系統都使用了相函數簇去實現加密演算法,可能 siteA 使用了最新的 OpenSSL 來實現了 AES 加密,但作為第三方服務的 siteB 可能仍在使用 Mcrypt 演算法,這就要求我們必須清楚 Mcrypt 同 OpenSSL 之間的差異,以便保證數據加解密的一致性。

下文中我們將分別使用 Mcrypt 和 OpenSSL 來實現 AES-128/192/256-CBC 加解密,二者同步加解密的要點為:

協同好以上兩點,就可以讓 Mcrypt 和 OpenSSL 之間一致性的對數據進行加解密。

AES 是當前最為常用的安全對稱加密演算法,關於對稱加密這里就不在闡述了。

AES 有三種演算法,主要是對數據塊的大小存在區別:

AES-128:需要提供 16 位的密鑰 key
AES-192:需要提供 24 位的密鑰 key
AES-256:需要提供 32 位的密鑰 key

AES 是按數據塊大小(128/192/256)對待加密內容進行分塊處理的,會經常出現最後一段數據長度不足的場景,這時就需要填充數據長度到加密演算法對應的數據塊大小。

主要的填充演算法有填充 NUL("0") 和 PKCS7,Mcrypt 默認使用的 NUL("0") 填充演算法,當前已不被推薦,OpenSSL 則默認模式使用 PKCS7 對數據進行填充並對加密後的數據進行了 base64encode 編碼,所以建議開發中使用 PKCS7 對待加密數據進行填充,已保證通用性(alipay sdk 中雖然使用了 Mcrypt 加密簇,但使用 PKCS7 演算法對數據進行了填充,這樣在一定程度上親和了 OpenSSL 加密演算法)。

Mcrypt 的默認填充演算法。NUL 即為 Ascii 表的編號為 0 的元素,即空元素,轉移字元是 "",PHP 的 pack 打包函數在 'a' 模式下就是以 NUL 字元對內容進行填充的,當然,使用 "" 手動拼接也是可以的。

OpenSSL的默認填充演算法。下面我們給出 PKCS7 填充演算法 PHP 的實現:

默認使用 NUL("") 自動對待加密數據進行填充以對齊加密演算法數據塊長度。

獲取 mcrypt 支持的演算法,這里我們只關注 AES 演算法。

注意:mcrypt 雖然支持 AES 三種演算法,但除 MCRYPT_RIJNDAEL_128 外, MCRYPT_RIJNDAEL_192/256 並未遵循 AES-192/256 標准進行加解密的演算法,即如果你同其他系統通信(java/.net),使用 MCRYPT_RIJNDAEL_192/256 可能無法被其他嚴格按照 AES-192/256 標準的系統正確的數據解密。官方文檔頁面中也有人在 User Contributed Notes 中提及。這里給出如何使用 mcrpyt 做標注的 AES-128/192/256 加解密

即演算法統一使用 MCRYPT_RIJNDAEL_128 ,並通過 key 的位數 來選定是以何種 AES 標准做的加密,iv 是建議添加且建議固定為16位(OpenSSL的 AES加密 iv 始終為 16 位,便於統一對齊),mode 選用的 CBC 模式。

mcrypt 在對數據進行加密處理時,如果發現數據長度與使用的加密演算法的數據塊長度未對齊,則會自動使用 "" 對待加密數據進行填充,但 "" 填充模式已不再被推薦,為了與其他系統有更好的兼容性,建議大家手動對數據進行 PKCS7 填充。

openssl 簇加密方法更為簡單明確,mcrypt 還要將加密演算法分為 cipher + mode 去指定,openssl 則只需要直接指定 method 為 AES-128-CBC,AES-192-CBC,AES-256-CBC 即可。且提供了三種數據處理模式,即 默認模式 0 / OPENSSL_RAW_DATA / OPENSSL_ZERO_PADDING 。

openssl 默認的數據填充方式是 PKCS7,為兼容 mcrpty 也提供處理 "0" 填充的數據的模式,具體為下:

options 參數即為重要,它是兼容 mcrpty 演算法的關鍵:

options = 0 : 默認模式,自動對明文進行 pkcs7 padding,且數據做 base64 編碼處理。
options = 1 : OPENSSL_RAW_DATA,自動對明文進行 pkcs7 padding, 且數據未經 base64 編碼處理。
options = 2 : OPENSSL_ZERO_PADDING,要求待加密的數據長度已按 "0" 填充與加密演算法數據塊長度對齊,即同 mcrpty 默認填充的方式一致,且對數據做 base64 編碼處理。注意,此模式下 openssl 要求待加密數據已按 "0" 填充好,其並不會自動幫你填充數據,如果未填充對齊,則會報錯。

故可以得出 mcrpty簇 與 openssl簇 的兼容條件如下:

建議將源碼復制到本地運行,根據運行結果更好理解。

1.二者使用的何種填充演算法。

2.二者對數據是否有 base64 編碼要求。

3.mcrypt 需固定使用 MCRYPT_RIJNDAEL_128,並通過調整 key 的長度 16, 24,32 來實現 ase-128/192/256 加密演算法。

6. php幾種排序演算法實例詳解

四種排序演算法的PHP實現:
1)插入排序(InsertionSort)的基本思想是:
每次將一個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子文件中的適當位置,直到全部記錄插入完成為止。

2)選擇排序(SelectionSort)的基本思想是:
每一趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排好序的子文件的最後,直到全部記錄排序完畢。

3)冒泡排序的基本思想是:
兩兩比較待排序記錄的關鍵字,發現兩個記錄的次序相反時即進行交換,直到沒有反序的記錄為止。

4)快速排序實質上和冒泡排序一樣,都是屬於交換排序的一種應用。所以基本思想和上面的冒泡排序是一樣的。

1.sort.php文件如下:

<?php
classSort{
private$arr=array();
private$sort='insert';
private$marker='_sort';
private$debug=TRUE;
/**
*構造函數
*
*@paramarray例如:
$config=array(
'arr'=>array(22,3,41,18),//需要排序的數組值
'sort'=>'insert',//可能值:insert,select,bubble,quick
'debug'=>TRUE//可能值:TRUE,FALSE
)
*/
publicfunctionconstruct($config=array()){
if(count($config)>0){
$this->_init($config);
}
}
/**
*獲取排序結果
*/
publicfunctiondisplay(){
return$this->arr;
}
/**
*初始化
*
*@paramarray
*@returnbool
*/
privatefunction_init($config=array()){
//參數判斷
if(!is_array($config)ORcount($config)==0){
if($this->debug===TRUE){
$this->_log("sort_init_param_invaild");
}
returnFALSE;
}
//初始化成員變數
foreach($configas$key=>$val){
if(isset($this->$key)){
$this->$key=$val;
}
}
//調用相應的成員方法完成排序
$method=$this->sort.$this->marker;
if(!method_exists($this,$method)){
if($this->debug===TRUE){
$this->_log("sort_method_invaild");
}
returnFALSE;
}
if(FALSE===($this->arr=$this->$method($this->arr)))
returnFALSE;
returnTRUE;
}
/**
*插入排序
*
*@paramarray
*@returnbool
*/
privatefunctioninsert_sort($arr){
//參數判斷
if(!is_array($arr)ORcount($arr)==0){
if($this->debug===TRUE){
$this->_log("sort_array(insert)_invaild");
}
returnFALSE;
}
//具體實現
$count=count($arr);
for($i=1;$i<$count;$i++){
$tmp=$arr[$i];
for($j=$i-1;$j>=0;$j--){
if($arr[$j]>$tmp){
$arr[$j+1]=$arr[$j];
$arr[$j]=$tmp;
}
}
}
return$arr;
}
/**
*選擇排序
*
*@paramarray
*@returnbool
*/
privatefunctionselect_sort($arr){
//參數判斷
if(!is_array($arr)ORcount($arr)==0){
if($this->debug===TRUE){
$this->_log("sort_array(select)_invaild");
}
returnFALSE;
}
//具體實現
$count=count($arr);
for($i=0;$i<$count-1;$i++){
$min=$i;
for($j=$i+1;$j<$count;$j++){
if($arr[$min]>$arr[$j])$min=$j;
}
if($min!=$i){
$tmp=$arr[$min];
$arr[$min]=$arr[$i];
$arr[$i]=$tmp;
}
}
return$arr;
}
/**
*冒泡排序
*
*@paramarray
*@returnbool
*/
privatefunctionbubble_sort($arr){
//參數判斷
if(!is_array($arr)ORcount($arr)==0){
if($this->debug===TRUE){
$this->_log("sort_array(bubble)_invaild");
}
returnFALSE;
}
//具體實現
$count=count($arr);
for($i=0;$i<$count;$i++){
for($j=$count-1;$j>$i;$j--){
if($arr[$j]<$arr[$j-1]){
$tmp=$arr[$j];
$arr[$j]=$arr[$j-1];
$arr[$j-1]=$tmp;
}
}
}
return$arr;
}
/**
*快速排序
*@bywww.5wx.org
*@paramarray
*@returnbool
*/
privatefunctionquick_sort($arr){
//具體實現
if(count($arr)<=1)return$arr;
$key=$arr[0];
$left_arr=array();
$right_arr=array();
for($i=1;$i<count($arr);$i++){
if($arr[$i]<=$key)
$left_arr[]=$arr[$i];
else
$right_arr[]=$arr[$i];
}
$left_arr=$this->quick_sort($left_arr);
$right_arr=$this->quick_sort($right_arr);

returnarray_merge($left_arr,array($key),$right_arr);
}
/**
*日誌記錄
*/
privatefunction_log($msg){
$msg='date['.date('Y-m-dH:i:s').']'.$msg.' ';
return@file_put_contents('sort_err.log',$msg,FILE_APPEND);
}
}
/*Endoffilesort.php*/
/*Locationhtdocs/sort.php*/
2.sort_demo.php文件如下:

<?php
require_once('sort.php');
$config=array(
'arr'=>array(23,22,41,18,20,12,200303,2200,1192),
//需要排序的數組值
'sort'=>'select',
//可能值:insert,select,bubble,quick
'debug'=>TRUE
//可能值:TRUE,FALSE
);
$sort=newSort($config);
//var_mp($config['arr']);
var_mp($sort->display());
/*Endofphp*/

7. 如何實現PHP的TEA演算法

演算法簡單,而且效率高,每次可以操作8個位元組的數據,加密解密的KEY為16位元組,即包含4個int數據的int型數組,加密輪數應為8的倍數,一般比較常用的輪數為64,32,16,QQ原來就是用TEA16來還原密碼的.


TEA演算法

核心為:

#include<stdint.h>

voidencrypt(uint32_t*v,uint32_t*k){
uint32_tv0=v[0],v1=v[1],sum=0,i;/*setup*/
uint32_tdelta=0x9e3779b9;/*akeyscheleconstant*/
uint32_tk0=k[0],k1=k[1],k2=k[2],k3=k[3];/*cachekey*/
for(i=0;i<32;i++){/*basiccyclestart*/
sum+=delta;
v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
}/*endcycle*/
v[0]=v0;v[1]=v1;
}

voiddecrypt(uint32_t*v,uint32_t*k){
uint32_tv0=v[0],v1=v[1],sum=0xC6EF3720,i;/*setup*/
uint32_tdelta=0x9e3779b9;/*akeyscheleconstant*/
uint32_tk0=k[0],k1=k[1],k2=k[2],k3=k[3];/*cachekey*/
for(i=0;i<32;i++){/*basiccyclestart*/
v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
sum-=delta;
}/*endcycle*/
v[0]=v0;v[1]=v1;
}


PHP部分代碼非我原創,大家可以了解一下這方面的知識

<?php
$date='8345354023476-3434';
$key='12345';
$t=newtea();
$tea=$t->encrypt($date,$key);
$eetea=$t->decrypt($tea,$key);
var_mp($tea);
var_mp($eetea);
classtea{
private$a,$b,$c,$d;
private$n_iter;
publicfunction__construct(){
$this->setIter(32);
}
privatefunctionsetIter($n_iter){
$this->n_iter=$n_iter;
}
privatefunctiongetIter(){
return$this->n_iter;
}
publicfunctionencrypt($data,$key){
//resizedatato32bits(4bytes)
$n=$this->_resize($data,4);

//convertdatatolong
$data_long[0]=$n;
$n_data_long=$this->_str2long(1,$data,$data_long);

//resizedata_longto64bits(2longsof32bits)
$n=count($data_long);
if(($n&1)==1){
$data_long[$n]=chr(0);
$n_data_long++;
}

//resizekeytoamultipleof128bits(16bytes)
$this->_resize($key,16,true);
if(''==$key)
$key='0000000000000000';

//convertkeytolong
$n_key_long=$this->_str2long(0,$key,$key_long);

//encryptthelongdatawiththekey
$enc_data='';
$w=array(0,0);
$j=0;
$k=array(0,0,0,0);
for($i=0;$i<$n_data_long;++$i){
//getnextkeypartof128bits
if($j+4<=$n_key_long){
$k[0]=$key_long[$j];
$k[1]=$key_long[$j+1];
$k[2]=$key_long[$j+2];
$k[3]=$key_long[$j+3];
}else{
$k[0]=$key_long[$j%$n_key_long];
$k[1]=$key_long[($j+1)%$n_key_long];
$k[2]=$key_long[($j+2)%$n_key_long];
$k[3]=$key_long[($j+3)%$n_key_long];
}
$j=($j+4)%$n_key_long;

$this->_encipherLong($data_long[$i],$data_long[++$i],$w,$k);

//
$enc_data.=$this->_long2str($w[0]);
$enc_data.=$this->_long2str($w[1]);
}

return$enc_data;
}
publicfunctiondecrypt($enc_data,$key){
//convertdatatolong
$n_enc_data_long=$this->_str2long(0,$enc_data,$enc_data_long);

//resizekeytoamultipleof128bits(16bytes)
$this->_resize($key,16,true);
if(''==$key)
$key='0000000000000000';

//convertkeytolong
$n_key_long=$this->_str2long(0,$key,$key_long);

//decryptthelongdatawiththekey
$data='';
$w=array(0,0);
$j=0;
$len=0;
$k=array(0,0,0,0);
$pos=0;

for($i=0;$i<$n_enc_data_long;$i+=2){
//getnextkeypartof128bits
if($j+4<=$n_key_long){
$k[0]=$key_long[$j];
$k[1]=$key_long[$j+1];
$k[2]=$key_long[$j+2];
$k[3]=$key_long[$j+3];
}else{
$k[0]=$key_long[$j%$n_key_long];
$k[1]=$key_long[($j+1)%$n_key_long];
$k[2]=$key_long[($j+2)%$n_key_long];
$k[3]=$key_long[($j+3)%$n_key_long];
}
$j=($j+4)%$n_key_long;

$this->_decipherLong($enc_data_long[$i],$enc_data_long[$i+1],$w,$k);

//(removepadding)
if(0==$i){
$len=$w[0];
if(4<=$len){
$data.=$this->_long2str($w[1]);
}else{
$data.=substr($this->_long2str($w[1]),0,$len%4);
}
}else{
$pos=($i-1)*4;
if($pos+4<=$len){
$data.=$this->_long2str($w[0]);

if($pos+8<=$len){
$data.=$this->_long2str($w[1]);
}elseif($pos+4<$len){
$data.=substr($this->_long2str($w[1]),0,$len%4);
}
}else{
$data.=substr($this->_long2str($w[0]),0,$len%4);
}
}
}
return$data;
}
privatefunction_encipherLong($y,$z,&$w,&$k){
$sum=(integer)0;
$delta=0x9E3779B9;
$n=(integer)$this->n_iter;

while($n-->0){
//Cv0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
//Cv1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
$sum=$this->_add($sum,$delta);
$y=$this->_add($y,$this->_add(($z<<4),$this->a)^$this->_add($z,$sum)^$this->_add($this->_rshift($z,5),$this->b));
$z=$this->_add($z,$this->_add(($y<<4),$this->a)^$this->_add($y,$sum)^$this->_add($this->_rshift($y,5),$this->b));
}

$w[0]=$y;
$w[1]=$z;
}
privatefunction_decipherLong($y,$z,&$w,&$k){
//sum=delta<<5,ingeneralsum=delta*n
$sum=0xC6EF3720;
$delta=0x9E3779B9;
$n=(integer)$this->n_iter;

while($n-->0){
//Cv1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
//Cv0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
$z=$this->_add($z,-($this->_add(($y<<4),$this->a)^$this->_add($y,$sum)^$this->_add($this->_rshift($y,5),$this->b)));
$y=$this->_add($y,-($this->_add(($z<<4),$this->a)^$this->_add($z,$sum)^$this->_add($this->_rshift($z,5),$this->b)));
$sum=$this->_add($sum,-$delta);
}

$w[0]=$y;
$w[1]=$z;
}
privatefunction_resize(&$data,$size,$nonull=false){
$n=strlen($data);
$nmod=$n%$size;
if(0==$nmod)
$nmod=$size;

if($nmod>0){
if($nonull){
for($i=$n;$i<$n-$nmod+$size;++$i){
$data[$i]=$data[$i%$n];
}
}else{
for($i=$n;$i<$n-$nmod+$size;++$i){
$data[$i]=chr(0);
}
}
}
return$n;
}
privatefunction_hex2bin($str){
$len=strlen($str);
returnpack('H'.$len,$str);
}
privatefunction_str2long($start,&$data,&$data_long){
$n=strlen($data);

$tmp=unpack('N*',$data);
$j=$start;

foreach($tmpas$value)
$data_long[$j++]=$value;

return$j;
}
privatefunction_long2str($l){
returnpack('N',$l);
}


privatefunction_rshift($integer,$n){
//convertto32bits
if(0xffffffff<$integer||-0xffffffff>$integer){
$integer=fmod($integer,0xffffffff+1);
}

//converttounsignedinteger
if(0x7fffffff<$integer){
$integer-=0xffffffff+1.0;
}elseif(-0x80000000>$integer){
$integer+=0xffffffff+1.0;
}

//dorightshift
if(0>$integer){
$integer&=0x7fffffff;//removesignbitbeforeshift
$integer>>=$n;//rightshift
$integer|=1<<(31-$n);//setshiftedsignbit
}else{
$integer>>=$n;//usenormalrightshift
}

return$integer;
}
privatefunction_add($i1,$i2){
$result=0.0;

foreach(func_get_args()as$value){
//removesignifnecessary
if(0.0>$value){
$value-=1.0+0xffffffff;
}

$result+=$value;
}

//convertto32bits
if(0xffffffff<$result||-0xffffffff>$result){
$result=fmod($result,0xffffffff+1);
}

//converttosignedinteger
if(0x7fffffff<$result){
$result-=0xffffffff+1.0;
}elseif(-0x80000000>$result){
$result+=0xffffffff+1.0;
}

return$result;
}

//}}}
}
?>

上面的是TEA的演算法,XTEA的演算法為:


#include <stdint.h>


void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const k[4]) {

unsigned int i;

uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;

for (i=0; i < num_rounds; i++) {

v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);

sum += delta;

v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);

}

v[0]=v0; v[1]=v1;

}


void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const k[4]) {

unsigned int i;

uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;

for (i=0; i < num_rounds; i++) {

v1 &#8722;= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);

sum &#8722;= delta;

v0 &#8722;= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);

}

v[0]=v0; v[1]=v1;

}


那PHP中只需要把運算的位置改下就OK


private function _teaencipherLong($y, $z, &$w, &$k) {

$sum = ( integer ) 0;

$delta = 0x9E3779B9;

$n = ( integer ) $this->n_iter;

while ( $n -- > 0 ) {

$y = $this->_add ( $y, $this->_add ( $z << 4 ^ $this->_rshift ( $z, 5 ), $z ) ^ $this->_add ( $sum, $k [$sum & 3] ) );

$sum = $this->_add ( $sum, $delta );

$z = $this->_add ( $z, $this->_add ( $y << 4 ^ $this->_rshift ( $y, 5 ), $y ) ^ $this->_add ( $sum, $k [$this->_rshift ( $sum, 11 ) & 3] ) );

}

$w [0] = $y;

$w [1] = $z;

}

private function _decipherLong($y, $z, &$w, &$k) {

// sum = delta<<5, in general sum = delta * n

$sum = 0xC6EF3720;

$delta = 0x9E3779B9;

$n = ( integer ) $this->n_iter;

while ( $n -- > 0 ) {

$z = $this->_add ( $z, - ($this->_add ( $y << 4 ^ $this->_rshift ( $y, 5 ), $y ) ^ $this->_add ( $sum, $k [$this->_rshift ( $sum, 11 ) & 3] )) );

$sum = $this->_add ( $sum, - $delta );

$y = $this->_add ( $y, - ($this->_add ( $z << 4 ^ $this->_rshift ( $z, 5 ), $z ) ^ $this->_add ( $sum, $k [$sum & 3] )) );

}

$w [0] = $y;

$w [1] = $z;

8. PHP快速排序演算法實現的原理及代碼詳解

演算法原理
下列動圖來自五分鍾學演算法,演示了快速排序演算法的原理和步驟。
步驟:
從數組中選個基準值
將數組中大於基準值的放同一邊、小於基準值的放另一邊,基準值位於中間位置
遞歸的對分列兩邊的數組再排序
代碼實現
function
quickSort($arr)
{
$len
=
count($arr);
if
($len
<=
1)
{
return
$arr;
}
$v
=
$arr[0];
$low
=
$up
=
array();
for
($i
=
1;
$i
<
$len;
++$i)
{
if
($arr[$i]
>
$v)
{
$up[]
=
$arr[$i];
}
else
{
$low[]
=
$arr[$i];
}
}
$low
=
quickSort($low);
$up
=
quickSort($up);
return
array_merge($low,
array($v),
$up);
}
測試代碼:
$startTime
=
microtime(1);
$arr
=
range(1,
10);
shuffle($arr);
echo
"before
sort:
",
implode(',
',
$arr),
"\n";
$sortArr
=
quickSort($arr);
echo
"after
sort:
",
implode(',
',
$sortArr),
"\n";
echo
"use
time:
",
microtime(1)
-
$startTime,
"s\n";
測試結果:
before
sort:
1,
7,
10,
9,
6,
3,
2,
5,
4,
8
after
sort:
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
use
time:
0.0009009838104248s
時間復雜度
快速排序的時間復雜度在最壞情況下是O(N2),平均的時間復雜度是O(N*lgN)。
這句話很好理解:假設被排序的數列中有N個數。遍歷一次的時間復雜度是O(N),需要遍歷多少次呢?至少lg(N+1)次,最多N次。
1)
為什麼最少是lg(N+1)次?快速排序是採用的分治法進行遍歷的,我們將它看作一棵二叉樹,它需要遍歷的次數就是二叉樹的深度,而根據完全二叉樹的定義,它的深度至少是lg(N+1)。因此,快速排序的遍歷次數最少是lg(N+1)次。
2)
為什麼最多是N次?這個應該非常簡單,還是將快速排序看作一棵二叉樹,它的深度最大是N。因此,快讀排序的遍歷次數最多是N次。
您可能感興趣的文章:PHP快速排序演算法實例分析PHP四種排序演算法實現及效率分析【冒泡排序,插入排序,選擇排序和快速排序】PHP排序演算法之快速排序(Quick
Sort)及其優化演算法詳解PHP遞歸實現快速排序的方法示例php
二維數組快速排序演算法的實現代碼PHP常用排序演算法實例小結【基本排序,冒泡排序,快速排序,插入排序】PHP快速排序quicksort實例詳解

9. 深入研究php的redlock演算法

為了應對伺服器高並發,可以採用鎖進行控制。

如果redis是單節點部署,基本上不會出現什麼問題。但如果redis是多節點的集群部署,那麼使用redis集群作為分布式鎖就會存在一些問題。本文參(抄)考(襲)了以下文章。
閑聊Redis分布式鎖
基於Redis的分布式鎖到底安全嗎(上)?
基於Redis的分布式鎖到底安全嗎(下)?

SET resource_name my_random_value NX PX 30000

如果返回成功,則說明客戶端獲取鎖成功,然後就可以訪問公共資源了,如果失敗則獲取鎖失敗。對於這條命令,需要注意

my_random_value:必須是一個隨機字元,並且唯一。如果不唯一,可能會出現以下情況:
1.客戶端1獲取資源成功
2.客戶端1阻塞超時,鎖自動釋放
3.客戶端2獲取鎖成功
4.客戶端1從阻塞中醒來,釋放了客戶端2的鎖

必須設置NX,表示只有resource_name不存在時才會設置成功,保證只有第一個請求的客戶端獲取鎖成功

PX 30000 表示過期時間為30s,為了保證原子操作必須在SET時設置過期時間

釋放鎖時使用下面的redis lua腳本執行來保證原子性。
只有當resource_name的值和客戶端持有的數據相等時才能夠調用del刪除resource_name,否則不進行刪除操作。從而防止一個客戶端釋放另一個客戶端持有的鎖。

分析一下redis鎖的原理,我們在redis實例中創建一個鍵值,同時設置該鍵值的超時時間。創建該鍵值的客戶端獲取鎖成功,訪問公共資源。同時如果客戶端宕機則鎖會自動釋放。客戶端需要釋放鎖時只需要刪除該鍵即可。但一旦單節點的Redis宕機則不能再提供服務,即使是基於Master-Slave模式的故障切換也是不安全的,例如下面場景

客戶端1從Master獲取鎖
Master宕機,但鎖key還沒有同步到Slave上
Slave升級為Master
客戶端2從新的Master上獲取鎖成功

演算法實現

php源碼實現

10. PHP程序演算法

用戶加入購物車 3個A and 2個B
在購物車下提示
當前使用(A+B) * 2 + A * 1 的方式可以節省多少錢

在資料庫建立商品組合表
自增ID 組合名稱 組合商品ID(1,2,3,4)優惠折扣
1 測試組合 1(A商品ID),2(B商品ID) 0.99

在每次用戶確認訂單之時判斷當前加入購物車的商品是符合組合優惠
如果有則提示,沒有就略過

閱讀全文

與php演算法場景相關的資料

熱點內容
不背單詞app單詞怎麼學習 瀏覽:479
程序員日常操作搞笑 瀏覽:379
android檢查是否安裝 瀏覽:373
蘋果手機編輯pdf文件 瀏覽:458
android系統名字 瀏覽:969
安卓手機如何進去有求必應屋 瀏覽:432
指數除法運演算法則底數不同 瀏覽:894
90壓縮干糧09壓縮干糧 瀏覽:516
android線程池框架 瀏覽:481
手機自帶解壓能解壓哪些文件 瀏覽:804
linux安裝hba驅動 瀏覽:119
java構造函數new 瀏覽:668
怎麼查家裡電器耗電量app 瀏覽:506
原神一直顯示重新連接伺服器怎麼辦 瀏覽:826
一般用途軸流式壓縮機 瀏覽:926
沒學歷的怎麼學編程 瀏覽:901
華為的隱藏相冊無法加密 瀏覽:782
聯通套餐app怎麼設置 瀏覽:752
關於刪除鏈表的演算法描述 瀏覽:894
標准盤和壓縮盤的區別 瀏覽:47