浅谈汽车网络安全(Cyber Security)-MCU

为何要引入汽车网络安全 随着汽车新四化的发展,尤其是网联化及自动驾驶的推进,汽车网络信息安全显得越来越重要。 一方面,汽车在使用过程中会产生大量用户数据,比如你什么时间去了什么地方,以及日常车辆行驶路线规律等信息,这些数据都是用户的隐私。假如你每个月的某一天都会驾车去一个固定的酒店(此处省略一万字),而你的车辆行驶信息被人窃取会带来什么样的后果。 另一方面,随着高级驾驶辅助(ADAS)及自动驾驶的推出,车辆动力及制动控制需要部分或全部授权给智能驾驶系统,而车辆又暴露在互联网当中,此时如果智能驾驶系统被黑客攻破,后果将不堪设想。 看过《升级》这部电影的朋友应该会对一个情景记忆犹新,男主Grey和女友Asha乘坐的自动驾驶汽车突然失控,车辆脱离预定驾驶路线,驶向一处暴民聚集的贫民窟。在那里,两人遭到了袭击,Asha不幸丧生,而Grey身受重伤下半身瘫痪。 这样的情景不只是发生在影视剧里,早在2015年黑客就能通过攻破车辆的通信系统从而控制汽车。 在以70英里/小时的速度行驶过程中,一辆吉普车的空调系统突然被打开,开始吹冷风;然后车的无线电开关自动开启,雨刮器也突然动了起来,雨刷液喷射到挡风玻璃上;最后车自动驶离了原来的路线。甚至可以远程控制车辆的制动系统,导致车毁人亡。 上述车辆奇怪的行为是IOActive的研究员Charlie Miller 和Chris Valasek 利用Jeep车Uconnect信息娱乐系统中的0-day漏洞,远程攻击车辆导致的后果。 今天来介绍一下MCU上有哪些网络安全相关的技术手段,虽然车载MCU一般不会直接通过网络与互联网连接,但是黑客一旦攻破车载无线通信系统(WIFI, 蓝牙等),之后就可以通过CAN网络访问MCU。因此在MCU上使用网络安全措施也是非常有必要的。 安全启动 - 检查Bootloader的完整性和可靠性 下图展示了如何检测和防止bootloader被篡改。 1)MCU上电之后,CSE模块(Cryptographic Services Engine - 加密服务引擎)会从Code Flash读取bootloader。 2)CSE模块使用boot key通过AES-128加密算法为bootloader计算出一个MAC值(Message Authentication Code)。 3)CSE模块比较第2步计算出来的MAC与存储在CSE寄存器中的MAC(该MAC值是刷写bootloader时写入的)是否相同。如果相同,则安全启动认证成功 -> 表示安全启动成功的数据位会被置位并解锁。 4)黑色箭头处,开始执行bootloader程序。 安全通信 下图展示了如何防止非法的消息发送。左侧是主ECU,右侧是传感器ECU,二者通过CAN网络进行通信。 1)主ECU的CSE模块会生成一个随机数并把它发送给传感器ECU。 2)传感器ECU读取传感器的值,把传感器的值、从主ECU收到的随机数和key #x输入给AES-128加密算法进行加密。 3)传感器ECU发送加密后的消息给主ECU。 4)主ECU的CSE模块使用key #x对收到的消息进行解密。 5)主ECU把解密出来的随机数和自己发送给传感器ECU的随机数进行对比,如果一致则认为该消息是合法的,否则丢弃该消息。 部件保护 ECU的替换或篡改会改变它唯一的ID或key。下面的例子将会展示这二者的改变是如何被检测的。 1)主ECU生成一个随机数并把它发送给ECU。 2)ECU把它自己特有的ID和收到的随机数进行加密(使用key #x),并把加密后的消息发送给主ECU。 3)主ECU使用key #x对收到的消息进行解密。 4)主ECU检查解密出来的随机数是否和自己发出去的相一致,解密出来的ID是否和本地存储的ECU的ID相一致。如果二者都一致,则认为ECU 正常,否则认为ECU被非法替换或者篡改了。 上面简单介绍了MCU上使用到的几个常用的Cyber security的手段,以后有机会再介绍更多相关技术。 欢迎订阅公号“日拱一卒不期而至”,获取更多相关内容。

【STM32移植机智云】超详细教程#1 ESP8266烧录机智云固件教程(烧录固件详细教学)

ESP8266烧录机智云固件教程(烧录固件详细教学) 本教程是【STM32移植机智云】的必须的准备步骤。 先烧固件,再移植代码。 代码移植参考教程:【STM32移植机智云】超详细教程#2‘代码移植’ 介绍 a.esp8266简介 esp8266是一款常用的WiFi模块,物美价廉,功能强大。 b.机智云 简单实用的物联网平台。 官网概述: 准备材料 1.esp8266模块。 本文使用的是esp8266_01,如图。 2.机智云官方固件 获取渠道: 机智云官网(需要先登录账号)–开发者中心–下载中心–GAgent,选择如图的ESP8266. 下载解压如下图。 3.固件烧写程序 网上下载一个。如图。 4.usb转ttl串口,杜邦线等 如图: 总结: 所需资料,如下图。 方式一:csdn下载:ESP烧录机智云固件打包下载 财力雄厚者,请支持一下,感谢 方式二:提取码: bh2j ,某云下载链接 理论知识 esp8266引脚图: 可能引脚名称略有不同,但是对应功能应该是相同的。 下面附上,引脚说明: 名称说明VCC电源GND地UTXD异步串口发送端(TTL 电平,可以直接接单片机RXD)URXD异步串口接收端(TTL 电平,可以直接接单片机TXD)GPIO16(/RST复位)外部复位引脚(默认电平是高电平,低电平有效)GPIO0GPIO 0引脚用于区分工作模式:悬空状态,Flash下载模式和工作模式;下拉状态:串口固件烧写模式CH_PD(EN使能)EN使能端口(高电平有效,低电平模块不工作)GPIO2GPIO 2引脚,默认高电平,上电时禁止下拉 注意: 需要用到两个VCC(3.3V)和两个GND,usb转ttl串口的引脚会不够用,可以使用排针或者其他方式拓展接口。 如下图,随手焊接短接一下排针就可以拓展接口(Ps:真丑 @_@,但能用) 具体步骤 ESP8266接线: 按照如下方式连接ESP8266 ESP8266引脚接口VCCVCC(3.3V)CH_PD(EN使能端口)VCC(3.3V)GNDGNDGPIO0GNDUTXDRXDURXDTXD其他悬空 2.打开烧录程序 3.选择固件,及地址。 选择下载的固件。 根据模块flash选择。本文用的模块flash是8M,选择如图固件。 按照下图配置。 注意: (1)不同产商的模块,MODE和SIZE可能不同 (2)记得选择正确的COM口,否则会提示连接失败。 (3)点击START后,可能需要快速断电再供电。 下载完成截图: 运行测试 运行与烧录程序接线唯一不同在于: GPIO0 接地-- 烧录程序 GPIO0 悬空或者VCC – 正常运行 运行测试接线: ESP8266引脚接口VCC、ENVCC3.3VGNDGNDUTXDRXDURXDTXD其他悬空 打开串口工具,显示类似如图字样,说明机智云烧录成功 本教程到此结束,谢谢观看。 欢迎评论交流。

【Python学习笔记之resize】

Python学习笔记之resize 代码如下(示例): from PIL import Image from torchvision.transforms import functional as F # 读取图片 img1 = Image.open("test1.jpg") # 打印图片尺寸 print(img1.size) # 将图片最短边缩放到目标尺寸480 # resize()是将图片的【最短边】缩放到目标尺寸,不改变图片的纵横比 img2 = F.resize(img1,120) print(img2.size) # 保存图片 img2.save("xx.jpg") img3 = Image.open("test2.png") print(img3.size) img4 = F.resize(img3,480) print(img4.size) img4.save("xx1.jpg") # 输出结果 img1的尺寸:(500, 375) img2的尺寸:(160, 120) img3的尺寸:(387, 500) img4的尺寸:(480, 620) img1: img2: img3: img4:

小程序提示code:500错误的解决经验分享

小程序提示code:500错误,常规解决方案应该查看Redis是否正常。然后有针对性的解决。 假若是LOADING Redis is loading the dataset in memory问题,建议按照以下思路解决: [root@masterA RedisTest]# redis-cli flushall (error) LOADING Redis is loading the dataset in memory [root@masterA RedisTest]# redis-cli flushdb OK [root@masterA RedisTest]# redis-cli flushall OK 清除缓存,重启服务器,应该就恢复正常!

计算机网络——应用层(http、SMTP、DNS)

目录 一、应用层协议原理: 1.网络应用程序体系结构: 1.1 客户-服务器体系: 1.2 P2P体系结构: 2.进程通信: 2.1基本了解: 2.2客户-服务器进程: 2.3进程与计算机网络之间的接口: 2.4进程寻址: 3.因特网提供的运输服务(TCP和UDP): 4.应用层协议: 二、web和http: 1.基本了解: 2.http和https: 3.持续连接和非持续连接: 4.http报文格式: 4.1请求报文: 4.2http的响应报文: 三、因特网中的电子邮件: 1.SMTP: 1.1 SMTP发送报文的过程: 1.2发送方邮件服务器到接收方邮件服务器的发送过程: 2.与http的对比: 2.1相同点: 2.2不同点: 3.邮件报文格式: 4.邮件访问协议: 4.1 为什么需要? 4.2 POP3: 4.3 IMAP: 4.4 基于webde电子邮件: 四、DNS:因特网的目录系统: 1.DNS提供的服务: 2.DNS的工作机理: 2.1DNS的两种设计方式: 一、应用层协议原理: 1.网络应用程序体系结构: 从应用程序研发者的角度看,网络体系结构是固定的,并为应用程序提供了特定的服务集合。 在另一方面,应用程序体系结构( application architecture)由应用程序研发者设计,规定了如何在各种端系统上组织该应用程序。在选择应用程序体系结构时,应用程序研发者很可能利用现代网络应用程序中所使用的两种主流体系结构之一:客户-服务器体系结构或对等(P2P)体系结构。 1.1 客户-服务器体系: 在客户-服务器体系结构(client- server architecture)中,有一个总是打开的主机称为服务器,它服务于来自许多其他称为客户的主机的请求。值得注意的是利用客户-服务器体系结构,客户相互之间不直接通信。客户-服务器体系结构的另一个特征是该服务器具有固定的、周知的地址,该地址称为IP地址。因为该服务器具有固定的、周知的地址,并且因为该服务器总是打开的,客户总是能够通过向该服务器的IP地址发送分组来与其联系。具有客户-服务器体系结构的非常著名的应用程序包括Web,FTP以及电子邮件。 在一个客户-服务器应用中,常常会出现一台单独的服务器主机跟不上它所有客户请求的情况。为此,配备大量主机的数据中心(data center)常被用于创建强大的虚拟服务器。一个数据中心能够有数十万台服务器,它们必须要供电和维护。此外,服务提供商必须支付不断出现的互联和带宽费用,以发送和接收到达/来自数据中心的数据。 1.2 P2P体系结构: 在一个P2P体系结构(P2P architecture)中,对位于数据中心的专用服务器有最小的(或者没有)依赖。相反,应用程序在间断连接的主机对之间使用直接通信,这些主机对被称为对等方。因为这种对等方通信不必通过专门的服务器,该体系结构被称为对等方到对等方的。许多目前流行的、流量密集型应用都是P2P体系结构的。这些应用包括文件共享(例如BitTorrent)、对等方协助下载加速器(例如迅雷)、因特网电话和视频会议(例如 Skype)。P2P体系结构的最引人入胜的特性之一是它们的自扩展性( self- scalability )。 2.进程通信: 2.1基本了解: 对运行在多个端系统上的程序之间的通信,用操作系统的术语来说,进行通信的实际上是进程( process)而不是程序。在两个不同端系统上的进程,通过跨越计算机网络交换报文而相互通信。 2.2客户-服务器进程: 在一对进程之间的通信会话场景中,发起通信(即在该会话开始时发起与其他进程的联系)的进程被标识为客户,在会话开始时等待联系的进程是服务器。

