回來更新一波,最近刷《劍指offer》,才又發現樹真是一個大頭,二叉樹的題目和變化運用好多啊~node
/** * PHP二叉樹算法 * Created on 2017-5-6 * Update on 2017-8-10 * Author entner * Email 1185087164@qq.com */
不少人說二叉樹沒什麼卵用,我以爲是他的工資和公司讓他跨不過這個坎;還有不少人學了一些樹的知識,發現也用不上,我想說的是,讀一本書體現不了這本書的價值,要多讀幾本纔會把你和別人的差異體現出來。
二叉樹是嚴格定義的,有很好的對稱性和比較高的數據關聯度,對數據的存儲和計算,有很好的演示做用,好比徹底二叉樹:算法
固然,二叉樹更適合鏈表存儲,效率更高,總的來講,以二叉樹爲基礎咱們能夠衍生出許多神奇的運用,舉幾個經常使用的場景爲我說的話正言:數組
遊戲場景劃分、監測、渲染數據結構
我認可,上面好多東西你並不會直接接觸,可是,咱們關鍵是去學習一種思惟和設計,退一萬步也能夠增長一點見識:)
關於書的操做太多了,我只列一些經常使用的(這些都是常考的知識點),有興趣的相信也有技能去淘到「好貨」 -InitTree 構造空樹 -PreTra 返回樹中某結點的值 -InTra 給樹中某結點賦值爲value -LevelTra 返回某非根結點的雙親,不然返回空 -LeftChild 返回某非葉結點的最左孩子,不然返回空
默寫會讓你記憶更深入,同時也會鍛鍊抽象的邏輯思惟,一邊看不懂,就多看幾遍,再查一查相關資料,應該問題不大,你甚至能夠找張紙默寫一下。
/** *InitTree 初始化樹 * * Typedef int TElementType //構造一個數據類型 Typedef Struct Tree{ //構造二叉樹抽象數據類型 TElementType data; //聲明一個數組,先構建一個樹 Struct Tree *leftChild; //左孩子節點 Struct Tree *rightChild; //右孩子節點 }Tree; */ /** * Value 獲取樹的結點(前序遍歷) * Return 返回獲取的結點值 Status Value(Tree *T,int e){ if(T == null){ return error; } e = T->Value(T->leftChild); e = T->Value(T->rightChild); return e; } */ /** * Assign 給樹中某結點賦值爲v(前序遍歷) * Return 返回賦值後的結點值 Status Assign(Tree *T,int e, TElementType v){ if(T == null){ return error; } e = T->Assign(T->leftChild); e = T->Assign(T->rightChilg); e = v; return e; } */
/** * PHP二叉樹算法 * Created on 2017-8-7 * Author entner * Email 1185087164@qq.com */ /* 假設我構造一顆以下的二叉樹 A B C # D # # # # */ error_reporting(E_ALL ^ E_NOTICE); $data = array( 0=>'A', 1=>'B', 2=>'#', 3=>'D', 4=>'#', 5=>'#', 6=>'C', 7=>'#', 8=>'#', ); Class BTNode{ public $data; public $lChild; public $rChild; public function __construct($data = null){ $this->data = $data; } } Class BinaryTree{ public $root; public $btData; public function __construct($data = null){ $this->root = null; $this->btData = $data; //$this->preOrderCreateBT($this->root); } public function preOrderCreateBT(&$root = null){ $elem = array_shift($this->btData); //移除數組頭部,並做爲結果返回 if($elem == null){ #判斷:當數組爲空時 return ; }else if($elem == '#'){ #判斷:當數組爲無效單元時,該節點是虛節點,退出當前遞歸,執行下一個遞歸 $root = '#'; return $root; }else{ $root = new BTNode(); $root->data = $elem; $this->preOrderCreateBT($root->lChild); $this->preOrderCreateBT($root->rChild); } return $root; } /** * TODO:先序遍歷二叉樹 * @param $tree object 二叉樹 * @param $temp array 二叉樹輸出節點存儲數組 */ public function printBTPreOrder($tree,&$temp){ if($tree != null){ $temp[] = $tree->data; $this->printBTPreOrder($tree->lChild,$temp); $this->printBTPreOrder($tree->rChild,$temp); }else{ return ; } return $temp; } /** * TODO:中序遍歷二叉樹 * @param $tree object 二叉樹 * @param $temp array 二叉樹輸出節點存儲數組 */ public function printBTInOrder($tree,&$temp){ if($tree != null){ $this->printBTInOrder($tree->lChild,$temp); $temp[] = $tree->data; $this->printBTInOrder($tree->rChild,$temp); }else{ return; } return $temp; } /** * TODO:中序遍歷二叉樹 * @param $tree object 二叉樹 * @param $temp array 二叉樹輸出節點存儲數組 */ public function printBTPosOrder($tree,&$temp){ if($tree != null){ $this->printBTPosOrder($tree->lChild,$temp); $this->printBTPosOrder($tree->rChild,$temp); $temp[] = $tree->data; }else{ return; } return $temp; } /** * TODO:層序遍歷二叉樹(須要將書中節點放入隊中) * */ function PrintFromTopToBottom(&$root) { // write code here if($root == null){ return ; } $queue = array(); array_push($queue,$root); while(!is_null($node = array_shift($queue))){ echo $node->data . ' '; if($node->left != null){ array_push($queue,$node->lChild); } if($node->left != null){ array_push($queue,$node->rChild); } } } } $object = new BinaryTree($data); $tree = $object->preOrderCreateBT($root); echo "<pre>"; print_r($tree);die;
/** *FindBitTree 二叉樹查找 *@param T BItTree 代指二叉樹及其元素結點 *@param key int 樹中某結點 *@param f point 指向該結點父結點 *@param p point 指向該元素結點或空 *@param return bool true|false status SearchBST(BitTree T,int key,BitTree f = null,BitTree p){ if(!T){ p = f; return false; } if(key == T->data){ p = T;//其實就是根結點 return true; }else if(key <T->data){ SearchBST(T->lChild,int key,T,p); }else if(key >T->data){ SearchBST(T->rChild,int key,T,p); } } */ /** InsertBitTree 二叉樹插入 *【若是當前樹中沒有key元素,則插入,插入的結點必定是葉子結點】 *@param T BItTree 代指二叉樹及其元素結點 *@param key int 樹中某結點 *@param return bool true|false status InsertBST(BitTree T,int key){ if(SearchBST(T,key,NULL,&p) == false){ s->data = key; s->lChild = s->rChild = NULL; if(!p){ T= s; }else if(key < p->data){ p->lChild = s; }else{ p->rChild = s; } return true; } return false; } */
$items = array( 1 => array('id' => 1, 'pid' => 0, 'name' => '江西省'), 2 => array('id' => 2, 'pid' => 0, 'name' => '黑龍江省'), 3 => array('id' => 3, 'pid' => 1, 'name' => '南昌市'), 4 => array('id' => 4, 'pid' => 2, 'name' => '哈爾濱市'), 5 => array('id' => 5, 'pid' => 2, 'name' => '雞西市'), 6 => array('id' => 6, 'pid' => 4, 'name' => '香坊區'), 7 => array('id' => 7, 'pid' => 4, 'name' => '南崗區'), 8 => array('id' => 8, 'pid' => 6, 'name' => '和興路'), 9 => array('id' => 9, 'pid' => 7, 'name' => '西大直街'), 10 => array('id' => 10, 'pid' => 8, 'name' => '東北林業大學'), 11 => array('id' => 11, 'pid' => 9, 'name' => '哈爾濱工業大學'), 12 => array('id' => 12, 'pid' => 8, 'name' => '哈爾濱師範大學'), 13 => array('id' => 13, 'pid' => 1, 'name' => '贛州市'), 14 => array('id' => 14, 'pid' => 13, 'name' => '贛縣'), 15 => array('id' => 15, 'pid' => 13, 'name' => '於都縣'), 16 => array('id' => 16, 'pid' => 14, 'name' => '茅店鎮'), 17 => array('id' => 17, 'pid' => 14, 'name' => '大田鄉'), 18 => array('id' => 18, 'pid' => 16, 'name' => '義源村'), 19 => array('id' => 19, 'pid' => 16, 'name' => '上壩村'), ); /** *TODO:經過引用方式實現無限極分類 * */ function tree_Classify1($items){ $tree=array(); $packData=array(); foreach ($items as $data) { $packData[$data['id']] = $data; } foreach ($packData as $key =>$val){ if($val['pid']==0){//表明跟節點 $tree[]=& $packData[$key]; }else{ //找到其父類 $packData[$val['pid']]['son'][]=& $packData[$key]; } } return $tree; } /** *TODO:經過遞歸方式實現無限極分類 * */ function tree_Classify2($items,$child='_child',$root = 0){ $tree=array(); foreach($items as $key=> $val){ if($val['pid']==0){ //獲取當前$pid全部子類 unset($items[$key]); if(! empty($items)){ $child=make_tree1($items,$child,$val['id']); if(!empty($child)){ $val['_child']=$child; } } $tree[]=$val; } } return $tree; } echo "<pre>"; print_r(make_tree1($items,$child='_child',$root=0)); ``