❉ 520情人节送女朋友的3D相册礼物~html+css+js实现抖音炫酷樱花3D相册(含音乐) 一年一度的/520情人节/七夕情人节/生日礼物/告白师妹/程序员表白,是不是要给女朋友或者正在追求的妹子一点小惊喜呢,今天这篇博客就分享下前端代码html+css+javascript 如何实现3D立体动态相册。赶紧学会了,来制作属于我们程序员的浪漫吧!
❉ 文章目录 ❉ 520情人节送女朋友的3D相册礼物~html+css+js实现抖音炫酷樱花3D相册(含音乐)❉ 前言❉ 3D相册演示(含背景音乐)可自定义12张相片1. PC(电脑端)演示 2. H5(手机端)演示 ❉ 代码文件目录一、3D相册(代码实现) html (3D相册部分)js (樱花飘落部分)css (3D相册部分) 二、3D相册裁剪(教程) 1.相片裁剪(教程)2.美图秀秀(电脑版)裁剪图片 三、歌曲mp3更换教程(教程)四、做好的网页效果,如何通过发链接给别人看?1.1 解决部署上线~> 部署上线工具(可永久免费使用)1.1部署流程1.2 哇~ 部署成功 五、前端 零基础 入门到高级 (视频+源码+开发软件+学习资料+面试题) 一整套 (教程) 六、❉ 源码获取 七、❉更多表白源码 ❉ 前言 520/七夕情人节表白[樱花飘落3D相册],程序员也可以很浪漫哦 ! 程序员向妹子表白专用代码!❤
HTML+css3+js 抖音很火的3d旋转相册-包含音乐,(送女友,表白,生日)动态生成效果,这样制作的~,现在,越来越多的人喜欢用视频记录生活,照片多的友友也会选择制作动态相册视频,不仅创意十足,同时还能展现自我风采, 撩妹神器哦!
❉ 3D相册演示(含背景音乐)可自定义12张相片 1.樱花雨3D相册-演示地址
2.文字开场白+浪漫樱花飘落-演示地址
3.萤火+樱花飘落3D相册-演示地址
1. PC(电脑端)演示 2. H5(手机端)演示 ❉ 代码文件目录 一、3D相册(代码实现) html (3D相册部分) <body> <!--音乐部分 --> <audio autoplay="autopaly"> <source src="renxi.mp3" type="audio/mp3" /> </audio> <div id="jsi-cherry-container" class="
Reduction in Cryptography me看了很多文章,但是还是有点不太明白,总之学习之前你要有一定的密码学基础以及要记住一句话:“原命题与逆否命题同真同假!”
归约 首先用词应该是归约(reduction),而不是规约。
归约通俗的讲,就是把一个密码方案的安全性建立在一个已知的困难问题上。我们假设存在PPT的敌手(adversary)可以以不可忽略(non-negligible)的优势(advantage)攻破此密码方案,那么通过归约(reduction),就可以同样以不可忽略的优势破解该困难问题。这与我们对该困难问题已知的困难性(hardness)相互矛盾(contradiction),所以不可能存在这样的敌手去攻破我们的密码方案,因此他是安全的。
1 从问题出发 假设现在我们提出了一个密码学方案或者协议 Π \Pi Π,我们需要证明它是安全的。怎么证明?
我们的协议一般是建立在已经被证明安全的协议/方案上面,或者建立在某些困难问题(记为Y)上面,比如RSA公钥加密算法就是建立在因数分解困难问题上。为了简化证明,站在巨人的肩膀上,我们希望通过搭建下面的逻辑命题关系来完成我们的证明。
条件命题1:只要Y是安全的,那么我们的方案 Π \Pi Π就是安全的。换句话说,若Y被有效攻破,那么 Π \Pi Π就不再安全。
这样做的好处是,我们站在了巨人的肩膀上:我们不需要从头开始证明,而是从Y开始。大大简化我们的证明过程。
密码学中的归约证明(reduction proof)是密码学非常重要的知识。现代密码学中的几大公钥加密算法建立在几个困难问题假设上面,比如大整数因数分解困难问题(Integer factorization)和离散对数问题(Discrete log problem)。很多现代密码协议或者密码加密方案建立在这些困难问题上面,比如RSA公钥加密算法就是建立在因数分解困难问题上,因此,如果某一天该困难问题能被快速计算出来(多项式时间复杂度),那么所有建立在这个假设上面的协议/方案都变得不安全了。
如何去证明呢? 根据离散数学的条件命题的逻辑等价式,若两个命题有如下关系: p → q p\rightarrow q p→q,等价于 ⇁ q → ⇀ p \rightharpoondown q\rightarrow \rightharpoonup p ⇁q→⇀p 。比如“只要晴天,我就去跑步”,等价于“如果我不去跑步,那么不是晴天”。这个命题等价式是“反证法”的基础。它被用在规约证明中证明某一个新提出的方案X的安全性(也即是下面的Thm),证明的形式为:
Thm(定理):Y 是安全的 → \rightarrow →X是安全的。
证明:
通过等价变换,也即是要证明(记为条件命题2):X不是安全的 → \rightarrow →Y不是安全的。
条件命题2进一步解释为:如果存在PPT的对手A可以攻破X,那么我们能构造一个PPT的敌手B来攻破Y。
其中,X是我们新提出的方案,Y某一个困难问题,PPT是多项式概率时间的英文缩写。“构造”一词可以理解为模拟。
如果我们能够让上面粗体的条件命题2成立,那么我们就完成了归约证明。这其实是一个反证法:若上面粗体的条件命题2成立,也意味着Thm成立,完成证明。
小结:现在我们明白了我们为什么要使用归约证明,以及使用归约证明的基本形式。接下来的问题是,如何来构造这个条件命题?
2 构造条件命题 我们将上面(B,Y)和(A,X)的关系表示成下图。其中A是试图攻破X的敌手;B是试图攻破Y的敌手。A作为B的一部分,B并不知道A是如何工作的。B是A的外部环境,它要模拟对A的输入和接收A的输出,让A完成对X的攻击游戏。密码学中经常使用Game的形式来定义一个协议的安全性。虽然A的外部环境是由B模拟的,但是,我们要求该模拟的环境等价于真实的A攻击X的game的环境(或者说A无法区分其外部环境是模拟的还是真实的)。因此,这里我们也叫B为模拟器。
除了B要完成上面的工作,它还需要应对别人(B的外部环境)对它的挑战:挑战B能否攻破Y。
结合下图,intuitively,在B接收到外部环境的挑战(chel)之后,将chel进行适当变换(图中红色部分,也即是进行模拟),将其输入给A,让A挑战X。B根据A的输出,适当地变换输出值,输出给外部环境,完成挑战。因此,B对Y的挑战转嫁到A对X的挑战上了。如果我们能够将下面条件关系关联起来,就完成了证明:A对X挑战成功->B对Y挑战成功,或者说 只要X不安全 -> 那么Y就不安全。
如何建模“挑战成功”?我们使用概率。在二选一的Game中,如果A成功的概率为1/2+non-neg(n),那么A就是成功的。neg(n)表示很小的值;而non-neg表示不是很小的值。同理,如果B要赢这个挑战Y的Game,其成功的概率也需要1/2+non-neg(n)。
当上传文件过大时,直接上传会增加服务器负载,负载过高会导致机器无法处理其他请求及操作,甚至导致宕机,这时分块上传是最佳选择。本次简单介绍两种分块上传文件方案(暂不考虑文件安全相关问题,如签名):
方案一: 客户端把单个文件切割成若干块,依次上传,最后由服务端合并
方案二: 客户端读取文件 offset 到 offset+chunk的文件块上传,每次上传完返回新的offset(或者每次上传后,本地保存最新的offset),客户端更新offset值并继续下一次上传,本文为了测试方便,最新的偏移量本地计算好即不通过接口返回最新偏移量
文件分块上传与断点下载相比,断点下载的进度保存在客户端(使用数据库保存),分块上传的进度保存在服务端并由服务端合并
效果图:
两种方案对比,方案二上传时间更短,因为方案一基于文件操作,方案二基于内存操作,所以方案二上传时间更短
方案一
客服端:
public void uploadTest1(View view) { countUploadSize = 0; clearDir(); totalSize = file.length(); //分割文件并组装数据上传,文件分割数量根据实际情况调整 List<File> cut = FileUtils.split(file.getAbsolutePath(), 10); int totalChunk = cut.size(); FileChunkReq[] items = new FileChunkReq[cut.size()]; for (int i = 0; i < cut.size(); i++) { FileChunkReq fileChunkReq = new FileChunkReq(); fileChunkReq.file = cut.get(i); fileChunkReq.fileName = file.getName(); fileChunkReq.fileSize = totalSize; fileChunkReq.chunkNum = i + 1; fileChunkReq.
Django 搭建博客网站 目录 Django 搭建博客网站前言一、软件和平台二、环境搭建步骤1.下载 U b u n t u Ubuntu Ubuntu2.在 v m w a r e vmware vmware 上安装 U b u n t u Ubuntu Ubuntu 三、在 v s c o d e vscode vscode 上配置 p y t h o n python python 环境1.连接 L i n u x Linux Linux 虚拟机2.在虚拟机上安装 p y t h o n python python 环境 四、安装宝塔面板1.安全设置2.安装必要的软件 总结 前言 搭建一个属于自己的博客平台,在上面发表文章不受其它平台的约束!
二叉查找树(BST) 二叉查找树(Binary Search Tree),也称二叉搜索树、有序二叉树(ordered binary tree),排序二叉树(orted binary tree),是指一棵空树或者具有下列性质的二叉树:
若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
任意节点的左、右子树也分别为二叉查找树;
没有键值相等的节点
二叉查找树在极端的情况下会退化成现线性的结构,降低查找效率
树的深度直接决定了最坏条件下的查找次数,也就是决定了查找的效率,因此降低树的深度很重要,所以引出了AVL树和红黑树
优点:有序
缺点:极端条件下会退化成链表,降低查找效率
平衡二叉树(AVL Tree) AVL 树是一种平衡二叉树,得名于其发明者的名字( Adelson-Velskii 以及 Landis),平衡二叉树全称平衡二叉搜索树,也叫AVL树。是一种自平衡的树。
平衡二叉树也是一种特殊的二叉查找树,满足二叉查找树的特性
AVL树也规定了左结点小于根节点,右结点大于根节点。并且还规定了左子树和右子树的高度差不得超过1。这样保证了它不会成为线性的链表。
AVL树的查找稳定,查找、插入、删除的时间复杂度都为O(logN)
但是由于要维持自身的平衡,所以进行插入和删除结点操作的时候,需要对结点进行频繁的旋转。
AVL树每一个节点只能存放一个元素,并且每个节点只有两个子节点。当进行查找时,就需要多次磁盘IO,(数据是存放在磁盘中的,每次查询是将磁盘中的一页数据加入内存,树的每一层节点存放在一页中,不同层数据存放在不同页。)这样如果需要多层查询就需要多次磁盘IO。为了解决AVL树的这个问题,就出现了B树。
优点:有序,解决了BST会退化成线性结构的问题
缺点:进行插入和删除结点操作的时候,需要对结点进行频繁的旋转
红黑树(R-B Tree) R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。
红黑树的特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
红黑树示意图如下:
红黑树在查找方面和AVL树操作几乎相同。但是在插入和删除操作上,AVL树每次插入删除会进行大量的平衡度计算,红黑树是牺牲了严格的高度平衡的优越条件为代价,它只要求部分地达到平衡要求,结合变色,降低了对旋转的要求,从而提高了性能。红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。
相比于BST,因为红黑树可以能确保树的最长路径不大于两倍的最短路径的长度,所以可以看出它的查找效果是有最低保证的。在最坏的情况下也可以保证O(logN)的,这是要好于二叉查找树的。因为二叉查找树最坏情况可以让查找达到O(N)。
红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高,在插入和删除中AVL树所做的后期维护操作肯定会比红黑树要耗时好多,但是他们的查找效率都是O(logN),所以红黑树应用还是高于AVL树的. 实际上插入 AVL 树和红黑树的速度取决于你所插入的数据.如果你的数据分布较好,则比较宜于采用 AVL树(例如随机产生系列数),但是如果你想处理比较杂乱的情况,则红黑树是比较快的。
红黑树广泛用于TreeMap、TreeSet,以及jdk1.8后的HashMap。
以上三种树都是基于二叉树
二叉树每一个节点只能存放一个元素,并且每个节点只有两个子节点。当进行查找时,就需要多次磁盘IO
在实际应用中,数据是存放在磁盘中的,每次查询是将磁盘中的一页数据加入内存,树的每一层节点存放在一页中,不同层数据存放在不同页。
这样如果需要多层查询就需要多次磁盘IO。为了解决这个问题,就出现了B树
B树(B-tree) B树不是二叉树,B树每一层存放了更多的节点,由AVL树的“瘦高”变成了“矮胖”。
B树属于多叉树又名平衡多路查找树(查找路径不只两个)
B树的阶数指的就是
该树每个节点最多有 m个子树,m为该树的阶数,
一个m阶的B树规定了:
根结点至少有两个子女。每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m,即k介于 m/2和m之间。每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m。所有的叶子结点都位于同一层。 5.
10. 批量插入 前言 上一章节,我们使用 PreparedStatement 操作了 BLOB 字段,下面我们再来看看批量插入的操作。
批量插入 1. 批量执行SQL语句 当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch():执行批量处理语句;
clearBatch(): 清空缓存的数据
通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理;
一个SQL语句的批量传参;
2. 高效的批量插入 举例:向数据表中插入20000条数据
数据库中提供一个goods表。创建如下:
CREATE TABLE goods( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) ); 测试插入数据
mysql> insert into goods(name) values('test'); Query OK, 1 row affected (0.00 sec) mysql> insert into goods(name) values('test1'); Query OK, 1 row affected (0.01 sec) mysql> select * from goods; +----+-------+ | id | NAME | +----+-------+ | 1 | test | | 2 | test1 | +----+-------+ 2 rows in set (0.
9. 操作BLOB类型字段 前言 在上一章节,我们使用PreparedStatement实现CRUD操作,那么在CRUD的操作中,对于一些特别的数据库字段操作,会有一些特别的处理。例如:BLOB类型的字段,常用来存储图片的二进制数据。
下面我们来看看如何操作 BLOB 类型字段。
操作BLOB类型字段 1. MySQL BLOB类型 MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)
1555581069798 实际使用中根据需要存入的数据大小定义不同的BLOB类型。
需要注意的是:如果存储的文件过大,数据库的性能会下降。
如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下的配置参数:max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。
2. 准备数据以及图片 准备访问 customer 的表,可以看到存在 photo 字段,如下:
image-20201021075450257 在项目中准备一个图片,准备下面操作:
image-20201021075535738 3. 向数据表中插入大数据类型 实现代码
//向数据表中插入大数据类型 @Test public void testInsert() throws Exception { //获取连接 Connection conn = JDBCUtils.getConnection(); String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)"; PreparedStatement ps = conn.prepareStatement(sql); // 填充占位符 ps.setString(1, "Jack"); ps.setString(2, "jack@126.com"); ps.setObject(3, new Date(new Date().getTime())); // 操作Blob类型的变量 FileInputStream fis = new FileInputStream("
# 怎样在网站上添加视频?
### 一、哪些地方可以添加在线视频?
只要有编辑器的地方就可以进行添加,如:产品详细页面,文章详细页面,首页简介模块,案例详细页面等。
### 二、什么是编辑器?在后台哪里可以看到?
编辑器是用来进行文本内容修改,排版的应用软件;在后台我们可以根据下图所示找到编辑器:

