這篇文章是介紹 二叉樹
和 二分搜索樹
,而後經過 PHP
代碼定義一下 二分搜索樹
的節點,使用遞歸思想操做向二分搜索樹
添加元素,而後實現了遞歸判斷二分搜索樹上是否包含某個元素,最後分別實現了前序遍歷
、中序遍歷
、後序遍歷
二分搜索樹。php
//二叉樹具備惟一根節點 class Node{ $e; //節點元素 $left; //左兒子 $right;//右兒子 }
Tips:二叉樹每一個節點最多有兩個兒子,每一個節點最多有一個父親。
二叉樹
。
class Node { public $e; public $left = null; public $right = null; /** * 構造函數 初始化節點數據 * Node constructor. * @param $e */ public function __construct($e) { $this->e = $e; } }
下面展現的的使用遞歸思想向二分搜索樹添加元素,其中 add($e)
方法表示想二分搜索樹添加元素 $e
,recursionAdd(Node $root, $e)
是一個遞歸函數,表示使用遞歸向二分搜索樹添加元素:git
/** * 向二分搜索樹添加元素 * @param $e */ public function add($e) { $this->root = $this->recursionAdd($this->root, $e); } /** * 遞歸向二分搜索樹添加元素 * @param Node $root * @param $e */ public function recursionAdd(Node $root, $e) { if ($root == null) { //若節點爲空則添加元素 而且返回當前節點信息 $this->size++; $root = new Node($e); } elseif ($e < $root->e) { //若元素小於當前節點元素 則向左節點遞歸添加元素 $root->left = $this->recursionAdd($root->left, $e); } elseif ($e > $root->e) { //若元素大於當前節點元素 則向右節點遞歸添加元素 $root->right = $this->recursionAdd($root->right, $e); } //若元素等於當前節點元素 則什麼都不作 }
Tips:這裏的二分搜索樹不包含重複元素,若是想要包含重複元素,能夠定義每一個左兒子全部元素小於等於父親節點,或者每一個節點右兒子全部節點元素大於等於父親節點。
下面展現的的使用遞歸思想查詢二分搜索樹元素是否包含某個元素,其中 contains($e)
方法表示查詢二分搜索樹是否包含元素 $e
,recursionContains(Node $root, $e)
是一個遞歸函數,表示使用遞歸查詢二分搜索樹元素:函數
/** * 判斷二分搜索樹是否包含某個元素 * @param $e * @return bool */ public function contains($e): bool { return $this->recursionContains($this->root, $e); } /** * 遞歸判斷二分搜索樹是否包含某元素 * @param $root * @param $e * @return bool */ private function recursionContains(Node $root, $e): bool { if ($root == null) { //若當前節點爲空 則表示不存在元素 $e return false; } elseif ($e == $root->e) { //若 $e 等於當前節點元素,則表示樹包含元素 $e return true; } elseif ($e < $root->e) { //若 $e 小於當前節點元素,則去左兒子樹遞歸查詢是否包含節點 return $this->recursionContains($root->left, $e); } else { //若 $e 大於當前節點元素,則去右兒子樹遞歸查詢是否包含節點 return $this->recursionContains($root->right, $e); } }
Tips:遞歸的時候會比較元素和節點的值,遞歸的時候判斷元素大小至關於 「指路」,最終指向到的位置就是判斷是否包含元素是否存在的依據。
前序遍歷操做就是把全部節點都訪問一次,前序遍歷
是先訪問節點,再遞歸遍歷左兒子樹,而後再遞歸遍歷右兒子樹:ui
/** * 前序遍歷 */ public function preTraversal() { $this->recursionPreTraversal($this->root, 0); } /** * 前序遍歷的遞歸 */ public function recursionPreTraversal($root, $sign_num) { echo $this->getSign($sign_num);//打印深度 if ($root == null) { echo "null<br>"; return; } echo $root->e . "<br>"; //打印當前節點元素 $this->recursionPreTraversal($root->left, $sign_num + 1); $this->recursionPreTraversal($root->right, $sign_num + 1); }
下面是打印結果:this
<?php require 'BinarySearchTree.php'; $binarySearchTree = new BinarySearchTree(); $binarySearchTree->add(45); $binarySearchTree->add(30); $binarySearchTree->add(55); $binarySearchTree->add(25); $binarySearchTree->add(35); $binarySearchTree->add(50); $binarySearchTree->add(65); $binarySearchTree->add(15); $binarySearchTree->add(27); $binarySearchTree->add(31); $binarySearchTree->add(48); $binarySearchTree->add(60); $binarySearchTree->add(68); //下面是預期想要的結果 /** * 45 * / * 30 55 * / / * 25 35 50 65 * / / / / * 15 27 31 48 60 68 * */ $binarySearchTree->preTraversal(); /** 打印輸出 45 -----30 ----------25 ---------------15 --------------------null --------------------null ---------------27 --------------------null --------------------null ----------35 ---------------31 --------------------null --------------------null ---------------null -----55 ----------50 ---------------48 --------------------null --------------------null ---------------null ----------65 ---------------60 --------------------null --------------------null ---------------68 --------------------null --------------------null */
Tips:能夠看到打印輸出結果和預期一致。
遍歷操做就是把全部節點都訪問一次,後序遍歷
是先遞歸遍歷右兒子樹,再訪問節點,而後再遞歸遍歷右兒子樹,最後的順序輸出結果是有序的
:spa
/** * 中序遍歷 */ public function midTraversal() { $this->recursionMidTraversal($this->root, 0); } /** * 中序遍歷的遞歸 */ public function recursionMidTraversal($root, $sign_num) { if ($root == null) { echo $this->getSign($sign_num);//打印深度 echo "null<br>"; return; } $this->recursionMidTraversal($root->left, $sign_num + 1); echo $this->getSign($sign_num);//打印深度 echo $root->e . "<br>"; $this->recursionMidTraversal($root->right, $sign_num + 1); }
下面是打印結果:code
<?php require 'BinarySearchTree.php'; $binarySearchTree = new BinarySearchTree(); $binarySearchTree->add(45); $binarySearchTree->add(30); $binarySearchTree->add(55); $binarySearchTree->add(25); $binarySearchTree->add(35); $binarySearchTree->add(50); $binarySearchTree->add(65); $binarySearchTree->add(15); $binarySearchTree->add(27); $binarySearchTree->add(31); $binarySearchTree->add(48); $binarySearchTree->add(60); $binarySearchTree->add(68); //下面是預期想要的結果 /** * 45 * / * 30 55 * / / * 25 35 50 65 * / / / / * 15 27 31 48 60 68 * */ $binarySearchTree->midTraversal(); /** 打印輸出 --------------------null ---------------15 --------------------null ----------25 --------------------null ---------------27 --------------------null -----30 --------------------null ---------------31 --------------------null ----------35 ---------------null 45 --------------------null ---------------48 --------------------null ----------50 ---------------null -----55 --------------------null ---------------60 --------------------null ----------65 --------------------null ---------------68 --------------------null */
Tips:能夠看到打印輸出結果和預期一致,可是此時的遍歷順序變了,最後的順序輸出結果是
有序的
。
遍歷操做就是把全部節點都訪問一次,後序遍歷
是先遞歸遍歷左兒子樹,而後再遞歸遍歷右兒子樹,再訪問節點:blog
/** * 後序遍歷 */ public function rearTraversal() { $this->recursionRearTraversal($this->root, 0); } /** * 後序遍歷的遞歸 */ public function recursionRearTraversal($root, $sign_num) { if ($root == null) { echo $this->getSign($sign_num);//打印深度 echo "null<br>"; return; } $this->recursionRearTraversal($root->left, $sign_num + 1); $this->recursionRearTraversal($root->right, $sign_num + 1); echo $this->getSign($sign_num);//打印深度 echo $root->e . "<br>"; }
下面是打印結果:遞歸
<?php require 'BinarySearchTree.php'; $binarySearchTree = new BinarySearchTree(); $binarySearchTree->add(45); $binarySearchTree->add(30); $binarySearchTree->add(55); $binarySearchTree->add(25); $binarySearchTree->add(35); $binarySearchTree->add(50); $binarySearchTree->add(65); $binarySearchTree->add(15); $binarySearchTree->add(27); $binarySearchTree->add(31); $binarySearchTree->add(48); $binarySearchTree->add(60); $binarySearchTree->add(68); //下面是預期想要的結果 /** * 45 * / * 30 55 * / / * 25 35 50 65 * / / / / * 15 27 31 48 60 68 * */ $binarySearchTree->rearTraversal(); /** 打印輸出 --------------------null --------------------null ---------------15 --------------------null --------------------null ---------------27 ----------25 --------------------null --------------------null ---------------31 ---------------null ----------35 -----30 --------------------null --------------------null ---------------48 ---------------null ----------50 --------------------null --------------------null ---------------60 --------------------null --------------------null ---------------68 ----------65 -----55 45 */
代碼倉庫 :https://gitee.com/love-for-po...ip
掃碼關注愛因詩賢