d3.js

news2024/10/5 16:21:02

D3:Data-Driven Documents
• 通过D3提供的接口来基于数据操控文档的各个图元。

标题对于D3(本讲解)最为重要的标签,主要操作的对象(画布)

HTML - 导入D3.js
D3.js作为JavaScript的外库,必须先将其导入,如:

  • Python的import,C/C++的include、

  • Java的import、node.js的require… … …

  • 通过Script标签导入

    1. 直接通过互联网链接
      https://d3js.org/d3.v5.min.js
    2. 通过本地服务器链接(推荐)
      ./d3.min.js
    3. 通过unpkg链接
      https://unpkg.com/browse/d3@5.15.0/dist/d3.js

    尽可能使用本地的d3.min.js库。

svg-可缩放矢量模型

  • svg d3用来绘制的"画布"
  • 可缩放矢量图形(英语:scalable vector graphics,svg)
  • svg是d3.js主要操作的对象
    • const svg=de3.select(‘svg’)
    • d3.js获取svg对象
  • svg同时也是一个容器,用于包含画在上面的各个图元
  • svg作为矢量图,不会随着图片的缩放而发生失真

image.png

引入svg

  <svg height="200" width="200" style="display:block;margin:0 auto">
    <g transfrom="translate(0,60)">
      <rect width=100 height=100 fill="#eee" />
      <circle r=15 fill="#72bf67" cx=25 cy=30></circle>
      <circle r=15 fill="RGB(100,149,237)" cx=75 cy=30></circle>
      <g transform="translate(15,60) rotate(10)">
        <path d="M0,0 A40,40 10 0,0 65,0" fill="none" stroke="gray" stroke-width=5></path>
      </g>
    </g>
  </svg>

HTML–文档对象模型

  • HTML -> DOM
  • DOM -> Document Object Model
  • 对于根节点的操作会影响到子节点;
  • 最常用的父节点 中的
    • Axis可封装成一个group
    • Legend(图例)可封装成一个group

image.png

https://en.wikipedia.org/wiki/File:DOM-model.svg

