音频转文字用什么软件?这些转文字技巧,就是轻松简洁

在快节奏的生活中,我们经常需要将会议、讲座或任何形式的口头交流转化为文字记录。 这不仅可以帮助我们回顾和整理信息,还能提高工作效率。为此,音频转文字工具应运而生,它们能够将声音转化为文字,让我们的双手得到解放,专注于思考和创造。 废话不多说,接下来让我们一起探索音频转文字的奥秘吧。 音频转文字软件一:全能速记宝 为什么选择它☟ √ 支持多种语言的音频输入,适应不同场景需求。 √ 提供高准确率的转写服务,确保信息无误。 √ 界面友好,操作简单,易于上手。 如何使用它☟ ▶ 下载应用 → 进入“录音转文字”界面 → 上传音频文件 → 选择语言和转写选项 → 启动转写 → 获取文字结果并导出。 音频转文字软件二:RealSpeaker Transcriber 为什么选择它☟ √ 专为专业人士设计,适合会议记录、采访等场合。 √ 采用先进的语音识别技术,提供快速准确的转写服务。 √ 支持编辑和校对转写内容,确保信息的准确性。 如何使用它☟ ▶ 访问官网 → 创建账户 → 上传音频文件 → 选择转写语言和选项 → 等待转写完成 → 下载或编辑转写文本。 音频转文字软件三:Otter.ai 为什么选择它☟ √ 强大的实时转写能力,支持在线会议和实时对话。 √ 智能区分说话者,方便识别不同发言者的观点。 √ 提供转写文本的搜索和分享功能,便于团队协作。 如何使用它☟ ▶ 注册账户 → 选择“实时转写”或“上传音频” → 进行转写 → 查看、编辑和分享转写结果。 音频转文字软件四:Speech notes 为什么选择它☟ √ 适用于快速记录和整理语音笔记。 √ 支持多种文件格式,方便导入和导出。

【LLM之RAG】RAT论文阅读笔记

研究背景 近年来,大型语言模型(LLMs)在各种自然语言推理任务上取得了显著进展,尤其是在结合大规模模型和复杂提示策略(如链式思维提示(CoT))时。然而,LLMs 在推理的事实准确性方面存在越来越多的担忧,特别是在零样本 CoT 提示和需要多步骤和上下文感知推理的长视野生成任务中。这些任务包括代码生成、任务规划、数学推理等,需要事实正确的中间思维过程来成功完成任务。 研究目标 本文探讨了如何通过信息检索迭代修改思维链显著提高大型语言模型在长视野生成任务中的推理和生成能力,同时大幅减轻幻觉现象。具体而言,提出的方法——检索增强思维(RAT),逐步修改每一步思维链,并结合检索到的相关信息,旨在改进初始零样本 CoT 生成的思维链。 相关工作 RAG: 旨在解决大型语言模型生成虚构事实的问题,通过提供从可信来源提取的相关文本,一般被用于问答(QA)任务。简单地说就是首先根据相关性找到和问题相关的内容,然后把相关的内容和用户问题拼接成 Prompt 交给大模型。然而,复杂的推理任务(例如,那些需要多步骤推理的任务)很难转化为有效的搜索查询,这导致在寻找相关文档时遇到挑战。传统上,RAG 一次性检索所有相关信息。然而,它忽略了一个事实,即很难预测在后续的推理和生成步骤中需要哪些“事实”或信息。任务提示本身几乎不足以为此提供足够的线索。 CoT:旨在提高 LLM 在需要复杂推理步骤的任务中的性能,例如多步骤的数学应用题。具体来说,CoT 提示不是直接让 LLM 生成正确答案,而是激励 LLM 首先输出中间推理步骤,这些步骤被称为“思维”。LLM 的这种行为可以通过 prompt 进行触发,比如著名的“Let’s think step by step”),或者通过在类似任务中执行少量样本示例来触发。然而,由于没有对中间思维进行直接监督,LLM 可能会因为缺乏相关的领域知识而犯错误,或者受到虚构信息的偏差。 方法论 数据处理 生成初始答案(prompt1):虽然 CoT 说自己是"step-by-step"的,但实际上是单轮的。因此需要从单轮回答中解析出有哪些步骤/思考。这里用了一个 trick,在 prompt 中让 LLM 通过换行来输出不同的 step。 生成搜索查询(prompt2):这个的流程是总结出当前文本写了什么,然后根据总结的内容去检索相关知识。prompt2 相当于生成 RAG 的 input。 根据检索到的上下文修订答案(prompt3):在 prompt3 之前,会进行 RAG 得到相关内容,然后再根据相关的内容去修订当前回答。 解决方案 核心思想: 利用 CoT 生成多个步骤,然后在每个步骤中加入 RAG 以减少模型幻觉并提高效果。即:RAG+CoT=RAT。 详细: RAT 是一种着重于迭代修正模型生成思路的新方法。首先,LLM产生的初始零样本CoT以及原始任务提示将被用作查询,以检索可能有助于修改可能有缺陷的CoT的信息。其次,设计一种渐进的方法,而不是用完整的CoT进行检索和修改并立即产生最终响应,其中LLM在CoT(一系列子任务)之后逐步生成响应,并且只有当前思维步骤将根据任务提示检索到的信息、当前和过去的CoT进行修改。这种策略可以类比于人类的推理过程:在复杂的长期问题解决过程中,利用外部知识来调整我们的逐步思维。 案例说明: 如何在Minecraft中获得钻石剑 用户Query 用户在Minecraft游戏中提出一个问题:“如何获得钻石剑?” 初始形态 在接收到用户的任务提示(Query)后,模型首先进行零样本链式思维(CoT)推理。初始的思维链可能会如下生成: T1: 获得4块木板(有误)

超级底层:10WQPS/PB级海量存储HBase/RocksDB,底层LSM结构是什么?

