数据结构——树

news2024/9/22 19:40:31

深度优先/广度优先遍历

深度优先:

  1. 访问根节点

  1. 对根节点的 children 挨个进行深度优先遍历

const tree = {
  val: "a",
  children: [
    {
      val: "b",
      children: [
        {
          val: "d",
          children: [],
        },
        {
          val: "e",
          children: [],
        },
      ],
    },
    {
      val: "c",
      children: [
        {
          val: "f",
          children: [],
        },
        {
          val: "g",
          children: [],
        },
      ],
    },
  ],
};

const dfs = (root) => {
  console.log(root.val);
  root.children.forEach((child) => {
    dfs(child);
  });
};

dfs(tree);

广度优先:

  1. 新建立一个队列,根节点入队

  1. 对头出队并访问

  1. 把对头的children挨个入队

  1. 重复2,3,直到队列为空

const tree = {
  val: "a",
  children: [
    {
      val: "b",
      children: [
        {
          val: "d",
          children: [],
        },
        {
          val: "e",
          children: [],
        },
      ],
    },
    {
      val: "c",
      children: [
        {
          val: "f",
          children: [],
        },
        {
          val: "g",
          children: [],
        },
      ],
    },
  ],
};

const bfs = (root) => {
  const q = [root];
  while (q.length > 0) {
    const n = q.shift();
    console.log(n.val);
    n.children.forEach((child) => {
      q.push(child);
    });
  }
};

bfs(tree);

二叉树的先中后序遍历

二叉树:每个节点最多只能有两个节点

先序遍历(根、左、右):

  1. 访问根节点

  1. 对根节点的左子树进行先序遍历

  1. 对根节点的右子树进行先序遍历

1、2、3、4、5、6、7

const tree = {
  val: "1",
  left: {
    val: "2",
    left: {
      val: "3",
      left: null,
      right: null,
    },
    right: {
      val: "4",
      left: {
        val: "5",
      },
      right: null,
    },
  },
  right: {
    val: "6",
    left: null,
    right: {
      val: "7",
      right: null,
      left: null,
    },
  },
};

const preorder = (root) => {
  if (!root) return;
  console.log(root.val);
  preorder(root.left);
  preorder(root.right);
};
preorder(tree);

中序遍历(左、中、右):

  1. 对根节点左子树遍历

  1. 访问根节点

  1. 对根节点右子树遍历

1、2、3、4、5、6、7

const tree = {
  val: "5",
  left: {
    val: "2",
    left: {
      val: "1",
      left: null,
      right: null,
    },
    right: {
      val: "4",
      left: {
        val: "3",
      },
      right: null,
    },
  },
  right: {
    val: "6",
    left: null,
    right: {
      val: "7",
      right: null,
      left: null,
    },
  },
};

const inorder = (root) => {
  if (!root) return;
  inorder(root.left);
  console.log(root.val);
  inorder(root.right);
};
inorder(tree);

后序遍历(左、右、根):

  1. 对根节点左子树遍历

  1. 对根节点右子树遍历

  1. 访问根节点

1、2、3、4、5、6、7

const tree = {
  val: "7",
  left: {
    val: "4",
    left: {
      val: "1",
      left: null,
      right: null,
    },
    right: {
      val: "3",
      left: {
        val: "2",
      },
      right: null,
    },
  },
  right: {
    val: "6",
    left: null,
    right: {
      val: "5",
      right: null,
      left: null,
    },
  },
};

const postorder = (root) => {
  if (!root) return;
  postorder(root.left);
  postorder(root.right);
  console.log(root.val);
};
postorder(tree);

非递归写法

递归调用函数,会不断的入栈出栈,所以考虑用栈实现。

先序遍历:

// 递归
const preorder = (root) => {
  if (!root) return;
  console.log(root.val);
  preorder(root.left);
  preorder(root.right);
};

