当前位置: 首页 > news >正文

数据结构与算法——20.B-树

这篇文章我们来讲解一下数据结构中非常重要的B-树。

目录

1.B树的相关介绍

1.1、B树的介绍

1.2、B树的特点

2.B树的节点类

3.小结


1.B树的相关介绍

1.1、B树的介绍

在介绍B树之前,我们回顾一下我们学的树。

首先是二叉树,这个不用多说,然后为了查找的效率,我们提出了搜索二叉树(或者称为二叉搜索树),就是节点类加个key值,然后左边小右边大的那个。然后为了避免极端情况的出现,就是二叉搜索树节点集中在一侧的情况,我们提出了平衡二叉树,就是带自旋的,可以左旋或者右旋的,高度差小于1的那种,平衡二叉树里面有AVL树和红黑树两种实现方式,注意,平衡二叉树是在二叉搜索树的基础上提出的,所以平衡二叉树也叫平衡二叉搜索树

下面介绍一下B树。

B-树是一种自平衡的多路查找树,注意: B树就是B-树,"-"是个连字符号,不是减号 。

在大多数的平衡查找树(Self-balancing search trees),比如 AVL树 和红黑树,都假设所有的数据放在主存当中。那为什么要使用 B-树呢(或者说为啥要有 B-树呢)?要解释清楚这一点,我们假设我们的数据量达到了亿级别,主存当中根本存储不下,我们只能以块的形式从磁盘读取数据,与主存的访问时间相比,磁盘的 I/O 操作相当耗时,而提出 B-树的主要目的就是减少磁盘的 I/O 操作

大多数平衡树的操作(查找、插入、删除,最大值、最小值等等)需要 O(ℎ)次磁盘访问操作,其中 ℎ 是树的高度。但是对于 B-树 而言,树的高度将不再是log(n)(n为数中节点的个数),而是一个我们可控的高度 ℎ (通过调整 B-树中结点所包含的键【你也可以叫做数据库中的索引,本质上就是在磁盘上的一个位置信息】的数目,使得 B-树的高度保持一个较小的值)一般而言,B-树的结点所包含的键的数目和磁盘块大小一样,从数个到数千个不等。由于B-树的高度 h 可控(一般远小于log(n)),所以与 AVL 树和红黑树相比,B-树的磁盘访问时间将极大地降低。

我们之前谈过红黑树与AVL树相比较,红黑树更好一些,这里我们将红黑树与B-树进行比较,并以一个例子对上面一段的内容进行解释。

假设我们现在有 838,8608 条记录,对于红黑树而言,树的高度 ℎ=log⁡(838,8608)=23 ,也就是说树的高度为23,也就是说如果要查找到叶子结点需要 23 次磁盘 I/O 操作;但是 B-树,情况就不同了,假设每一个结点可以包含 8 个键(当然真实情况下没有这么平均,有的结点包含的键可能比8多一些,有些比 8 少一些),那么整颗树的高度将最多 8 ( log8⁡(838,8608)=7.8 ) 层,也就意味着磁盘查找一个叶子结点上的键的磁盘访问时间只有 8 次,这就是 B-树提出来的原因所在。

1.2、B树的特点

下面讲一下B树的特点

在讲B树的特点之前,我们先来了解几个概念

度:degree 指树中节点的孩子数

阶:order 指所有节点中孩子数最大值

B树的特点:

  1. 每个节点最多有m个孩子,其中m称为B-树的阶;(孩子数目的上限)
  2. 除根节点和叶子节点外,其他节点至少有 ceil(m/2) (阶数除以2向上取整)个孩子,就是说B树中节点最大有m个孩子即阶个孩子,至少有 m/2(向上取整) 个孩子;(孩子数目的下限)
  3. 若根节点不是叶子节点,则至少有两个孩子;(根节点孩子数的下限)
  4. 所有叶子节点都在同一层;(B树是否平衡的前提条件)
  5. 每个非叶子节点由 n 个关键字(就是n个关键值,参考二叉搜索树中的关键值)和 n+1 个指针(就是n+1个孩子)组成,其中 ceil(m/2)-1 <= n <= m-1;
  6. 关键字按非降序排列(就是升序排列,和二叉树搜索相同),即节点中的第 i 个关键字大于等于第 i-1 个关键字;
  7. 指针P[ i ] 指向关键字值位于第 i 个关键字和第 i+1 个关键字之间的子树;