JavaScript – D3中的常用接口

  • 模板字符串:
    • let a = 10;
    • let myString = abc-${a}; (myString最终为’abc-10’)
  • 数组 a = [1, 2, 3]
  • 对象 a = {name: ‘Shao-Kui’, age: 24.3, lab: ‘cscg’}
    • D3数据可视化中常见对象数组,如:
      • a = [{name: ‘Shao-Kui’, age: 25.3, dept: ‘cs’},
      • {name: ‘Wen-Yang’, age: 23, dept: ‘cs’},
      • {name: ‘Yuan’, age: 29, dept: ‘cs’}]
  • 数组的排序 a.sort()
    • 可加入回调函数来替代缺省的排序方案,如对日期排序
    • a.sort(function(a,b){ return new Date(b.date) - new Date(a.date); }
  • 数组的查询 a.find( d => d.name === ‘Wen-Yang’)
  • 把字符串转换成数值:+(‘3.14’)
  • D3.js经常读取CSV、JSON等文件,会涉及大量的数组、对象的操作!

D3语法基础概览

  • 使用D3获取、修改、增加与删除节点(图元)
  • 数据的读取 – CSV
  • D3.js的数值计算。
  • 比例尺:
    • 线性比例尺(Linear Scale)
    • “条带”比例尺(Band Scale)
  • 坐标轴的绘制:
    • Margin。
  • Data-Join基础
  • 基于D3的基础语法与Data-Join绘制柱状图

元素(标签)的标识

  • 当我们在一个同学群体中(比如微信群)对某些同学发出通知时
    • 学号为2020123456的同学在东主楼集合
    • 计算机系研一的同学在东主楼集合
  • 在一个群体中,索引个体:
    • 通过唯一的标识索引到唯一的个体
    • 通过共同点索引到一批个体

元素(标签)的标识

  • 操作元素首先需要知道元素的标识
    • 即要得到已有或已经创建的元素
  • 元素的ID
    • 可以唯一找到元素的标识符
  • 元素的Class
    • 人为赋予的“类别”可以标记元素的集合,其中的元素标签可以不相同
  • 元素的标签
    • HTML自带的标签名称,可以找到一批同类别的物体,如所有的“矩形”
    • 使用自带的标签往往难以直接索引到目标元素
    • , ,

image.png

使用D3查询SVG

  • d3.select(…)
    • d3.select(‘#rect1’)
    • 查询ID为’rect1’的元素
    • #表示后面的字符串是一个ID
    • 只找一个,若有重名也只返回第一个
  • d3.selectAll(…)
    • d3.selectAll(‘.class1’)
    • 查询所有class是’class1’的元素
    • d3.selectAll(‘rect’)
    • 查询所有标签是’rect’的元素(rect为SVG中的矩形标签)
    • 有多少返回多少
    • 可配合Data-Join选取‘不存在’的图元
  • ID前加‘#’,Class前加‘.’ ,标签名前不加符号。
  • 基于层级的查询:
    • d3.select(‘#maingroup rect’)
    • d3.selectAll('.tick text’)
    • d3.selectAll(‘#secondgroup rect’)
  • 如:’#secondgroup rect’
    • 首先会找到id为secondgroup的标签
    • 进一步找到secondgroup的子标签中是rect的
    • 仍然是对rect做查询,只是结果通过父标签做了筛选
  • d3.select(…)也可用于查询类别,如
    • d3.select(‘.class1’)
    • 但只会返回找到的第一个元素
  • 因此对于class、标签名称的查询建议使用d3.selectAll
  • 对于特定某一个元素的查询建议使用d3.select

使用D3设置SVG中的属性

  • 常见的属性
    • id, class(特殊的属性,可以使用.attr设置)
    • x, y, cx, cy
    • fill, stroke
    • height, width, r (圆的半径)
    • transform -> translate, rotate, scale
  • SVG的属性非常多,且属性的取值 **范围&类型 **各不同
    • tip1: 尽可能记住一些常见的属性,以提高编程速度
    • tip2: 遇到不认识or想要设置某个属性,一定要查阅

https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute

  • 屏幕空间的坐标系与常见坐标系不同
    • 左上方为原点
    • Y、X分别垂直向下、水平向右

image.png

element.attr(…)

  • 设置元素的属性: element.attr(‘attr_name’, ‘attr_value’)
    • 两个参数:属性名、设置的值
    • rect1.attr(‘y’, ‘100’)
    • d3.select(‘#rect1’).attr(‘y’, ‘100’)
  • 获取元素的属性: element.attr(‘attr_name’)
    • 一个参数:属性名
  • 链式调用
    • selection.attr(…).attr(…).attr(…)
    • .attr(…)返回的是选择的图元本身

修改整组属性

  • DOM
    • 父节点的属性会影响子节点
    • 子节点的属性会相对于父节点
  • 下方代码可以直接移动组内所有元素
    • d3.select('#maingroup’)
    • .attr(‘transform’, ‘translate(200, 100)’)

image.png

image.png


使用D3 添加&**删除 **SVG元素

  • element.append(…)
    • const myRect = svg.append(‘rect’);
    • const myRect = d3.select(‘#mainsvg’).append(‘rect’)
    • const myRect = d3.select(‘#mainsvg’).append(‘rect’).attr(‘x’, ‘100’)
  • D3的链式添加(调用)
    • const myRect = d3.select(‘#mainsvg’).append(‘g’).attr(‘id’, ‘maingroup’)
    • .append(‘rect’).attr(‘fill’, ‘yellow’)
  • element.remove()
    • 会移除整个标签
  • Tip:在debug的过程中可以考虑使用’opacity’属性hack出移除的效果
    • element.attr(‘opacity’, ‘0’)

操控SVG

image.png

数据的读取 – CSV数据

  • 第一行为属性列表,后续每行对应一‘条’数据。
  • CSV本质上是纯文本,区别于EXCEL的格式。

image.png

image.png

  • d3.csv(…):

    • 读取目标路径下的某一个CSV文件。
    • 例:d3.csv(‘static/data/hello.csv’);
  • d3.csv是一个JavaScript异步函数:

    • 不可以直接获得它的返回值,如:
    • let myData = d3.csv(‘static/data/hello.csv’); ❌
  • d3.csv(‘path/to/data.csv’).then( data => { // ‘数据读取后的代码逻辑’ } )

    • 要通过.then( **data **=> {…} )的方式来获得读取后的数据。
    • then(…)中的 ‘data => {…}’ 是一个函数
    • 函数接受的输入(参数),即data,为读取后的数据。
  • JavaScript异步机制

    • d3.csv作为异步函数,即便没有读取好数据,后面的代码也会继续执行
    • d3.csv被调用后,其返回值是一个JavaScript的‘Promise’对象(object)
    • Promise‘询问’:数据读取好了之后要做什么?‘做什么’即对应.then()中函数的内容。
  • 代码调用示例:

image.png

  • 读取后的数据格式(接口)与原本的CSV结构不同。

image.png

D3.js的数值计算

  • 数据可视化常涉及对数据的处理与计算:
    • 下述三个接口分别用于计算数组的最大值、最小值、[最小值,最大值]。
  • d3.max(array)
    • 返回数组中的最大值。
    • d3.max([5,4,6,1,8,16,9]) // 16
  • d3.min(array)
    • 返回数组中的最小值。
    • d3.min([5,4,6,1,8,16,9]) // 1
  • d3.extent(array)
    • 同时返回最小值与最大值,以数组的形式,即[最小值,最大值]。
    • d3.extent([5,4,6,1,8,16,9]) // [1, 16]
  • 数组中的内容可以是任意对象:
    • 每个对象可能包含多个属性。
    • 具体取哪个属性的最大值通过回调函数来提示d3.max、d3.min与d3.extent。
  • 例:
    • let a = [ {name: ‘Shao-Kui’, age:25, height: 176}, {name:‘Wen-Yang’, age:24, height: 180}, {name:‘Liang Yuan’, age: 29, height: 172}, {name:‘Wei-Yu’, age:23, height: 173}]
    • d3.max(a, d => d.age) // 29
    • d3.max(a, d => d.height) // 180
    • d3.extent(a, d => d.height) // [172, 180]
    • d3.min(a, d => d.age) // 23

比例尺

  • 比例尺用于把实际数据空间映射到屏幕(画布)空间,即两个空间的转化。
  • 常用于映射数据and创建坐标轴。
  • 区别主要在于数据的尺度不同

image.png
image.png

Scale - Linear

  • d3.scaleLinear():
    • 定义一个线性比例尺,返回的是一个函数
    • let scale = d3.scaleLinear(); // scale为函数
  • scale.domain([min_d, max_d]).range([min, max]):
    • 设置比例尺的定义域值域
    • 线性比例尺的定义域和值域都是连续的(Continuous),需分别给出最大值与最小值。
    • const scale = d3.scaleLinear().domain([20, 80]).range([0, 120]);
  • 比例尺本质上是一个函数
    • scale(20) // 0
    • scale(50) // 60
  • 常结合读取的数据与d3.max等接口连用:
    • const xScale = d3.scaleLinear() .domain([0, d3.max(data, d => d.value)]).range([0, innerWidth]);

image.png

image.png

Scale - Band

  • d3.scaleBand():
    • 定义一个‘条带’比例尺,返回的是一个函数
    • let scale = d3.scaleBand();
  • scale.domain(array).range([min, max]):
    • 设置比例尺的定义域与值域
    • Band比例尺的定义域是离散的(Discrete),值域是连续的。
    • const scale = d3.scaleBand().domain([‘a’, ‘b’, ‘c’]).range([0, 120]);
  • 比例尺本质上是一个函数
    • scale(‘b’) // 40
    • scale(‘c’) // 80

image.png

  • 常结合JavaScript的array.map接口一起使用:
    • let a = [{name: ‘Shao-Kui’, value:6}, {name:‘Wen-Yang’, value:6}, {name:‘Yuan Liang’, value:16}]
    • a.map(d => d.name) // [‘Shao-Kui’, ‘Wen-Yang’, ‘Yuan Liang’]
    • const yScale = d3.scaleBand().domain(data.map(d => d.name)).range([0, innerHeight])
    • scale.padding(0.1):
      • 设置条带的间距占各自区域的比重。
    • scale.bandwidth():
      • 返回条带的长度。

image.png

引入坐标轴

  • 一个坐标轴为一个group( ),通常需要两个坐标轴。
  • 坐标轴中包含:
    • 一个 用于横跨坐标轴的覆盖范围
    • 若干个刻度(.tick)
      • 每个刻度也是一个group
    • 每个刻度下属还会包含一个 和一个
      • 用于展示坐标轴的轴线,如左到右或上到下
      • 用于展示坐标轴的刻度值,如实数、姓名、日期
    • (可选)一个标签用以描述坐标轴
  • 坐标轴的定义通常需要比例尺。

image.png

  • 定义坐标轴(获得结果仍是函数):

    • const yAxis = d3.axisLeft(yScale);
    • const xAxis = d3.axisBottom(xScale);
    • axisLeft:左侧坐标轴。
    • axisBottom:底侧坐标轴。
    • 坐标轴的刻度对应比例尺的定义域。
    • 坐标轴在画布的绘制对应比例尺的值域。
    • 仅是对坐标轴的定义,还未绘制。
  • 绘制坐标轴:

    • const yAxisGroup = g.append(‘g’).call(yAxis);
    • const xAxisGroup = g.append(‘g’).call(xAxis);
    • 实际配置后会发现 中增添了与坐标轴相关的元素
  • 任何坐标轴在初始化之后会默认放置在坐标原点,需要进一步的平移。

  • 关于 selection.call(…)

  • 函数的输入为另一个函数

  • 另一个函数以selection本身(即图元)作为输入

  • 另一个函数中会根据函数体的内容修改selection对应的图元。

  • 定义一个空白的 ,D3会帮助我们定义好 另一个函数,我们通过.call(…)让 得以在 另一个函数中修改。

    • const yAxis = d3.axisLeft(yScale);
    • const yAxisGroup = g.append(‘g’).call(yAxis);

配置坐标轴

  • 可以对坐标轴的风格进行修改:
    • 坐标轴本质上是图元的集合。
    • d3.selectAll(‘.tick text’).attr(‘font-size’, ‘2em’);
    • .tick是D3对于坐标轴定义的统一class
  • 坐标轴的标签加入不在D3-Axis接口的负责范围内:
    • 通过对坐标轴的 标签 .append(‘text’)来实现
    • (左)纵轴坐标需要 .attr(‘transform’, ‘rotate(-90)’) 来旋转
    • 纵轴坐标旋转后,x / y 会颠倒甚至取值范围相反
    • 回忆DOM:父节点的属性会影响子节点,而坐标轴默认的’fill’属性是 ‘none’,因此请一定手动设置文字颜色 .attr(‘fill’, ‘black’)

引入坐标轴 - Margin

  • SVG对于D3.js是一个“画布”。
  • SVG范围外的任何内容属于画布之外,浏览器将不予显示。
    • 然而坐标轴通常初始化在所在父节点的左上角。
  • 定义Margin:
    • const margin = {top: 60, right: 30, bottom: 60, left: 200}
  • 计算实际操作的 inner 长/宽
    • const innerWidth = width - margin.left - margin.right;
    • const innerHeight = height - margin.top - margin.bottom;
  • 在SVG下额外定义一个组作为新的根节点
    • const g = svg.append(‘g’).attr(‘id’, ‘maingroup’).attr(‘transform’, translate(${margin.left}, ${margin.top}));
  • Tip: HTML确实在样式表中提供margin属性,然而设置其他图元的位置,仍需要计算innerWidth(Height)。

引入坐标轴

  • 调用示例:
    • 比例尺可通过坐标轴可视化。

image.png

Data-Join

  • 本质上是将数据与图元进行绑定:

    • 每个国家的人数绑定到矩形的长度;
    • 疫情感染的人数比例绑定到圆的半径;
    • 产品的销量绑定到矩形的长度;
    • 各类别商品的销售占比绑定到扇形的弧度。
  • Why?

    • 以数据为中心(Data-Driven)的可视化操作:
      • 根据数据自动调整图元的属性。
      • .attr(…)接口可基于图元自己绑定的数据自动调整属性值
    • 数据发生变化时可以自动对图元增删改查:
      • 不再需要手动添加、‘修改’、删除图元。
      • 根据数据的增加or删除or更新,自动补充or移除or更新图元。
  • Data-Join并不是必要的操作,不使用Data-Join同样可以画出所有可视化作品。

  • Data-Join只是让D3.js编程变得更高效且语法更简洁。

  • d3.selectAll(‘.class’)**.data( dataArray ) **

  • dataArray在保证是一个数组的前提下可以是任何形式:

    • 例: [0, 2, 32, 18];
    • 例:[{name: ‘Sebastian’, value:384}, {name:’ Ciel’, value:32}, {name:‘Wen-Yang’, value:16}, {name:‘Shao-Kui’, value:19}];
  • .data(…)只考虑数据和图元数目相同的情况:

    • dataArray是一个数组,其中的每‘条’数据会与一个图元绑定。
  • 默认的绑定按照双方的索引顺序:

    • (Data的Key:后续D3中会讨论。)
  • 不调用.data(…),则图元不会与任何数据绑定

  • 数据的更新只需要重新绑定另一个 dataArray 即可。

image.png

  • 调用形式:
    • **d3.selectAll(‘.class’).data(myData).join(‘图元’).attr(d => …).attr((d, i) => …) **
    • .join(…)会根据数据的条目补全or删除图元。
  • 若有新增的数据,则会自动增加对应图元。
  • 若有修改的数据,则会自动更新对应图元。
  • 若有删除的数据,则会自动移除对应图元。

image.png

Data-Join – 用函数设置图元属性

  • selection.attr(‘attrbuteName’, ‘value’)
    • 通过值设置属性
  • selection.attr(‘attrbuteName’, (d, i) => {…})
    • 通过函数设置属性,函数的输入为绑定的数据,返回值为图元得到的属性值
    • d为Data-Join中,‘.data(array)’绑定给每个图元的数据。
    • i为Data-Join中,‘.data(array)’绑定图元的顺序,即图元对应原本数组的第几个
    • 例:d3.selectAll(‘rect’).attr(‘width’, (d, i) => 1000 * d.age )
    • 例:d3.selectAll(‘circle’).attr(‘cy’, (d, i) => 200 * i + 30);
    • 由于绑定数据的不同,故得到的结果也不同。
  • 设置图元属性的函数遵循如下规则(顺序性):
    • 函数可仅使用 d => {…},即只有一个参数,但此时函数体无法使用索引。
    • 即使未使用到绑定的数据,如需使用索引,仍需要完整的写出 (d, i) => {…}。

基于D3的基础语法与Data-Join绘制柱状图

  • 数据来源:
    • https://www.kaggle.com/gregorut/videogamesales

image.png

Tip:颜色 – ‘fill’属性

  • PlanA:人为定义一系列颜色组合
  • PlanB:使用D3提供的颜色组合(见下页)
  • PlanC:采样

image.png

image.png

image.png

Tip:D3提供的各种色盘

  • 定义一个离散数据到离散数据的映射
    • 如:每个水果对应到某个颜色

image.png

  • D3.js的内嵌(自带)配色方案?
    • https://github.com/d3/d3-scale-chromatic

image.png
image.png
image.png

网络数据的数据结构?

  • 网络数据包括节点的集合与边的集合:
    • 节点与边通常分布在不同的文件中,通过节点的ID索引
  • D3.js也没有统一的网络数据结构规范:
    • 只要能整理成D3.js对应接口接受的格式即可
  • 常见的数据形式:
    • 【节点列表】+【连接矩阵】
    • 【节点数、边数与基于ID的连接】
    • 【节点列表】+【边列表】

image.png【节点数、边数与基于ID的连接】
image.pngimage.png【节点列表】+【边列表】
image.pngimage.png【连接矩阵】

d3力模拟基础

  • d3的力模拟与“transition”是完全不同的两个体系
  • let nodes = [{}, {}, {}, {}, {}, {}];
  • let simulation = d3.forceSimulation(nodes) 定义后会发生…
    • 补全nodes中每个节点的数据结构:
      • 包括index, x, y, vx, vy,后两者为速度。
    • 开始模拟粒子运动:
      • 粒子质量为1。
      • 不断地通过内部timer触发’tick’事件。
    • 根据一系列的‘’来计算每个例子的加速度、速度、位置…
      • ‘力’都是哪来的呢?

image.png

不同力的作用

  • d3.forceManyBody().strength( value ):
    • 粒子之间两两的作用力,类似于‘万有引力’。
    • .strength(value)’用来设置力的大小,value为正互相吸引,为负则互相排斥。
  • d3.forceCenter(w, h).strength( value ):
    • 指向某一个中心的力,会尽可能让粒子向中心靠近。
    • .strength(…)的用法同上。
    • ‘d3.forceCenter(w, h)’中的‘w’与‘h’为中心的位置,通常为画布的中心。
  • d3.forceLink(links).strength(strength).distance(distance):
    • 部分粒子之间的两两作用力,不同于‘d3.forceManyBody’。
    • 'd3.forceLink’中,每个节点仅仅会与一部分节点有力的作用。
    • 有链接的节点间,受力的作用,保持在特定的距离即靠近互斥远离吸引
    • 是否有链接需要通过图的边集合给出。
    • .strength( vs )’ 与 ‘.distance( vd )’分别设置力的大小预期的距离
  • Link要通过一个数据格式给出,即link的source与target。
  • 格式非常类似于‘d3.hierarchy’给出的root.links()

image.png

编程实例:

image.png

image.png


‘Tic-Toc’

  • forceSimulation会通过每次‘tick’来更新当前节点的状态:
    • 状态包括位置、速度、加速度等。
  • 更新后的状态仅仅为‘状态’:
    • 不会反映到任何图元,仅修改数据。
    • 需要添加修改图元属性的回调函数
  • 人为设置每次tick要如何更新图元
    • simulation.on(‘tick’, ticked);
  • 在初始化每个图元后,只要为simulation配置了’tick’的回调,simulation会自动开始模拟。

image.png

基于‘d3-force’实现力导图

数据来源:http://networkrepository.com/socfb-Caltech36.php

编程实例:

image.png
image.png

Tip:带权重的图?

  • d3.forceLink(links).strength(…).distance(…):
    • 本质上根据link的权重设置forceLink的strength与distance。
    • 分别输入回调函数,基于每一个‘link’元素来设置各自的力与距离。
  • 编程实例:

image.png

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

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

相关文章

[autojs]用户界面GUI编程

用户界面: UI视图: View attr(name, value)attr(name)whidgravitylayout_gravitymarginmarginLeftmarginRightmarginTopmarginBottompaddingpaddingLeftpaddingRightpaddingToppaddingBottombgalphaforegroundminHeightminWidthvisibilityrotationtransformPivotXtransformPivo…

移位操作符 位操作符详解

hello hello&#xff0c;想我了吗? &#x1f604;&#x1f604;&#x1f604; 首先是移位操作符&#xff1a;<< 左移操作符 >> 右移操作符 注&#xff1a;移位操作符的操作数只能是整数。 << 左移操作符&#xff1a;移位规则&#xff1a; 左边抛弃、…

我的AIGC部署实践03

我的AIGC部署实践03 这会是AIGC部署实践的第三回&#xff0c;用免费的GPU部署自己的stable-diffusion下面我们就开始吧。 1.创建项目 创建项目的镜像及数据集如下&#xff1a; 选择完成后点击创建&#xff0c;代码选择暂不上传。 2.初始化开发环境实例 点击最右侧的“开发…

服务器往客户端发送字符串的网络编程

服务器主要就是能够打开命令行提供的网络端口&#xff0c;然后一有客户端连接上&#xff0c;就会向客户端发送Welcome to Our Server!这段话。 服务器代码serverSayWelcome.c的代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.…

【ARM Trace32(劳特巴赫) 使用介绍 3 - trace32 访问运行时的内存】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 文章目录 1.1 trace32 访问运行时的内存1.1.1 侵入式 运行时内存访问1.1.2 非侵入式运行时访问1.1.3 缓存一致性的非侵入式运行时访问 1.2 Trace32 侵入式和非侵入式 运行时访问1.2.1 侵入式访问1.2.2 非侵入式运行时访问 1…

C++:关联式容器map的使用

1、map的简介 map是关联容器&#xff0c;它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。 在map中&#xff0c;键值key通常用于排序和惟一地标识元素&#xff0c;而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同&#xff0c;并…

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

【Linux系统化学习】冯诺依曼体系结构 | 操作系统

个人主页点击直达&#xff1a;小白不是程序媛 Linux专栏&#xff1a;Linux系统化学习 目录 冯诺依曼体系结构 组成介绍 CPU和内存 以使用微信发消息为例理解冯诺依曼体系结构 操作系统 冯诺依曼体系结构 随着世界上第一台计算机ENIAC&#xff08;埃尼阿克&#xff09;的…

2、鸿蒙开发工具首次运行时开发环境配置

请务必在第一次运行时配置好开发环境&#xff0c;如果取消了配置&#xff0c;后续再配置会比较麻烦 1、点击工具图标运行 2、在欢迎页中点击“Agree” 3、默认“Do not import setting”&#xff0c;点击“OK” 3、此片设置Nodejs和Ohpm的安装&#xff0c;其中&#xff0c; …

传来喜讯,优维又获奖了!!!

优维科技作为国内DevOps领域的行业领先企业&#xff0c;从诞生之日起&#xff0c;就一直致力于为中国企业提供一流的数字化运维服务&#xff0c;不断深耕核心技术&#xff0c;向客户提供专业强大的产品与服务。多年来&#xff0c;不仅获得了大量客户认可&#xff0c;更是屡次获…

Apache Airflow (三) :Airflow WebUI操作介绍

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

Android修行手册 - POI操作Excel常用样式(字体,背景,颜色,Style)

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

【媒体邀约】媒体宣传——企业成长的催化剂

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传是企业成长的催化剂&#xff0c;它在各种方面对企业的成功和发展起到了关键作用。 1. 曝光和知名度&#xff1a; 媒体宣传可以将企业和其产品或服务推向广泛的受众&#xff0c;…

SQL第四次上机实验

1.查询借阅了计算机类或者文学类图书的读者的借书证号 USE TSGL GO SELECT DISTINCT Reader.Lno FROM Book,Lend,Reader WHERE Book.ISBNLend.ISBN AND Lend.LnoReader.Lno AND Class 计算机类 OR Class 文学类2.查询同时借阅了计算机类和文学类图书的读者的借书证号 USE T…

C语言之文件操作(剩余部分)

上篇博客字数到极限了&#xff0c;给大家把内容补充在这一篇&#xff0c;我们还剩下文件读取结束的判定和文件缓冲区的内容没有介绍&#xff0c;让我们开始下面的学习吧&#xff01; 目录 1.文件读取结束的判定 1.1feof函数 1.2ferror函数 代码示例 2.文件缓冲区 2.1fflu…

制造行业怎么做?看低代码如何引领未来

随着科技的不断发展&#xff0c;制造行业正面临着巨大的变革和挑战。为了提高生产效率、降低成本并更好地适应快速变化的市场需求&#xff0c;越来越多的制造企业将目光投向了低代码开发平台。在众多低代码开发平台中&#xff0c;JNPF低代码快速开发平台凭借其卓越的性能和灵活…

“三门问题”解决方案:换不换?更换策略与贝叶斯策略?附 Java 验证代码

文章目录 前言一、什么是“三门问题”&#xff1f;二、“三门问题”解决策略详解2.1、错误策略&#xff1a;直觉策略与随机策略2.2、更换策略与事件分析计算2.3、贝叶斯策略及分析流程 三、Java 语言验证“三门问题”总结 前言 “三门问题”作为一道经典逻辑推理题&#xff0c;…

物联网AI MicroPython学习之语法 ustruct 打包和解压原始数据类型

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; ustruct 介绍 ustruct提供打包和解压原始数据类型的功能。 默认情况下&#xff0c;C类型以机器的本机格式和字节顺序表示&#xff0c;并在必要时通过跳过填充字节来正确对齐&#xff08;根据C编译器使用的规…

使用Vite创建Vue3项目 配置路由+路径(包教包会)

使用Vite创建Vue3项目 配置路由路径 一、创建项目&#xff1a;二、配置路由1. vue3vitets路由配置2. vue3vitejs路由配置 三、配置路径 一、创建项目&#xff1a; 创建一个文件夹在文件夹上的 地址栏 或者是 winR 打开cmd命令窗口。 输入命令 npm create vitelatest 这里我们…