最新要闻
- 女生例假注意事项文案_女生例假注意事项
- 中国家庭渗透率不足1% 中国电视回音壁开始发力 给昂贵的外资品牌敲响警钟
- 4月首飞空中爆炸 马斯克:星舰下次成功机会大增 可能60%
- 85%肉含量无淀粉 一口爆汁:火山石烤肠22.9元2斤大促|环球新资讯
- 天天最资讯丨美国一列货运火车压垮桥梁坠入河中:车厢内危险品泄漏
- 学生高考成绩被屏蔽老师激动欢呼:原来这代表全省前30
- 国家邮政局:今年全国快递业务量已达600亿件
- 亚马逊云斥资1亿美元建AIGC中心,帮助企业使用生成式人工智能
- 全球实时:创建17年的17K小说网创始人刘英去世:年仅42岁
- 继任者ZV-1 II发售后:索尼ZV-1已正式停产
- 天天即时看!竞争激烈!广汽丰田展台上演“武术表演”:蓝衣、白衣销售互殴
- 赶快收藏 官方公布2023年高考志愿填报十问十答
- 男子每天1斤杨梅狂吃20天要做血透 医生提醒:高钾水果、肾不好少吃_环球精选
- 茅台贵州大曲酒怎么样?贵州大曲是什么档次?贵州大曲酒80年代评价
- 端午情怀“艾”在心间 天天微资讯
- 22岁小伙挑选私人飞机 预算5.5亿元 马斯克看了都害怕 世界观天下
广告
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
当前快讯:B+ tree implemented in Java
(相关资料图)
B+树相关介绍
B+树是一棵多叉排序树,即每个非叶子节点可以包含多个子节点,其整体结构呈扁平化,所以其非常适配于数据库和操作系统的文件系统中。且B+树能够保持数据的稳定有序,插入和删除都拥有较稳定的对数时间复杂度。
B+树的特性:以 m 阶为例,m 表示内部节点即非叶子节点可以包含的最大子节点个数 maximumNum
- 若一个内部节点有 \(n(n <= m)\) 个子节点,则该内部节点应包含 \(n - 1\) 个关键字,也就是索引值
- 除根节点和叶子节点外,其他节点至少包含
Math.ceil(m / 2)
个子节点,这是因为B+树的生成顺序导致的- 最开始,B+树只有一个根节点和若干不超过m个的叶子节点;
- 逐渐添加,导致叶子节点超过m时,此时根节点的子节点个数大于m,不符合要求,需要分裂
- 分裂则导致增加2个内部节点,其中一个内部节点个数为
(m+1)/2
,另一个为(m+2)/2
- 其他内部节点也是如此规律形成,所以所有内部节点的子节点个数均大于
Math.ceil(m / 2)
- 内部节点即对应索引部分,节点中仅包含子树中最大/最小的索引值
- 叶子节点即对应数据部分,节点中不仅包含索引值,也包含其他的值信息
- 最底层所有叶子节点通过双向链表串联,优化范围查询
B+树实现
目前实现的B+树的简易版,叶子节点是存储的Entry
键值对,内部节点存储的是Integer
索引,后续有时间再进行泛型的通用扩展。
节点定义
抽象公共父类 Node
package bplustree;public abstract class Node { InternalNode parent; // 父节点 public Node() {} public abstract boolean isValid(); // 判断删除节点后各B+树节点是否满足要求 public abstract boolean isAvailable(); // 判断B+树节点是否可以分裂节点给其他节点 public abstract boolean isMergeable(); // 判断B+树节点是否可以和其他节点合并}
内部节点定义
public class InternalNode extends Node{ int maxChildNodes; // 子节点个数最大值 m,m为阶数 int minChildNodes; // 除根节点及叶子节点外,子节点个数最小值 ceil(m / 2) int curNodesNum; // 内部节点当前的子节点个数 InternalNode leftSibling; // 左兄弟节点 InternalNode rightSibling; // 右兄弟节点 Integer[] keys; // 内部节点当前的索引值,最多有 m - 1 个 Node[] childPointers; // 内部节点当前的子节点,最多有 m 个}
叶子节点定义
public class LeafNode extends Node { int maximumNum; // 叶子节点最多元素个数 m - 1 int minimumNum; int curNum; // 叶子节点当前的元素个数 LeafNode leftSibling; // 左兄弟和右兄弟形成双向链表 LeafNode rightSibling; Entry[] entries; // 叶子节点键值对,不仅存储索引值,也存储其他值信息}class Entry implements Comparable { Integer key; String value; public Entry(Integer key, String value) { this.key = key; this.value = value; } @Override public int compareTo(Entry o) { return key.compareTo(o.key); }}
B+树定义
public class BPlusTree { int m; InternalNode root; // B+树根节点 LeafNode head; // 叶子节点的首元素}
查询操作
单值查询
B+树的查找过程:根据查找的索引值k,从根节点向叶子节点搜索,对数时间复杂度。
public String search(int key) { if (isEmpty()) { return null; } // 树查找 LeafNode leafNode = (this.root == null) ? this.head : findLeafNode(key); Entry[] entries = leafNode.entries; // 叶子节点内进行二分查找 int index = binarySearch(entries, leafNode.curNum, key, null); if (index == -1) { return null; } else { return entries[index] }}// 从根节点开始查找private LeafNode findLeafNode(Integer key) { return findLeafNode(root, key);}// 找到索引值所在的叶子节点private LeafNode findLeafNode(InternalNode internalNode, Integer key) { Integer[] keys = internalNode.keys; int i; for (i = 0; i < internalNode.curNodesNum - 1; i++) { if (key.compareTo(keys[i]) < 0) { break; } } Object child = internalNode.childPointers[i]; if (child instanceof LeafNode) { return (LeafNode) child; } else { return findLeafNode((InternalNode) child, key); }}
区间查询
B+树区间查询左值可能在的叶子节点位置,然后通过双向链表向后遍历。
// 闭区间 [left, right]public ArrayList searchRange(int left, int right) { List values = new ArrayList<>(); LeafNode leafNode = findLeafNode(left); // 查找左值可能存在的位置,并从该位置向后遍历 boolean flag = true; while (leafNode != null && flag) { Entry[] entries = leafNode.entries; for (Entry entry : entries) { if (entry == null) { break; } if ( entry.key > right) { flag = false; break; } if (left <= entry.key && right >= entry.key) { values.add(entry.value); } } leafNode = leafNode.rightSibling; } return values;}
插入操作
B+树的插入操作仅在叶子节点进行:
- 若为空树,则创建一个叶子节点,该叶子节点同时也是根节点,插入操作结束;
- 根据插入的 key 值,找到应该在的叶子节点插入;
- 若插入后叶子节点个数符合要求即小于m,则插入结束
- 若插入后叶子节点个数不符合要求即大于等于m,将该节点分裂成两半,则判断当前叶子节点是否为根节点
- 若当前叶子节点为根节点,则构建一个新的root节点,指向分裂后的两个子节点
- 若当前叶子节点不为根节点,则在父节点处添加一个新的子节点,新子节点则存储原节点一半的值,并循环向上判断中间节点是否满足要求
public void insert(int key, String value) { if (isEmpty()) { this.head = new LeafNode(this.m, new Entry(key, value)); } else { LeafNode leafNode = (this.root == null) ? this.head : findLeafNode(key); // 插入叶子节点失败,即叶子节点中存储已到达上限 if (!leafNode.insert(new Entry(key, value))) { leafNode.entries[leafNode.curNum++] = new Entry(key, value); sortEntries(leafNode.entries); // 叶子节点分裂的位置 int mid = getIndexOfMidPointer(); Entry[] halfEntry = splitEntries(leafNode, mid); // 若叶子节点为根节点,即parent为null if (leafNode.parent == null) { Integer[] parent_keys = new Integer[m]; parent_keys[0] = halfEntry[0].key; // 创建新的 root InternalNode parent = new InternalNode(m, parent_keys); leafNode.parent = parent; parent.appendChildPointer(leafNode); } // 若叶子节点不为根节点 else { int newParentKey = halfEntry[0].key; leafNode.parent.keys[leafNode.parent.curNodesNum - 1] = newParentKey; Arrays.sort(leafNode.parent.keys, 0, leafNode.parent.curNodesNum); } // 分裂后的另一半叶子节点,添加到父节点 LeafNode newLeafNode = new LeafNode(this.m, halfEntry, leafNode.parent); // 分裂后的另一半叶子节点对应的下标 int index = leafNode.parent.getIndexOfPointer(leafNode) + 1; for (int i = index; i < leafNode.parent.childPointers.length - 1; i++) { leafNode.parent.childPointers[i + 1] = leafNode.parent.childPointers[i]; } leafNode.parent.childPointers[index] = newLeafNode; // 关联兄弟节点 newLeafNode.rightSibling = leafNode.rightSibling; if (newLeafNode.rightSibling != null) { newLeafNode.rightSibling.leftSibling = newLeafNode; } leafNode.rightSibling = newLeafNode; newLeafNode.leftSibling = leafNode; if (this.root == null) { this.root = leafNode.parent; } else { // 逐渐上浮,判断插入是否会导致B+树内部节点不符合要求 InternalNode internalNode = leafNode.parent; while (internalNode != null) { if (internalNode.isOverfull()) { splitInternalNode(internalNode); } else { break; } internalNode = internalNode.parent; } } } }}/** * 叶子节点插入,导致的上层内部节点分裂 */private void splitInternalNode(InternalNode internalNode) { InternalNode parent = internalNode.parent; int mid = getIndexOfMidPointer(); Integer newParentKey = internalNode.keys[mid]; // 内部节点的 node 分裂 Node[] halfPointers = splitChildPointers(internalNode, mid); // 内部节点的 key 分裂 Integer[] halfKeys = splitKeys(internalNode.keys, mid); // 分裂后内部节点的子节点个数 internalNode.curNodesNum = linearNullSearch(internalNode.childPointers); InternalNode sibling = new InternalNode(this.m, halfKeys, halfPointers); for (Node pointer : halfPointers) { if (pointer != null) { pointer.parent = sibling; } } sibling.rightSibling = internalNode.rightSibling; internalNode.rightSibling = sibling; sibling.leftSibling = internalNode; if (sibling.rightSibling != null) { sibling.rightSibling.leftSibling = sibling; } // root node if (parent == null) { Integer[] keys = new Integer[this.m]; keys[0] = newParentKey; InternalNode newRoot = new InternalNode(this.m, keys); newRoot.appendChildPointer(internalNode); newRoot.appendChildPointer(sibling); this.root = newRoot; internalNode.parent = newRoot; sibling.parent = newRoot; } else { parent.keys[parent.curNodesNum - 1] = newParentKey; Arrays.sort(parent.keys, 0, parent.curNodesNum); int index = parent.getIndexOfPointer(internalNode) + 1; parent.insertChildPointer(sibling, index); sibling.parent = parent; }}private Node[] splitChildPointers(InternalNode node, int split) { Node[] pointers = node.childPointers; Node[] newPointers = new Node[this.m + 1]; for (int i = split + 1; i < pointers.length; i++) { newPointers[i - split - 1] = pointers[i]; node.removePointer(i); } return newPointers;}private Integer[] splitKeys(Integer[] keys, int split) { Integer[] newKeys = new Integer[m]; keys[split] = null; for (int i = split + 1; i < keys.length; i++) { newKeys[i - split] = keys[i]; keys[i] = null; } return newKeys;}
删除操作
B+树的删除操作仅在叶子节点进行:
- 若删除后,叶子节点中的索引个数仍然满足要求即大于等于
Math.ceil(m / 2)
时,将该叶子节点的其他索引左移一位,删除结束;- 若删除后,叶子节点中的索引个数不满足最低要求,则查询左右兄弟节点:
- 若左/右兄弟节点中索引个数大于
Math.ceil(m / 2)
,则从左/右兄弟节点中移动一个索引项到当前叶子节点中,并修改父节点的索引值,删除结束- 若左/右兄弟节点中索引个数等于
Math.ceil(m / 2)
,则将左/右节点与当前节点合并,修改父节点的索引记录,并向上逐级判断内部节点是否因为页合并导致索引项不满足最低要求,删除结束
public void delete(int key) { if (isEmpty()) { System.out.println("Invalid: The B+ tree is empty!"); } else { LeafNode leafNode = this.root == null ? this.head : findLeafNode(key); int index = binarySearch(leafNode.entries, leafNode.curNum, key, null); if (index < 0) { System.out.println("Invalid: The key does not exist in the B+ tree!"); } else { leafNode.deleteAtIndex(index); // 删除后,叶子节点仍然满足要求,删除结束 if (leafNode.isValid()) { LeafNode sibling; InternalNode parent = leafNode.parent; // 删除后,叶子节点不满足要求,左兄弟节点可以移动一个索引项到当前叶子节点 if (leafNode.leftSibling != null && leafNode.leftSibling.parent == parent && leafNode.leftSibling.isAvailable()) { sibling = leafNode.leftSibling; Entry entry = sibling.entries[sibling.curNum - 1]; leafNode.insert(entry); sortEntries(leafNode.entries); sibling.deleteAtIndex(sibling.curNum - 1); // 更新 parent 的 key int pointIndex = getIndexOfLeafNode(parent.childPointers, leafNode); if (entry.key < parent.keys[pointIndex - 1]) { parent.keys[pointIndex - 1] = entry.key; } } // 删除后,叶子节点不满足要求,右兄弟节点可以移动一个索引项到当前叶子节点 else if (leafNode.rightSibling != null && leafNode.rightSibling.parent == parent && leafNode.rightSibling.isAvailable()) { sibling = leafNode.rightSibling; Entry entry = sibling.entries[0]; leafNode.insert(entry); sortEntries(leafNode.entries); sibling.deleteAtIndex(0); // 更新 parent 的 key int pointIndex = getIndexOfLeafNode(parent.childPointers, leafNode); if (entry.key > parent.keys[pointIndex]) { parent.keys[pointIndex] = entry.key; } } // 删除后,叶子节点不满足要求,左兄弟节点可以与当前叶子节点合并 else if (leafNode.leftSibling != null && leafNode.leftSibling.parent == parent && leafNode.leftSibling.isMergeable()) { sibling = leafNode.leftSibling; int pointIndex = getIndexOfLeafNode(parent.childPointers, leafNode); parent.removeKey(pointIndex - 1); parent.removePointer(leafNode); sibling.rightSibling = leafNode.rightSibling; if (parent.isValid()) { handleDeficiency(parent); } } // 删除后,叶子节点不满足要求,右兄弟节点可以与当前叶子节点合并 else if (leafNode.rightSibling != null && leafNode.rightSibling.parent == parent && leafNode.rightSibling.isMergeable()) { sibling = leafNode.rightSibling; int pointIndex = getIndexOfLeafNode(parent.childPointers, leafNode); parent.removeKey(pointIndex); parent.removePointer(leafNode); sibling.leftSibling = leafNode.leftSibling; if (sibling.leftSibling == null) { this.head = sibling; } // 逐级向上层判断是否满足要求 if (parent.isValid()) { handleDeficiency(parent); } } // 删除后,B+树为空 else if (this.root == null && this.head.curNum == 0) { this.head = null; } } } }}/** * 处理不满足要求的内部节点 * @param internalNode */private void handleInvalidInternalNode(InternalNode internalNode) { InternalNode sibling; InternalNode parent = internalNode.parent; // 当前内部节点为根节点 if (root == internalNode) { for (int i = 0; i < internalNode.childPointers.length; i++) { if (internalNode.childPointers[i] != null) { if (internalNode.childPointers[i] instanceof InternalNode) { root = (InternalNode) internalNode.childPointers[i]; root.parent = null; } else if (internalNode.childPointers[i] instanceof LeafNode) { root = null; } } } } // 左兄弟节点可以移动索引项 else if (internalNode.leftSibling != null && internalNode.leftSibling.isAvailable()) { sibling = internalNode.leftSibling; Integer key = sibling.keys[internalNode.curNodesNum - 2]; Node pointer = sibling.childPointers[internalNode.curNodesNum - 1]; shiftKeys(internalNode.keys, 1); shiftPointers(internalNode.childPointers, 1); internalNode.keys[0] = key; internalNode.childPointers[0] = pointer; sibling.removePointer(pointer); } // 右兄弟节点可以移动索引项 else if (internalNode.rightSibling != null && internalNode.rightSibling.isAvailable()) { sibling = internalNode.rightSibling; Integer key = sibling.keys[0]; Node pointer = sibling.childPointers[0]; internalNode.keys[internalNode.curNodesNum - 1] = parent.keys[0]; internalNode.childPointers[internalNode.curNodesNum] = pointer; parent.keys[0] = key; sibling.removePointer(0); shiftPointers(sibling.childPointers, -1); } // 左兄弟节点可以合并 else if (internalNode.leftSibling != null && internalNode.leftSibling.isMergeable()) { sibling = internalNode.leftSibling; int index = -1; for (int i = 0; i < parent.childPointers.length; i++) { if (parent.childPointers[i] == internalNode) { index = i; break; } } parent.keys[index - 1] = parent.keys[index]; for (int i = index; i < parent.keys.length - 1; i++) { parent.keys[i] = parent.keys[i + 1]; } shiftPointers(internalNode.childPointers, (int) Math.ceil(m / 2.0)); for (int i = 0; i < (int) Math.ceil(m / 2.0); i++) { internalNode.childPointers[i] = sibling.childPointers[i]; } internalNode.leftSibling = sibling.leftSibling; if (internalNode.leftSibling != null) { internalNode.leftSibling.rightSibling = internalNode; } if (parent != null && parent.isValid()) { handleInvalidInternalNode(parent); } } // 右兄弟节点可以合并 else if (internalNode.rightSibling != null && internalNode.rightSibling.isMergeable()) { sibling = internalNode.rightSibling; int index = -1; for (int i = 0; i < parent.childPointers.length; i++) { if (internalNode == parent.childPointers[i]) { index = i; break; } } parent.keys[index] = parent.keys[index + 1]; for (int i = index + 2; i < parent.keys.length; i++) { parent.keys[i - 1] = parent.keys[i]; } for (int i = 0; i < (int) Math.ceil(m / 2.0); i++) { internalNode.childPointers[internalNode.curNodesNum++] = sibling.childPointers[i]; } internalNode.rightSibling = sibling.rightSibling; if (internalNode.rightSibling != null) { internalNode.rightSibling.leftSibling = internalNode; } if (parent != null && parent.isValid()) { handleInvalidInternalNode(parent); } }}
参考文章:
1. B+树
关键词:
当前快讯:B+ tree implemented in Java
女生例假注意事项文案_女生例假注意事项
中国家庭渗透率不足1% 中国电视回音壁开始发力 给昂贵的外资品牌敲响警钟
4月首飞空中爆炸 马斯克:星舰下次成功机会大增 可能60%
85%肉含量无淀粉 一口爆汁:火山石烤肠22.9元2斤大促|环球新资讯
天天最资讯丨美国一列货运火车压垮桥梁坠入河中:车厢内危险品泄漏
学生高考成绩被屏蔽老师激动欢呼:原来这代表全省前30
国家邮政局:今年全国快递业务量已达600亿件
ABAQUS 在车辆驻车制动系统中的应用
金鸡湖赛龙舟 | 璞华龙舟队飞舟竞渡,荣获“最佳团队拼搏奖”!
Apache RocketMQ EventBridge:构建下一代事件驱动引擎_世界短讯
中国石油天然气集团有限公司原党组副书记、副总经理徐文荣接受审查调查
亚马逊云斥资1亿美元建AIGC中心,帮助企业使用生成式人工智能
全球实时:创建17年的17K小说网创始人刘英去世:年仅42岁
继任者ZV-1 II发售后:索尼ZV-1已正式停产
天天即时看!竞争激烈!广汽丰田展台上演“武术表演”:蓝衣、白衣销售互殴
赶快收藏 官方公布2023年高考志愿填报十问十答
男子每天1斤杨梅狂吃20天要做血透 医生提醒:高钾水果、肾不好少吃_环球精选
茅台贵州大曲酒怎么样?贵州大曲是什么档次?贵州大曲酒80年代评价
前端Vue仿京东加入购物车弹框立即购买弹框shopDialog自定义弹框内容 全球快消息
关于lvm磁盘管理-lv的大小调整-lv的扩展与缩减|天天新视野
面试官:MySQL 自增主键一定是连续的吗?大部分人都会答错!
端午情怀“艾”在心间 天天微资讯
22岁小伙挑选私人飞机 预算5.5亿元 马斯克看了都害怕 世界观天下
全球看热讯:女生考前3天连续失眠 一查684分落泪:激动到不行 网友祝贺
Intel Arc显卡为Linux推送新驱动:《CS:GO》帧数提升11%-全球快报
首发骁龙8 Gen3!小米14系列代号出炉:后稷、神农
惊险!马路中间悬挂一根电缆 摩托车骑手经过刚好被套住脖子
一天吃透SpringCloud面试八股文
全球速递!在Linux下搭建Git服务器
【技术积累】算法中的贪心算法【三】_环球速读
女模砸评委后续:正面照曝光,疑全部模特均被潜规则,比赛很公平-全球快播报
至少涨价1500元该买还是买!iPhone 15备货量曝光:苹果出手近亿台-天天热推荐
【天天播资讯】19岁少年为救陌生姐姐放弃考试 网友点赞:换你会做吗?
【播资讯】特斯拉L3能力藏不住了!无需手扶方向盘:966公里0提醒接管
当前热议!今天周日调休上班!iPhone闹钟没响用户被坑:苹果本土化服务为啥不行?
广东高考今日放榜 26日17时前可提出复查分数申请_全球头条
焦点信息:联通2000M宽带有多快?中国联通小姐姐:下200分钟4K电影仅78秒
48GB内存笔记本正式上市 插满可扩至96GB
清华大学校长呼吁本科毕业生:不要过度关注个人利益 会烦恼焦虑 世界即时看
为什么119灭火不直接对准火源射水?消防员专业揭秘 全球关注
当前动态:《上古卷轴5:天际》4代湮灭Mod实机演示
『题解』BZOJ3462 DZY Loves Math II
读发布!设计与部署稳定的分布式系统(第2版)笔记11_无限长的结果集
10万元到1万元 激光电视降价为了什么
全球新消息丨ASML:芯片供应链脱钩自主生产不可能 美国日本也不例外
全球速讯:k8s 深入篇———— pod 深入实战[七]
CAP定理
【环球速看料】强化学习从基础到进阶-常见问题和面试必知必答[4]::深度Q网络-DQN、double DQN、经验回放、rainbow、分布式DQN
《消失的她》票房破5亿:打破44项影史纪录 端午档最强国产悬疑电影诞生 全球最新
五年来最火端午假期正式结束!这些城市最热门 你去了吗?
鸿海加快iPhone 15在印度量产:与中国大陆时间差将缩减至一个月-天天速递
400万播放量 救不了东北偶像
标压i7+32GB仅2999元 这款迷你主机能入手吗?实测来了
党的最大优势是党执政后的最大危险是_党执政后的最大危险是
全球新消息丨韩国yg公司旗下艺人_韩国yg公司
每日动态!使用libavcodec将mp3音频文件解码为pcm音频采样数据【[mp3float @ 0x561c1ec49940] Header missing
小试Blazor——实现Ant Design Blazor动态表单
焦点快看:【解决方法】按键精灵 实现 狂野飙车9 自动领取每日广告卡牌包 (1)
k360次列车硬卧分布图(k360次列车)|天天时讯
安徽唯一盲人考生 高考成绩出来了:311分
因脑溢血开颅3次的少年高考445分 母亲:努力有了结果
k8s 深入篇———— pod 实战[六]
garage两种读音_garage怎么读有几种读法是对的
观焦点:女子醉酒吐车上 20元都不肯赔 司机怒骂不要脸:网友力挺
环球快报:再获11亿美元投资:蔚来“长期主义”的底气
距离今年“召回王”又进一步 本田海外召回超百万辆汽车
法媒:罗马准备听取对贝洛蒂的报价,意甲英超西甲多队有意
腾讯两大国民APP账号又打通了!QQ悄然支持微信登陆 有了微信为啥仍离不开QQ?
2023年端午小长假收官:1.06亿人次出游 满血超越2019-当前热讯
【世界独家】word安装(ppt、excel),以及word的常用设置
【当前独家】Blazor开发小游戏?趁热打铁上!!!
当前热门:火狐主页diy设置以及常用的扩展
DZY Loves Math|全球即时看
女生发烧考出618分:一蹦三尺高 挨个房间报喜
每日消息!ChatGPT漏洞 讲故事送Window11激活Key!
世界快播:刘慈欣谈ChatGPT:人类的无能反而是人类最后的屏障
今日热议:关于高考志愿填报,这些热点问题需要关注
缓存一致性如何保障
推出长达7年:任天堂股东质疑Switch已逼近极限
实时焦点:苹果前总监炮轰App Store存在灰色地带 标准随心所欲
三乙醇胺油酸皂商品报价动态(2023-06-24)
救命一声吼!山洪暴发女子大喊提醒救下多名游客 世界讯息
索尼PS5串流掌机价格曝光:最高2100元能接受么?
全球视点!泰坦号观光潜艇“打破常规留名后世”,老板一语成谶片受热议
DLang 与 C 语言交互
Apollo2.1.0+Springboot使用OpenApI
邮箱:微信企业域名邮箱给gmail或hotmail等域外邮箱发邮件被退回问题如何解决? 环球观焦点
今日热门!Stable Diffusion模型发布新版本:生成图像以假乱真
钻石价格,突发“跳水”!未来还会更便宜?
使用python发送sip协议的OPTIONS 热门
k8s 深入篇———— k8s 的pod[五]-全球播资讯
8. Java-AOP 面向切面编程
文心一言 VS 讯飞星火 VS chatgpt (46)-- 算法导论6.1 4题|全球热点评
泰坦号事故后:加拿大将展开事故调查
车主自曝差点被闷死在特斯拉Model X里 车门锁死 原因揭晓
蔡徐坤巡演新加坡站开票 《Hug me(remix版)》同日上线
来一打自建IP Proxy玩玩之Majora
kafka学习之五_多个磁盘的性能验证 世界快看点
Go——常用函数