这些特性都要理解。看一下一个B树的实例:

2.B树的节点类

下面,我们来看一下B树的具体实现吧

package Tree;import java.util.Arrays;public class L5_BTree {//B数的节点类static class Node{int[] keys; //关键字,即关键值,排序用的Node[] children; //孩子,存孩子用的节点类数组int keyNumber; //有效关键字数目(就是真正存了几个关键字)boolean leaf = true; //是否是叶子节点int t; //最小度数(最小孩子数)//构造函数public Node(int t) { // t >= 2this.t = t;//手动设置最小孩子数this.children = new Node[2 * t];//最大孩子数是最小孩子数的二倍this.keys = new int[2 * t -1];//关键字的最大数量 是 最大孩子数-1}@Overridepublic String toString() {return Arrays.toString(Arrays.copyOfRange(keys,0,keyNumber));}//多路查找,就是我给你一个关键值,你返回这个关键值对应的节点Node get(int key){int i = 0; //设置个变量i,方便用来循环遍历while (i < keyNumber){ //节点中有关键字if (keys[i] == key){ //如果节点中的关键字 等于 我给出的关键字,那就返回这个关键字对应的节点return this;}if (keys[i] > key){ //如果关键字中的最小值都比给出的大,那就直接退出这个节点的循环了break;}i++; //变量i自增}//执行到这里,就是说当前节点的关键字一定比给出的大,或者说,超出索引了,即keys[i]>key 或 i == keyNumberif (leaf){ //如果是叶子节点,那就肯定没有孩子了return null;}//这种情况就是 i == keyNumber 了,就找这个节点所对应的孩子了(孩子数比节点关键值数多1)return children[i].get(key);}//写一个方法,向 keys 指定索引 index 处插入 keyvoid insertKey(int key, int index){for (int i = keyNumber-1; i >= index ; i--) {keys[i+1] = keys[i];}keys[index] = key;keyNumber++;}//写一个方法,向 children 指定索引 index 处插入 childvoid insertChild(Node child, int index){System.arraycopy(children,index,children,index+1,keyNumber);children[index] = child;}//移除指定index处的keyint removeKey(int index){int t = keys[index];System.arraycopy(keys,index+1,keys,index,--keyNumber-index);return t;}//移除最左边的keyint removeLeftmostKey(){return removeKey(0);}//移除最右边的keyint removeRightmostKey(){return removeKey(keyNumber-1);}//移除指定index处的childNode removeChild(int index){Node node = children[index];children[index] = null;return children[index];}//移除最左边的childNode removeLeftmostChild(){return removeChild(0);}//移除最右边的childNode removeRightmostChild(){return removeChild(keyNumber);}//返回index孩子处左边的兄弟Node childLeftSibling(int index){return index > 0 ? children[index-1]:null;}//返回index孩子处右边的兄弟Node childRightSibling(int index){return index == keyNumber ? null : children[index+1];}//复制当前节点的所有key和child到targetvoid moveToTarget(Node target){int start = target.keyNumber;if (!leaf){for (int i = 0; i <= keyNumber; i++) {target.children[start+i] = children[i];}}for (int i = 0; i < keyNumber; i++) {target.keys[target.keyNumber++] = keys[i];}}}Node root; //定义一个根节点int t; //树中节点的最小度数(就是一个节点的最小孩子数,根节点叶子节点除外)final int MIN_KEY_NUMBER;//最小关键字的数量final int MAX_KEY_NUMBER;//最大关键字的数量//无参构造,最小度数默认值为2public L5_BTree() {this(2);}//有参构造public L5_BTree(int t) {this.t = t;root = new Node(t);//new出根节点,并给出根节点最小度数MIN_KEY_NUMBER = t-1;MAX_KEY_NUMBER = 2*t-1;}//判断关键字中是否存在指定关键字对应的节点public boolean contains(int key){return root.get(key) != null;}//新增一个关键字/**描述一下流程吧* 你构造一颗B树,给定了最小度数,那么最小关键字数、最大关键字数、阶数也就都定了* 你开始往节点中插入关键值,一开始没满,你继续插入* 当插入的关键字数等于最大关键字数时,这个节点就要分裂了,即将自身的关键字分出去,变为孩子节点* 然后你再插入,它就会按照关键字的顺序去选位置,* 如果找到位置了,是叶子节点,那么就直接插入(当然超过MAX_KEY_NUMBER就分裂一下)* 如果恰好发现一个非叶子节点里面也有位置,那么应该先搜索一下这个节点的孩子,然后再进行判断插在哪里* 当某个节点的关键字数再满,那这个树就再分裂一次* */public void put(int key){doPut(root,key,null,0);}//递归的函数private void doPut(Node node,int key,Node parent,int index){int i = 0;while (i < node.keyNumber){if (node.keys[i] == key){return; //更新逻辑}if (node.keys[i] > key){break; //找到插入位置,记为i}i++;}if (node.leaf){node.insertKey(key,i);//可能到达上限}else {doPut(node.children[i],key,node,i);//可能到达上限}if (node.keyNumber == MAX_KEY_NUMBER){split(node,parent,index);}}//分裂函数/*** left:要分裂的节点* parent:分裂节点的父节点* index:分裂节点是第几个孩子* */private void split(Node left, Node parent, int index){if (parent == null){//分裂的是根节点Node newRoot = new Node(t);newRoot.leaf = false;newRoot.insertChild(left,0);this.root = newRoot;parent = newRoot;}//1.创建right节点,把left中t之后的key和child移动过去Node right = new Node(t);right.leaf = left.leaf;System.arraycopy(left.keys,t,right.keys,0,t-1);//分裂节点是非叶子节点的情况if (!left.leaf){System.arraycopy(left.children,t,right.children,0,t);}right.keyNumber = t-1;left.keyNumber = t-1;//2.中间的key(t-1处)插入到父节点中int mid = left.keys[t-1];parent.insertKey(mid,index);//3.right节点作为父节点的孩子parent.insertChild(right,index+1);}//删除一个关键字public void remove(int key){doRemove(null,root,0,key);}private void doRemove(Node parent,Node node,int index,int key){int i = 0;while (i < node.keyNumber){if (node.keys[i] >= key){break;}i++;}//找到了,代表待删除key的索引//没找到,表示到第 i 个孩子里面继续查找if (node.leaf){if(!found(node, key, i)){//case1return;}else {//case2node.removeKey(i);}}else {if(!found(node, key, i)){//case3doRemove(node,node.children[i],i,key);}else {//case4Node s = node.children[i+1];while (!s.leaf){s = s.children[0];}int skey = s.keys[0];node.keys[i] = skey;doRemove(node,node.children[i+1],i+1,skey);}}if (node.keyNumber < MIN_KEY_NUMBER){//调整平衡 case5 and case6balance(parent,node,index);}}private void balance(Node parent, Node x, int i){//case6 根节点if (x == root){if (root.keyNumber == 0 && root.children[0] != null){root = root.children[0];}return;}Node left = parent.childLeftSibling(i);Node right = parent.childRightSibling(i);if (left != null && left.keyNumber > MAX_KEY_NUMBER){//case5-1 左边富裕 右旋//把父节点中前驱key旋转下来x.insertKey(parent.keys[i-1],0);if (!left.leaf){//left中最大的孩子换爹x.insertChild(left.removeRightmostChild(),0);}//left中最大的key旋转上去parent.keys[i-1] = left.removeRightmostKey();return;}if (right != null && right.keyNumber > MAX_KEY_NUMBER){//case5-2 右边富裕 左旋//把父节点中后继key旋转下来x.insertKey(parent.keys[i],x.keyNumber);//right中最小的孩子换爹if (!right.leaf){x.insertChild(right.removeLeftmostChild(),x.keyNumber+1);}//right中最小的key旋转上去parent.keys[i] = right.removeLeftmostKey();return;}//case5-3 两边都不富裕 向左合并if(left != null){//向左兄弟合并parent.removeChild(i);left.insertKey( parent.removeKey(i-1), left.keyNumber);x.moveToTarget(left);}else {//自己合并parent.removeChild(i+1);x.insertKey(parent.removeKey(i),x.keyNumber );right.moveToTarget(x);}}private boolean found(Node node, int key, int i) {return i < node.keyNumber && node.keys[i] == key;}}

为了对应代码中插入和删除的逻辑思路,下面给出两张图来看一下。

节点中插入key值后的节点分裂展示图:

在节点中删除key的6种情况展示图(删除的是某个节点的key):

3.小结

说实话,我感觉这东西挺难的,写完之后脑瓜子都嗡嗡的。没有在纸上画图,单靠脑子想,我是肯定写不出来的,所以我的建议是:一定一定一定要画图,一定一定一定要看着图对着代码来一步一步的走,一定一定一定要看图!

相关文章:

数据结构与算法——20.B-树

这篇文章我们来讲解一下数据结构中非常重要的B-树。 目录 1.B树的相关介绍 1.1、B树的介绍 1.2、B树的特点 2.B树的节点类 3.小结 1.B树的相关介绍 1.1、B树的介绍 在介绍B树之前&#xff0c;我们回顾一下我们学的树。 首先是二叉树&#xff0c;这个不用多说&#xff…...

Tomcat源码解析——Tomcat的启动流程

一、启动脚本 当我们在服务启动Tomcat时&#xff0c;都是通过执行startup.sh脚本启动。 在Tomcat的启动脚本startup.sh中&#xff0c;最终会去执行catalina.sh脚本&#xff0c;传递的参数是start。 在catalina.sh脚本中&#xff0c;前面是环境判断和初始化参数&#xff0c;最终…...

蓝桥杯真题演练:2023B组c/c++

日期统计 小蓝现在有一个长度为 100 的数组&#xff0c;数组中的每个元素的值都在 0 到 9 的范围之内。 数组中的元素从左至右如下所示&#xff1a; 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 …...

微信小程序实现预约生成二维码

业务需求&#xff1a;点击预约按钮即可生成二维码凭码入校参观~ 一.创建页面 如下是博主自己写的wxml&#xff1a; <swiper indicator-dots indicator-color"white" indicator-active-color"blue" autoplay interval"2000" circular > &…...

专业140+总分410+北京理工大学826信号处理导论考研经验北理工电子信息通信工程,真题,参考书,大纲。

今年考研专业课826信号处理导论&#xff08;信号系统和数字信号处理&#xff09;140&#xff0c;总分410&#xff0c;顺利上岸&#xff01;回看去年将近一年的复习&#xff0c;还是记忆犹新&#xff0c;有不少经历想和大家分享&#xff0c;有得有失&#xff0c;希望可以对大家复…...

做一个后台项目的架构

后台架构的11个维度 架构1&#xff1a;团队协助基础工具链的选型和培训架构2&#xff1a;搭建微服务开发基础设施架构3&#xff1a;选择合适的RPC框架架构4&#xff1a;选择和搭建高可用的注册中心架构5&#xff1a;选择和搭建高可用的配置中心架构6&#xff1a;选择和搭建高性…...

嵌入式单片机 TTL电平、232电平、485电平的区别和联系

一、简介 TTL、232和485是常见的串口通信标准&#xff0c;它们在电平和通信方式上有所不同&#xff0c; ①一般情况下TTL电平应用于单片机外设&#xff0c;属于MCU/CPU等片外外设&#xff1b; ②232/485电平应用于产品整体对外的接口&#xff0c;一般是片外TTL串口转232/485…...

2024年大唐杯备考

努力更新中…… 第一章 网络架构和组网部署 1.1 5G的网络整体架构 5G网络中的中传、回传、前传&#xff08;这里属于承载网的概念&#xff09; CU和DU之间是中传 BBU和5GC之间是回传 BBU和AAU之间是前传&#xff08;这个好记&#xff09; 这里竟然还藏了MEC&#xff08;…...

Spring Boot(06):Spring Boot与MySQL搭配,打造极简高效的数据管理系统

1. 前言 Spring Boot 是一个基于Spring框架的快速开发框架&#xff0c;可以使开发者快速搭建一个可靠的Java Web应用程序。而MySQL是最广泛使用的关系型数据库系统之一&#xff0c;也是Spring Boot整合数据库的首选。本文将介绍Spring Boot如何整合MySQL数据库。 2. 摘要 本文…...

Vue3 + Vite 构建组件库发布到 npm

你有构建完组件库后&#xff0c;因为不知道如何发布到 npm 的烦恼吗&#xff1f;本教程手把手教你用 Vite 构建组件库发布到 npm 搭建项目 这里我们使用 Vite 初始化项目&#xff0c;执行命令&#xff1a; pnpm create vite my-vue-app --template vue这里以我的项目 vue3-xm…...

Vite多环境配置与打包:灵活高效的Vue开发工作流

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

从零实现诗词GPT大模型:数据集介绍和预处理

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 本章将介绍该系列文章中使用的数据集&#xff0c;并且编写预处理代码&#xff0c;处理成咱们需要的格式。 一、数据集介绍 咱们使用的数据集名称是chinese-poetry&#xff0c;是一个在github上开源的中文诗…...

45.HarmonyOS鸿蒙系统 App(ArkUI)创建列表(List)

列表是一种复杂的容器&#xff0c;当列表项达到一定数量&#xff0c;内容超过屏幕大小时&#xff0c;可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集&#xff0c;例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求&#xff08;如通讯录、音乐列…...

推荐算法之协同过滤

算法原理 透过百科&#xff0c;我们了解到协同过滤推荐&#xff08;Collaborative Filtering recommendation&#xff09;是在信息过滤和信息系统中正迅速成为一项很受欢迎的技术。与传统的基于内容过滤直接分析内容进行推荐不同&#xff0c;协同过滤算法结合用户行为分析用户…...

Kotlin 面试题

lifecycleScope.launchWhenResumed launchWhenResumed是一个扩展函数,它是LifecycleCoroutineScope的一部分,并且它是在Android的Lifecycle库中引入的。 这个函数的主要目的是在Lifecycle的对应组件(通常是Activity或Fragment)处于“resumed”状态时启动协程。 public fun …...

TCM(Tightly Coupled Memory)紧密耦合存储器简介

在ARM Cortex处理器中&#xff0c;TCM通常指的是紧密耦合存储器&#xff08;Tightly Coupled Memory&#xff09;。TCM是一种位于处理器核心旁边的高速存储器&#xff0c;它的设计目的是为了提供低延迟和高带宽的内存访问性能。 TCM的特点是它与处理器内核紧密耦合&#xff0c;…...

《自动机理论、语言和计算导论》阅读笔记:p172-p224

《自动机理论、语言和计算导论》学习第 8 天&#xff0c;p172-p224总结&#xff0c;总计 53 页。 一、技术总结 1.Context-Free Grammar(CFG) 2.parse tree (1)定义 p183&#xff0c;But perhaps more importantly, the tree, known as a “parse tree”, when used in a …...

typescript playwright 笔记

录制调式 命令 npx playwright codegen url npx playwright codegen https://www.baidu.com/typescript 中 format 和 split 的使用 import * as util from util;const str1 hellow %s; const format util.format; const str2 format(str1, word);// 提取taskId const str3…...

从零实现诗词GPT大模型:了解Transformer架构

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 这篇文档我们开始对GPT的核心组件Transformer进行一个详细的讲解, 加急编写中…...

温故知新之-TCP Keepalive机制及长短连接

[学习记录] 前言 TCP连接一旦建立&#xff0c;只要连接双方不主动 close &#xff0c;连接就会一直保持。但建立连接的双方并不是一直都存在数据交互&#xff0c;所以在实际使用中会存在两种情况&#xff1a;一种是每次使用完&#xff0c;主动close&#xff0c;即短连接&…...

架构师系列-搜索引擎ElasticSearch(七)- 集群管理之分片

集群健康检查 Elasticsearch 的集群监控信息中包含了许多的统计数据&#xff0c;其中最为重要的一项就是集群健康&#xff0c;它在 status字段中展示为 green&#xff08;所有主分片和副本分片都正常&#xff09;、yellow&#xff08;所有数据可用&#xff0c;有些副本分片尚未…...

基于Spring Boot实现的图书个性化推荐系统

基于Spring Boot实现的图书个性化推荐系统 开发语言&#xff1a;Java语言 数据库&#xff1a;MySQL工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统实现 前台首页功能模块 学生注册 登录 图书信息 个人信息 管理员功能模块 学生管理界面图 图书分类管理界面图 图书信息管…...

安全加速SCDN带的态势感知能为网站安全带来哪些帮助

随着安全加速SCDN被越来越多的用户使用&#xff0c;很多用户都不知道安全加速SCDN的态势感知是用于做什么的&#xff0c;德迅云安全今天就带大家来了解下什么是态势感知&#xff0c;态势感知顾名思义就是对未发生的事件进行预知&#xff0c;并提前进行防范措施的布置&#xff0…...

java面向对象.day21(继承02--super)

说明 super父 this当前 使用super时&#xff0c;首先要继承父类&#xff0c;其次是在子类里面才能使用super。 继承父类后&#xff0c;运行子类时会同时调用父类的构造方法&#xff0c;如果要显性调用父类的构造方法必须在子类的第一行调用。 单使用super()表示调用父类构造…...

【数据结构】4.List的介绍

目录 1.什么是List 2.常见接口介绍 3.List的使用 1.什么是List 在集合框架中&#xff0c;List是一个接口&#xff0c;继承自Collection。 Collection也是一个接口&#xff0c;该接口中规范了后序容器中常用的一些方法&#xff0c;具体如下&#xff1a; Iterable也是一个接口…...

acwing算法提高之图论--最近公共祖先

目录 1 介绍2 训练 1 介绍 本博客用来记录"对于有根图中&#xff0c;求最近公共祖先"的题目。 求解方法&#xff1a; 向上标记法。每次求两个结点的最近公共祖先的时间复杂度是O(N)。由于时间复杂度较高&#xff0c;通常不用。倍增法。 倍增法重要思路&#xff1…...

C语言 函数——断言与防御式编程

目录 如何确定假设的真假&#xff1f; 断言 防御式编程&#xff08;Defensive programming&#xff09; 如何确定假设的真假&#xff1f; 程序中的假设 *某个特定点的某个表达式的值一定为真 *某个特定点的某个表达式的值一定位于某个区间等 问题&#xff1a;如何确定这些…...

【opencv】示例-travelsalesman.cpp 使用模拟退火算法求解旅行商问题

// 载入 OpenCV 的核心头文件 #include <opencv2/core.hpp> // 载入 OpenCV 的图像处理头文件 #include <opencv2/imgproc.hpp> // 载入 OpenCV 的高层GUI(图形用户界面)头文件 #include <opencv2/highgui.hpp> // 载入 OpenCV 的机器学习模块头文件 #includ…...

【linux深入剖析】深入理解软硬链接 | 动静态库的制作以及使用

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1.理解软硬链接1.1 操作观…...

xss常用标签和触发事件

无过滤情况 <script> <scirpt>alert("xss");</script> <img> 图片加载错误时触发 <img src"x" οnerrοralert(1)> <img src"1" οnerrοreval("alert(xss)")> 鼠标指针移动到元素时触发 <im…...

网站建设杭州滨江/产品推广网站

这是一个所有做前端都会遇到的问题&#xff1b;布局是这样的&#xff0c;有一个宽高100px背景为红的div&#xff0c;默认是display&#xff1a;none 隐藏状态&#xff1b;给两个a标签绑定的同一个click事件&#xff0c;改变div的display为block&#xff1b;让其显示&#xff1b…...

广州地铁5号线/海南seo

目录 1.市场上常见的数据库 2.数据库语句 2.1DDL语句 2.2DML数据操作语句 2.3DQL语句 2.4DCL语句 3.数据约束 4.表关系 5.数据库的三范式 6.多表查询&#xff08;有关系的表&#xff09; 7.子查询 1.市场上常见的数据库 Oracle Mysql SQLServer 2.数据库语句 DD…...

爱情动做网站推荐/免费测试seo

2019独角兽企业重金招聘Python工程师标准>>> 当设置了父元素的宽度&#xff0c;子元素设置宽度为100%后再在加上子元素上添加padding或margin值就会溢出。举个例子&#xff1a; <!-- 示例 --><!-- html --> <div class"parent"><div…...

磐安建设局网站/海外品牌推广

质谱可以用来测量样品中带电分子(离子)的丰度&#xff08;即一个特定的质荷比 m/z的离子计数&#xff09;。 但是&#xff0c;当许多离子具有相同或非常相似的 m/z&#xff0c;光凭借质谱是很难或不可能进行区分的。因此&#xff0c;MS 经常与其他分离技术相结合&#xff0c;基…...

项目负责人质量建设厅官方网站/上海网站推广服务

在实际的项目中&#xff0c;图片的处理往往是最麻烦的&#xff0c;无论是前后台&#xff0c;我自己也试手了一两个图片上传的小项目&#xff0c;把步骤写下来&#xff0c;以后自己忘记可以返回来看一下&#xff0c;同时希望能够帮到小伙伴们... 前端网页 框架&#xff1a; vue …...

网站介绍的ppt怎么做/长沙网站制作费用

随着年龄的增大&#xff0c;感觉自己也在慢慢的变大&#xff0c;心智也越发的成熟了。不断的自我完善&#xff0c;达到内心的平和与平稳。平静才是最幸福的。你中了彩票&#xff0c;很激动&#xff0c;那都是暂时的&#xff0c;过一段时间你就忘记了&#xff0c;那是超级喜悦&a…...