学GIS的你,是时候自己做张中国地图了(附行政区划数据下载)

源数据的介绍 bou2_4l.shp:中国政区的线文件,在这个线文件里包含了南海的九段线 bou2_4p.shp:中国政区的面文件 rivers.shp:世界主要河流 country.shp:世界国家面文件 Res1_4m.shp:中国省会城市点文件 文末有练习数据下载链接。 操作步骤 01 设置投影 打开ArcMap软件将这些数据文件添加进去,接下来我们要为其设置一个投影坐标系。在这里我们使用等面积的Albers投影。右击Layers -> Properties -> Coordinate System -> New -> Projected Coordinate System,选择Albers,设置Central_Meridian为105,Standard_Parallel_1为25度,Standard_Parallel_2为47度,单击change,在地理坐标系中选择WGS 1984。设置如图: 02 提取南海诸岛以及其它岛屿 打开软件的Editor工具,在下拉菜单中点击Start Editing进入编辑状态。 打开bou2_4p图层的属性表,单击Select By Attributes,输入公式"AREA" = 0。 右键bou2_4p -> Data -> Export Data,将选中的要素输出为新的图层并命名为南海诸岛及其他岛屿。 03 提取出中国的轮廓线 接下来,我们要从bou2_4p中提取出中国的轮廓线。其目的是我们要区分开中国陆地上的国界和海上的国界,因为这两者在制图的时候所显示的符号是不同的。 打开Arc Toolbox -> Data Management Tools -> Features -> Polygon to Line(Feature to Line也能实现面转线的功能,但是没有选项),将输出文件命名为“中国线.shp”。勾选“Identify and store polygon neighboring information(optional)”(保留每条线段两边的多边形信息)。 打开“中国线.shp”属性表,单击Select By Attributes,输入公式"LEFT_FID" = -1 OR “RIGHT_FID” = -1,这个时候边界上的所有线要素就被选中了。如前所述的方法,将选中的要素导出成单独的图层,并命名为“中国轮廓线.shp”。

parser.add_argument()

看这个小demo就能弄懂到底什么是parser.add_argument()了: 这个demo一共四步: import argparse #1.创建一个ArgumentParser类的对象a a=argparse.ArgumentParser(description="Test") #description里面的字符串内容可以随便填,就是描述你这个对象ArgumentParser类的对象a是用来干什么的 #2.一系列的a.add_argument() a.add_argument("--age",type=int,default=10) a.add_argument("--sex",type=str,default="male") a.add_argument("--height",type=float,default=1.73) #3.调用对象a的parse_args()方法,得到一个新的对象 b=a.parse_args(); print(b) #4.输出b对象的属性 print(b.age) print(b.sex) print(b.height) 1.注意必须”--age“,以--开头,如果没有以这个开头,就会报错 2.其实我们就是关注两个东西,这个属性type是多少,默认值default是多少 3.a.add_argument(_),方法里面参数完整的话:除了name一共有10个 parser.add_argument('name', action='store_true', nargs=, const=, metavar='E', choices=, required= type=int, default=500, help='Number of epochs' dest= ) 一般不会每个参数都带上,那么全,一般都是带type,default,help这三个参数,action,metavar,dest偶尔也会有,剩下nargs,const,choices,required基本没见过 (1)name :名字 (2)action:动作,默认值是store (3)default:默认值 (4)type:参数的类型 (5)help:参数的帮助信息

Docker Desktop简介

Docker Desktop 一、简介 Docker Desktop是可以部署在windows运行docker的应用服务,其基于windos的Hyper-V服务和WSL2内核在windos上创建一个子系统(linux),从而实现其在windows上运行docker。 二、部署 1.开启Hyper-V(自行百度) 2.安装WSL2内核 https://docs.microsoft.com/zh-cn/windows/wsl/install-manual#step-4---download-the-linux-kernel-update-package 3.安装docker-compose https://github.com/docker/compose/releases 三、配置 1.配置镜像加速 { "registry-mirrors": [ "https://hub-mirror.c.163.com", "https://1rlt72n0.mirror.aliyuncs.com", "https://registry.docker-cn.com", "https://mirror.ccs.tencentyun.com", "https://mirror.baidubce.com" ] } 2.使用docker-compose管理常用的服务 version: '3' services: mysql: environment: MYSQL_ROOT_HOST: "%" MYSQL_ROOT_PASSWORD: root MYSQL_USER: wanchen # 创建新用户 MYSQL_PASSWORD: wanchen # 新用户的密码 # restart: always container_name: mysql8.0 image: mysql:v8 ports: - 3306:3306 command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci volumes: - D:\ku\dockerku\contains\mysql\conf:/etc/mysql/conf.d - D:\ku\dockerku\contains\mysql\data:/var/lib/mysql redis: image: redis:v7 ports: - 6379:6379 # restart: always container_name: redis7 hostname: redis volumes: - D:\ku\dockerku\contains\redis\data:/data - D:\ku\dockerku\contains\redis\conf:/etc/redis/redis.

数字IC设计——用Verilog实现序列检测器(有限状态机FSM)

数字IC设计——用Verilog实现序列检测器(有限状态机) 序列检测器在数据通讯,雷达和遥测等领域中用与检测步识别标志。它是一种用来检测一组或多组序列信号的电路。例如检测器收到一组串行码{1110010}后,输出标志1,否则,输出0。 一、“101” 序列检测器 序列检测器:有“101”序列输入时输出为1,其他输入情况下,输出为0。画出状态转移图,并用Verilog描述。 先分析输入序列时,产生的结果 序列检测器就是将一个指定序列从数字码流中识别出来。本例中将设计一个“101”序列的检测器。设X为数字码流的输入,Z为检测出标记输出,高电平表示发现指定的序列101.考虑码流为10101010101…则 时钟1234567891011输入X10101010101输出Z00101010101 将上述功能转化为状态转移图: 用Verilog语言描述状态机 module Detect_101( input clk, input rst_n, input data, output flag_101 ); parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3; reg [1:0] state; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin state <= S0; end else begin case(state) S0: if(data == 1) state <= S1; else state <= S0; S1: if(data == 0) state <= S2; else state <= S1; S2: if(data == 1) state <= S3; else state <= S0; S3: if(data == 1) state <= S1; else state <= S2; default: state <=S0; endcase end end assign flag_101 = (state == S3)?

添加Latex上标一点或者一撇的命令

今天写论文的时候,发现总有一个错误很是特别,如下:要编辑出一个上标有一撇的符号 可以直接在B'_{-}加,或者在上标上B^{'}_{-}加键盘上的'按键。 而如果是B本身就有平方的,如下: 就需要在上标的大括弧命令里面加'了,而不能直接在符号后面加',如下才是正确的命令: 2A_{-}^{'2}+2B_{-}^{'2}

【vue3 新特性 expose 使用与讲解】options和composition api的defineExpose案例

expose 类型:Array<string> vue3新特性,如果是options api类型的组件,不声明 expose 时,默认暴露当前组件实例的全部内容,声明了 expose 选项, expose 数组内标记的才会暴露。(expose:[]则什么都不暴露,注意这个问题。也可以利用这个特性提高组件使用的规范。) export default defineComponent({ expose:['nameA',...],// 可以 expose 当前实例的任何内容 methods:{ nameA(){} } }) <script setup> setup语法糖的情况下,默认是封闭的,需要获取当前组件里的内容的话,必须显式expose出去 <script lang='ts' setup> import {ref} from 'vue'; let refData = ref('寒蝉鸣泣之时') defineExpose({ refData, }) </script> TS类型: import { ref,Ref } from "vue"; //> defineExpose interface exFace { ex1:Ref<string>, ex2?:number } let ex1 = ref('1') let exObj:exFace = { ex1, } // 源码类型: const defineExpose: (exposed?: Record<string, any>) => void defineExpose(exObj) QQ交流群:5229 76012 ,欢迎来玩。

WKWebView 渲染出现白屏的可能因素

WKWebView 继 UIWebView 之后的 Web 组件,拥有更佳的渲染效率,加载更快内存占用也更低,但渲染页面的时候可能出现白屏的情况. UIWebView 遇到占用内存较高的情况下会导致 App Process 的 crash; WKWebView 遇到占用内存较高的情况下会导致 WebContentProcess 的 crash; 两者总体内存占用情况相差并不太多,不过 WKWebView 将其一部分内存的消耗通过多进程的方式拆解执行; 可以基于 WKWebView 这项 webViewWebContentProcessDidTerminate 的代理方法进行白屏的处理,当其整体内存占用较大即将出现白屏的情况下调用其方法并执行重新加载的操作.此时的 URL 还未被置为 nil,而白屏后则会丢失其 URL. - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView { // 内存消耗较大导致当前所加载的 webView 出现白屏状况 [webView reload]; // 刷刷刷它的 } 除此之外还遇到了同样存在白屏可能的情况,初始化 WKWebView 时未预先设置与JS的通信桥协议,具体如下 [wkConfig.userContentController addScriptMessageHandler:self name:@"WebCallApp"]; 目前开发中暂时遇到了这两种可能性会导致白屏的情况出现,可供大家参考排查. 以上便是此次分享的全部内容,希望能对大家有所帮助!

Spring笔记(五): spring 整合jdbc、hibernate、jpa

一、简介 (一)需要的jar包 1、需要的jar包:spring、hibernate、mysql、xml、apache-commons等等的jar包。 2、以上jar包,如spring、xml和commos都是冗余的。 (二)分析 1、涉及到的实体、service、dao接口、jdbc配置文件以及service实现类都可以通用,只需要实现不同的dao实现类、配置、测试类。 2、通用的源码如下: 1)实体: <span style="font-size:18px;">@Entity @Table(name="spring_person") //@Cache(usage=CacheConcurrencyStrategy.READ_WRITE,region="main.java.com.spring.entity.PersonEntity") // region用于设置单独的缓存机制,在ehcache.xml 中定义。 public class PersonEntity { @Id @Column(name="person_id",nullable=true ) @GeneratedValue(strategy=GenerationType.AUTO) private int personId; private String name; public PersonEntity() { } public int getPersonId() { return personId; } public void setPersonId(int personId) { this.personId = personId; } public String getName() { return name; } public void setName(String name) { this.name = name; } } </span> 2)service接口: <span style="

Spring笔记(四): spring的编程式事务与声明式事务

一、Spring 事务属性分析 事务管理对于企业应用而言至关重要。它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失。 在 Spring 中,事务是通过 TransactionDefinition 接口来定义的。该接口包含与事务属性有关的方法。在 Spring 中,事务是通过 TransactionDefinition 接口来定义的。该接口包含与事务属性有关的方法。 public interface TransactionDefinition{ int getIsolationLevel(); int getPropagationBehavior(); int getTimeout(); boolean isReadOnly(); } (一)事务隔离级别 隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量: 1、TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。 2、TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。 3、TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。 4、TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。 5、TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 (二)事务传播行为 所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量: 1、TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。 2、TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。 3、TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 4、TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 5、TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。 6、TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 7、TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。 这里需要指出的是,前面的六种事务传播行为是 Spring 从 EJB 中引入的,他们共享相同的概念。而 PROPAGATION_NESTED是 Spring 所特有的。以 PROPAGATION_NESTED 启动的事务内嵌于外部事务中(如果存在外部事务的话),此时,内嵌事务并不是一个独立的事务,它依赖于外部事务的存在,只有通过外部的事务提交,才能引起内部事务的提交,嵌套的子事务不能单独提交。如果熟悉 JDBC 中的保存点(SavePoint)的概念,那嵌套事务就很容易理解了,其实嵌套的子事务就是保存点的一个应用,一个事务中可以包括多个保存点,每一个嵌套子事务。另外,外部事务的回滚也会导致嵌套子事务的回滚。 (三)事务超时 所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。 (四)事务的只读属性 事务的只读属性是指,对事务性资源进行只读操作或者是读写操作。所谓事务性资源就是指那些被事务管理的资源,比如数据源、 JMS 资源,以及自定义的事务性资源等等。如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。在 TransactionDefinition 中以 boolean 类型来表示该事务是否只读。 (五)事务的回滚规则 通常情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常),则默认将回滚事务。如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务。这通常也是大多数开发者希望的处理方式,也是 EJB 中的默认处理方式。但是,我们可以根据需要人为控制事务在抛出某些未检查异常时任然提交事务,或者在抛出某些已检查异常时回滚事务。 二、Spring 事务管理 API 分析 1、Spring 框架中,涉及到事务管理的 API 大约有100个左右,其中最重要的有三个:TransactionDefinition、PlatformTransactionManager、TransactionStatus。 2、所谓事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。“给定的事务规则”就是用 TransactionDefinition 表示的,“按照……来执行提交或者回滚操作”便是用 PlatformTransactionManager 来表示,而 TransactionStatus 用于表示一个运行着的事务的状态。打一个不恰当的比喻,TransactionDefinition 与 TransactionStatus 的关系就像程序和进程的关系。 (一)TransactionDefinition 该接口在前面已经介绍过,它用于定义一个事务。它包含了事务的静态属性,比如:事务传播行为、超时时间等等。Spring 为我们提供了一个默认的实现类:DefaultTransactionDefinition,该类适用于大多数情况。如果该类不能满足需求,可以通过实现 TransactionDefinition 接口来实现自己的事务定义。 (二)PlatformTransactionManager 1、PlatformTransactionManager 用于执行具体的事务操作。PlatformTransactionManager 接口中定义的主要方法: Public interface PlatformTransactionManager{ TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status)throws TransactionException; void rollback(TransactionStatus status)throws TransactionException; } 2、PlatformTransactionManager 具体化,根据底层所使用的不同的持久化 API 或框架,PlatformTransactionManager 的主要实现类大致如下: 1)DataSourceTransactionManager:适用于使用JDBC和iBatis进行数据持久化操作的情况。 2)HibernateTransactionManager:适用于使用Hibernate进行数据持久化操作的情况。 3)JpaTransactionManager:适用于使用JPA进行数据持久化操作的情况。 4)另外还有JtaTransactionManager 、JdoTransactionManager、JmsTransactionManager等等。 如果我们使用JTA进行事务管理,我们可以通过 JNDI 和 Spring 的 JtaTransactionManager 来获取一个容器管理的 DataSource。JtaTransactionManager 不需要知道 DataSource 和其他特定的资源,因为它将使用容器提供的全局事务管理。而对于其他事务管理器,比如DataSourceTransactionManager,在定义时需要提供底层的数据源作为其属性,也就是 DataSource。与 HibernateTransactionManager 对应的是 SessionFactory,与 JpaTransactionManager 对应的是 EntityManagerFactory 等等。 (三)TransactionStatus PlatformTransactionManager.

