树是一种非线性的数据结构,它类比于实际生活中的树。在树结构中每个元素称为一个节点,有一个根节点,之后是子节点,那些没有子节点的结点我们称为叶子结点。
树有几个概念:
- 节点的高度:节点到叶子节点的最长路径所包含的边数
- 节点的深度:根节点到节点的路径所包含的边数
- 节点的层数:节点的深度+1(根节点的层数是1)
- 树的高度:等于根节点的高度
二叉树相关概念
- 每个结点最多有两个子节点,分别为左子节点和右子节点
- 有一种二叉树,除了叶子节点外,每个节点都有左右两个子节点,这种二叉树叫做满二叉树
- 有一种二叉树,叶子节点都在最底下两层,最后一层叶子节都靠左排列,并且除了最后一层,其他层的节点个数都要达到最大,这种二叉树叫做完全二叉树。
二叉树的存储
链式存储
采用链式存储如下图所示。每个节点都有三个字段,分别对应数据以及左右两个节点的指针。只要拎住根节点,就可以通过左右子节点的指针,把整棵树都串起来。这种存储方式我们比较常用。
顺序存储
顺序存储是基于数组的,如下图所示。如果节点 X 存储在数组中下标为 i 的位置,下标为 2 * i 的位置存储的就是左子节点,下标为 2 * i + 1 的位置存储的就是右子节点。反过来,下标为 i/2 的位置存储就是它的父节点。通过这种方式,我们只要知道根节点存储的位置(一般情况下,为了方便计算子节点,根节点会存储在下标为 1 的位置),这样就可以通过下标计算,把整棵树都串起来。
二叉树的遍历
通常我们把二叉树的遍历分为三种情况:
- 前序遍历。对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树
- 中序遍历。对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。
- 后序遍历。对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。 具体如下图所示 从图中可以分析出树的遍历是一个递归的过程。
代码实现(php)
<?php
class Node
{
public $value;
public $left;
public $right;
}
class Tree
{
/**
* 前序遍历
* @param $root
*/
public function preOrder($root)
{
if ($root != null) {
echo $root->value . " "; // 根
if ($root->left != null) {
$this->preOrder($root->left); //递归遍历左树
}
if ($root->right != null) {
$this->preOrder($root->right); //递归遍历右树
}
}
}
/***
* 中序遍历
* @param $root
*/
public function midOrder($root)
{
if ($root != null) {
if ($root->left != null) {
$this->midOrder($root->left); // 递归遍历左树
}
echo $root->value . " ";
if ($root->right != null) {
$this->midOrder($root->right); // 递归遍历右树
}
}
}
/***
* 后序遍历
* @param $root
*/
public function endOrder($root)
{
if ($root != null) {
if ($root->left != null) {
$this->endOrder($root->left); // 递归遍历左树
}
if ($root->right != null) {
$this->endOrder($root->right); // 递归遍历右树
}
echo $root->value . " ";
}
}
}