### 三、如何添加本地 MP4 格式视频

**直接上传[H.264编码的MP4](https://help.metinfo.cn/faq/395.html "H.264编码的MP4") 格式视频文件(注意:视频文件命名需要是数字或字母命名,不能含有中文命名)**;
3.1、首先需要联系空间商将空间MIME类型添加 MP4 格式,**如果视频文件大小超过2M**,则需要空间商将允许上传的最改为大于视频文件大小数字;
可参考教程:[如何设置服务器上传临时文件大小限制值](http://help.metinfo.cn/faq/shownews.php?lang=cn&id=323 "如何设置服务器上传临时文件大小限制值")
3.2、然后到网站后台-更多设置--安全与效率中修改文件类型里面添加mp4,在将文件上传最大值改为大于视频文件大小的数字;

3.3、打开网站后台编辑器,添加上传视频

3.4 如何给网站视频添加封面图片? [教程](http://help.metinfo.cn/faq/341.html "教程")
3.4 如何修改网站上的视频尺寸?[教程](https://help.metinfo.cn/faq/391.html "教程")
### 四、如何添加第三方视频

通过网络视频网站,如优酷,来上传在线视频,这个是一种不占空间大小且快速便捷的方法。接下来讲解一下此方法的操作步骤
4.1、首先注册帐号,在优酷注册一个帐号,有帐号的可以跳过这一步:http://www.youku.com/user_signup/
4.2、然后上传视频,登录优酷,上传视频,优酷提供的教程:http://www.youku.com/pub/youku/help/video.shtml
视频上传成功后,一般需要审核,等待审核成功后,打开视频的播放页面,在视频的底部,有个小三角箭头,点击展开:

4.3、粘贴代码到编辑器html代码中,**粘贴后,再点击html切换到正常编辑状态,点击保存才能生效**

### 五、如何通过FTP上传大视频文件
5.1 通过 [FTP工具 ](http://help.metinfo.cn/faq/273.html "FTP工具 ")把视频文件上传到站点根目录/upload/video目录下(视频文件不能是中文命名,如果不存在video文件夹可以右键创建一个目录);
5.2 插入视频网址:「 http://当前网站网址/upload/video/视频文件名称.mp4 」

题目描述: 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
输入描述: 测试输入包含若干测试用例。每个测试用例的第 1 1 1行给出两个正整数,分别是节点数 N N N ( 1 < N < 1000 1 < N < 1000 1<N<1000 )和边数 M M M;随后的 M M M行对应 M M M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从 1 1 1到 N N N编号)。当 N N N为 0 0 0时输入结束。
输出描述: 每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
示例: 输入1
3 3 1 2 1 3 2 3 输出1
1 输入2
3 2 1 2 2 3 输出2
0 源码: //确定无向图欧拉回路的充要条件:除孤立节点外,其它节点满足 //1.
文章目录 一、前期准备1. 启动后端2. 启动前台管理员端3. 启动前台学员端 二、用户添加2.1. 学生添加2.2. 管理员添加 三、题目管理3.1. 添加学科2.2. 单选题添加2.3. 多选题添加2.4. 判断题添加2.5. 填空题添加2.6. 简答题添加 四、试卷管理4.1. 固定试卷添加4.2. 时段试卷添加4.3. 任务试卷添加 五、任务管理5.1. 任务查询5.2. 任务添加 六、消息管理6.1. 消息查询6.2. 消息发送 七、学生端考试7.1. 固定考试7.2. 时段考试7.3. 任务考试 八、考试记录8.1. 查看试卷8.2. 错题本 一、前期准备 账号密码admin123456student123456 1. 启动后端 2. 启动前台管理员端 浏览器访问:
http://localhost:8002/
3. 启动前台学员端 浏览器访问:
http://localhost:8001/
二、用户添加 2.1. 学生添加 2.2. 管理员添加 三、题目管理 3.1. 添加学科 2.2. 单选题添加 2.3. 多选题添加 2.4. 判断题添加 2.5. 填空题添加 2.6. 简答题添加 四、试卷管理 4.1. 固定试卷添加 4.2. 时段试卷添加 4.3. 任务试卷添加 五、任务管理 声明:必须提前添加任务试卷,这里才可以创建任务
Android ROOM数据库 多表查询出现数据错乱或重复的问题修复-kotlin 前言说明解决Github完事 前言 关于多表查询,之前我写过一篇文章介绍,Android Room 数据库使用@Relation注解进行多表查询-Kotlin,是基于官方的描述来写的,一直没有机会在项目中使用,但是最近使用的时候才发现了它的问题,当关系表中增加一个标记,就会出现查询的数据不正确的问题;
说明 假设一个音乐类APP,首先有账户系统,也就是有个用户UserInfo的表,然后有歌单GroupInfo的表,歌曲SongInfo的表,有个歌单与歌曲的关系表
/** * 用户信息 * @Author: D10NG * @Time: 2021/6/3 3:28 下午 */ @Entity data class UserInfo( @PrimaryKey var userId: Long = 0, var name: String = "" ): Serializable /** * 歌单 * @Author: D10NG * @Time: 2021/6/3 3:32 下午 */ @Entity( primaryKeys = ["groupId", "userId"] ) data class GroupInfo( var groupId: Long = 0, var userId: Long = 0, var name: String = "
1、矩阵不仅表示多维数组,而且是表示图的重要工具。图的表示方法有邻接矩阵和邻接表。
2、对于不同的特殊矩阵应该采用不同的存储方式。
对称矩阵只需要存一半,三角矩阵也有自己的存储方式。
3、二维数组可以理解为一维的一维,一维数组是线性表,那么二维数组可以看成数据元素为线性表的线性表。
4、数组名代表的是数组的首地址,是一个地址常量,所以不能给数组名赋值。
char * strcpy(char * dest,const char * src) // c语言的方法,将src内容存放到dest中,
5、c语言宏定义后面不能有分号。
6、二维数组a[1……m,1……n] ,每个元素大小为2字节
列存储:a[i,j]的偏移量为
[(j-1)* m+(i-1)]*2
行存储:a[i,j]的偏移量为
[(i-1)*n+(j-1)]*2
注意:如果数组从零开始就不用减1了。
7、二叉树是按数的大小存储的,左小右大。随机数未经排序不能用二叉树存储。‘
随机数数据类型不一样,也不能用数组存储;
随机数不强调数据之间的关系,图不适合;
hash表离散存储,利用hash算法决定存储位置,遍历麻烦。
8、访问链表是链式存储结构时无法支持随机访问,要访问一个指定位置的元素必须从头开始做指针移动。
9、线性表有两种存储方式:顺序表,链式表。顺序表逻辑顺序和物理顺序一致。而链式表不是。
10、数组的长度是固定不变的,数组是线性表的一种。
而线性表有多种形式(顺序表,链式表),其长度可变。
11、队列、栈、链表、数组都是线性表。
关联数组是一种具有特殊索引方式的数组,不仅可以通过整数来索引它,还可以使用字符串或者其他类型的值(除了null)来索引它。
关联数组,又称映射(Map)、字典。是一种抽象的数据结构,它包含类似于(键、值)的有序对。 不是线性表。
关联数组和数组类似,由以名称作为键的字段和方法组成。它包含标量数据,可用索引值来单独选择这些数据,和数组不同的是,关联数组的索引值不是非负的的整数而是任意的标量,这些标量称为keys,可以在以后用于检索数组中的数值。
关联数组的元素没有特定的顺序,你可以把它们想象为一组卡片,每张卡片上半部分是索引而下半部分是数值。
12、二维数组定义:
int[2][3]={1,2,3,4,5,6},这种定义正确的,也就是二维数组也可以当做特殊的一维数组,可以用一维数组定义。
13、int(p)[4],()优先级最高先看小括号里的,首先p是一个指针,类型是int,后面的[4]表明这是一个指向一维整型数组的指针。
int *p[4],[]优先级高,首先p[4]是一个数组,类型是int *,也就是这是一个存放4个整型指针(指向整型数据的指针)的数组。
14、快速排序:关键节点前面的元素都比它小,后面的元素都比它大。
选择排序:从剩余元素后面找最小元素和当前元素交换;
插入排序:关键元素前面的元素已经排好序。
15、二分查找,注意下一轮查找的low或high,应该是min+1或者min-1,而不是min,千万别犯浑。还有并不是high和low等于那个寻找的值,而是min的值等于寻找的值
16、稀疏矩阵压缩的存储方法是:三元组,十字链表,行逻辑链接的顺序表。
三元组表示稀疏矩阵可大大节省空间,但是当涉及到矩阵运算时,要大量移动元素。
十字链表表示法可以避免大量移动元素。
17、二维数组和一维数组的区别在于,二维数组可以理解为一维的一维。在一维中 * 表示取数值,在二维中 * 表示取第几行的地址,**表示取值。
18、注意:并不是所有的数据结构都有搜索算法,栈就没有搜索操作。
19、将10阶对称矩阵压缩存储到一维数组中,数组长度最少为:
主对角线都存:10个;
剩下的90个只存一半45个;
共55个。
20、线性结构应满足:有且只有一个根结点与每个结点最多有一个前件,也最多有一个后件。
虽然只有一个根节点的数据结构不一定是线性结构,但是所有一个以上根节点的数据结构一定是非线性结构。
21、顺序存储:在一块连续的存储区域一个接着一个的存放数据。顺序存储方式把逻辑上相邻的节点存储在物理位置相邻的存储单元里,节点间逻辑关系由存储单元的相邻关系来体现。顺序存储方式也称为顺序存储结构,一般采用数组或结构数组来描述。
优点:
在结点等长时可以随机存取;
存储密度高节省存储空间;
用结点的物理次序反映结点之间的逻辑关系。
缺点:
1、如果反斜杠后面跟着八进制数字超过3个,只有前面3个数字与\构成转义序列。
\x1234,表示的是一个16进制数字,后面跟着的数字应该是4位,超过4位的处理和八进制一样。
2、用二进制来编码字符串“abcdabaa”,需要能够根据编码,解码回原来的字符串,至少需要()长的二进制字符串。
需要对abcd进行霍夫曼编码。根据权值建立霍夫曼数,得到最优编码,编码不唯一。
若:
a=1
b=01
c=000
d=111
则总位数为:1+2+3+3+1+2+1+1=13
3、对字符串进行全排列:
几种不同的方式?
首先整体按顺序排A,上下角标为字符串整体长度,但是可能有字母重复,一个字母重复将结果除以2,两个除以4,以此类推。
4、串中任意个连续的字符组成的子序列称为该串的子串。注意:这里的连续的连续的连续的
5、设有两个串S1和S2,求S2在S1中首次出现位置的运算称为求子串。
6、char s[8];s是个数组名,等价于数组的地址,不能用其直接赋值s=“good”。
7、空串:零个字符的串,它的长度为0;
空格串也称为空白串:由一个或者多个空格组成的串,它的长度为串中空格字符的个数。
8、串是字符的有限序列;‘
模式匹配是串的一种重要运算;
串既可以采用顺序存储,也可以采用链式存储。
9、MFC中的CString是类型安全的类。
\0后面的字符是八进制数。
10、非空子串的个数共有n(n+1)/2个,如果相同子串算一个,要减去多余的字符,比如:www.qq.com,需要减去2个w,1个q,1个.,1个ww
11、在字符串数组中char * s[i]
s+i表示指针数组的地址。
s[i]表示取数组的值;(和 *(s+i)一样吗?)
*s[i]表示这个元素内保存的地址
&s[i]相当于s+i,表示指针数组的地址
12、算next值:
字符串的前缀和后缀(这里的前缀是不包括最后一个字符的子串,后缀是不包含第一个字符的子串)
比如:“babab”,
首先第一位0,第二位1,这个是固定的。
第三位,字符串是“bab”,这个时候“bab”的前缀有b,ba;后缀有ab,b,可以看出前后缀相等的最长的字符串只有b,因为b的长度为1,所以这第三位的next值就是1;
到了第四位,字符串时“baba”,前缀是bab,ba,b,后缀是aba,ba,a,前后缀相等的最长字符串是ba,长度为2,因此第四位的next值是2;
第五位,字符串是“babab”,前缀是baba,bab,ba,b,后缀是abab,bab,ab,b,前后缀相等的最长字符串是bab,其长度为3,所以第四位的next值为3
综上,next值为01123
13、字符串是一种特殊的线性表;
字符串可以连续存储,也可以链式存储;
15、字符常量是用单引号括起来的一个字符。
13、Linux在给定文件中查找与设定条件相符字符串的命令为grep.
16、在霍夫曼树中,出现频率越高的节点越接近根,深度越小即编码值位数越短;出现频率越低的节点越远离根,深度越大即编码位数越长。
17、字符串是一种对象,是一种引用数据类型。
18、寻找子串首次出现的位置叫做字符串匹配。
19、当注明空串也是子串时,求子串数目n(n+1)/2,后记得加一才是总的子串数目。
20、strcpy(s1,s2)是把s2字符拷贝到s1这个字符串中,同时也把s2的‘\0’拷贝过去(字符串最后以‘\0’结束)其也占一个字符的位置,但是最后计算字符串长度用strlen()的话,不计算’\0’在内,因为其遇到’\0’停止。
在strcpy(s1,s2)函数,如果s1被覆盖之后,空间足够还保留自己的那部分。
7. 使用 preparedStatement 解决 SQL 注入问题 前言 在上一章节中,我们使用 statement 执行 sql 完成了用户登录的小案例,但是在这个案例中也发现了 SQL 注入的问题。
而 SQL 注入的问题主要就是在字符串拼接中,存在查询条件拼接了 ' or '' = ' 后,导致可以查询所有数据的情况。
那么为了解决这个问题,我们就需要固化查询语句的结构,不允许随意拼接字符串。那么下面我们来介绍使用 preparedStatement 解决 SQL 注入问题。
案例-登录中SQL注入问题解决 1.目标 能够完成PreparedStatement改造登录案例, 解决SQL注入问题
2. preparedStatement概述 预编译SQL语句对象, 是Statement对象的子接口。
特点:
性能要比Statement高
会把sql语句先编译,格式固定好,
sql语句中的参数会发生变化,过滤掉用户输入的关键字(eg: or)
3. preparedStatement 用法 3.1 通过connection对象创建
connection.prepareStatement(String sql) ;创建prepareStatement对象
sql表示预编译的sql语句,如果sql语句有参数通过?来占位
SELECT * FROM user WHERE username = ? AND password = ? 3.2 设置参数
prepareStatement.set类型(int i,Object obj);
参数1 i 指的就是问号的索引(指第几个问号,从1开始),
Vue 数据响应式原理 Vue2 中的数据响应式原理用的是观察者模式,下面用一张流程图来简单说明一下观察者模式的原理。
从流程图不难看出,观察者模式的核心就是 Dep 和 Watcher 这两个对象。Dep 负责收集依赖(这里的依赖实际就是 watcher),并在监听到数据变化的时候发送通知。发送通知的过程实际就是调用 watcher.update() 方法。从而更新视图内容。
下面我们来详细看看 Vue 具体是如何实现数据响应式的。
我将 Vue 实现数据响应式的过程分为三步:
创建响应式数据,也就是创建 Observer 对象(这里会创建 dep 对象)收集依赖和发送通知的过程创建依赖 Watcher 创建响应式数据 Dep 对象是收集依赖的容器。没有容器又如何能装下依赖,所以在 Vue 实例化的时候都会对数据进行初始化,如 props,data 等数据都是要进行响应式处理的。因此,首先我们要知道 Vue 如何将这些普通的数据转换为响应式属性。
首先我们要知道 Vue 内有那些数据是响应式的,这里重点分析 data 属性的初始化。vue 处理 data 属性是在 Vue 实例初始化函数 _init 中进行的
_init 方法定义的地方是在:src/core/instance/init
而初始化 data 的过程是在上图的 initState 方法中,该方法是负责初始化我们的一些状态成员
initState 方法定义在:`src/core/instance/state
标红的地方就是初始化 data 的函数。
初始化 data 的入口我们已经找到了,由于代码比较长,这里我按自己的理解来说说它是如何初始化 data 的。
这里我们假设 data 的值为
data: { name: 'vue', age: 3 } 基于这个data 的值看看,Vue 是如何处理的
我们在进行多条件筛选的时候总是会遇到这个问题:
#原代码 筛选时提示在切片上修改数据报错,并且返回一个空datafeame price_df9 = hou_df1[(hou_df1.计费重量 > 2) & (hou_df1.计费重量 <= 3.2) & (hou_df1['区域'] == '余杭东+临安区')] 我们只要在整个筛选的最后调用copy()方法就好了。
price_df9 = hou_df1[(hou_df1.计费重量 > 2) & (hou_df1.计费重量 <= 3.2) & (hou_df1['区域'] == '余杭东+临安区')].copy() 这样就不会有提示了,也能正常筛选到数据。
Retrofit 定义:它是一个基于Ok的网络请求框架。
优势:
1、使用更方便,
2、相对于Ok来说网络请求过程更加解耦,通过注解和动态代理的方式将请求体和请求过程分离。
3、并且还处理了Ok在使用过程中一些问题。回调结果的处理和对象映射(也就是实体类映射)的处理
4、通过提供的工厂方法工具实现实体类的映射,提供配置三方工厂的一些操作。
Retrofit使用注意:
1、注意注解的搭配使用,BaseUrl()必须以“/”结尾,注解:@GET,@POST等使用过程中注意事项
2、实体类映射时,如果字符串
Retrofit2.6之前和Retrofit2.6之后区别:
2.6之后支持了kotlin的协程
Retrofit注解:
@Query
用于拼接Url路径后面的查询参数,一个@Query相当于拼接一个参数,多个参数中间用,隔开。
@QueryMap
主要的效果等同于多个@Query参数拼接,参数以map的形式传入,以Map的键值对为参数传入,只用于GET请求(@Query, @QueryMap)
@Field 用法类似于@Query 但只用于POST请求
@FieldMap
和QueryMap用法一样以Map形式传入键值对拼接请求参数
只用于POST请求,必须添加@FormUrlEncoded要不然会报异常(@Field, @FieldMap)
@FormUrlEncoded
表示这个请求为表单请求,如果在使用POST请求时不添加这行会报异常
Java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding.
@Path
用于替换Url路径中的变量字符。可以使用在Url里添加{page} 然后在参数里@Path("page") 类型 参数名 声明这个page是一个拼接参数,注意使用@Path时,path对应的路径不能包含”/”,不然每个加到host Url后面的东西都会被省略掉
@Url
@Url是动态的Url请求数据的注解
@Multipart
标记这个请求用于文件传输,可以用@Part("字段名") Multipart.Part 参数名 来传入文件参数,也可以用 RequestBody来传文件
@Streaming
标记说明要把请求的返回数据转换为IO数据流 在文件下载时使用
@Headers/Header
@Headers传入多个头信息以{}来括住头信息 以,号隔开
@Header 传入单个头信息 以"键:值"的形式传入
Rxjava: 定义:Rxjava只是一个异步链式调用的库,不是网络请求!!!Rxjava是一种扩展的观察者模式,整个模式中有4个角色:
1.被观察者(Observable),用来产生事件。观察者(Observer),用来接收事件,并给出响应动作。订阅(Subscribe),用来连接被观察者和观察者。事件(Event),作为被观察者和观察者沟通的载体。
2.Rxjava的执行流程:被观察者(Observable)通过订阅(Subscribe)按顺序发送事件给观察者(Observer),观察者(Observer)按顺序接收事件和作出对应的响应。
3.Rxjava的基本实现:
1. 创建Observable,它决定什么时候触发事件以及触发怎样的事件。
2. 创建Observer,Observer,它决定事件触发的时候将有怎样的行为。还可以用Subscriber代替。
4. 案例-使用 Statement 完成 JDBC 增删改查 前言 在前面的章节中,我们已经懂得如何获取数据库连接 以及 单元测试,下面我们来使用 Statement 来实现 JDBC 的增删查改。
案例-增删改查练习 1.需求 使用JDBC完成增删改查练习
2.步骤 注册驱动
获得连接
创建执行sql语句对象
执行sql语句, 处理结果
释放资源
3.实现 3.1 准备提供操作的数据库表
首先准备提供操作的 testdb 数据库 以及 user 数据表,如下:
mysql> use testdb Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> mysql> show tables; +------------------+ | Tables_in_testdb | +------------------+ | t_user | | user | +------------------+ 2 rows in set (0.
关闭visual studio右键的在此处打开vs 这个右键菜单很麻烦,总是点错,网上的其他教程都是直接复制命令为reg文件执行,如果想恢复也无从说起,通过观察其他几个注册表设置我找到了一个方法来隐藏这个菜单
首选打开注册表,在地址栏定位到
计算机\HKEY_CLASSES_ROOT\Directory\Background\shell\AnyCode
然后在anycode文件夹上右键,新建DWORD
然后重命名新建的项为HideBasedOnVelocityId
内容为16位,639bc8
如图所示
此时右键就不会有vs的在此处打开了,如果需要恢复直接删除这个项就行了
关于注册表值的意义我也不清楚,我是在anycode同级的几个文件夹下发现的相同的项,比如下面的cmd文件夹,删除他们就会出现在右键菜单,不删除则没有,那么我推测它就是用来隐藏右键菜单的
uniapp 离线打包实战 最近在做app,需要离线打包,跟着官网弄了一上午,个人觉得官网的不够详细,所以写个博客记录一下
打开hbuild =>发行=>原生app本地打包=>安卓本地打包指南,
如上图,下载Android Studio,以及app离线sdk,这个安卓离线sdk一会我们会用到,下载的同时点击链接去申请appkey
登录开发者中心,账号就是登录hbulidx的账号
登录成功后,如果你发现你的应用里没有当前的项目,那么可能是你项目的appid不对,你可以点击下方这个文件,重新获取下
然后返回开发者中心刷新就能看到你的项目,接着
点击应用名称,在应用管理界面选择离线打包Key管理,根据需要选择对应平台,输入包名和SHA1,确认无误点击保存,即可获取到对应平台的App ,如下图
这里的Android 包名和iOS BundleId是你自己自定义的,SHA1证书需要我们自己生成,生成步骤可以按照官网说的
打开cmd步骤在桌面 Windows+R,输入cmd,回车即打开cmd命令行,打开以后输入‘d:’,回车,在输入第二行命令,然后执行依次执行上方的语句,证书密码和别名需要记住,后面还会需要
这里的口令就是你上面的密码,然后你就会看到你的SHA1密码,复制下来填入Android 证书签名SHA1,点击保存,你就会得到一个App Key,得到以后,我们先将应用生成app资源,点击发行=>原生app本地打包=>生成本地打包app资源,点击以后会生成unpackage,在unpackage=>resources下就是一个文件夹名为你的appId的文件夹,复制这个文件夹,打开你下载的Android 离线SDK,找到HBuilder-HelloUniApp这个项目(你可以先在Android Studio打包下这个项目看看)
将Android-SDK@3.1.13.80836_20210517\HBuilder-HelloUniApp\app\src\main\assets\apps这个路径下的文件夹替换成你刚刚复制的文件夹,然后用Android Studio 打开HBuilder-HelloUniApp这个项目,将刚才生成的test.keystore复制到app主目录下
然后在这填写你的appid,
打开AndroidManifest.xml
在最下方有
<meta-data android:name="dcloud_appkey" android:value="替换为自己申请的Appkey" /> 替换成你申请的Appkey
然后打开app目录下的build.gradle
修改signingConfigs 这里面的内容
这里的keyAlias就是这里的别名,keyPassword和storePassword就是秘钥库口令,storeFile file就是刚才复制到目录下的test.keystore的路径
在这里可以给你的apk换图片以及改app名字,
在这之后
应该就大功告成了,觉得有用的希望给个三连,你的鼓励是我分享最大的动力,也欢迎大家多沟通交流,共同进步,嘿嘿