一次穿透:10WQPS/PB级海量存储HBase/RocksDB的底层LSM结构 LSM tree 是很多数据库内部的核心数据结构,包括BigTable,ClickHouse、Cassandra, Scylla, RocksDB,HBase。 ClickHouse基于Log-Structured Merge-Tree 结构(思想),实现磁盘的顺序写入,和数据的预排序。 Cassandra 是一个使用 LSM 树作为内部数据结构,可以轻松存储万亿级日志,具体请参见: 阿里2面:万亿级消息,如何做存储设计? RocksDB是 Facebook 开源的一个高性能持久化 KV 存储,越来越多的新生代数据库,都不约而同地选择 RocksDB 作为它们的存储引擎。 前几天时候尼恩辅导一个字节的小伙伴改造简历,得知他们内部使用的可以持久化的自研分布式Redis,就是基于 RocksDB 做的二次架构。 回到工业级的场景:百亿级数据存储架构,只有分库分表吗? 很多的小伙伴来咨询尼恩, 百亿级数据存储怎么架构,说他们的面试中,都遇到的。 他们回到回答了分库分表,比如,当一个表(比如t_order) 达到500万条或2GB时,需要考虑水平分表。 然后面试官,不满意。很多的小伙伴来咨询尼恩,为什么? 这里,尼恩用20年的技术功力,给大家做一个彻底性、系统化梳理,帮助大家吊打面试。 从0到1, 百亿级数据存储架构,怎么设计? 咱们的生产需求上,百亿级数据存储架构, 一般来说,需要具备以下四个能力: 高并发的在线ACID事务, 这里需要用到 分库分表 高并发的在线搜索, 这里需要用到 ElasticSearch 海量数据的离线处理, 这里需要用到 HBase 冗余表双写能力 (不同业务维度的副本) 把商品数据冗余存储在HBase 中,实现海量数据的离线处理, 同时也具备高速访问的能力 HBase 的底层结构,恰恰是LSM。 所以,咱们必须首先搞定LSM。 LSM结构(Log Structured Merge Tree)的使用场景 log-structured merge-tree (LSM tree) 是一种被精心设计的数据结构,常用于处理大量写入的场景。 通过对写入操作进行顺序写入优化实现性能提升。 Hbase 适合存储 PB 级别的海量数据,在 PB 级别的数据以及采用廉价 PC 存储的情况下,能在几十到百毫秒内返回数据。这与 Hbase 的极易扩展性息息相关。正式因为 Hbase 良好的扩展性,才为海量数据的存储提供了便利。

【系统架构设计师】一、计算机系统基础知识(指令系统|存储系统|输入输出技术|总线结构)

目录 一、指令系统 1.1 计算机指令 1.2 指令寻址方式 1.3 CISC 与 RISC 1.4 指令流水线 二、存储系统 2.1 分级存储体系 2.2 地址映射 2.3 替换算法 2.4 磁盘 2.4.1 磁盘结构和参数 2.4.2 磁盘调度算法 三、输入输出技术 四、总线结构 五、考试真题练习 一、指令系统 1.1 计算机指令 计算机指令的组成:一条指令由操作码和操作数两部分组成,操作码决定要完成的操作,操作数指参加运算的数据及其所在的单元地址。在计算机中,操作要求和操作数地址都由二进制数码表示,分别称作操作码和地址码,整条指令以二进制编码的形式存放在存储器中。 计算机指令执行过程:取指令-一分析指令--执行指令三个步骤: 首先将程序计数器PC中的指令地址取出,送入地址总线,CPU依据指令地址去内存中取出指令内容存入指令寄存器IR; 而后由指令译码器进行分析,分析指令操作码; 最后执行指令,取出指令执行所需的源操作数。 1.2 指令寻址方式 指令寻址方式 顺序寻址方式:当执行一段程序时,是一条指令接着一条指令地顺序执行。 跳跃寻址方式:指下一条指令的地址码不是由程序计数器给出,而是由本条指令直接给出。程序跳跃后,按新的指令地址开始顺序执行。因此,程序计数器的内容也必须相应改变,以便及时跟踪新的指令地址。 指令操作数的寻址方式 立即寻址方式:指令的地址码字段指出的不是地址,而是操作数本身。 直接寻址方式:在指令的地址字段中直接指出操作数在主存中的地址。 间接寻址方式:指令地址码字段所指向的存储单元中存储的是操作数的地址。 寄存器寻址方式:指令中的地址码是寄存器的编号。 基址寻址方式:将基址寄存器的内容加上指令中的形式地址而形成操作数的有效地址,其优点是可以扩大寻址能力。 变址寻址方式:变址寻址方式计算有效地址的方法与基址寻址方式很相似,它是将变址寄存器的内容加上指令中的形式地址而形成操作数的有效地址。 1.3 CISC 与 RISC CISC是复杂指令系统,兼容性强,指令繁多、长度可变,由微程序实现; RISC是精简指令系统,指令少,使用频率接近,主要依靠硬件实现(通用寄存器硬布线逻辑控制) 指令系统类型指令寻址方式实现方式开发时间指令周期CISC数量多,使用频率差别大,可变长格式多微程序控制技术(微码)较短多周期为主RISC数量少,使用频率接近定长格式,大部分为单周期指令,操作寄存器,只有Load/Store操作内存少增加了通用寄存器;硬布线逻辑控制为主适合采用流水线较长单周期为主(采用流水技术,大部分指令在一个机器周期内完成) 1.4 指令流水线 指令流水线原理:将指令分成不同段,每段由不同的部分去处理,因此可以产生叠加的效果,所有的部件去处理指令的不同段。 流水线时间计算 流水线周期:指令分成不同执行段,其中执行时间最长的段为流水线周期 流水线执行时间:1条指令总执行时间+(总指令条数-1)*流水线周期 流水线吞吐率计算:吞吐率即单位时间内执行的指令条数。 公式:指令条数/流水线执行时间。 流水线的加速比计算:加速比即使用流水线后的效率提升度,即比不使用流水线快了多少倍,越高表明流水线效率越高。 公式:不使用流水线执行时间/使用流水线执行时间。 二、存储系统 2.1 分级存储体系 计算机采用分级存储体系的主要目的是为了解决存储容量、成本和速度之间的矛盾问题。