// 非递归
const preorder = (root) => {
    if (!root) return;
    const stack = [root]
    while(stack.length){
        const n = stack.pop()
        console.log(n.val)
         // 栈后进先出,先右后左
        if(n.right) stack.push(n.right)
        if(n.left) stack.push(n.left)
    }
}

中序遍历:

// 递归
const inorder = (root) => {
  if (!root) return;
  inorder(root.left);
  console.log(root.val);
  inorder(root.right);
};
// 非递归
const inorder = (root) => {
  if (!root) return;
  const stack = [];
  let p = root;
  while (stack.length || p) {
    // 所有的左子树进栈
    while (p) {
      stack.push(p);
      p = p.left;
    }
    //最尽头的左子树出栈
    const n = stack.pop();
    console.log(n.val);
    p = n.right;
  }
};

后续遍历:

const postorder = (root) => {
  if (!root) return;
  postorder(root.left);
  postorder(root.right);
  console.log(root.val);
};
// 先序遍历是 根、左、右,后续遍历时:左、右、根,倒过来是根、右、左,只需要把先序遍历的后面两个颠倒顺序

const postorder = (root) => {
  if (!root) return;
  const outputStack = [];
  const stack = [root];
  while (stack.length) {
    const n = stack.pop();
    outputStack.push(n);
    if (n.left) stack.push(n.left);
    if (n.right) stack.push(n.right);
  }
  while (outputStack.length) {
    const n = outputStack.pop();
    console.log(n.val);
  }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/373167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

可靠性设计

目录 一、可靠性设计概述 二、冗余的类型 三、冗余系统的设计 1.N版本程序设计 2.恢复块设计 3.防卫式程序设计 4.双机容错 一、可靠性设计概述 可靠性指系统能够正常运行的概率。如何设计出一个具有高可靠性的系统呢?可以利用避错技术,容错技术…

【LeetCode】剑指 Offer 16. 数值的整数次方 p110 -- Java Version

题目链接:https://leetcode.cn/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/ 1. 题目介绍(16. 数值的整数次方) 实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,…

文献计量分析方法:Citespace安装教程

Citespace是一款由陈超美教授开发的可用于海量文献可视化分析的软件,可对Web of Science,Scopus,Pubmed,CNKI等数据库的海量文献进行主题、关键词,作者单位、合作网络,期刊、发表时间,文献被引等…

数据结构入门5-2(数和二叉树)

目录 注: 树的存储结构 1. 双亲表示法 2. 孩子表示法 3. 重要:孩子兄弟法(二叉树表示法) 森林与二叉树的转换 树和森林的遍历 1. 树的遍历 2. 森林的遍历 哈夫曼树及其应用 基本概念 哈夫曼树的构造算法 1. 构造过程 …

响应性基础API

一.什么是proxy和懒代理?什么是proxy?proxy对象是用于定义基本操作的自定义行为(如:属性查找,赋值,枚举,函数调用等等)。什么是懒代理?懒代理:在初始化的时候不会进行全部代理,而是…

数据仓库Hive

HIve介绍 Hive是建立在Hadoop上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载,可以简称为ETL。 Hive 定义了简单的类SQL查询语言,称为HQL,它允许熟悉SQL的用户直接查询Hadoop中的数据&#xf…

三万字全面概述关于5G-V2X技术和应用

5G技术有望实现更快的网联链接、更低的延迟、更高的可靠性、更大的容量和更广的覆盖范围。希望依靠这些技术来实现车辆到一切(V2X)的通信,除了道路安全外,还能提高车辆的安全性和自动驾驶性能,节约能源和成本。车辆通信…

算法设计与分析期末考试复习(四)

贪心算法(Greedy Algorithm) 找零钱问题 假设有4种硬币,面值分别为:二角五分、一角、五分和一分,现在要找给顾客六角三分钱,如何找使得给出的硬币个数最少? 首先选出1个面值不超过六角三分的最…

improve-2

BFC 块级格式化上下文,是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。 IE下为 Layout,可通过 zoom:1 触发 触发条件: 根元素position: absolute/fixeddisplay: inline-block /…

[计算机网络(第八版)]第三章 数据链路层(学习笔记)

物理层解决了相邻节点透明传输比特的问题 3.1 数据链路层的几个共同问题 3.1.1 数据链路和帧 链路: 从一个节点到相邻节点的一段物理线路,中间没有任何其他的交换节点 数据链路: 节点间的逻辑通道是把实现控制数据传输的协议的硬件和软件加…

Unity Avatar Foot IK - Avatar Foot Placement Resolution

文章目录简介实现Avatar FBX Import SettingsAnimator SettingsOn Animator IKCalculate IK Position & RotationBody PositionApply IK Position & Rotation简介 通过Unity内部的Mecanim动画系统实现的FootIK功能,效果如图所示,左右分别为开启…

计算机网络协议—应用层

应用层网络协议 应用层的常见协议 超文本传输:HTTP、HTTPS文本传输:FTP电子邮件:SMTP、POP3、IMAP动态主机配置:DHCP域名系统:DNS 域名(Domain Name) 由于IP地址不方便记忆,并且不…

【CAN】手把手教你学习CAN总线(一)

CAN总线一、CAN总线概念二、CAN的差分信号三、CAN总线的通信协议1、 帧起始2、仲裁段3、控制段4、数据段5、CRC段6、ACK段7、帧结束四、CAN的位时序1、同步段(SS)2、传播时间段(PTS)3、相位缓冲段(PBS)4、再…

gin 框架初始教程文档

一 、gin 入门1. 安装gin :下载并安装 gin包:$ go get -u github.com/gin-gonic/gin2. 将 gin 引入到代码中:import "github.com/gin-gonic/gin"3.初始化项目go mod init gin4.完整代码package mainimport "github.com/gin-go…

java 一文讲透面向对象 (20万字博文)

目录 一、前言 二、面向对象程序设计介绍 1.oop三大特性 : 2.面向对象和面向过程的区别 : 3.面向对象思想特点 : 4.面向对象的程序开发 : 三、Java——类与对象 1.java中如何描述一个事物? 2.什么是类? 3.类的五大成员: 4.封装的前提——抽象 : 5.什么是对…

使用python暴力破解zip压缩包的密码

如果你有压缩包的密码忘记了,并且压缩包的加密算法采用的是ZipCrypto,并且压缩参数如下图所示: 那么你就可以使用本文中的方法进行破解。 压缩包的加密,是根据输入的密码进行运算加密,输入不同的密码,加密…

OpenCV-Python系列(二)—— 图像处理(灰度图、二值化、边缘检测、高斯模糊、轮廓检测)

一、【灰度图、二值化】 import cv2 img cv2.imread("lz2.png") gray_img cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图 # 二值化,(127,255)为阈值 retval,bit_img cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY) cv2.imshow(photo1,im…

java:自定义变量加载到系统变量后替换shell模版并执行shell

这里的需求前提是,在项目中进行某些操作前,需要在命令后对shell配置文件的进行修改(如ip、port),这个对于用户是不友好的,需要改为用户页面输入ip、port,后台自动去操作修改配置;那么…

SAP 能不能撤销已冲销的凭证?能的话怎么操作?

本篇涉及SAP的SAP 财务凭证的冲销操作的。有需要可以查看:前面的文章有一篇是专门介绍如何介绍如何冲销SAP财务凭证的文章。SAP财务凭证常见的冲销步骤详细操作手册(FB08、AB08、VF11、FBRA等) 开始进入正题。假如有这么一种场景:…

【Acwing 周赛复盘】第92场周赛复盘(2023.2.25)

【Acwing 周赛复盘】第92场周赛复盘(2023.2.25) 周赛复盘 ✍️ 本周个人排名:1293/2408 AC情况:1/3 这是博主参加的第七次周赛,又一次体会到了世界的参差(这次周赛记错时间了,以为 19:15 开始&…