Spring笔记(三):Aop详解

一、Aop原理 (一)动态代理 1、详见:java进阶(七):详解JAVA代理 2、主要是Proxy 与 InvocationHandle r接口 (二)Cglib 实现 1、主要是 Enhancer 和 MethodInterceptor 接口 2、实现代码如下: <span style="font-size:18px;"> /** * 利用 cglib 实现 * @param targrt * @return */ public static Object getCgProxy(final Object targrt,final Advice advice){ //利用cglib 中的Enhancer Enhancer enhancer = new Enhancer(); //把目标类设置为代理的父类(继承目标类,覆盖其所有非final的方法) enhancer.setSuperclass(targrt.getClass()); //设置回调 enhancer.setCallback(new MethodInterceptor() {//实现MethodInterceptor 接口 @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object object = null; try{ advice.

浅析JVM是如何处理异常的?finally块必须执行的原理?

JVM是如何捕捉异常的? 每个方法在经过Javac编译之后,都会附带一个异常表;看下面代码的字节码指令 public void method2() { try { int a = 1 / 0; } catch (Exception e) { e.printStackTrace(); } } 在该异常表中有四个重要的概念,from指针、to指针、target指针、异常类型。 from指针和to指针:表示该异常处理器监控的范围(也就是try代码块覆盖的范围) target指针:异常处理器的起始位置(catch代码块的起始位置) 异常类型:捕获的异常类型 当异常发生时,JVM会去遍历异常表中的所有条目,如果发现异常发生的位置在某个条目的from-to的范围内,那么就会对比抛出的异常和捕获的异常是否一致。如果一致跳转到target指针指向的异常处理器的起始位置执行。一旦该方法的异常表没有找到,则会在弹出该方法对应的栈帧,对调用该方法的方法执行同样的处理。 最坏的情况就是遍历整个线程栈也没有匹配的异常。 💦分析以下代码对应的异常的执行流程: public void method2() { try { int a = 1 / 0; } catch (Exception e) { e.printStackTrace(); } } 对应的字节码如下 0 iconst_1 1 iconst_0 2 idiv 3 istore_1 4 goto 12 (+8) 7 astore_1 8 aload_1 9 invokevirtual #3 <java/lang/Exception.

Android系统默认打开开发者选项中的TP触摸开关

在定制系统开发中,有时会遇到客户为了方便生产测试硬件主板,客户会提出生产测试软件需要默认打开开发者选项中的TP触摸开关,也就是show_touches和pointer_location 具体实现方法如下: diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml old mode 100644 new mode 100755 index e86f90a..cf1f41c --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -17,6 +17,8 @@ */ --> <resources> + <integer name="def_show_touches">1</integer> + <integer name="def_pointer_location">1</integer> <string name="tts_default_synth">com.google.android.tts</string> <string name="def_time_12_24" translatable="false">24</string> <bool name="def_dim_screen">true</bool> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index c921099..83c2c00 100755 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2267,6 +2267,12 @@ class DatabaseHelper extends SQLiteOpenHelper { loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT, R.integer.def_screen_off_timeout); + loadIntegerSetting(stmt, Settings.System.SHOW_TOUCHES, + R.integer.def_show_touches); + + loadIntegerSetting(stmt, Settings.

栈stack和队列Queue

目录 1.栈 1.1栈的概念及结构 1.2栈的实现 完整代码 Stack.c Test.c 2.队列 2.1队列的概念及结构 2.2队列的实现 完整代码 Queue.h Queue.c Test.c 2.3队列应用的两个场景: 1.栈 1.1栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。 (顺序表和链表可以在任意位置插入和删除数据) 栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 出栈:栈的删除操作叫做出栈。出数据也在栈顶。 1.2栈的实现 栈的实现一般可以使用数组或者链表实现 相对而言数组的结构实现更优一些,因为数组在尾上插入数据的代价比较小 栈是不能遍历的 完整代码 Stack.h #pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <stdbool.h> 静态栈 //#define N 10 //typedef int STDataType; //typedef struct Stack //{ // STDataType a[N]; // int top;//栈顶位置的标志 //}ST; //动态栈 typedef int STDataType; typedef struct Stack { STDataType* a; int top; int capacity;//容量 }ST; // 初始化栈 void StackInit(ST* ps); // 销毁栈 void StackDestroy(ST* ps); //入栈 void StackPush(ST* ps, STDataType x); //出栈 void StackPop(ST* ps); //获取栈顶元素 STDataType StackTop(ST* ps); //检测栈是否为空,如果为空返回非零结果,如果不为空返回0 bool StackEmpty(ST* ps); //获取栈中有效元素个数 int StackSize(ST* ps); Stack.

多个事务并发的场景及可能遇到的问题及解决方法(一)

多线程并发执行多个事务的业务逻辑如下: 多个事务对缓存页中的同一条数据同时进行更新或者查询,可能产生以下四种问题: 脏写、脏读、不可重复读、幻读。 1. 脏写 有两个事务,事务A和事务B,同时在更新一条数据,数据的值为Null,事务A将数据的值更新为A,事务B紧接着将数据的值更新为B。这个时候事务A发生了回滚,就会把数据回滚到更新之前的Null值。对于事务B来说,更新的数据没了,这就是脏写。 其本质是:事务B修改了事务A修改过的值,但此时事务A没有提交,所以事务A可能发生回滚,导致事务B的数据丢失,这就是脏写的定义。 2.脏读 有两个事务,事务A和事务B,同时在操作一条数据,数据的值为Null,事务A将数据的值更新为A,事务B查询这条数据,查的结果是A值,事务B使用查到的这个值进行业务处理。这个时候事务A发生了回滚,把数据回滚到更新之前的Null值。事务B再次查询数据,获得的结果是Null值,与之前的查询不一致,这就是脏读。 其本质是:事务B查询事务A修改过的数据,但此时事务A没有提交,所以事务A可能发生回滚,导致事务B再次查询时读取不到刚才的数据了,这就是脏读的定义。 无论是脏读还是脏写,都是因为一个事务去更新或查询了另一个还没有提交的事务更新过的数据。由于另一个事务还没有提交,可能会发生回滚,就会导致更新或者查询的数据没有了。 3. 不可重复读 有三个事务,事务A、B、C,事务A中会对一条数据进行多次查询,事务B、事务C都会对同一条数据进行更新。 现在假设有一个前提,事务未提交之前,其他事务无法获取到当前事务修改的内容。即事务B更新了数据,如果没有提交事务,事务A就读取不到,只有事务B提交之后,修改的内容才会被事务A读取到。这种情况可以避免脏读的发生。 假设缓存页中的一条数据原来的值是A,事务A第一次查询,读取得到A值。 接着事务B对数据进行更新,更新为B值,并立刻提交了事务。但事务A还在执行中,第二次对数据进行查询,得到事务B修改,并已经提交后的数据B值。 然后事务C对数据进行更新,更新为C值,并立刻提交了事务。但事务A还在执行中,第三次对数据进行查询,得到事务C修改,并已经提交后的数据C值。 这种情况对于不同的业务场景来说可能会有问题: 事务A第一次查询到的是A值,如果希望在后面的事务执行期间,多次查询都是同样的A值,这样就是希望数据是可重复读的。 但实际是,A值是不可重复读的,因为事务B和事务C更新值并提交事务之后,事务A读取的结果就变了。这样数据就是不可重复读的,这可能就是一种问题。 简单来说就是: 如果期望的是可重复读,但数据库的表现是不可重复读,事务A执行期间多次查询的值不一致,是其他事务修改后的值,就可以认为数据有问题,这个问题是“不可重复读”的问题。 当然,如果期望的是不可重复读,那么数据库就是正常的表现。 4.幻读 有一个事务A,先发送一条SQL语句,里面有一个条件查询:“select * from table where id > 10;”,第一次查询出10条数据。 接着事务B往表中插入两条记录,并提交了事务。这样表中就多了几条数据。 接着事务A再次进行查询,执行之前的SQL语句,会查询出12条数据。同样的SQL语句,查询出的数据不一样,这就是幻读。 简单来说:幻读就是一个事务中用一样的SQL多次查询,结果每次查询会有一些之前没有看到过的数据。(幻读特指查询到之前没有看到过的数据) 总结: 脏写、脏读、不可重复读、幻读都是由于数据库的多事务并发导致的问题。脏写:是两个事务没有提交状态下修改同一个值。 脏读:是一个事务修改了数据的值,还没提交,被另一个事务读取到了,然后发生回滚,导致再次读取,就读取不到了。不可重复读:针对的是已经提交的事务修改的值,被事务读取到了,事务内多次查询,多次读取的是别的已经提交的事务修改后的值。幻读:就是一个事务中用一样的SQL多次查询,结果每次查询会有一些之前没有看到过的数据。

解决ArcMap中栅格的统计问题,提高工作效率

1 问题描述 针对下载或处理得到的栅格图,如何进一步的提取分析栅格数据是关键?本次解决的问题是:根据技术要求,将栅格数据按照某一分类方法进行4分类,需要提取斜坡单元内某一类栅格属性最多的值作为该单元的最终分类结果。 2 用到的工具 ArcMap+Excel 3 转换思想 统计分类值数最多作为分类结果,可以统计分类面积的大小,到达相同的效果 4 处理过程 4.1 将栅格数据转换为矢量“面” 4.1.1 栅格重分类 栅格一般是连续值,需要根据分类标准,对栅格数据重分类。如果直接转矢量“面”会报错,提示:The input is not within the defined domain.ERROR 000889:Invalid field type.(输入的图层没有定义范围。错误000889:无效的字段类型。) 点击Spatial Analyst Tools,选择Reclass,双击Reclassify,在classify可以选择分类方法和个数。点击OK。 4.1.2 栅格转矢量 依此选择Conversion Tools、From Raster、Raster to Polygon,这时工具不再提示错误。 4.2 相交分析 依此选择:转换得到的面与要统计的矢量面,进行相交分析,得到两个图层的相交面,查看属性表信息,有对应的分类结果和面积。 4.3 图斑打散 得到的相交图层,需要进行打散操作,在开始编辑状态下,可以发现打散后,图斑个数由30变成39个。 5 使用Excel统计 5.1 数据透视表工具 在Excel中选择插入,点击数据透视表,行表示斜坡单元的编号,列表示分类结果值,求和值表示落在某个斜坡单元内,各类的面积之和。 5.2 使用INDEX()函数,返回引用 =INDEX($B$4:$E$4,MATCH(MAX(B5:E5),B5:E5,0)),得到分类结果。 5.3 在ArcMap中Join链接分类结果 将打开的dbf另存为excel,存为Excel 97-2003 工作薄(*.xls)格式 根据唯一值进行属性表链接,比如斜坡单元编号,将分类结果进行显示。右击图层,依此选择Joins and Relates、Join。 选择刚才保存的(*.xls)文件,找到对应的唯一值“value”,确定。属性表里已经链接好。 根据分类结果进行符号显示,得到最终的分类结果。

PowerMock(一):PowerMock的基本使用

文章目录 为啥要使用PowerMock PowerMock的使用 环境 引入依赖 注解说明 mock普通方法 mock抛出异常 mock新建对象 mock无返回值的方法 mock被final修饰的方法 参数模糊匹配 mock静态方法 mock私有方法 总结 参考 为啥要使用PowerMock 现在流行的测试驱动开发TDD(Test-Driven Development) ,是敏捷开发中一项核心实践和技术。也是一种设计方法论。其中最重要的一环就是使用单元测试。 单元测试是保证代码质量的一个重要手段,通过单元测试我们可以快速的测试代码的各个分支,各种场景,代码重构时只需要重新跑下单元测试就是能知道代码潜在的问题。 单元测试是通过Mock的方式调用被测试的方法,其有如下几个优点: Mock可以解除测试对象对外部服务的依赖(比如数据库,第三方接口等),使得测试用例可以独立运行。不管是单体应用还是微服务,这点都特别重要。 Mock的第二个好处就是替换外部服务调用,提升测试用例的运行速度。因为任何外部服务调用至少是跨进程级别的消耗,甚至是跨系统、跨网络的消耗,而Mock可以把消耗降低到进程内。 Mock的第三个好处就是提升测试效率,提高单位时间内测试的接口数量。 Mock的框架有很多中比如EasyMock等,这里选用PowerMock是因为PowerMock可以用来Mock 私有方法,静态方法以及final方法。EasyMock等则不能。 PowerMock的使用 环境 软件 版本 junit 4.13 powermock 2.0.7 引入依赖 <properties> <powermock.version>2.0.7</powermock.version> </properties> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <!--powermock开始--> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <!--powermock结束--> 这里引入了是三个依赖,junit依赖如果项目中已有的话,则不需要重复引入,需要注意的是JUnit 4.4及以上版本的JUnit需要引入2.0.x 版本以上的 powermock 。如果项目中有mockito依赖还需要注意mockito的版本与powermock版本对应关系,对应如下图: 详细请参考Using PowerMock with Mockito,如果引入的版本不匹配则可能会报如下错误: java.lang.TypeNotPresentException: Type org.

xpath获取父元素的方法

xpath获取父元素的方法 两种方法: # 1使用../ # 2使用parent::父级元素 import requests from lxml import etree url = 'https://www.spzs.com/chanpin/' resp = requests.get(url,headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0' }) tree = etree.HTML(resp.text) type_list = tree.xpath("//div[@class='main-pro bgfff']/div[1]/div/h2") typell = [] for type in type_list: typell.append((type.xpath('./text()')[0]).replace(' | ','/')) print(len(type.xpath('./parent::div/parent::div/parent::div/div[2]/p'))) print(len(type.xpath('./../../../div[2]/p'))) print(typell) 推荐链接文章:https://blog.csdn.net/chushujin/article/details/109016922

回调函数—Java实现

1 回调函数的概念 同步调用 一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用 异步调用 一种类似于消息或者时间的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方。 回调 一种双向调用模式,被调用方在接口被调用时也会调用对方的接口 2 回调函数的demo 手机购买商品正常下单付款后,会反馈给用户一个扣款成功的提醒 2.1 同步回调 //自定义Callback接口 package demo; public interface Callback { public void process(String msg); } //实现Callback接口的实现类 package demo; public class MyCallback implements Callback{ @Override public void process(String msg) { System.out.println("回调:" + msg); } } //客户端 package demo; public class User { private String name; private App app; public User(String name, App app){ this.name = name; this.app = app; } public void buy(String thing){ System.

VUE 记录学习

之前在学习vue的时候,觉得自己已经明白了 但其实还有很多细节没有去深研究,在实际的工作开发中还是遇到很多问题 今天就系统的记录一下vue的知识体系,持续更新ing... 前言 概述:Vue是一款前端渐进式框架,可以提高前端开发效率。 特点: ​ Vue通过MVVM模式,能够实现视图与模型的双向绑定。 ​ 简单来说,就是数据变化的时候, 页面会自动刷新, 页面变化的时候,数据也会自动变化. mvvm模型: M:模型(model):对应data中的数据V:视图(View):模板VM:视图模型(ViewModel):Vue实例对象 Vue.js三种安装方式 此处引荐下大佬的文章 讲的非常详细 vue.js 三种方式安装(vue-cli)_muzidigbig的博客-CSDN博客_vue安装 一、 Vue导入 案例: 二、Vue基本语法 1.钩子函数 概述:**钩子函数, 其实就是Vue提前定义好的事件, 其作用类似于Servlet的init方法和distory方法 语法 补充:Vue声明周期和钩子函数 (1)什么是vue生命周期? Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。 (2)vue生命周期的作用是什么? Vue生命周期中有多个事件钩子,让我们在控制整个Vue实例过程时更容易形成好的逻辑。 (3)vue生命周期总共有几个阶段? 可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/后。 (4)第一次页面加载会触发哪几个钩子? 第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子 (5)DOM 渲染在 哪个周期中就已经完成? DOM 渲染在 mounted 中就已经完成了。 (6)简单描述每个周期具体适合哪些场景? 生命周期钩子的一些使用方法: beforecreate : 可以在此阶段加loading事件,在加载实例时触发; created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用; mounted : 挂载元素,获取到DOM节点; updated : 如果对数据统一处理,在这里写上相应函数; beforeDestroy : 可以做一个确认停止事件的确认框;

《漫画算法:小灰的算法之旅》读后

第一章:算法概述 略 第二章:数据结构基础 基础定义 同量级函数: 存在函数f(n),使得f(n)/T(n)的极限值为不是0的常数。记作T(n) = O(f(n)),这里的O渐进时间复杂度,简称时间复杂度 if f(n) exist && f(n max)/T(n) !=0 其实就是把时间函数T(n),简化成一个数 随机读取: 比如有个数组,你array[3],就是拿下标为3的数据,这种根据下标读取元素的方式就叫随机读取 物理结构:内存中实实在在存在的就叫物理结构,比如list、array 逻辑结构:靠意淫想象出来的结构,比如redis的跳表 栈:线性的数据结构。先入后出(FILO),比如吧一个球放进只有一个孔的半密闭容器,只能从上往下拿球。最上面的叫栈顶,最下面的叫栈底。方法分别对应压栈/入栈 push和出栈pop 队列:线性的数据结构。先入先出。按照顺序一个一个的执行,不能跳过或者删除。队列的出口叫队头,入口叫队尾。方法分别对应入队enqueue和出队dequeue。需要注意的是出队只允许出对头的那个 循环队列:吧队列想成一个首尾相接的圆环,下次取队头的时候就根据 (队尾下标+1)%数组长度 来算。 栈的一些小应用举例 1.比如某些网页的返回上一次 2.比如递归找到上一层调用,从而找到整个的调用链 队列的一些小应用举例 1.按顺序争夺公平锁的等待队列 2.rabbitmq 优先级队列的小举例: 1.非公平锁里面可能是按照优先级来获取的 散列表/哈希表:其实就是键值对 哈希函数:将键和数据下班进行转换的方法,就叫哈希函数 哈希的写操作: 1.先对key做hash操作,返回值就是找到key的下标位置 具体的是 // 先对key做哈希运算 // 这个>>> 表示无符号右移,如果是正数 则和>>一样,表示除以2的n次方; 忽略符号位,空位都以0补齐 (h = key.hashCode()) ^ (h >>> 16) 2.putValue 如果长度不够就扩容(含负载因子) 如果对应的下标没有就吧这个entry放过去 如果已经存在了,则吧原来的key的值和当前的值做对比。如果是一样的,就覆盖;如果不是一样的,就先变成链表,数量到了8个以上就变成红黑树。这就是所谓的哈希冲突 发生哈希碰撞(就是出现了多个相同的哈希值),jdk7是将新的放到头部去,jdk8是放到数组最后面去。哈希碰撞主要是为了避免哈希碰撞拒绝服务攻击(因为在元素放置过程中,如果一个对象哈希冲突, 都被放置到同一个桶里,则会形成一个链表,我们知道链表查询是线性的,查的慢,会严重影响存取的性能。然后导致cpu大量占用) 至于解决哈希冲突的方法方法,有4个方法 开放地址再哈希链地址(这个是hashmap现在用的大value链表的,出现重复的就把它们串在同一个list里面。这个方法叫链地址法)建立公共溢出区 其中开放地址又分为: 线性探测再散列二次探测再散列伪随机探测再散列 开放地址寻址法可以理解为:比如我的key的下标是5,那么我继续往下看看下标为6的有没有数据,有的话,去看看7.如果7没有数据,则吧当前数据插进去。ThreadLoack就是用的开放寻址法 map的getValue 1.寻找下标等等和put一样。 2.明显是如果找到了就先比较下字面值,如果一样则返回走,如果不一样则继续往下查。现在知道为什么哈希冲突会增大查询速度吧? 我们知道链表查询是线性的,查的慢,会严重影响存取的性能。然后导致cpu大量占用 扩容

Linux--Ubuntu18.04交叉编译链;多窗口终端;彻底删除不用的虚拟机镜像

文章目录 建立共享文件夹交叉编译查看是否安装了交叉编译工具安装交叉编译工具链退出root模式 多窗口终端--Terminator彻底删除不用的虚拟机镜像 建立共享文件夹 实现windows系统与虚拟机中的ubuntu之间的文件共享 PC机新建共享文件夹 在 Windows 系统的中创建 [任意名]文件夹,记住路径。 移除虚拟机原有共享文件夹 在 VMware 虚拟机界面点击“虚拟机”,弹出选项后选择“设置”进入虚拟机设置界面,点击“选项”–>“共享文件夹”–>“总是启用”–>“文件夹(F)”中移除无法使用的共享路径。 3.添加共享文件夹 添加刚刚建立的共享文件夹 4.共享文件夹的测试 cd /mnt/hgfs/ ls 交叉编译 查看是否安装了交叉编译工具 which arm-linux-gccgcc 安装交叉编译工具链 在 Windows 系统中,将压缩包 复制到 ubuntu 共享目录夹中,然后linux进入该目录,执行解压命令。 进入目录: cd /mnt/hgfs/share 解压命令: sudo tar Jxvf arm-linux-gnueabi-5.4.0.tar.xz -C / C 后面有个空格,并且 C 是大写的,它是英文单词“Change”的第一个字母,在此是改变目录的意思。 2. 把编译器路径加入系统环境变量,运行命令 先进入root模式 sudo -i (这是我进入root模式的命令) cd /etc/ vim /etc/bash.bashrc **在.bashrc 文件最后一行加上 (该路径要与实际安装路径一致,即/usr/local/arm/5.4.0/usr/bin 这个路径要在你的 Ubuntu 中找的到,要是实际存在的路径) ** export PATH=/usr/local/arm/5.4.0/usr/bin:$PATH 保存退出后,执行以下操作: source /etc/bash.bashrc (立即使新的环境变量生效,不用重启电脑) 检查是否将路径加入到 PATH,执行以下命令

fiddler抓手机显示网络连接失败

下载地址 如果你是第一次抓手机,找了好多攻略手机都显示网络弱,直接看3中的插件 目录 1.关杀毒软件、防火墙2.电脑手机安装配置的问题3.手机网络加强插件4.之前可以抓,现在不能抓5.怎么不抓PC端 1.关杀毒软件、防火墙 不管是啥原因,第一件事先把杀毒软件防火墙关掉,防火墙别就关一种网络的,全关了!重启fiddler,重连手机代理试一下! 2.电脑手机安装配置的问题 1.电脑端下载 fiddler 并配置各个配置信息、安装信任证书等 下载安装步骤 2. 手机端 3. 连入与电脑相同网络(不是一个 wifi 就行,wifi 网络必须ping通) 4. 设置代理:电脑ip(win+R 运行cmd,然后输入ipconfig就可以查看) 5. 端口号下载证书:https://ip地址:端口号,连了代理再来下证书,没连代理别说没网!iPhone手机,设置-通用-描述文件中安装证书,设置-通用-关于本机-证书信任设置中信任证书!ios 10之后给我点信任!!! 3.手机网络加强插件 电脑端下载fiddle插件 CertMaker for iOS and Android 上述都没解决,那就装就完事了! 4.之前可以抓,现在不能抓 如果不是新连的 WiFi 有问题,不是杀毒软件防火墙又开了,那就把电脑 fiddler 重启试试,还不行就是忘记手机 WiFi,重新输一下密码。 5.怎么不抓PC端 第一次抓手机的朋友多半会想关掉PC端,免得看不到。 点击capturing就可以取消抓取pc端的包

CentOS mysql常用命令

使用root管理员登录MySQL:mysql -u root -p 保存数据修改:flush privileges; 启动MySQL:service mysqld start 停止MySQL:service mysqld stop 重启MySQL:service mysqld restart 开机自启MySQL:chkconfig mysqld on 关闭开机自启MySQL:chkconfig --level 345 mysqld off 创建abc数据库:create database abc; 显示所有数据库:show databases; 切换数据库:use root; #切换到root数据库 删除数据库:drop database 数据库名 #默认数据库(test) 查看表:show tables; 查看表结构:describe user; 更改默认mysql管理员用户为admin update mysql.user set user = "admin" where user = "root"; 查看当前策略 SHOW VARIABLES LIKE 'validate_password%'; 修改密码策略 set global validate_password_policy=0; set global validate_password_mixed_case_count=0; set global validate_password_special_char_count=0; set global validate_password_length=6; 授权

Golang学习笔记

一、Go语言的知识图谱 上图表示了go的应用领域,包括容器如k8s, 服务发现如consul,kv存储如etcd,中间件如codis, 存储如minio,分布式数据库tidb,此外还有devops、区块链、人工智能、web框架、微服务等等领域的应用。 二、Go语言概述 2.1、为什么需要Go语言 相比C++和java, Go语言更年轻,他存在的意义何在呢? 1)在计算领域,是C/C++的天下,因为执行效率高,但缺点是开发和编译效率低。 2)对于Java,虽然编译速度快、开发效率高,但执行效率不如C/C++。 3)而动态语言如Python,由于没有强类型约束,很多问题需要在运行时发现:这种低级错误由编译器来发现更好些。 综上,期待出现一种语言来解决上述语言的缺点,Go语言这时出现,它易于开发、快速编译、高效执行。 Go语言起源于2007年,由google 2009年发布。 Go编译后的代码,运行速度可媲美C/C++,且编译速度更快,因此风靡全球,被称为21世纪的C语言(Go不仅具备C的性能与安全,且提供了21世纪互联网环境下服务端开发的各种使用特性) Go语言的设计哲学是:简单、实用。 Go语言是对类C语言的重大改进,它可以访问底层操作系统,还提供了强大的网络编程和并发编程的支持。Go语言可进行网络编程、系统编程、并发编程、分布式编程。 1)并发场景性能快 2)静态的语言:没有面向对象中的“类” 3)支持自动垃圾回收 4)编译型语言:编译速度快 Go遵循简洁编程原则: 1)它没有隐式的数值转换 2)没有构造函数和析构函数 3)没有运算符重载 4)没有默认参数 5)也没有继承 6)没有泛型 7)没有异常 8)没有宏 9)没有函数修饰 10)更没有线程局部存储 Go承诺保证向后兼容: 用之前的Go语言编写程序可以用新版本的Go语言编译器和标准库直接构建而不需要修改代码 Go语言支持交叉编译,即可以在Linux系统上开发基于Windows上运行的程序,因为这是一门完全支持UTF-8的语言,不仅体现在他可以处理使用UTF-8编码的字符串,就连他的源码稳居格式都是使用UTF-8编码。 2.2、Go是编译型语言 Go代码在运行前,需要使用编译器来编译代码,编译器将源代码编译成二进制(或字节码)格式;在编译代码时,编译器会做错误检查、性能优化,然后输出可在不同平台上运行的二进制文件。 要运行Go程序,需要的步骤: 1)使用文本编辑器写Go代码 2)编译程序 3)运行编译后得到的可执行文件。 这与Python, Javascript等语言不同,Go自带了编译器。 2.3、Go语言的特性 1、语法简单 Go语法与C类似,但没有C那些隐秘晦涩的规则,Go语法简单严谨,无歧义。 2、并发模型 Go引入了携程Goroutine,从根本上将一切都并发化,运行时用goroutine运行所有的一切,包括main.main入口函数。 Goroutine用类携程的方式来处理并发单元,却又在运行时层面做了更深度的优化处理。但语法上的并发编程变得极为简单,无需处理回调,无需关注现场切换。 goroutine搭配channel,实现CSP模型。将并发单元间的数据耦合拆解开来,各司其职。这样对所有纠结于内存共享、锁粒度的程序员都是一种解脱。 3、内存分配 将一起并发化虽然好,但也带来了新问题,即如何实现高并发下内存的分配和管理。Go选择了tcmalloc,他本就是为了并发儿设计的高性能内存分配组件。 去除因配合垃圾回收而修改的内容,内存分配器完整保留了tcmailoc的原始架构。使用cache为当前线程提供无锁分配,多个central在不同线程间平衡内存单元复用。在更高层次里,heap管理大块内存分配,用以切分成不同等级的复用内存块。快速分配和二级平衡机制,让内存分配器能优秀地完成高压力下的内存管理任务。 除了偶尔因性能问题而被迫采用对象池和自主内存管理外,我们基本无需参与内存管理操作。 4、垃圾回收 相比Java, Go的垃圾回收面临的困难更多,因为指针的存在。幸好,指针运算被阻止,否则要做到精确回收都难。 每次版本升级,垃圾回收期都是核心组件里修改最多的部分,从并发清理,到降低STW的时间,直到Go的1.5版本实现并发标记,逐步引入三色标记和写屏障等,都是为了能让垃圾回收在不影响用户逻辑的情况下更好地工作。但当前最新版本的垃圾回收算法也只能说堪用,距离好用还有不少距离。 5、静态链接 静态链接,只需编译后的一个可执行文件(将运行时、依赖库直接打包到可执行文件内部),无需附加任何东西,就能部署。这种简单的方式对于编写系统软件有极大好处,无需实现安装运行环境和下载各种第三方库。 6、标准库 Go的标准库算比较丰富,其中值得称道的事net/http,仅需要简单的几条语句,就能实现一个高性能的web server,大批基于此的优秀第三方Framework更将Go推到了Web/微服务 开发标准之一的位置。 7、工具链 完整的工具链对日常开发极有帮助,Go的工具链做的不错,无论是编译、格式化、错误检查、帮助文档,还是第三方包的下载、更新,都有对应的工具。虽然这些工具算不上多完善,但简单易用。 Go内置的测试框架,其中包括单元测试、性能测试、代码覆盖率、数据竞争,及用来调优的pprof,都是包子代码正确与稳定运行的必备利器。 此外,还可通过环境变量输出运行时的监控信息,尤其是垃圾回收和并发调度跟踪,可进一步帮助我们改善算法,获得最佳的运行期表现。 2.4、Go语言为并发而生 Go语言的祖先C语言的指令都是串行执行,即同一时刻仅有一个指令在使用CPU。