Python中绘制折线图的全面指南

在数据分析和可视化的世界里,折线图是一种强大的工具,它能够清晰地展示数据随时间或其他连续变量的变化趋势。Python,作为一款功能强大的编程语言,结合其Matplotlib库,为我们提供了绘制折线图的强大能力。本文将详细介绍如何在Python中使用Matplotlib库绘制折线图,并通过图文结合的方式,深入探讨其各种用法和自定义选项。 目录 一、引言 二、Matplotlib库 2.1安装Matplotlib库 2.2什么是Matplotlib库 2.3Matplotlib库的核心功能有哪些 1.多样化的绘图类型: 2.高度定制: 三、Matplotlib中常用的参数及其说明 1. 绘图基础参数 1.1 创建画布 1.2 坐标轴与标题 1.4 图例 1.5 显示与保存 2. 绘图样式参数(plt.plot()等绘图函数) 2.2 线条样式 2.3 标记样式 2.4 其他样式参数 3. 网格与坐标轴 4. 自定义配置 四、绘制基础折线图 五、自定义折线图样式 六、绘制多条折线图 七、高级自定义选项 八、补充其他绘制参数 1. 坐标轴样式 2. 图例 3. 网格 4. 坐标轴显示范围 5. 坐标轴标签 6. 日期和时间 7. 自定义样式 8. 绘图标记 9. 3D绘图参数 10. 自定义颜色映射 11. 文本和注释 12. 动画和交互性 九、部分参数运行代码示例 1. 设置坐标轴范围和标签 2. 添加图例 3. 设置坐标轴样式 4. 添加网格 5.

Java 消息队列详解

