摘要:回來更新一波,最近刷劍指,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊二叉樹算法引子很多人說二叉樹沒什么卵用,我覺得是他的工資和公司讓他跨不過這個坎還有很多人學(xué)了一些樹的知識,發(fā)現(xiàn)也用不上,我想說的是,讀一本書體現(xiàn)不了這本書
回來更新一波,最近刷《劍指offer》,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊~
/** * PHP二叉樹算法 * Created on 2017-5-6 * Update on 2017-8-10 * Author entner * Email [email protected] */引子
????很多人說二叉樹沒什么卵用,我覺得是他的工資和公司讓他跨不過這個坎;還有很多人學(xué)了一些樹的知識,發(fā)現(xiàn)也用不上,我想說的是,讀一本書體現(xiàn)不了這本書的價(jià)值,要多讀幾本才會把你和別人的差別體現(xiàn)出來。
????二叉樹是嚴(yán)格定義的,有很好的對稱性和比較高的數(shù)據(jù)關(guān)聯(lián)度,對數(shù)據(jù)的存儲和計(jì)算,有很好的演示作用,比如完全二叉樹:
????當(dāng)然,二叉樹更適合鏈表存儲,效率更高,總的來說,以二叉樹為基礎(chǔ)我們可以衍生出許多神奇的運(yùn)用,舉幾個常用的場景為我說的話正言:
編譯器表達(dá)式處理
快速查找與排序
文件壓縮
文件系統(tǒng)管理
游戲場景劃分、監(jiān)測、渲染
我承認(rèn),上面好多東西你并不會直接接觸,但是,我們關(guān)鍵是去學(xué)習(xí)一種思維和設(shè)計(jì),退一萬步也可以增加一點(diǎn)見識:)一、二叉樹抽象數(shù)據(jù)類型操作條目
關(guān)于書的操作太多了,我只列一些常用的(這些都是??嫉闹R點(diǎn)),有興趣的相信也有技能去淘到“好貨” -InitTree 構(gòu)造空樹 -PreTra 返回樹中某結(jié)點(diǎn)的值 -InTra 給樹中某結(jié)點(diǎn)賦值為value -LevelTra 返回某非根結(jié)點(diǎn)的雙親,否則返回空 -LeftChild 返回某非葉結(jié)點(diǎn)的最左孩子,否則返回空二、默寫二叉樹常用數(shù)據(jù)結(jié)構(gòu)
默寫會讓你記憶更深刻,同時(shí)也會鍛煉抽象的邏輯思維,一邊看不懂,就多看幾遍,再查一查相關(guān)資料,應(yīng)該問題不大,你甚至可以找張紙默寫一下。
/** *InitTree 初始化樹 * * Typedef int TElementType //構(gòu)造一個數(shù)據(jù)類型 Typedef Struct Tree{ //構(gòu)造二叉樹抽象數(shù)據(jù)類型 TElementType data; //聲明一個數(shù)組,先構(gòu)建一個樹 Struct Tree *leftChild; //左孩子節(jié)點(diǎn) Struct Tree *rightChild; //右孩子節(jié)點(diǎn) }Tree; */ /** * Value 獲取樹的結(jié)點(diǎn)(前序遍歷) * Return 返回獲取的結(jié)點(diǎn)值 Status Value(Tree *T,int e){ if(T == null){ return error; } e = T->Value(T->leftChild); e = T->Value(T->rightChild); return e; } */ /** * Assign 給樹中某結(jié)點(diǎn)賦值為v(前序遍歷) * Return 返回賦值后的結(jié)點(diǎn)值 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; } */三、二叉樹結(jié)構(gòu)基本實(shí)現(xiàn)
/** * PHP二叉樹算法 * Created on 2017-8-7 * Author entner * Email [email protected] */ /* 假設(shè)我構(gòu)造一顆如下的二叉樹 A B C # D # # # # */ error_reporting(E_ALL ^ E_WARNING); Class BinaryTree{ public $lChild; public $rChild; public $value; /* 初始化構(gòu)造空樹 */ public function __construct($data = null){ $this->value = $data; } /** * TODO:構(gòu)建二叉樹 * @param $root object 二叉樹 */ public function preOrderCreateBT(&$root){ while(!is_null($elem = array_shift($this->value))){ $root = ""; if($elem == null){ #判斷:當(dāng)數(shù)組為空時(shí) return $root; }else if($elem == "#"){ #判斷:當(dāng)數(shù)組為無效單元時(shí),該節(jié)點(diǎn)是虛節(jié)點(diǎn)(無孩子節(jié)點(diǎn)),退出當(dāng)前遞歸,執(zhí)行下一個遞歸 $root->value = "#"; return ; }else{ $root->value = $elem; $this->preOrderCreateBT($root->lChild); $this->preOrderCreateBT($root->rChild); } } return $root; } /** * TODO:先序遍歷二叉樹 * @param $tree object 二叉樹 * @param $temp array 二叉樹輸出節(jié)點(diǎn)存儲數(shù)組 */ 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 二叉樹輸出節(jié)點(diǎn)存儲數(shù)組 */ 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 二叉樹輸出節(jié)點(diǎn)存儲數(shù)組 */ 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:層序遍歷二叉樹(需要將書中節(jié)點(diǎn)放入隊(duì)中) * */ function PrintFromTopToBottom(&$root) { // write code here $queueVal = array(); $queue = array(); if($root == null){ return $queueVal; #注意當(dāng)二叉樹為空樹時(shí),應(yīng)該返回空數(shù)組 } array_push($queue,$root); while($queue){ $node = array_shift($queue); array_push($queueVal,$node->value); if($node->lChild != null){ array_push($queue,$node->lChild); } if($node->rChild != null){ array_push($queue,$node->rChild); } } return $queueVal; } /** * TODO:樹的深度 * */ public function treeDeepth(&$root){ if($root == null){ return 0; } if($root != null){ $ld = $this->treeDeepth($root->lChild) + 1; $rd = $this->treeDeepth($root->rChild) + 1; } $max = max($ld,$rd); return $max; } } $node = array( 0=>"A", 1=>"B", 2=>"#", 3=>"D", 4=>"#", 5=>"#", 6=>"C", 7=>"#", 8=>"#", ); $object = new BinaryTree($node); $tree = $object->preOrderCreateBT(); echo ""; print_r($tree); echo $object->treeDeepth($tree) . "四、二叉排序樹
"; print_r($object->PrintFromTopToBottom($tree)); 以下為效果圖: 分別是構(gòu)造樹的結(jié)構(gòu)、樹的深度、層序遍歷輸出 ![圖片描述][3]/** *FindBitTree 二叉樹查找 *@param T BItTree 代指二叉樹及其元素結(jié)點(diǎn) *@param key int 樹中某結(jié)點(diǎn) *@param f point 指向該結(jié)點(diǎn)父結(jié)點(diǎn) *@param p point 指向該元素結(jié)點(diǎn)或空 *@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;//其實(shí)就是根結(jié)點(diǎn) return true; }else if(key五、樹應(yīng)用實(shí)現(xiàn)-無限極分類(引用&遞歸)data){ SearchBST(T->lChild,int key,T,p); }else if(key >T->data){ SearchBST(T->rChild,int key,T,p); } } */ /** InsertBitTree 二叉樹插入 *【如果當(dāng)前樹中沒有key元素,則插入,插入的結(jié)點(diǎn)一定是葉子結(jié)點(diǎn)】 *@param T BItTree 代指二叉樹及其元素結(jié)點(diǎn) *@param key int 樹中某結(jié)點(diǎn) *@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" => "香坊區(qū)"), 7 => array("id" => 7, "pid" => 4, "name" => "南崗區(qū)"), 8 => array("id" => 8, "pid" => 6, "name" => "和興路"), 9 => array("id" => 9, "pid" => 7, "name" => "西大直街"), 10 => array("id" => 10, "pid" => 8, "name" => "東北林業(yè)大學(xué)"), 11 => array("id" => 11, "pid" => 9, "name" => "哈爾濱工業(yè)大學(xué)"), 12 => array("id" => 12, "pid" => 8, "name" => "哈爾濱師范大學(xué)"), 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" => "茅店鎮(zhèn)"), 17 => array("id" => 17, "pid" => 14, "name" => "大田鄉(xiāng)"), 18 => array("id" => 18, "pid" => 16, "name" => "義源村"), 19 => array("id" => 19, "pid" => 16, "name" => "上壩村"), ); /** *TODO:通過引用方式實(shí)現(xiàn)無限極分類 * */ 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){//代表跟節(jié)點(diǎn) $tree[]=& $packData[$key]; }else{ //找到其父類 $packData[$val["pid"]]["son"][]=& $packData[$key]; } } return $tree; } /** *TODO:通過遞歸方式實(shí)現(xiàn)無限極分類 * */ function tree_Classify2($items,$child="_child",$root = 0){ $tree=array(); foreach($items as $key=> $val){ if($val["pid"]==0){ //獲取當(dāng)前$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 ""; print_r(make_tree1($items,$child="_child",$root=0)); `` [1]: /img/bV7ljv [2]: /img/bV7ljz
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/25964.html
摘要:回來更新一波,最近刷劍指,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊二叉樹算法引子很多人說二叉樹沒什么卵用,我覺得是他的工資和公司讓他跨不過這個坎還有很多人學(xué)了一些樹的知識,發(fā)現(xiàn)也用不上,我想說的是,讀一本書體現(xiàn)不了這本書 回來更新一波,最近刷《劍指offer》,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊~ /** * PHP二叉樹算法 * Create...
摘要:當(dāng)集合為空時(shí),稱該二叉樹為空二叉樹。也就是說,如果一個二叉樹的層數(shù)為,且結(jié)點(diǎn)總數(shù)是,則它就是滿二叉樹。完全二叉樹完全二叉樹是效率很高的數(shù)據(jù)結(jié)構(gòu),完全二叉樹是由滿二叉樹而引出來的。 ...
摘要:二叉搜索樹是二叉樹的一種,其特征是左側(cè)子節(jié)點(diǎn)存儲比父節(jié)點(diǎn)小的值,右側(cè)子節(jié)點(diǎn)存儲比父節(jié)點(diǎn)大或等于父節(jié)點(diǎn)的值。實(shí)現(xiàn)和這個兩個方法其實(shí)挺簡單的,最小的節(jié)點(diǎn)就在二叉搜索樹的最左反之,最大的就在最右。 本系列所有文章:第一篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之棧與隊(duì)列第二篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之鏈表第三篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之集合第四篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之字典和散列表第五篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)...
摘要:例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹并返回。操作給定的二叉樹,將其變換為源二叉樹的鏡像。劍指中還有一道類似的變種題目,就是下面的這道,之字形遍歷二叉樹。最后下面的兩道題目分別運(yùn)用了二叉樹先序中序遍歷算法。 開篇 以下內(nèi)容可能偏應(yīng)試但很好理解,所以大家一定要堅(jiān)持看下去,因?yàn)槲覀冏儚?qiáng)的過程注定孤獨(dú)的,堅(jiān)持下來就會看到明天的太陽。 回顧 showImg(https://user-...
摘要:二叉樹是數(shù)據(jù)結(jié)構(gòu)中很重要的結(jié)構(gòu)類型,學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)也是深入學(xué)習(xí)編程的必由之路,這里我們簡單介紹下我對于二叉樹的理解,水平有限,如有錯誤還請不吝賜教。 二叉樹是數(shù)據(jù)結(jié)構(gòu)中很重要的結(jié)構(gòu)類型,學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)也是深入學(xué)習(xí)編程的必由之路,這里我們簡單介紹下我對于二叉樹的理解,水平有限,如有錯誤還請不吝賜教。 首先照例定義一個二叉樹的節(jié)點(diǎn)類 class Node { private int ...
閱讀 2382·2023-04-26 00:01
閱讀 832·2021-10-27 14:13
閱讀 1882·2021-09-02 15:11
閱讀 3415·2019-08-29 12:52
閱讀 561·2019-08-26 12:00
閱讀 2597·2019-08-26 10:57
閱讀 3438·2019-08-26 10:32
閱讀 2873·2019-08-23 18:29