二叉树的基本知识你还记得多少?

前言

今天我们来聊聊数据结构中的二叉树结构。树是一种非线性的数据结构,而二叉树是树结构中的一种,由节点(node)和连接这些节点的边(edge)组成。

基本概念

什么是树,在现实生活中我们的树就是由一根主干加许多枝条,枝条上有许多叶子组成。那么在数据结构中我们也是这么表示的,只不过这棵树是倒过来的树。

树的定义

  • :树是一种由节点组成的层次结构,其中每个节点包含一个值或条件,节点之间通过边连接。
  • 根节点(Root):树的顶层节点,没有父节点。
  • 子节点(Child):从一个节点直接连接下来的节点称为其子节点。
  • 父节点(Parent):直接连接到一个子节点的节点称为其父节点。
  • 叶节点(Leaf):没有子节点的节点。
  • 内部节点(Internal Node):有至少一个子节点的节点。
  • 兄弟节点(Sibling):同一个父节点的子节点。

树的属性

  • 高度(Height):从根节点到叶节点的最长路径上的边数。
  • 深度(Depth):从根节点到某一节点的边数。
  • 层次(Level):树中所有深度相同的节点的集合。
  • 度(Degree):一个节点拥有的子节点的数量。树的度是所有节点中最大的度。

树的类型

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

    • 完全二叉树(Complete Binary Tree):除了最后一层外,所有层都是满的,最后一层的节点从左到右依次排列。
    • 满二叉树(Full Binary Tree):每个节点要么有两个子节点,要么没有子节点。
  • 红黑树(Red-Black Tree):一种自平衡二叉搜索树,每个节点带有额外的颜色属性(红或黑),用于保持树的平衡。

二叉树的定义

在代码中,我们经常使用这两种方式来表示一颗树。

使用对象的方式

ini 复制代码
function TreeNode(val){
    this.val = val;
    this.left = null;
    this.right = null;
}

const node = new TreeNode(1)
node.left = new TreeNode(2)
node.right = new TreeNode(3)

使用数组的方式

css 复制代码
const root = {
    val: 1,
    left: {
        val: 2,
        left: {
            val: 4
        },
        right: {
            val: 5
        }
    },
    right: {
        val: 3,
        left: {
            val: 6
        },
        right: {
            val: 7
        }
    }
}

二叉树的遍历

二叉树的遍历分为深度优先(dfs)和广度优先(bfs)

深度优先是指先尽可能的深入树的分支,当无法深入时再回溯,遍历上一个分叉口的另一个分支。

广度优先是指逐层访问节点,先访问离起始节点最近的节点,一层一层遍历,就像漫出去的水一样。

接下来我们用算法来实现这两种遍历方式。使用递归的方式很简单,你能实现使用迭代的方式完成吗?

深度优先

  1. 先序遍历

先遍历根节点,再遍历左节点、右节点

scss 复制代码
function preOrder(root){
    if(!root){
        return;
    }
    console.log(root.val);
    preOrder(root.left)
    preOrder(root.right)
}
  1. 中序遍历

先遍历左节点,再遍历根节点、右节点

scss 复制代码
function midOrder(root) {
    if (!root) {
        return;
    }
    midOrder(root.left)
    console.log(root.val);
    midOrder(root.right)
}
  1. 后序遍历

先遍历左节点,再遍历右节点、根节点

scss 复制代码
function afterOrder(root) {
    if (!root) {
        return;
    }
    afterOrder(root.left)
    afterOrder(root.right)
    console.log(root.val);
}

接下来我们使用迭代的方式来实现一个先序遍历

scss 复制代码
var preorderTraversal = function(root) {
    if(!root) return []//如果是空树则返回一个空数组
    let stack = []//定义一个栈来辅助遍历
    let res = []//将结果存储并且返回
    stack.push(root)//首先将根节点入栈
    while(stack.length){
        let top = stack.pop()
        res.push(top.val);//拿到当前栈顶元素,并将值存储
        if(top.right){//如果当前出栈的节点有右节点,则入栈
            stack.push(top.right)
        }
        if(top.left){//如果当前出栈的节点有左节点,则入栈
            stack.push(top.left)
        }
    }
    return res
};

广度优先

层序遍历

一层一层遍历,逐层访问节点

scss 复制代码
function levesOrder(root){
    let queue = []
    queue.push(root)
    while(queue.length){
        let top = queue.shift()
        console.log(top.val);
        if(top.left){
            queue.push(top.left)
        }
        if(top.right){
            queue.push(top.right)
        }
    }
}
相关推荐
西哥写代码5 分钟前
基于cornerstone3D的dicom影像浏览器 第十八章 自定义序列自动播放条
前端·javascript·vue
清风细雨_林木木9 分钟前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
FungLeo31 分钟前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
不灭锦鲤41 分钟前
xss-labs靶场第11-14关基础详解
前端·xss
不是吧这都有重名1 小时前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹1 小时前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架
Maỿbe1 小时前
利用html制作简历网页和求职信息网页
前端·html
森叶2 小时前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron
霸王蟹2 小时前
React 19 中的useRef得到了进一步加强。
前端·javascript·笔记·学习·react.js·ts
霸王蟹2 小时前
React 19版本refs也支持清理函数了。
前端·javascript·笔记·react.js·前端框架·ts