什么是消息队列? 消息队列是一种通过存储消息来实现系统间通信的中间件。消息生产者将消息发送到队列中,消息消费者从队列中取出并处理消息。这种模式实现了生产者和消费者的解耦,即使它们不同时在线,也可以通过消息队列进行通信。 消息队列的关键概念 消息(Message):传递的数据单元,可以是文本、JSON、XML等格式。生产者(Producer):发送消息的应用程序或组件。消费者(Consumer):接收并处理消息的应用程序或组件。队列(Queue):存储消息的容器,遵循先进先出(FIFO)原则。 为什么使用消息队列? 消息队列在分布式系统中有许多优势: 解耦:生产者和消费者可以独立开发、部署和扩展,互不影响。异步处理:生产者发送消息后立即返回,不必等待消费者处理完毕,提高系统响应速度。削峰填谷通过消息队列可以平滑高峰期的流量,避免系统过载。可靠性 消息队列可以保证消息的持久化和传递,即使系统故障也不会丢失消息。扩展性:可以轻松地增加生产者或消费者来提高系统的处理能力。 常见的 Java 消息队列实现 ActiveMQ Apache ActiveMQ 是一个开源的消息中间件,支持多种消息传递协议。它具有高性能、高可用性和高可扩展性的特点,广泛应用于企业级应用中。 import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; public class ActiveMQExample { public static void main(String[] args) throws JMSException { // 创建连接工厂 ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616"); // 创建连接 Connection connection = factory.createConnection(); connection.start(); // 创建会话 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 创建队列 Queue queue = session.createQueue("exampleQueue"); // 创建生产者 MessageProducer producer = session.createProducer(queue); TextMessage message = session.createTextMessage("Hello, ActiveMQ!"); producer.

独辟蹊径:我是如何用Java自创一套工作流引擎的(上)

作者:后端小肥肠 创作不易,未经允许严谨转载。 目录 1. 前言 2. 我为什么要自创一套工作流引擎 3. 表结构设计及关系讲解 3.1. 流程类别business_approval_workflow 3.1.1. 表结构 3.1.2. 表关系说明 3.2. 流程定义business_approval_workflow_detail 3.2.1. 表结构 3.2.2. 表关系说明 3.3. 流程任务记录approval_detail 3.3.1. 表结构 3.3.2. 表关系说明 3.4. 流程审批历史 approval_history 3.4.1. 表结构 3.4.2. 表关系说明 3.5. 申请表(流程实例)request 3.5.1. 表结构 4. 核心代码讲解 4.1. 设计用户表 4.2. 集成权限框架SpringSecurity 4.3. 工作流基础代码 4.4. 提交申请 4.5. 查看待我审批 4.6. 执行审批操作 4.7. 查看我已审批 5. 结语 1. 前言 在当前的技术生态中,工作流引擎如Activiti7和Flowable已经成为企业自动化的重要组成部分。然而,使用这些流行解决方案往往伴随着不小的学习成本,特别是Activiti7与Spring Security深度集成,使得不采用Security作为权限框架的系统面临集成上的挑战。此外,许多业务场景并不需要如此复杂的工作流框架。因此,出于对更灵活、更轻量级工作流解决方案的追求,我决定自主开发一套工作流引擎,以更好地满足特定的业务需求,同时减少对外部库的依赖。这不仅是一次技术上的挑战,也是对现有工作流理念的一次实践探索。 2. 我为什么要自创一套工作流引擎 熟悉我的博客读者都知道,我曾经基于Activiti7开发了一套成熟的工作流管理框架。然而,为何我还要自己动手创造一套新的工作流引擎呢?答案很简单:追求轻量化和更精准的边界。我长期专注于数据中台项目,涉及数据的汇集、管理与分发,其中审批流程即为其中一环。除了一个复杂的自定义流程设计和动态指定审批人的项目外,绝大多数系统仅需简单的审批流程,通常仅需1至2级审批,不涉及复杂的流程设计工具。 因此,我开发了一套轻量级工作流引擎,仅需要5张表就能完全满足简单审批流程的需求。这种定制化的设计不仅极大地简化了系统架构,还充分体现了对于业务需求精准匹配的追求。 这一决定不仅是技术上的挑战,更是对传统工作流理念的一次革新实践。 3. 表结构设计及关系讲解 3.1. 流程类别business_approval_workflow 3.

【Linux】使用 iptables 验证访问HDFS 所使用到的端口

目录 ​编辑 一、实操背景 二、iptables 简介 三、模拟操作 一、实操背景 背景: 在客户有外网的服务器需要访问内网大数据集群HDFS,使用iptable模拟测试需要开放的端口。 二、iptables 简介 具体介绍看文章: 【Linux】Iptables 详解与实战案例_linux iptable-CSDN博客 表(tables)提供特定的功能,iptables内置了4个表,即filter表、nat表、mangle表和raw表,分别用于实现包过滤,网络地址转换、包重构(修改)和数据跟踪处理。 链(chains)是数据包传播的路径,每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一 条或数条规则。当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定 义的默认策略来处理数据包。 规则链名包括(也被称为五个钩子函数(hook functions)): INPUT链 :处理输入数据包。OUTPUT链 :处理输出数据包。FORWARD链 :处理转发数据包。PREROUTING链 :用于目标地址转换(DNAT)。POSTOUTING链 :用于源地址转换(SNAT)。 三、模拟操作 对某台HDFS Client服务器禁止所有的INPUT FORWARD OUTPUT 只对某些端口开放。 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP 开启 22端口 可以使用远程工具连接 iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT 开启8020 ,88, 749 端口

SCAU期末笔记 - 数据结构(STL版)

在完结了算法之后 我又来写数据结构啦!真的很讨厌校OJ数据结构的题,输出提示词太捞了,每一题都是超级缝合怪,像个小课设一样。 值得一提的是,虽然数据结构课上要求是用C语言实现这些功能,但是因为频繁用到引用,所以考试可以直接提交C++,再加上机试没有填空题,所以我们完全可以直接使用C++的STL,本文也是直接使用STL实现的。 但是!这并不代表数据结构实现的原理不重要,因为我们数据结构的笔试的大题会要求你在试卷上进行试卷填空,这一部分等我有空再开一篇文章,如果你在CSDN搜到别的看不懂的话,建议翻开你的高程回去恶补指针,结构体相关知识。那么闲话少叙,我们直接开始! 实验1 本章主要介绍了顺序表这一数据结构,我们使用STL的话对应的就是vector这一容器了。使用时需要引用头文件<vector> 常用的相关函数有这些 vector<int> a;//创建一个int类型的数组a 相当于int a[n]; a.empty();//判断数组是否为空 a.push_back(8);//在数组的末尾插入一个元素8 a.push_front(8);//在数组的开头插入一个元素8 a.pop_back();//删除数组的最后一个元素 a.pop_front();//删除数组的第一个元素 a.front();//返回数组的第一个元素 a.back();//返回数组的最后一个元素 a.size();//返回数组的大小 a.clear();//清空数组 a.insert(a.begin()+1,8);//在数组的第二个元素后面插入一个元素8 a.erase(a.begin()+1);//删除数组的第二个元素 a.erase(a.begin()+1,a.begin()+3);//删除数组的第二个到第四个元素 //copilot自动填充注释太好用了 快去拿校园邮箱白嫖一个 8576 顺序线性表的基本操作 #include <iostream> #include <algorithm> #include <vector> using namespace std; typedef long long i64; int main() { vector<int> a; printf("A Sequence List Has Created.\n"); again://防伪标识 printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n"); int cmd; scanf("%d",&cmd); if(cmd==1) { int p,x; scanf("%d%d",&p,&x); if(p==1) { a.insert(a.begin(),x); printf("The Element %d is Successfully Inserted!

打造工业操作系统开源开放体系

我国制造业具有细分行业、领域众多,产品丰富,制造模式多样等特点,围绕以工业操作系统为核心的工业软件赋能体系建设,离不开平台运营商、工业软件开发商、系统服务商、科研机构、工业企业等多方联合参与。聚众同行、聚力创新,统一的开源开放的工业操作系统生态建设,有助于不同行业、不同领域的工业APP富集,从而实现工业企业的高质量赋能。 蓝卓正在探索supOS工业操作系统的开源开放。基于supOS建设连接协议、数据应用、开发工具等方向的开源标准,为企业和开发者提供开放交流、软件协作开发、供需对接、专家咨询、开源许可协议与知识产权保护等综合服务的开源技术平台。在开源社区,开发者可以快速获取相关代码、工具等,基于可视化、组态式的低代码开发环境,通过拖拉拽方式快速生成工业APP,提升开发效率,降低开发成本,同时,supOS提供三种工业APP集成与改造方式,集成改造后的工业APP将汇聚到蓝卓应用商店。 在未来,蓝卓还将探索设立工业操作系统开源基金会,为生态参与方提供软件知识产权管理法律框架、技术指导等服务,提供资金财务等日常的运营和治理支持,批量孵化产业生态及优质工业APP应用,构建共生共赢的生态系统。

【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)

🔥引言 本篇将深入解析单链表:探索底层逻辑,理解底层是如何实现并了解该接口实现的优缺点,以便于我们在编写程序灵活地使用该数据结构。 🌈个人主页:是店小二呀 🌈C语言笔记专栏:C语言笔记 🌈C++笔记专栏: C++笔记 🌈初阶数据结构笔记专栏: 初阶数据结构笔记 🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 一、链表的概念二、链表的分类四、实现无头单向非循环链表的相关接口(SLTlist.h)五、知识铺垫六、正式开始模拟实现单链表6.1 创建链表中的节点6.2 单链表的插入节点6.2.1 单链表的尾插6.2.2 单链表的头插 6.3 单链表的删除6.3.1 单链表的尾删6.3.2 单链表的头删 6.4 查找单链表中数据6.5 关于单链表的任意位置插入和删除6.5.1 单链表的pos指定前插入6.5.2 单链表的删除pos当前结点6.5.3 单链表的pos之后插入6.5.4 单链表的pos之后删除 6.6 单链表的打印 七、顺序表和链表的区别 一、链表的概念 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。 二、链表的分类 我们重点需要关注以下两个链表: 1.无头单向非循环链表 结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。 2.带头双向循环链表 结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。虽然结构复杂,但是使用代码实现,以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了 链表是通过一个个结点链接起来的数据结构,多个结点链接形成下列结构(箭头是不存在,是为了方便理解) 下列图片会简化结点间的链接过程: 【注意】: 从图上可以看出,链式结构在逻辑上是连续的,但是在物理上不一定连续 现实中的节点一般都是从堆上申请出来的 从堆上申请的空间。是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续 四、实现无头单向非循环链表的相关接口(SLTlist.h) 五、知识铺垫 1.实现部分接口需要通过二级指针接受实参 原因在于我们需要可以修改实参,而是实参为一级指针时(同样是传递地址),需要使用二级指针进行接受,否则获得临时拷贝,不会影响到实参。修改实参的情况,比如一开始为空,在插入时需将头指针存储在有效结点的的地址上,需要改变实参的值 2.单链表的初始化 这里实现链表,没有必要进行初始化,初始化对于一开始就要开辟的空间有初始化的需求,表是多个节点通过地址链接在一起,那么只需要开辟新节点的时候,初始化下就行了(有哨兵位需要初始化) 3.二级指针断言 二级指针存放的是头节点的地址,头节点的地址为空,那么还有什么意义呢? 当我们有所了解链表的结构,接下来是实现链表的相关接口,比如增删查改 六、正式开始模拟实现单链表 6.1 创建链表中的节点 在插入中需要先创建一块结点空间,再通过上一个结点通过当前结点的地址指向当前结点的位置。这是因为结点是通过地址访问的,结点里面存储着下一个节点的地址,理解为当前结点(通过下一个结点地址)指向下一个结点 SLNode* CreateNode(SLNDataType x) { SLNode* newnode = (SLNode*)malloc(sizeof(SLNode)); if (newnode==NULL) { perror("

【一步一步了解Java系列】:认识String类

看到这句话的时候证明:此刻你我都在努力 加油陌生人 个人主页:Gu Gu Study 专栏:一步一步了解Java 喜欢的一句话: 常常会回顾努力的自己,所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者:小闭 String在Java中是一个类,平常我们存储字符串时也是储存在这个类型中的,但是Java创建Strring类肯定不仅仅让我们储存字符串而已,他也为我们提供了许多成员方法。接下来就让我们来学习一下。 String的构造 字符串的构造有挺多的,现在我就列出比较常用的三种构造方式: 以下是三种构造方式: 使用常量串进行构造使用new关键字进行构造使用字符串进行构造 public class Test { public static void main(String[] args) { //使用常量串进行构造 String s1="hehe"; //使用new关键字进行构造 String s2=new String("hehe"); //使用字符串进行构造 char[] arr={'h','e','h','e'}; String s3=new String(arr); } } 注意:String是一个引用类型, 内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下: 在现在的jdk中是一个byte类型的数组进行储存的。 String 的比较 在Java中String中,==的比较对于不同类型的数据比较方式是不同的,对于基本类型是比较其中的值是否相等,对于引用类型是进行比较引用的地址是否相等。当然如果用常量字符串进行构造那么其地址是一样的,也就是两个用常量字符串构造的字符串成员变量他们是相等的。 public static void main(String[] args) { int a = 10; int b = 20; int c = 10; // 对于基本类型变量,==比较两个变量中存储的值是否相同 System.out.println(a == b); // false System.

在人工智能背景下,程序员要有什么职业素养,怎么改进

文章目录 1. 持续学习和适应能力原因改善方法 2. 跨学科知识原因改善方法 3. 高效的计算资源利用原因改善方法 4. 模型解释性和可控性原因改善方法 5. 数据隐私和安全意识原因改善方法 在AI大模型的背景下,程序员要有什么职业素养,怎么改进,才能与时俱进: 持续学习和适应能力跨学科知识高效的计算资源利用模型解释性和可控性数据隐私和安全意识 1. 持续学习和适应能力 原因 AI和大模型领域的发展非常迅速,几乎每天都有新的技术、工具、算法和研究成果出现。工程师如果不持续学习,就会很快被淘汰。 改善方法 终身学习: 阅读论文: 定期阅读顶级AI会议和期刊上的最新论文,了解最新的研究进展和技术趋势。技术博客和书籍: 关注知名技术博客(如CSDN)和书籍,获取实践经验和理论知识。在线课程: 参加在线课程和培训,如CSDN等平台提供的机器学习和AI课程,获得认证和技能提升。 社区参与: 技术论坛: 参与CSDN、GitHub、Stack Overflow等技术社区,与同行交流,解决实际问题,分享经验。会议和研讨会: 参加AI相关的技术会议、研讨会和其他相关活动,聆听专家讲座,结识业内人士。 实验和项目: 个人项目: 独立或团队进行AI项目开发,应用新学到的知识进行实践。开源贡献: 参与开源项目,贡献代码和文档,学习他人项目的实现方法和代码风格。 2. 跨学科知识 原因 AI应用广泛,涉及多个学科的知识,包括统计学、数据科学、计算机科学、云计算等。缺乏跨学科知识会限制工程师在AI领域的应用和创新能力。 改善方法 跨学科学习: 统计学和数学: 学习统计学、线性代数、概率论等基础数学知识,这些是机器学习和数据分析的基础。数据科学: 掌握数据清洗、数据分析和数据可视化的技能,熟悉常用的数据科学工具和库,如Pandas、NumPy、Matplotlib等。 跨学科项目: 多领域合作: 参与涉及多个学科的项目,如医疗AI、金融科技等,与其他领域的专家合作,获取跨学科的实践经验。案例研究: 研究其他领域的成功案例,了解AI技术在不同领域的应用和挑战。 与专家合作: 多学科团队: 参与或组织多学科团队项目,学习不同领域的知识和方法。专家指导: 寻求其他领域专家的指导和合作,通过实际项目提升跨学科知识。 3. 高效的计算资源利用 原因 大模型的训练和推理需要大量的计算资源,如何高效利用计算资源以提高模型训练速度和降低成本,是工程师面临的重要挑战。 改善方法 云计算和分布式计算: 云平台使用: 学习如何使用AWS、Google Cloud、Azure等云计算平台,掌握如何在云上部署和管理AI模型。分布式计算框架: 熟悉分布式计算框架,如Apache Spark、TensorFlow分布式训练,提升计算资源利用效率。 优化算法和模型: 模型剪枝和量化: 学习模型剪枝、模型量化等技术,减少模型参数数量,提高模型运行效率。知识蒸馏: 掌握知识蒸馏技术,通过教师模型指导学生模型,提高学生模型的性能,同时减少计算资源需求。 异构计算: GPU和TPU: 学习如何在GPU和TPU上进行高效的模型训练和推理,了解其架构和编程方法。其他专用硬件: 探索和使用其他专用硬件(如FPGA、ASIC)来加速AI计算。 4. 模型解释性和可控性 原因 大模型通常是“黑箱”,缺乏解释性和可控性,这对于实际应用、用户信任和合规性来说是一个重大问题。

Java 集合框架:LinkedList 的介绍、使用、原理与源码解析

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 014 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自己的技术栈的同学。与此同时,本专栏的所有文章,也都会准备充足的代码示例和完善的知识点梳理,因此也十分适合零基础的小白和要准备工作面试的同学学习。当然,我也会在必要的时候进行相关技术深度的技术解读,相信即使是拥有多年 Java 开发经验的从业者和大佬们也会有所收获并找到乐趣。 – Java 集合框架中包含了多种用于数据存储和操作的类,其中 LinkedList 是一个重要且常用的实现。LinkedList 作为一个双向链表,提供了高效的插入和删除操作,特别适用于频繁进行元素增删的场景。对于很多开发者而言,深入理解 LinkedList 的特性和工作原理是提高代码性能和优化数据处理逻辑的关键。本文将对 LinkedList 进行全面的介绍和解析,帮助读者掌握其使用方法、内部原理以及源码实现。 文章目录 1、LinkedList 概述2、LinkedList 的具体实现原理2.1、LinkedList 底层的数据结构2.2、LinkedList 增删改查的实现2.2.1、LinkedList 的插入2.2.2、LinkedList 的删除2.2.3、LinkedList 的修改2.2.4、LinkedList 的查询 2.3、LinkedList 对链表结构的实现 3、LinkedList 相关知识点3.1、关于 Queue 队列3.2、关于 ArrayList 和 LinkedList 的区别3.3、算法:翻转链表 4、LinkedList 的使用(常用方法)4.1、LinkedList 的常用方法4.2、继承自 `Queue` 接口的方法4.3、Collections 类中涉及 LinkedList 的常用方法 1、LinkedList 概述 LinkedList 是 List 接口的一个实现,它是一个双向链表。与 ArrayList 相比,LinkedList 的元素在内存中不是连续存放的。每个元素(称为节点)都包含两部分数据:一部分是存储的数据,另一部分是指向前一个节点和后一个节点的链接(指针)。 LinkedList 的优点在于插入和删除元素时效率很高。因为链表的数据结构使得它只需要修改前后节点的指针即可,而不需要像 ArrayList 那样移动其他元素。因此,LinkedList 适合用在需要频繁执行添加和删除操作的场景。

Java 集合框架:ArrayList 的介绍、使用、原理与源码解析

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 013 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自己的技术栈的同学。与此同时,本专栏的所有文章,也都会准备充足的代码示例和完善的知识点梳理,因此也十分适合零基础的小白和要准备工作面试的同学学习。当然,我也会在必要的时候进行相关技术深度的技术解读,相信即使是拥有多年 Java 开发经验的从业者和大佬们也会有所收获并找到乐趣。 – 本文将从介绍 ArrayList 开始,详细探讨其使用方法、工作原理以及背后的源码实现,帮助读者深入理解并灵活运用 ArrayList,以提升编程效率和代码质量。 在接下来的部分中,我们将首先概述 ArrayList 的基本特性及其在 Java 集合框架中的地位。随后,通过实际代码示例展示如何创建、操作和管理 ArrayList。接着,我们会揭示 ArrayList 的内部工作机制,包括其底层数据结构、扩容策略和性能优化等方面的内容。最后,我们将深入分析 ArrayList 的源码,探讨其设计思想和实现细节,以便读者能够更全面地掌握这一重要的集合类。 文章目录 1、ArrayList 概述2、ArrayList 的具体实现原理2.1、ArrayList 底层的数据结构2.2、ArrayList 随机访问和按索引操作2.3、ArrayList 的扩容机制2.4、ArrayList 元素的删除 3、遍历 ArrayList 时移除元素时的问题及解决方案3.1、在遍历 ArrayList 时移除一个元素时的问题3.1.1、ConcurrentModificationException3.1.2、跳过元素 3.2、在遍历 ArrayList 时移除一个元素时推荐的解决方案3.2.1、使用迭代器的 remove 方法3.2.2、使用 Java 8 的 removeIf 方法3.2.3、使用逆向遍历 4、ArrayList 的使用(常用方法)4.1、ArrayList 的常用方法4.2、Collections 类中涉及 ArrayList 的常用方法 1、ArrayList 概述 ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。

深入分析 Android Service (五)

文章目录 深入分析 Android Service (五)1. 深入分析 Service 与 Activity 之间的通信2. Messenger 的内部工作原理2.1 服务端实现2.2 客户端实现 3. AIDL 的内部工作原理3.1 定义 AIDL 接口3.2 服务端实现3.3 客户端实现 4. Service 的优化建议和最佳实践4.1 异步操作4.2 资源管理4.3 前台服务4.4 权限管理 5. 使用场景和总结 深入分析 Android Service (五) 1. 深入分析 Service 与 Activity 之间的通信 前面我们介绍了通过 Messenger 和 AIDL 实现 Service 与 Activity 之间的通信。接下来,我们将进一步深入分析这些通信机制的内部工作原理和设计思想。 2. Messenger 的内部工作原理 Messenger 是基于 Handler 实现的轻量级进程间通信(IPC)机制。它利用 Binder 传递消息。下面是 Messenger 工作的详细流程: 创建 Messenger 和 Handler: 服务端创建一个 Handler,用于处理客户端发送的消息。使用这个 Handler 创建一个 Messenger 对象,并通过 Binder 返回给客户端。 绑定服务:

【C/C++】【学生成绩管理系统】深度剖析

可接各类C/C++管理系统课设 目录 实现功能 部分1:系统设置和主菜单 1. 引入头文件 2. 定义结构体 3. 函数声明 4. 主函数 部分2:添加学生信息 部分3:删除学生信息 部分4:修改学生信息 部分5:查询学生信息 部分6:显示信息列表 部分7:统计学生数据 部分8:清空系统数据 部分9: 退出系统函数 总结代码 该学生成绩管理系统是一个用C++实现的程序,通过控制台界面实现对学生信息的增删改查。系统包括以下功能:添加学生信息、删除学生信息、修改学生信息、查询学生信息、显示所有学生信息、统计学生成绩数据和清空系统数据。 实现功能 添加学生信息: 用户可以通过输入学生的ID、姓名、年龄、性别和成绩来添加学生信息。新添加的学生信息会被存储在一个向量中。 删除学生信息: 用户可以通过输入学生的ID来删除学生信息。程序会在向量中查找对应的学生ID,如果找到则删除该学生的信息。 修改学生信息: 用户可以通过输入学生的ID来修改学生信息。程序会在向量中查找对应的学生ID,如果找到则允许用户修改该学生的姓名、年龄、性别和成绩。 查询学生信息: 用户可以通过输入学生的ID来查询学生信息。程序会在向量中查找对应的学生ID,如果找到则显示该学生的详细信息。 显示信息列表: 程序会显示所有存储在向量中的学生信息列表,包括每个学生的ID、姓名、年龄、性别和成绩。使用格式化输出使信息更加整齐美观。 统计学生数据: 程序会计算并显示学生成绩的平均值、最高值和最低值。这有助于用户了解整体的学生成绩分布情况。 清空系统数据: 用户可以选择清空系统中所有学生的数据。这会删除向量中存储的所有学生信息。 退出系统: 用户选择退出系统时,程序会显示退出提示信息,并终止运行。 部分1:系统设置和主菜单 首先设置程序的基本结构和主菜单界面。 #include <iostream> #include <vector> #include <string> #include <iomanip> using namespace std; // 定义一个结构体来保存学生信息 struct Student { int id; string name; int age; string gender; double grade; }; // 函数声明 void addStudent(vector<Student>& students); void deleteStudent(vector<Student>& students); void modifyStudent(vector<Student>& students); void queryStudent(const vector<Student>& students); void displayStudents(const vector<Student>& students); void statistics(const vector<Student>& students); void clearData(vector<Student>& students); void exitSystem(); int main() { vector<Student> students; int choice; while (true) { cout << "

AI大模型探索之路-实战篇:智能化IT领域搜索引擎之github网站在线搜索

系列篇章💥 No.文章1AI大模型探索之路-实战篇:智能化IT领域搜索引擎的构建与初步实践2AI大模型探索之路-实战篇:智能化IT领域搜索引擎之GLM-4大模型技术的实践探索3AI大模型探索之路-实战篇:智能化IT领域搜索引擎之知乎网站数据获取(初步实践)4AI大模型探索之路-实战篇:智能化IT领域搜索引擎之知乎网站数据获取(函数封装)5AI大模型探索之路-实战篇:智能化IT领域搜索引擎之知乎网站数据获取(流程优化)6AI大模型探索之路-实战篇:智能化IT领域搜索引擎之github网站在线搜索7AI大模型探索之路-实战篇:智能化IT领域搜索引擎之HuggingFace网站在线搜索 目录 系列篇章💥一、前言二、总体概览三、准备工作1、网站地址排除2、获取github token 四、github基础API测试1、定义github关键词提取函数2、github资源搜索测试3、github api调用测试4、定义github readme页面获取函数5、google api搜索github测试6、封装gihub搜索查询函数 五、完整流程封装1、定义github repos地址解析函数2、定义github问题搜索函数3、定义的github答案获取函数4、定义github自动搜索函数5、外部函数信息生成测试6、定义大模型调用函数7、大模型调用测试(咨询大模型不知道的问题)8、大模型调用测试(测试大模型不知道的问题)9、大模型调用测试(测试大模型知道的问题)10、智能对话助手测试 结语 一、前言 在上一篇文章中,我们完成了知乎网站数据的智能搜索流程的代码开发。本篇章将主要实现Github网站的在线智能搜索,为用户提供更全面、准确的搜索结果。 二、总体概览 本章将逐步通过代码落地实现Github网站数据的智能搜索。我们将从获取Github token开始,逐步实现对Github项目readme文档的获取和解析,最终整合到我们的智能化IT领域搜索引擎中,为用户提供更便捷、高效的搜索服务。 三、准备工作 1、网站地址排除 排除github中不需要爬取的网页地址 2、获取github token 如何获取github这些项目的readme文档。这里我们不再需要使用爬虫,而是简单调用Github API即可获取完整的项目readme文档。而要使用Github API,则首先需要获取Github token。Github token全称为GithubPersonal Access Token,用于在调用Github时进行身份验证,其本质上就是一串字符串形式的加密密钥,也就相当于OpenAI API Key 地址:https://github.com/settings/tokens 生成token 配置到本地环境变量 四、github基础API测试 1、定义github关键词提取函数 def convert_keyword_github(q): """ 将用户输入的问题转化为适合在Github上进行搜索的关键词 """ response = client.chat.completions.create( model="glm-4", messages=[ {"role": "system", "content": "你专门负责将用户的问题转化为Github上的搜索关键词,只返回一个你认为最合适的搜索关键词即可"}, {"role": "user", "content": "请问DeepSpeed是什么?"}, {"role": "assistant", "content": "DeepSpeed"}, {"role": "user", "content": q} ] ) q = response.choices[0].message.content return q 函数测试

python GUI开发: tkinter事件处理的几种方式详解与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,linux,shell脚本等实操经验,网站搭建,数据库等分享。 所属的专栏:python图形化GUI编程tkinter精讲 景天的主页:景天科技苑 文章目录 tkinter事件处理Tkinter如何指定事件处理程序实例绑定(Instance bind):可以将事件绑定到一个特定的控件。tkinter常见事件表示汇总常见的鼠标事件类型汇总常见的键盘事件类型汇总窗口和控件相关事件类型汇总 鼠标事件和键盘事件用法测试类绑定(bind_class):可以将事件绑定到类的所有小部件多种事件绑定方式总结 tkinter事件处理 事件处理(Event Handling),是 GUI 程序中不可或缺的重要组成部分,相比来说,控件只是组成一台机器的零部件, 而事件处理则是驱动这台机器“正常”运转的关键所在,是实现人机交互的关键。 在一款 GUI 程序中,我们将用户对软件的操作统称为“事件”,比如鼠标点击按钮、键盘输入文本以及窗口管理器触发的重绘等,这些事件有一个共同的特点,即都是由用户自身直接或者间接触发的。 一个 GUI 应用整个生命周期都处在一个消息循环 (event loop) 中,它等待事件的发生,并作出相应的处理。 Tkinter 提供了用以处理相关事件的机制处理函数可被绑定给各个控件的各种事件。 事件(event)是应用程序需要知道识别的一些事情。或者说,事件(event)表示程序某件事发生的信号,可以用来触发一段特定的代码——事件处理程序。 事件处理程序(event handler)是应用程序中的一个函数,当事件发生时调用它。 当事件发生在控件(widget:组件、小部件、控件)上,调用事件处理程序时,我们称之为绑定( binding)。绑定就是将事件和事件处理程序建立联系。 Tkinter如何指定事件处理程序 一、在创建控件对象时,可以使用控件中的command参数指定事件处理程序:command=函数,那么点击控件的时候将会触发函数,适合简单不需获取 event 对象。 二、还可以使用绑定(bind)方法指定事件处理程序,Tkinter可以在以下两个级别将事件处理程序绑定(bind)到事件: 实例绑定(Instance bind):可以将事件绑定到一个特定的控件。 其语法格式如下: widget.bind(sequence,func,add='') 其中,widget 代表控件的控件对象,之后,采用 bind() 方法进行事件绑定, 该函数的参数: sequence:表示事件的类型,也称事件码,是 Tkinter 模块规定好的,并使用“尖括号”的形式进行包裹; Tkinter 中经常使用的事件类型,描述格式为:<[modifier-]-type[-detail]>,其中: modifier:事件修饰符。如:Alt、Shit组合键和Double事件。 type:事件类型。如:按键(Key)、鼠标(Button/Motion/Enter/Leave/Relase)、Configure等。 detail:事件细节。如:鼠标左键(1)、鼠标中键(2)、鼠标右键(3)。 tkinter常见事件表示汇总 常见的鼠标事件类型汇总 常见的键盘事件类型汇总 窗口和控件相关事件类型汇总 func:表示事件的处理函数,当触发事件时执行。事件处理函数或为普通的函数,或为类中定义的函数(也叫方法)。 函数 def 事件处理函数名称(event): 函数体 类的一个方法 def 事件处理函数名称(self, event):

【数据结构】排序(下)

个人主页~ 排序(上) 栈和队列 排序 二、常见排序的实现8、快速排序的优化9、非递归快速排序(1)基本思想(2)代码实现(3)时间复杂度(4)空间复杂度 10、归并排序(1)基本思想(2)代码实现(3)时间复杂度(4)空间复杂度 11、非递归归并排序(1)基本思想(2)代码实现(3)时间复杂度(4)空间复杂度 12、非比较排序(1)基本思想(2)代码实现(3)时间复杂度(4)空间复杂度 三、各个排序方法所用时间的比较1、代码实现2、分析 四、各个排序的稳定性1、基本概念2、各个排序的稳定性复杂度一览表 二、常见排序的实现 8、快速排序的优化 当我们使用快速排序时,最坏的情况就是数组有序,此时的时间复杂度为O(N^2) 最好的情况就是key每次取中位数 所以我们为了避免最坏情况的发生,我们在快速排序的基础上衍生了一种优化的方法叫做三数取中 还有一种方法是随机选key,但随机选key的效果不如三数取中 int GetMidIndex(int* a, int left, int right) { int mid = (left + right) / 2; if (a[left] < a[mid]) { if (a[mid] < a[right]) return mid; else if (a[left] < a[right]) return right; else return left; } else { if (a[mid] > a[right]) return mid; else if (a[left] > a[right]) return right; else return left; } } 将三个比较出中间的数字作为key然后换到left上,进行partsort