Skip to content

树(Tree)是一种层次化的数据结构,它由节点(Node)和边(Edge)组成。每个节点都有一个值,并且可能有零个或多个子节点。树的一个节点称为根(Root),没有父节点;节点之间的关系分为父节点、子节点和兄弟节点。

一、基本概念:

  1. 根节点(Root): 树的顶端节点,没有父节点。
  2. 子节点(Child): 树中的节点,有一个父节点。
  3. 父节点(Parent): 有子节点的节点。
  4. 叶子节点(Leaf): 没有子节点的节点,位于树的末端。
  5. 深度(Depth): 从根节点到某个节点的唯一路径的长度。
  6. 高度(Height): 从某个节点到其最远叶子节点的路径的长度。

二、常见类型:

  1. 二叉树(Binary Tree): 每个节点最多有两个子节点,分别称为左子节点和右子节点。

  2. 二叉搜索树(Binary Search Tree): 一种二叉树,左子树上的节点值小于根节点值,右子树上的节点值大于根节点值,且左右子树也都是二叉搜索树。

  3. 平衡二叉树(Balanced Binary Tree): 一种二叉搜索树,确保左右子树的高度差不超过 1,以保持树的平衡。

  4. AVL 树: 一种自平衡二叉搜索树,通过旋转操作保持平衡。

  5. B 树(B-tree): 一种多路搜索树,常用于文件系统和数据库的索引结构。

  6. 树状数组(Binary Indexed Tree): 用于高效处理数组的前缀和操作。

三、应用场景:

  1. 文件系统: 文件和目录的组织结构通常可以表示为树。

  2. 数据库索引: 数据库中的索引结构往往使用树的形式,例如 B 树和 B+ 树。

  3. 表达式树: 将数学表达式表示为树状结构,方便求值和优化。

  4. 网络路由表: 路由器使用树状结构表示网络的路由信息。

  5. XML/JSON 解析: 在解析 XML 或 JSON 数据时,常常使用树状结构表示数据的层次关系。

  6. 编译器语法树: 在编译器中,源代码通常被表示为一棵语法树。

四、二叉搜索树(实例)

javascript
// 定义二叉树节点
class TreeNode {
  constructor(value) {
    this.value = value
    this.left = null
    this.right = null
  }
}

// 定义二叉搜索树
class BinarySearchTree {
  constructor() {
    this.root = null
  }

  // 插入节点
  insert(value) {
    const newNode = new TreeNode(value)

    if (this.root === null) {
      this.root = newNode
    } else {
      this._insertRecursive(this.root, newNode)
    }
  }

  _insertRecursive(root, newNode) {
    if (newNode.value < root.value) {
      if (root.left === null) {
        root.left = newNode
      } else {
        this._insertRecursive(root.left, newNode)
      }
    } else {
      if (root.right === null) {
        root.right = newNode
      } else {
        this._insertRecursive(root.right, newNode)
      }
    }
  }

  // 查找节点
  search(value) {
    return this._searchRecursive(this.root, value)
  }

  _searchRecursive(root, value) {
    if (root === null || root.value === value) {
      return root
    }

    if (value < root.value) {
      return this._searchRecursive(root.left, value)
    } else {
      return this._searchRecursive(root.right, value)
    }
  }

  // 中序遍历
  inOrderTraversal() {
    const result = []
    this._inOrderTraversalRecursive(this.root, result)
    return result
  }

  _inOrderTraversalRecursive(root, result) {
    if (root !== null) {
      this._inOrderTraversalRecursive(root.left, result)
      result.push(root.value)
      this._inOrderTraversalRecursive(root.right, result)
    }
  }
}

// 示例使用
const bst = new BinarySearchTree()

bst.insert(10)
bst.insert(5)
bst.insert(15)
bst.insert(3)
bst.insert(7)
bst.insert(12)
bst.insert(18)

console.log('In-Order Traversal Result:', bst.inOrderTraversal())
// 输出: [3, 5, 7, 10, 12, 15, 18]

const searchResult = bst.search(7)
console.log('Search Result for 7:', searchResult)
// 输出: TreeNode { value: 7, left: TreeNode { ... }, right: TreeNode { ... } }

在这个例子中,我们创建了一个二叉搜索树,并依次插入了一些节点。然后,我们展示了中序遍历操作,它按照从小到大的顺序输出树中的节点值。最后,我们查找了树中值为 7 的节点,并输出了搜索结果。这个例子涵盖了二叉搜索树的插入、查找和遍历等基本操作。