二叉樹php
A. php面試有什麼技巧么
PHP程序員在面試的時候一般應該抓住以下幾個點。
一、應該介紹自己掌握的開發一種,主要介紹PHP語言的獨特語法以及如何使用,比如PHP語言會比CGI更快的執行動態頁面。
二、必須熟悉Oracle、Mysql等資料庫,並能簡單的介紹自己掌握的程度。由於php做出的動態頁面比用其他語言做出來的頁面在執行效率以及CGI方面高得多,所以你還需要在面試中說出自己的文檔撰寫能力很強。
三、PHP程序員應該具備獨立分析和解決問題的能力,可以在自我介紹中講講自己曾經遇到過的問題是如何解決的。讓面試官看到你的能力,這將會直接影響到你自我介紹的成功與否。
四、一個PHP程序員必須有良好的職業道德和工作態度,所以在面試中應該盡量講自己在做項目時的認真態度以及今後的工作規劃,表現出自己的進取心。
五、還有關於溝通能力和理解能力的體現,這個在與HR的交談中就可以表現出來,所以需要做的工作就是從容的有條理的把自我介紹說完,回答每一個問題時都應該簡潔明了,關於自我介紹可以提前做個草稿,背一下。
六、團隊合作能力也是企業非常看重的,在培訓中老師一般都會帶領大家做項目,大的項目一般會分小組,每個人都有相對應的任務,這就模擬了公司中的團隊合作,在自我介紹過程中要把做項目的具體流程以及相互協作的過程說出來,讓HR看到自己具備團隊合作的能力。
七、最後就是執行力,每當任務分配下來的時候該如何執行,還有自己講過職業規劃後該如何執行,還有在學習的過程中是如何人字形的,遇到困難又是如何執行的,這些都可以體現出php程序員的執行力,回答的時候抓住發現及時尋找原因,快速展開行動的這個主線即可。
八、最重要的是你的能力、技術以及自己的項目
B. 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實例詳解
C. 求php+mysql 的二叉樹每一層的葉子統計
Hi,這是一個很有意思的問題,二叉樹,無限極分類一般都會用到遞歸。這里使用函數來模擬mysql查詢,解決思路如下:
<?php
header("Content-type:text/html;charset=utf-8");
$data=array(
array('id'=>1,'pid'=>0,'name'=>'name1'),
array('id'=>2,'pid'=>1,'name'=>'name2'),
array('id'=>3,'pid'=>2,'name'=>'name3'),
array('id'=>4,'pid'=>3,'name'=>'name4'),
array('id'=>5,'pid'=>2,'name'=>'name5'),
array('id'=>6,'pid'=>2,'name'=>'name6'),
array('id'=>7,'pid'=>2,'name'=>'name7'),
array('id'=>8,'pid'=>7,'name'=>'name8'),
array('id'=>9,'pid'=>8,'name'=>'name9'),
array('id'=>10,'pid'=>9,'name'=>'name10'),
array('id'=>11,'pid'=>10,'name'=>'name11'),
array('id'=>12,'pid'=>11,'name'=>'name12'),
array('id'=>13,'pid'=>12,'name'=>'name13'),
array('id'=>14,'pid'=>13,'name'=>'name14'),
array('id'=>15,'pid'=>14,'name'=>'name15'),
array('id'=>16,'pid'=>1,'name'=>'name16'),
array('id'=>17,'pid'=>16,'name'=>'name17'),
array('id'=>18,'pid'=>17,'name'=>'name18'),
array('id'=>19,'pid'=>18,'name'=>'name19'),
array('id'=>20,'pid'=>3,'name'=>'name20'),
array('id'=>21,'pid'=>3,'name'=>'name21'),
array('id'=>22,'pid'=>2,'name'=>'name22'),
);
$result=array();
$id=2;
$lv=20;
get_child_node_nums($id,$lv,$result);
foreach($resultas$no=>$row)
{
echo'第'.($lv-$no+1).'層有'.count($row).'個葉子節點'.'<br/>';
}
p($result);
//模擬mysql根據pid獲取多行記錄
functionfetch_rows($pid=0)
{
global$data;
$pid=(int)$pid;
$items=array();
//相當於sql語句:select*fromtestwherepid=$pid
echo"select*fromtestwherepid=$pid;<br/>";
foreach($dataas$row)
{
if($row['pid']==$pid)
{
$items[]=$row;
}
}
return$items;
}
//$id為父節點id,$lv為深度,$result為引用傳值結果數組
functionget_child_node_nums($id,$lv,&$result)
{
//首先根據其id作為子節點的pid獲取其所有子節點
$children=fetch_rows($id);
if($children)
{
//存儲其葉子節點
if(isset($result[$lv]))
{
$result[$lv]=array_merge($result[$lv],$children);
}else{
$result[$lv]=$children;
}
$lv--;
if($lv>0)
{
foreach($childrenas$child)
{
$id=$child['id'];
get_child_node_nums($id,$lv,$result);
}
}
}
}
functionp($var)
{
echo'<pre>';
if($var===false)
{
echo'false';
}elseif($var===null){
print_r("null");
}elseif($var===''){
print_r("''");
}else{
print_r($var);
}
echo'</pre>';
}
輸出結果如下:
select*fromtestwherepid=2;
select*fromtestwherepid=3;
select*fromtestwherepid=4;
select*fromtestwherepid=20;
select*fromtestwherepid=21;
select*fromtestwherepid=5;
select*fromtestwherepid=6;
select*fromtestwherepid=7;
select*fromtestwherepid=8;
select*fromtestwherepid=9;
select*fromtestwherepid=10;
select*fromtestwherepid=11;
select*fromtestwherepid=12;
select*fromtestwherepid=13;
select*fromtestwherepid=14;
select*fromtestwherepid=15;
select*fromtestwherepid=22;
第1層有5個葉子節點
第2層有4個葉子節點
第3層有1個葉子節點
第4層有1個葉子節點
第5層有1個葉子節點
第6層有1個葉子節點
第7層有1個葉子節點
第8層有1個葉子節點
第9層有1個葉子節點
Array
(
[20]=>Array
(
[0]=>Array
(
[id]=>3
[pid]=>2
[name]=>name3
)
[1]=>Array
(
[id]=>5
[pid]=>2
[name]=>name5
)
[2]=>Array
(
[id]=>6
[pid]=>2
[name]=>name6
)
[3]=>Array
(
[id]=>7
[pid]=>2
[name]=>name7
)
[4]=>Array
(
[id]=>22
[pid]=>2
[name]=>name22
)
)
[19]=>Array
(
[0]=>Array
(
[id]=>4
[pid]=>3
[name]=>name4
)
[1]=>Array
(
[id]=>20
[pid]=>3
[name]=>name20
)
[2]=>Array
(
[id]=>21
[pid]=>3
[name]=>name21
)
[3]=>Array
(
[id]=>8
[pid]=>7
[name]=>name8
)
)
[18]=>Array
(
[0]=>Array
(
[id]=>9
[pid]=>8
[name]=>name9
)
)
[17]=>Array
(
[0]=>Array
(
[id]=>10
[pid]=>9
[name]=>name10
)
)
[16]=>Array
(
[0]=>Array
(
[id]=>11
[pid]=>10
[name]=>name11
)
)
[15]=>Array
(
[0]=>Array
(
[id]=>12
[pid]=>11
[name]=>name12
)
)
[14]=>Array
(
[0]=>Array
(
[id]=>13
[pid]=>12
[name]=>name13
)
)
[13]=>Array
(
[0]=>Array
(
[id]=>14
[pid]=>13
[name]=>name14
)
)
[12]=>Array
(
[0]=>Array
(
[id]=>15
[pid]=>14
[name]=>name15
)
)
)
親測,望採納^_^。
D. PHP,二叉樹,求一個演算法
var oNowNode;//現節點
var aArray;//所存數組
var i=0;
if(oNowNode.sibling.id>oNowNode.id){
alert(」位於左區「);
}else{
alert(」位於右區「);
}
while(oNowNode.id!=0){
oNowNode=oNowNode.parent;
aArray(i)=oNowNode.id;
i++;
}
print_r(aArray);
E. php-紅黑樹、散列表、跳錶理解入門
就是把鏈表的結構稍加改造,這種數據結構叫
為了提升鏈表的查詢效率,怎麼讓鏈表支持類似『數組』那樣的『二分』演算法呢
跳錶是一個各方面性能都比較優秀的 動態數據結構 ,可以支持快速地插入、刪除、查找操作,寫起來也不復雜,甚至可以替代紅黑樹。
Redis 中的有序集合(Sorted Set)就是用跳錶來實現的。
那 Redis 為什麼會選擇用跳錶(和散列表)來實現有序集合呢? 為什麼不用紅黑樹呢?這個問題一會在回答,先看看跳錶的數據結構
其實概念很簡單,就是在鏈表上加上了
當我們在不停插入數據,如果我們不更新索引,可能出現某 2 個索引結點之間數據非常多的情況。極端情況下,跳錶還會退化成單鏈表。
紅黑樹、AVL 樹這樣平衡二叉樹,是通過左右旋的方式保持左右子樹的大小平衡,而跳錶是通過 隨機函數 來維護平衡性。
插入、刪除、查找以及迭代輸出有序序列這幾個操作,紅黑樹也可以完成,時間復雜度跟跳錶是一樣的。但是, 按照區間來查找數據這個操作,紅黑樹的效率沒有跳錶高。
對於按照區間查找數據這個操作,跳錶可以做到 O(logn) 的時間復雜度定位區間的起點,然後在原始鏈表中順序往後遍歷就可以了。
Redis 鍵值構建一個散列表,這樣按照 key 來刪除、查找一個成員對象的時間復雜度就變成了 O(1)。同時,藉助跳錶結構,其他操作也非常高效。
散列表的英文叫「Hash Table」,我們平時也叫它「哈希表」或者「Hash 表」
散列技術是在記錄的存儲位置和它的關鍵字之間建立一個確定的對應關系 f,使得每個關鍵字 key 對應一個存儲位置 f(key)。查找時根據這個對應關系匠互給定的 key 的映射 f(key)
這種關系 f 稱為散列函數(又稱哈希函數)。散列技術將記錄存儲在一塊連續的存儲空間中,這塊連續存儲空間稱為散列表或哈希表。那麼關鍵字對應的記錄存儲位置稱為散列地址。
散列函數的構造方法特點就是:計算簡單、散列地址分布均勻
大家一定聽說過 hash 碰撞。就是2個不同的 key 對應著不同的 f 關系。但這是幾乎不可能的,即便像業界著名的MD5、SHA、CRC等哈希演算法,也無法完全避免這種散列沖突。而且,因為數組的存儲空間有限,也會加大散列沖突的概率。
我們只能通過其它途徑來尋找方法。我們常用的散列沖突解決方法有兩類,開放定址法(open addressing)和鏈表法(chaining)。
所謂的開放定址法就是一但發生了沖突,就去尋找下一個空的散地址,只要散列表足夠大,空的散列表地址總能找到,並將記錄存入。
鏈地址法又稱鏈表法,其實當發生沖突時存入鏈表,如下圖很容易就可以看明白。此時,已經不存在什麼沖突地址的問題,無論有多少沖突,都只是在當前位置給單鏈表增加結點的問題。
這種不常見,就是把沖突的單獨找個地方。
顧名思義,紅黑樹中的節點,一類被標記為黑色,一類被標記為紅色。除此之外,一棵紅黑
平衡二叉樹 是一種二叉排序樹,其中每一個節點的左子樹和右子樹的高度不能大於 1
紅黑樹是一種平衡二叉查找樹。它是為了解決普通二叉查找樹在數據更新的過程中,復雜度退化的問題而產生的。紅黑樹的高度近似 log2n,所以它是近似平衡,插入、刪除、查找操作的時間復雜度都是 O(logn)。
平衡二叉查找樹其實有很多,比如,Splay Tree(伸展樹)、Treap(樹堆)等,但是我們提到平衡二叉查找樹,聽到的基本都是紅黑樹。
紅黑樹在眾多裡面,表現的最為平衡。
「近似平衡」就等價為性能不會退化得太嚴重。
一棵紅黑樹還需要滿足這樣幾個要求:
看到這里你會很頭大,什麼黑的紅的,完全不懂。賦上連接,有時間在看
散列表 :插入刪除查找都是O(1), 是最常用的,但其缺點是不能順序遍歷(存入的數據是無順序的)以及擴容縮容的性能損耗。適用於那些不需要順序遍歷,數據更新不那麼頻繁的。
散列表總和鏈表、跳錶一起出現組合使用。
跳錶 :插入刪除查找都是O(logn), 並且能順序遍歷。缺點是空間復雜度O(n)。適用於不那麼在意內存空間的,其順序遍歷和區間查找非常方便。
跳錶還可以和散列表組合讓刪除、查找一個成員對象操作變為O(1),也就是說利用了散列表查找速度,跳錶的順序結構
紅黑樹 :插入刪除查找都是O(logn), 中序遍歷即是順序遍歷,穩定。缺點是難以實現,去查找不方便。其實跳錶更佳,但紅黑樹已經用於很多地方了。