npm 在安装的时候提示 没有权限操作的解决办法 Error: EACCES: permission denied

npm 在安装的时候提示 没有权限操作的解决办法 Error: EACCES: permission denied 在安装插件的时候出现这样的错误,权限不够,是因为之前用 root 用户进行了局部安装npm包的操作,留下所属权为 root 的文件,导致普通用户无法访问 root的文件内容。 报错日志如下: npm ERR! path /Users/Kyle/.npm/_cacache/index-v5/d8/1f/98ab242d0cbad080828ef3e3f4b864c25e506a719121c293fec810b14b3c npm ERR! code EACCES npm ERR! errno -13 npm ERR! syscall open npm ERR! Error: EACCES: permission denied, open '/Users/Kyle/.npm/_cacache/index-v5/d8/1f/98ab242d0cbad080828ef3e3f4b864c25e506a719121c293fec810b14b3c' npm ERR! { [Error: EACCES: permission denied, open '/Users/Kyle/.npm/_cacache/index-v5/d8/1f/98ab242d0cbad080828ef3e3f4b864c25e506a719121c293fec810b14b3c'] npm ERR! cause: npm ERR! { Error: EACCES: permission denied, open '/Users/Kyle/.npm/_cacache/index-v5/d8/1f/98ab242d0cbad080828ef3e3f4b864c25e506a719121c293fec810b14b3c' npm ERR! errno: -13, npm ERR! code: 'EACCES', npm ERR! syscall: 'open', npm ERR!

【游戏开发答疑】马里奥派对选面积大作战玩法的功能实现(Unity | 算法 | 四邻域 | 连通块 | 面积比例分割)

本文运行效果如下 文章目录 一、前言二、实现方案1、构造二维数组2、顺序填充颜色3、交换格子颜色4、计算连通块个数(四邻域连通)5、运行起来 三、工程源码四、完毕 一、前言 嗨,大家好,我是新发。 有同学私信问了我一个问题,如下 游戏视频如下 【超级马力欧派对】(四十六)选面积大作战 我以第一回合为例,也就是把5*9的方格分成9:11:12:13的面积,并且确保面积是四邻域连通的,什么是四邻域呢?一个格子的上下左右紧邻的格子就是它的四邻域。 好了,下面讲一下实现方案。 二、实现方案 1、构造二维数组 为了演示,我先做了一个简单的UI界面,如下,下面是一个5*9的方格阵列, 如果对应成代码,它就是一个二维数组,像这样子 /// <summary> /// 行数 /// </summary> private const int ROW_CNT = 5; /// <summary> /// 列数 /// </summary> private const int COL_CNT = 9; /// <summary> /// 格子二维数组 /// </summary> public Image[,] grid = new Image[ROW_CNT, COL_CNT]; 2、顺序填充颜色 我们定义四种颜色, 把格子按9:11:12:13的比例顺序填充不同的颜色,像这样子 对应成代码就是这样子: // 划分成4种颜色,9个color1, 11个color2, 12个color3, 13个color4 for (int i = 0; i < ROW_CNT; ++i) { for (int j = 0; j < COL_CNT; ++j) { var index = i * COL_CNT + j; if (index < 9) { grid[i, j].

redis优化篇

前言 redis都是基于内存的操作,CPU不是redis的性能瓶颈,则服务器的内存利用率和网络IO就是redis的性能瓶颈,redis优化主要是从这2个维度做优化。 写博客是自己对知识梳理,目前是写给自己看,算是自己学习后的作业,也是为了养成一个良好的习惯。 一、数据存储优化 1. 控制key的长度 在保证key在简单、清晰的前提下,尽可能把key定义得短一些来控制key的长度,如 uerOreder:0001 缩写为uo:0001。 建议:做好key规范管理的文档,定义好每个key缩写的含义。 如按以上规范来做当redis中有大量的key时也会节约redis大量的内存空间,使其性能更高。 建议规范。 2. 控制元素的大小 在决定使用redis建议强制规定元素的大小,推荐规范如下: 1. String类型数据的值控制在10K以下; 2. List/Hash/Set/ZSet数据类型的元素要控制在1W以内。 以上的是杜绝bigkey有效措施,在bigkey对redis的性能影响是最为致命的。 强制规范。 3. 存储合适数据类型 除非业务的强要求,建议选择合适的数据类型来优化内存,具体如下: 1. String、Set:尽可能存储 int 类型数据; 2. Hash、ZSet:存储的元素数量控制在转换阈值之下,以压缩列表存储,节约内存。 建议规范。 关于具体原因的可以参考下面这篇博客: redis数据类型 4. 设置过期key 强制要求所有的key必须设置过期时间,以优化redis内存。 强制规范。 5. 冷热分离 热key需要单独存放并分配合理的资源,防止大流量下直接冲垮整个缓存系统。 强制规范。 6. 数据压缩 可以采用snappy、gzip 等压缩算法来先将数据压缩后再存入缓存中,来节约redis的内存空间, 但这种方法会使客户端在读取时还需要解压缩,在这期间会消耗更多CPU资源,你需要根据实际情况进行权衡。 建议,只是在redis匮乏时的一种方案。 二、内存淘汰优化 杜绝使用默认的内存淘汰策略,避免在业务扩展下Redis的内存持续膨胀,需要根据你的业务设置对应内存淘汰策略。 强制规范。 三、过期策略优化 由于redis采用的是定期删除+懒加载删除策略,且这个过程在redis 6.0之前是在主线程上执行的, 建议所有key的过期时间用随机数打散,杜绝大批量的数据同时过期,拉胯redis的性能和造成缓存雪崩。 强制规范。 关于过期策略的具体的细节请参考我之前博客: redis过期策略 四、持久化优化 除非业务的强要求,否则不要开启AOF,避免写磁盘拖垮redis的性能。 如果有业务要求开启AOF,建议配置为 appendfsync everysec 把数据持久化的刷盘操作, 放到后台线程中去执行,尽量降低 Redis 写磁盘对性能的影响。 强制规范! 关于redis持久化的细节可以参考我之前写的博客: redis持久化

机器学习——基础概念

一. 机器学习基础概念 总结过层中,我结合了头歌上的相关公开课程:详见 (一).什么是机器学习? 机器学习致力于通过计算的手段,利用经验来改善系统的性能。 “经验”——>通常“数据”形式存在——>产生“模型”的算法被称为“学习算法” (二).基本术语 1.数据集: 记录的集合。其中每一条记录关于一个事件或者对象,称为一个“示例”,或者“样本”。 2.属性(或特征) 反映事件或对象在某方面的表现或者性质的事项,如色泽,根蒂,敲声; 3.属性值 属性上的取值成为“属性值” 4.属性空间 属性张成的空间称为“属性空间”,或样本空间,输入空间 5.特征向量 有属性作为坐标轴,由各属性组成一个点。由于空间中的每个点对应一个坐标向量,因此每一个示例也称为一个“特征向量”。 6.维数 若一个示例由d个属性描述,Xi为d维样本空间X中的一个向量,Xij是指样本Xi在第j个属性上的取值。d称为样本Xi的维数。 7.数据集 定义:数据的总和称为数据集。分类: (1)训练集:用来学习或者叫训练的数据集。 (2)测试集: 8.样例 拥有标记信息(描述特征或属性的信息)的示例,一般用(xi,yi)表示第i个示例,其中yi∈Y是示例xi的标记,Y是所有标记的集合,称为标记空间或输出空间。 9.学习任务 监督学习 (1)定义:监督学习是从标记的训练数据来推断一个功能的机器学习任务。训练数据包括一套训练示例。在监督学习中,每个实例都是由一个输入对象(通常为矢量)和一个期望的输出值(也称为监督信号)组成。 (2)代表:分类和回归。监督学习是训练神经网络和决策树的常见技术。这两种技术高度依赖事先确定的分类系统给出的信息,对于神经网络,分类系统利用信息判断网络的错误,然后不断调整网络参数。对于决策树,分类系统用它来判断哪些属性提供了最多的信息。 (3)常见监督算法:线性回归算法、BP神经网络算法、决策树、支持向量机、KNN等。 (4)弱监督学习:为什么需要弱监督学习 ①现实的数据往往缺乏标签; ②数据标注过程的高成本; ③很多任务很难获得如全部真实标签这样的强监督信息;半监督学习(自我训练) 详细信息,推荐——>半监督学习 无监督学习 (1)定义:根据类别未知(没有被标记)的训练样本解决模式识别中的各种问题,称之为无监督学习。 (2)常见无监督算法:主成分分析方法PCA等,等距映射方法、局部线性嵌入方法、拉普拉斯特征映射方法、黑塞局部线性嵌入方法和局部切空间排列方法等。 (3)聚类: ①聚类算法一般有五种方法,最主要的是划分方法和层次方法两种。 ②划分聚类算法通过优化评价函数把数据集分割为K个部分,它需要K作为输入参数。典型的分割聚类算法有K-means算法, K-medoids算法、CLARANS算法。 ③层次聚类由不同层次的分割聚类组成,层次之间的分割具有嵌套的关系。它不需要输入参数,这是它优于分割聚类算法的一个明显的优点,其缺点是终止条件必须具体指定。典型的分层聚类算法有BIRCH算法、DBSCAN算法和CURE算法等。 ④利用聚类结果,可以提取数据集中隐藏信息,对未来数据进行分类和预测。应用于数据挖掘,模式识别,图像处理等。 (4)无监督学习的方法分类: ① 一类为基于概率密度函数估计的直接方法:指设法找到各类别在特征空间的分布参数,再进行分类。 ②另一类是称为基于样本间相似性度量的简洁聚类方法:其原理是设法定出不同类别的核心或初始内核,然后依据样本与核心之间的相似性度量将样本聚集成不同的类别。二者的区别 10.训练、验证、测试、评估 首先我们先通过一个形象的类比来了解一下什么是训练、验证、测试与评估。 训练–学生的课本;学生根据课本里的内容来掌握知识。 验证–作业,通过作业可以知道不同学生学习情况、进步的速度快慢。 测试–考试,考的题是平常都没有见过,考察学生举一反三的能力。 评估–分数,通过分数的高低了解学生对知识点的掌握情况。 训练:从数据中学得模型的过程称为“学习”(learning)或“训练”(training),这个过程通过执行某个学习算法来完成. 验证:对同一个学习算法,当使用不同的参数配置时,也会产生不同的模型.那么,选用哪一个学习算法、使用哪一种参数配置,这就是机器学习中的“模型选择”(modelselection)问题。对学习出来的模型,微调他们的参数,如在神经网络中选择隐藏单元数。验证集还用来确定网络结构或者控制模型复杂程度的参数。 测试:使用一个“测试集”(testing set)来测试学习器对新样本的判别能力,然后以测试集上的“测试误差”(testing error)作为泛化误差的近似。**值得注意的是:**测试集应该尽可能与训练集互斥,即测试样本尽量不在训练集中出现、未在训练过程中使用过. 评估: (1)把学习器的实际预测输出与样本的真实输出之间的差异称为“误差”(error),学习器在训练集上的误差称为“训练误差”(training error)或“经验误差”(empirical error),在新样本上的误差称为“泛化误差”(generalizationerror)。显然,我们希望得到泛化误差小的学习器。 (2)评估方法 留出法 ①“留出法”(hold-out)直接将数据集D划分为两个互斥的集合,其中一个集合作为训练集S,另一个作为测试集T.在S上训练出模型后,用T来评估其测试误差,作为对泛化误差的估计. ②注意: a.训练/测试集的划分尽可能保持数据分布的一致性。 b.一般采用若干次随即划分、重复进行实验评估后取平均值作为留出法的评估结果。

sort目标跟踪算法

sort目标跟踪算法 概述sort算法流程图sort关键参数sort过程代码匈牙利算法 概述 sort(Simple Online and Realtime Tracking),简单的在线实时跟踪,常用于多目标追踪(Multiple Object Tracking)中,其中不涉及到图像识别、特征匹配等算法,sort算法以目标检测结果作为输入,用数据关联算法(匈牙利算法)进行目标匹配,并以卡尔曼进行目标预测,通过IOU也建立目标间的关系,其主要目的在于连续跟踪目标的ID,优点是跟踪速度快。 sort算法流程图 sort关键参数 self.max_age = 1 # 在跟踪列表中有几帧没有关联匹配成功就从跟踪列表中移除,否则就将失去关联计数加1 self.min_hits = 3 # 连续3帧以上都匹配成功,则作为跟踪结果输出 self.iou_threshold = 0.3 # IOU匹配的阈值 self.trackers = [] # 跟踪缓存 self.frame_count = 0 # 帧率统计 sort过程代码 1.从现有跟踪器中获取预测位置 const auto get_pred_boxes = [] (auto &trackers) { std::vector<cv::Rect2f> boxes; boxes.reserve(trackers.size()); for (auto it = trackers.begin(); it != trackers.end();) { const cv::Rect2f &box = (*it)->Predict(); if (box.x >= 0 && box.

Linux上部署多个 Tomcat 服务器

1、将下载好的tomcat安装包上传到linux 使用解压命令将文件解压到指定目录下:tar -zxvf apache-tomcat-9.0.13.tar.gz -C /usr/qinTools/ 复制多个并修改名字 2、修改 /etc/profile文件,在文件的末尾加上如下内容 *************first tomcat************* CATALINA_BASE=/usr/qinTools/tomcat-9.0.13 CATALINA_HOME=/usr/qinTools/tomcat-9.0.13 TOMCAT_HOME=/usr/qinTools/tomcat-9.0.13 export CATALINA_BASE CATALINA_HOME TOMCAT_HOME *************first tomcat************* *************second tomcat************* CATALINA2_BASE=/usr/qinTools/tomcat-9.0.13One CATALINA2_HOME=/usr/qinTools/tomcat-9.0.13One TOMCAT2_HOME=/usr/qinTools/tomcat-9.0.13One export CATALINA_One_BASE CATALINA_One_HOME TOMCAT_One_HOME *************second tomcat************* *************third tomcat************* CATALINA3_BASE=/usr/qinTools/tomcat-9.0.13Two CATALINA3_HOME=/usr/qinTools/tomcat-9.0.13Two TOMCAT3_HOME=/usr/qinTools/tomcat-9.0.13Two export CATALINA_Two_BASE CATALINA_Two_HOME TOMCAT_Two_HOME *************third tomcat************* 修改完文件要输入命令:source /etc/profile 刷新配置,否则不会生效 3、进入第二、第三个 Tomcat 的 bin 目录修改 catalina.sh 文件。 第一个 Tomcat 无需更改 第二个 Tomcat 将 catalina.sh 中的 CATALINA_BASE 和 CATALINA_HOME 批量替换成在 /etc/profile 中配置的第二个 tomcat 对应的信息 切换目录:cd /usr/qinTools/tomcat-9.

算法题07(搜索插入位置)

public class searchInsert { public static int searchInsert(int[] nums, int target) { int n = nums.length; int left = 0, right = n - 1, ans = n; while (left <= right) { int mid = ((right - left) >> 1) + left; if (target <= nums[mid]) { ans = mid; right = mid - 1; } else { left = mid + 1; } } return ans; } public static void main(String[] args) { int[]nums={1,3,5,7}; int target=5; int a=searchInsert(nums,target); System.

CSS基本样式

1. font-famliy:引入字体,font-size:改变字体大小;font-weight设置字体粗细,值没有单位,只加数字 2. border-radius:是用来调整边角的圆润,50%就是圆形。 例子:box-radius:50px 50px 50px 50px/20px 20px 20px 20px;即通过X轴/Y轴;第一个是左上角 3. 可以拥有好几个class类,例如class=" pink-text blue-text",如果两个类的样式冲突,在style中 下面的会覆盖上面的。 4. class类优先级高于继承,id选择器高于class选择器,内联样式高于id选择器。 5. !import优先级最高 .pink-text { color: pink !important; } 6. CSS 变量可以实现仅需要更新一个值,就可以将更改应用到多个。若有很多都应用这个值的时候 在改的时候就不用全部改,只改这个赋值的值就行 例:在最外层:root里定义一个值,在:root里面定义,下面所有的子元素都会继承,会作用于整个页面。一般都在:root里面定义 :root{ --a-color:black; } 在b类里用的时候: .b{ background:var(--a-color,red) //red,在--a-color定义的这个颜色值不能用的时候就取red这个背景颜色 } 7. 使用媒体查询,在某个值发生改变,相应的样式也会改变,例:在页面宽度大于350px的时候,之前定义的--a-color变成黄色 @media(max-width:350px){ :root{ --a-color:yellow; } } 8. text-align 文本对齐方式 justify:将文本中用空格隔开,使每行一样长 center:文本都居中 right:右对齐 left:左对齐 9. strong加粗文本,u给文本添加下划线,em强调文本,即斜体,s添加删除线,hr创建水平线,hr不用闭合标签. 10. rgba(45,45,45,0.1)前三个都是组合颜色,第四个参数是透明度。opacity也可以设置透明度,只是是所有的透明度,可以继承到子元素 11. box-shadow 给盒子添加阴影,可以添加多个阴影列表,用逗号隔开, offset-x 阴影的水平偏移量; offset-y 阴影的垂直偏移量; blur-radius 模糊半径; spread-radius 阴影扩散半径; color 阴影颜色

【自然语言处理】【聚类】DCSC:利用基于对比学习的半监督聚类算法进行意图挖掘

利用基于对比学习的半监督聚类算法进行意图挖掘 《Semi-Supervised Clustering with Contrastive Learning for Discovering New Intents》 论文地址:https://arxiv.org/pdf/2201.07604.pdf 相关博客: 【自然语言处理】【聚类】基于神经网络的聚类算法DEC 【自然语言处理】【聚类】基于对比学习的聚类算法SCCL 【自然语言处理】【聚类】DCSC:利用基于对比学习的半监督聚类算法进行意图挖掘 【自然语言处理】【聚类】DeepAligned:使用深度对齐聚类发现新意图 【自然语言处理】【聚类】CDAC+:通过深度自适应聚类发现新意图 【计算机视觉】【聚类】DeepCluster:用于视觉特征无监督学习的深度聚类算法 【计算机视觉】【聚类】SwAV:基于对比簇分配的无监督视觉特征学习 【计算机视觉】【聚类】CC:对比聚类 【计算机视觉】【聚类】SeLa:同时进行聚类和表示学习的自标注算法 【自然语言处理】【聚类】ECIC:通过迭代分类增强短文本聚类 【自然语言处理】【聚类】TELL:可解释神经聚类 一、简介 1. 意图挖掘 ​ 任务导向的对话系统依赖于自然语言理解( NLU \text{NLU} NLU),用于将对话分类到一个已知的意图,并利用预先准备好的答案进行回复。如果能够尽可能的发现新意图,那么聊天机器人就能够回答更多种类的问,从而改善用户体验。通常会使用聚类算法将意图相同的样本聚在同一个簇中,每个簇可以看作是一个意图。此外,聚类的准确率对于意图识别模型也很重要,因为聚类后的样本会被用于训练分类模型。因此,一个好的聊天机器人不仅依赖 NLU \text{NLU} NLU能力,还依赖聚类这种前期准备的工作。 2. 聚类 ​ 意图挖掘这个领域有很多的工作被提出。早期主要是聚焦在无监督聚类算法,基础的方法是合并一个编码器模型和聚类模型。一般来说,特征抽取编码器使用 BERT \text{BERT} BERT及 SBERT \text{SBERT} SBERT这样的语言模型,聚类模型则使用 K-Mean++ \text{K-Mean++} K-Mean++和 HDBSCAN \text{HDBSCAN} HDBSCAN等机器学习方法。但是,这种分离编码步骤和聚类步骤的方法,并不能通过聚类损失函数来优化编码器的向量表示。为了解决这个问题,早期的一些工作使用基于深度学习的距离方法,例如 DEC \text{DEC} DEC和 DCN \text{DCN} DCN。这些方法将向量表示和无监督聚类合并至同一优化过程,并改善了最终的效果。近期,一些研究尝试引入对比学习损失函数来进一步改善效果。模型 DeepCluster \text{DeepCluster} DeepCluster和 SwAV \text{SwAV} SwAV通过使用对比学习和基于深度学习的聚类极大的改善了下游任务的图像表示。模型 SCCL \text{SCCL} SCCL则使用对比学习改善 DEC \text{DEC} DEC,在无监督文本聚类任务上取得了相当好的效果。 半监督聚类

nginx 配置指令之server_name

前言 作为nginx的http模块中的重要指令,对于使用nginx的同学来说,有必要做深入的了解; server_name指令 用于设置虚拟主机服务名称,如:127.0.0.1 、 localhost 、域名[www.baidu.com | www.jd.com] 关于 server_name 的配置方式有三种,分别是: 精确匹配通配符匹配正则表达式匹配 精确匹配配置 server { listen 80; server_name www.baidu.com www.localhost; } 如下:在windows本地的nginx.conf配置文件中配置了如下参数 需要注意的是,如果是在实际的生产服务器上面进行配置的话,域名一定是有效的,server_name可以配置多个,然后重启nginx服务,访问下试试,可以看到通过两种方式都可以访问到nginx; 通配符模式配置 server_name 中支持通配符 "*", 但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段 server_name localhost www.zcy.*; 如本地的nginx按照上面的配置,重启nginx服务之后,通过浏览器进行访问,可以看到均可以访问到; 正则表达式配置 server_name 中可以使用正则表达式,并且使用 ~ 作为正则表达式字符串的开始标记 常见的正则表达式 代码 说明 ^ 匹配搜索字符串开始位置 $ 匹配搜索字符串结束位置 . 匹配除换行符 \n 之外的任何单个字符 \ 转义字符,将下一个字符标记为特殊字符 [xyz] 字符集,与任意一个指定字符匹配 [a-z] 字符范围,匹配指定范围内的任何字符 \w 与以下任意字符匹配 A-Z a-z 0-9 和下划线 , 等效于 [A-Za-z0- 9_] \d 数字字符匹配,等效于 [0-9] {n} 正好匹配 n 次 {n,} 至少匹配 n 次 {n,m} 匹配至少 n 次至多 m 次 * 零次或多次,等效于 {0,} + 一次或多次,等效于 {1,} ? 零次或一次,等效于 {0,1} 实际配置案例

Linux命令之日历cal

概述 cal 命令用于显示当前日历,或者指定日期的日历。 Windows系统查看日历直接点击日期即可。 语法 cal 命令的基本语法如下:cal [选项] [参数]。即: cal [options] [[[day] month] year] cal [options] <timestamp|monthname> 支持的选项有: 选项说明-1只显示单个月的日历,默认-3显示上个月、这个月和下个月的日历-s将星期日作为一个星期的第一天,默认-m将星期一作为一个星期的第一天-j显示在当年中是第几天-y显示当年所有月的日历-h显示帮助-V显示版本信息 如果只有一个参数,则表示年份;如果有两个参数,则表示月份和年份。 使用 显示当前月份日历 显示当前月份的日历,输入命令: cal 显示上月、本月和下月的日历 可以显示上个月、这个月及下个月的日历信息: cal -3 查看今年的日历 可以查看今年十二个月的日历: cal -y 日历按天数显示 可以查看日历本月日期是今年第几天: cal -j 以星期一作为一周的第一天 国内更习惯将周一作为一周的第一天,但日历中默认是将周日作为一周的第一天。所以如果要以周一作为一周的第一天,执行如下命令: cal -m 查看指定某年的日期 我们可以指定查看某一年的日历,例如查看 1999 年的日历,可以通过如下命令: cal 1999 # 或者 cal -y 1999 查看指定某年某月的日历 还可以查看指定具体某年某月日历,格式如下: # 语法 cal 月份 年份 # 示例 cal 3 2008 查看指定某年某月某日的日历 还可以具体到某年某月某日,即使用三个参数分别指定天数、月份和年份。语法如下: # 语法 cal 天数 月份 年份 # 示例,查看2022年5月13日的日历信息 cal 13 5 2022

C语言-验证哥德巴赫猜想

C语言算法-04-验证哥德巴赫猜想 1.解题思路2.C语言代码 1.解题思路 任意一个大于等于6 的偶数都可以分解为两个素数之和基本思想:n为大于等于6 的任一偶数, 可分解为n1 和 n2两个数,分别检查n1和n2是否为素数,如都是,则为一组解。 如n1不是素数,就不必再检查n2是否素数。先从n1=2开始, 检验n1 和 n2 (n2=n-n1)是否素数。然后使n1+1再检验n1、n2是否素数, …直到n1=n/2为止。 2.C语言代码 #include "stdio.h" #include "math.h" int main(){ // 初始化变量 int x, i; x = 8; int prime(int m); if (x < 6 || x % 2 != 0) printf("请输入大于6或大于6的偶数"); else for(i=2; i<= x/2; i++) { // 两个数都为素数则进入 if (prime(i) && prime(x-i)){ printf("%d+%d\n", i, x-i); printf("成功了\n"); break; } } } int prime(int m) { // 初始化变量 int i, k; // sqrt求数字的平方根 k = (int)sqrt(m); // 运算判断过程 for (i=2; i<=k; i++) if (m % i == 0) break; // 判断是否为素数 if (i > k) return 1; else return 0; }

Mockito PowerMock 的demo示例及踩坑记录

文章目录 1. Mockito 和 PowerMock是做什么的2. Mockito 和 PowerMock的实现原理是什么3. Mockito 和 PowerMock的区别4. 踩坑记录4.1 Mockito未返回预期值,实际执行返回null4.2 Mockito与PowerMock的版本对应关系4.3 PowerMock 静态方法、函数参数的模拟 5. demo示例5.1 github地址5.2 Mockito的模拟过程5.3 maven配置,jar引入5.4 项目结构图5.5 文件内容 参考资料 1. Mockito 和 PowerMock是做什么的 Mockito:单元测试框架,通过模拟进行单元测试。owerMock:Mockito和EasyMock的功能扩展框架。 2. Mockito 和 PowerMock的实现原理是什么 Mockito:通过代理(bytebuddy动态生成匿名子类)实现类功能的模拟。PowerMock:通过修改字节码实现类功能的模拟。 3. Mockito 和 PowerMock的区别 // mockito最开始使用的Cglib创建动态代理,后来使用bytebuddy。 实现原理的不同,PowerMock可以实现对static和final等方法的mock。 // 关于Mockito对static method、final class、final method、private method。 Mockito未支持,可以用PowerMock。 static method:还未支持。 private method:Mockito官方认为,从测试角度来来说,私有方法时不存在的,所以不关心对它的测试。 final class、final method:Mockito 2.1.0中增加了mocking final classes/methods的支持(PowerMock自PowerMock 1.7.0起增加了支持。PowerMock的GitHub上的文档建议Mockito 2.1.0之后的版本使用Mockito)。 4. 踩坑记录 4.1 Mockito未返回预期值,实际执行返回null 注意参数是否匹配,若是精确匹配,注意是equals比较(引用类型对象equals方法是否重写)。 若出现NullPointerException,必然是null.method() 。 一个午觉引发的写案之 Mockito.when返回null,非预期值

2021.07.31 --------基于时序InSAR的城市地表形变检测与分析-------SAR基础知识

2021.07.31 --------基于时序InSAR的城市地表形变检测与分析------- 可能会花费您10分钟的时间阅读以下内容 文章目录 一、SAR基础知识1.1 基本概念1.1.1 雷达基本概念1.1.2 波的基本概念 1.2 SAR相关参数SAR的相关参数:波长1.1.4 SAR的相关参数:极化1.1.5 SAR的相关参数:入射角 1.3 雷达的几何特征雷达的观测几何SAR图像几何分辨率SAR图像几何特征 1.4 SAR散射机制穿透散射对于SAR图像的理解 1.5 水面上的溢油1.6 SAR特性总结1.7 主要的机载雷达系统1.8 雷达的应用 一、SAR基础知识 1.1 基本概念 1.1.1 雷达基本概念 ​ Radar(Radio Detection And Ranging),雷达是主动微波遥感,与光学遥感相比,最大的区别就在于光学遥感不会主动发射电磁波;而雷达是一种主动微波遥感,通过雷达发射电磁波,然后接收散射的能量。影响雷达的三个重要因素为:RAR——真实孔径雷达、成像分辨率、雷达天线长度 ​ 因此一个Radar系统主要包括三个功能: 发射微波信号到场景接收从场景中传回的部分后向散射能量观测返回的强度(检测)和延时(测距)信号 雷达的分辨率是和雷达天线的长度相关的,在真实测距过程中,雷达的天线越长,成像分辨率也就越高。但是由于受到卫星和发射条件的限制,雷达天线的长度不可能被无限延长,因此我们想要得到高分辨率的雷达影像,通常会使用合成孔径雷达。 合成孔径雷达:是利用雷达与目标的相对运动把尺寸较小的真实天线孔径用数据处理的方法合成一较大的等效天线孔径的雷达,也称综合孔径雷达。利用这种方式,就能够在减小雷达体积的同时,获得高分辨率的雷达影像。 1.1.2 波的基本概念 波长 λ \lambda λ和频率 f f f的关系: λ = c / f \lambda=c/f λ=c/f振幅 A A A和强度 I I I的关系: I = A 2 I=A^2 I=A2,反映电磁波能量。相位( ρ \rho ρ):描述波的振动状态的物理量 Φ = 2 π L λ \Phi=2\pi \frac{L}{\lambda} Φ=2πλL​,其中 L L L为传播距离。极化:光学中叫偏振。 1.

安卓Android收银系统手机app源码在线演示实景分享

1,综述:安卓Android收银系统手机app源码版,部分在线实景页面介绍。 1.1,基于安卓8.0原生开发 1.2,完整源码,可独立部署 1.3,商家,店长,收银员,分权限使用 1.4,与桌面收银,自助机收银,网页端收银,pc管理后台,小程序收银,小程序商城完美打通 1.5,pc后端的几乎所有必要性功能都可以通过手机端完美实现。 1.6,自主研发,自主产权 2,安卓收银系统手机app-广告页 3,安卓收银系统手机app--注册登录页 可按照商家/店长/收银员,不同权限登录。 4,安卓收银系统手机app--首页 首页显示了今日关键数据指标的统计,以及常用功能的icon,常用功能可自定义。 6,安卓收银系统手机app--会员列表页 会员列表页显示会员头像/会员姓名/手机号/账户余额/积分余额/会员级别/会员类型等基础信息,可搜索。 7,安卓收银系统手机app--会员详情页 会员详情页显示会员的各类详情信息。可实时编辑。 8,安卓收银系统手机app--营业数据统计 9,安卓收银系统手机app-- 新增商品 10,安卓收银系统手机app--进销存单据详情 11,安卓收银系统手机app--常用功能的配置管理

RK3588 Android12 DMABUF内存泄漏问题分析

RK3588 Android12 DMABUF内存泄漏问题分析 什么是DMABUF DMABUF是多媒体设备之间共享内存的一种特定buffer结构,不同设备可以通过DMABUF的fd进行跨进程共享内存,实现零拷贝提高性能,支持异步访问降低模块耦合度。 问题描述 RK3588机器在线视频播放长时间拷机出现系统重启,log里面可以看到dma-buf内存分配失败,最后导致系统重启。 [05-15 04:55:46][64021.496139][ T6554] rk_vcodec: mpp_task_attach_fd:1696: can't import dma-buf 1 [05-15 04:55:46][64021.496144][ T6554] iep2_process_reg_fd:270: reg[044]: 00000401 failed [05-15 04:55:46][64021.496149][ T6554] rk_vcodec: mpp_process_task_default:602: alloc_task failed. [05-15 04:55:46][64021.496155][ T6554] rk_vcodec: mpp_wait_result_default:842: session 6553:531 pending list is empty! [05-15 04:55:46][64021.496160][ T6554] rk_vcodec: mpp_msgs_wait:1549: session 531 wait result ret -5 [05-15 04:55:46][64021.499857][ T6554] mpp_dma_import_fd:198: dma_buf_get fd 16 failed(-22) [05-15 04:55:46][64021.499870][ T6554] rk_vcodec: mpp_task_attach_fd:1696: can't import dma-buf 16 [05-15 04:55:46][64021.

Java Agent介绍及其使用

一、简介 Java Agent技术,也被称为Java代理、Java探针,它允许程序员利⽤其构建⼀个独⽴于应⽤程序的代理程序。 Java Agent 本质上就是一个 jar 包,对于普通的Jar包,通过指定类的 main 函数进行启动,但是 Java Agent 并不能单独启动,必须依附在一个 Java 应用程序运行。使用Java Agent可以实现在Java程序运行的过程中对其进行修改。 Java Agent的jar包主要包含两个部分:实现代码与配置文件。配置文件名为MANIFEST.MF,放在META - INF文件夹下,包含下列配置项: Manifest-Version: 版本号 Created-By: 创作者 Premain-Class :包含 premain 方法的类 Agent-Class :包含 agentmain 方法的类 Can-Redefine-Classes :true表示能重定义此代理所需的类,默认值为 false Can-Retransform-Classes :true 表示能重转换此代理所需的类,默认值为 false Java Agent的入口是premain或agentmain,具体选用哪一个以及其中的内容需要根据应用场景决定。 二、使用场景 Java Agent 技术有以下主要功能: 在加载java文件前拦截字节码并做修改在运行期间变更已加载的类的字节码 获取所有已经被加载过的类获取所有已经被初始化过了的类获取某个对象的大小 这些功能使得Java Agent在作为一个独立于Java应用程序的代理程序的同时,可以协助监测、运行甚至替换 JVM 上的程序。Agent的应用十分广泛,可用于实现Java IDE的调试功能、热部署功能、线上诊断⼯具和性能分析⼯具。例如,百度网络攻击防护工具OpenRASP中就使用了Java Agent来对敏感函数进行插桩,以此实现攻击检测。 三、使用方法 Java Agent分为两种:静态agent与动态agent,这两种方式的启动方法与运行机制是不同的。 1. 静态agent 这种方式是使用premain作为agent的入口方法,以vm参数的方式载入,在Java程序的 main 方法执行之前执行。要使用agent,需要在premain中实现我们想要的功能。agent技术使用JVMTI提供的接口来实现对应的功能,下面是一些官方的Instrumentation接口: void addTransformer(ClassFileTransformer transformer, boolean canRetransform) //注册ClassFileTransformer实例,注册多个会按照注册顺序进行调用。所有的类被加载完毕之后会调用ClassFileTransformer实例,相当于它们通过了redefineClasses方法进行重定义。布尔值参数canRetransform决定这里被重定义的类是否能够通过retransformClasses方法进行回滚。 void addTransformer(ClassFileTransformer transformer) //相当于addTransformer(transformer, false),也就是通过ClassFileTransformer实例重定义的类不能进行回滚。 boolean removeTransformer(ClassFileTransformer transformer) //移除(反注册)ClassFileTransformer实例。 void retransformClasses(Class<?

HTML中的表格和表单(含有示例代码)

表格 表格的基本构成标签 table 标签:表格标签 caption标签:表格标题 tr 标签:表格中的行 th 标签 : 表格的表头 td 标签:表格单元格 表格的基本结构 <table>定义表格 <caption>表格标题</caption> <tr>定义表行 <th>定义表头</th> </tr> <tr> <td>定义单元格</td> </tr> </table> table 表示表格 border="1" width="300" bgcolor="aqua" cellspacing="0"(单元格之间的间距) tr 表行 bgcolor="chartreuse" height="50" th 表头(单元格) 加粗 居中 width="80" td 单元格 colspan="4" 在同一行跨多列合并 从哪列开始,添加colspan,给定合并的列数rowspan="3" 跨多行合并 从哪个开始添加rowspan 给定合并的数量 简历代码示例: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <table border="1" cellspacing="0" align="center"> <caption><font size="20" color="black" ><h3 align="center">个人简历</h3></font></caption> <tr> <th width="100" height="40" bgcolor="

实验六、数据挖掘之关联分析

实验六、数据挖掘之关联分析 一、实验目的 1. 理解Apriori算法的基本原理 2. 理解FP增长算法的基本原理 3. 学会用python实现Apriori算法 4. 学会用python实现FP增长算法 二、实验工具 1. Anaconda 2. sklearn 3. Pandas 三、实验简介 Apriori算法在发现关联规则领域具有很大影响力。算法命名源于算法使用了频繁项集性质的先验(prior)知识。在具体实验时,Apriori算法将发现关联规则的过程分为两个步骤:第一步通过迭代,检索出事务数据库中的所有频繁项集,即支持度不低于用户设定的阈值的项集;第二步利用频繁项集构造出满足用户最小信任度的规则。其中,挖掘或识别出所有频繁项集是该算法的核心,占整个计算量的大部分。 在对深度优先数据挖掘算法的研究工作中,Han等人没有采用潜在频繁项集的方法求解频繁项集,而是提出了称为频率模式增长(FP_growth)的算法。该算法通过扫描数据库创建FP_tree的根节点并标示为null,对数据库D中的每一个事务Tran,按L中的次序对Tran中的频繁项排序,设Tran中排序后的频繁项列表[p|P],这里p是第一个元素,P是保留列表。接着调用函数insert_tree([p|P],T),如果树T有一个子节点N且N.item_name=p.item_name,就将N节点计数加1;否则就创建一个新节点N,设计数为1,它的父节点连接到T,节点连接到同名的节点连接结构上。如果P是非空的,就递归调用insert_tree(P,N)。由于压缩了数据库内容,并且在将频繁项写入FP_tree结构时,保留了项集间的相连信息。求解频繁项集的问题,就转化为递归地找出最短频繁模式并连接其后缀构成长频繁模式的问题。 四、实验内容 1. 利用python语言编写Apriori算法,挖掘出下表中数据集的频繁项集,最小支持度为30%。 # -*- coding: utf-8 -*- """ Created on Fri May 20 20:25:24 2022 @author: zhenkai """ def load_data_set(): data_set = [ ['a','b','d','e'], ['b', 'c', 'd'], ['a','b','d','e'], ['a','b','d','e'], ['a','b','d','e'], ['b', 'd', 'e'], ['c', 'd'], ['a', 'b', 'c'], ['a', 'd', 'e'], ['b', 'd'] ] return data_set ''' 参数:数据库事务集 ''' def Create_C1(data_set): C1 = set() for t in data_set: for item in t: item_set = frozenset([item]) # 为生成频繁项目集时扫描数据库时以提供issubset()功能 C1.