1. 遍历准则
前序遍历:先遍历以后结点,再遍历以后结点的左儿子,最初遍历以后结点的右儿子
中序遍历:先遍历以后结点的左儿子,再遍历以后结点,最初遍历以后结点的右儿子
后续遍历:先遍历以后结点的左儿子,再遍历以后结点的右儿子,最初遍历以后结点
2. 前序遍历示意图
3. 中序遍历示意图
4. 后序遍历示意图
5. 二分搜寻树的递归遍历实现
<?phpnamespace TreeBundle;use ArrayBundle\BaseArray;use StackBundle\BaseStack;class BaseBinaryTree{ public function __construct() { $this->rootNode = null; $this->size = 0; } /** * 二叉树的根节点 * @var Node */ protected $rootNode; /** * 获取根节点 * @return Node */ public function getRootNode(): Node { return $this->rootNode; } /** * 二叉树的个数 * @var int */ protected $size; /** * 获取二叉树的元素个数 * @return int */ public function getSize(): int { return $this->size; } /** * 判断是否为空 * @return bool */ public function isEmpty(): bool { return $this->size == 0; } /** * 插入结点 * @param mixed $value * @return void */ public function add($value): void { // 如果不存在根节点就插入根节点 if (is_null($this->rootNode)) { $this->rootNode = new Node($value); $this->size; return; } else { $this->addChild($value, $this->rootNode); return; } } /** * 插入儿子结点 * @param mixed $value * @param Node|null $parentNode */ private function addChild($value, ?Node $parentNode): void { if (bccomp($parentNode->getValue(), $value) > 0) { // 左儿子 if (is_null($parentNode->getLeftChild())) { $parentNode->setLeftChild(new Node($value)); $this->size++; return; } else { $this->addChild($value, $parentNode->getLeftChild()); } } elseif (bccomp($parentNode->getValue(), $value) < 0) { // 右儿子 if (is_null($parentNode->getRightChild())) { $parentNode->setRightChild(new Node($value)); $this->size++; return; } else { $this->addChild($value, $parentNode->getRightChild()); } } else { return; } } const TRAVERSAL_PREORDER = 1; // 先序遍历 const TRAVERSAL_INORDER = 2; // 中序遍历 const TRAVERSAL_POSTORDER = 3; // 后序遍历 /** * 遍历二叉树 * @param int $traversalType * @return string */ public function traversal(int $traversalType = 1): string { $result = ''; switch ($traversalType) { case self::TRAVERSAL_PREORDER: $this->preorderTraversal($result, $this->rootNode); break; case self::TRAVERSAL_INORDER: $this->inorderTraversal($result, $this->rootNode); break; case self::TRAVERSAL_POSTORDER: $this->postorderTraversal($result, $this->rootNode); break; default: break; } return $result; } /** * 先序遍历 * @param string $result 后果值 * @param Node|null $node 结点 * @return void */ protected function preorderTraversal(string &$result, ?Node $node): void { if (is_null($node)) return; // 拼接 if ($result != '') $result .= ' -> '; // 先遍历以后节点 $result .= $node->getValue(); // 再遍历左儿子 $this->preorderTraversal($result, $node->getLeftChild()); // 在遍历右儿子 $this->preorderTraversal($result, $node->getRightChild()); return; } /** * 中序遍历 * @param string $result 后果值 * @param Node|null $node 结点 * @return void */ public function inorderTraversal(string &$result, ?Node $node): void { if (is_null($node)) return; // 先遍历左儿子 $this->inorderTraversal($result, $node->getLeftChild()); // 拼接 if ($result != '') $result .= ' -> '; // 再获取以后结点 $result .= $node->getValue(); // 在遍历右儿子 $this->inorderTraversal($result, $node->getRightChild()); return; } /** * 后序遍历 * @param string $result 后果值 * @param Node|null $node 结点 * @return void */ public function postorderTraversal(string &$result, ?Node $node): void { if (is_null($node)) return; // 先遍历左儿子 $this->postorderTraversal($result, $node->getLeftChild()); // 在遍历右儿子 $this->postorderTraversal($result, $node->getRightChild()); // 拼接 if ($result != '') $result .= ' -> '; // 再获取以后结点 $result .= $node->getValue(); return; }}
6. demo
<?php// composer主动加载require_once __DIR__ . '/../../vendor/autoload.php';// 获取一个二分搜寻树$tree = new TreeBundleBaseBinaryTree();// 插入结点$tree->add(10);$tree->add(5);$tree->add(15);$tree->add(1);$tree->add(0);$tree->add(2);$tree->add(9);$tree->add(8);$tree->add(11);$tree->add(12);$tree->add(19);$tree->add(18);$tree->add(29);$tree->add(16);$tree->add(17);// 前序遍历echo $tree->traversal(TreeBundleBaseBinaryTree::TRAVERSAL_PREORDER). PHP_EOL;// 中序遍历echo $tree->traversal(TreeBundleBaseBinaryTree::TRAVERSAL_INORDER). PHP_EOL;// 后续遍历echo $tree->traversal(TreeBundleBaseBinaryTree::TRAVERSAL_POSTORDER). PHP_EOL;
打印后果:
10 -> 5 -> 1 -> 0 -> 2 -> 9 -> 8 -> 15 -> 11 -> 12 -> 19 -> 18 -> 16 -> 17 -> 290 -> 1 -> 2 -> 5 -> 8 -> 9 -> 10 -> 11 -> 12 -> 15 -> 16 -> 17 -> 18 -> 19 -> 290 -> 2 -> 1 -> 8 -> 9 -> 5 -> 12 -> 11 -> 17 -> 16 -> 18 -> 29 -> 19 -> 15 -> 10