学习
算法红皮书 1.1.1-1.1.5
基础编程模型 #
Java程序的基本结构 #
- 本书学习算法的方法:用Java编程语言编写的程序来实现算法(相比用自然语言有很多优势)
- 劣势:编程语言特定,使算法的思想和实现细节变得困难(所以本书尽量使用大部分语言都必须的语法)
- 把描述和实现算法所用到的语言特性、软件库和操作系统特定总称为基础编程模型
- Java程序的基本结构
一段Java程序或者是一个静态方法库,或者定义了一个数据类型,需要用到的语法
- 原始数据类型(在计算机中精确地定义整数浮点数布尔值等)
- 语句(创建变量并赋值,控制运行流程或引发副作用来进行计算,包括声明、赋值、条件、循环、调用和返回)
- 数组(多个同种数据类型值的集合)
- 静态方法(封装并重用代码)
- 字符串(一连串的字符,内置一些对他们的操作)
- 标准输入/输出(是程序与外界联系的桥梁)
- 数据抽象(数据抽象封装和重用代码,可以定义非原始数据类型,进而面向对象编程)
把这种输入命令执行程序的环境称为 虚拟终端
要执行一条Java程序,需要先用javac命令编译,然后用java命令运行,比如下面的文件,需要使用命令
javac BinarySearch.java java BinarySearch
原始数据类型与表达式 #
- 数据类型就是一组数据和其所能进行的操作的集合
- Java中最基础的数据类型(整型int,双精度实数类型double,布尔值boolean,字符型char)
- Java程序控制用标识符命名的变量
- 对于原始类型,用标识符引用变量,+-*/指定操作,用字面量来表示值(如1或3.14),用表达式表示对值的操作( 表达式:(x+2.334)/2 )
- 只要能够指定值域和在此值域上的操作,就能定义一个数据类型(很像数学上函数的定义)
- +-*/是被重载过的
- 运算产生的数据的数据类型和参与运算的数据的数据类型是相同的(5/3=1,5.0/3.0=1.6667等)
- 如下图(图歪了亿点点..)
- 表达式
- 表达式具有优先级,Java使用的是中缀表达式(一个字面量紧接运算符,然后是另一个字面量)。逻辑运算中优先级 ! && || ,运算符中 * / % 高于+ - 。括号能改变这些规则。代码中尽量使用括号消除对优先级的依赖
- 类型转换
- 数值会自动提升为高级数据类型,如1+2.5 1会被先转为double 1.0,值也为double的3.5
- 强转(把类型名放在括号里讲其转换为括号中的类型) 讲高级数据类型转为低级可能会导致精度的缺失,尽量少使用
- 比较
- ==、!=、<、<=、>、>=,这些运算符称为 混合类型运算符,因为结果是布尔型而不是参与比较的数据类型
- 结果是布尔型的表达式称为布尔表达式
- 其他原始类型(int为32位,double为64位)
- long,64位整数
- short,16位整数
- char,16位字符
- byte,8位整数
- 32位单精度实数,float
语句 #
- 语句用来创建和操作变量、对变量赋值并控制操作的执行流程
- 包括声明语句、赋值语句、条件语句、循环语句、调用和返回语句
- 声明:让一个变量名和一个类型在编译时关联起来
- 赋值:将(由一个表达式定义的)某个数据类型额值和一个变量关联起来
- 条件语句:
if (<boolean expression>) { <block statement> }
- 循环语句
其中循环语句中的代码段称为循环体while(<boolean expression>) { <block statement> }
- break与continue语句
- break,立即退出循环
- continue,立即开始下一轮循环
简便记法 #
- 声明并初始化
- 隐式赋值
- ++i;–i
- i/=2;i+=1
- 单语句代码段(省略if/while代码段的花括号)
- for语句
这段代码等价于后面的for(<initialize>;<boolean expression>;<increment>) { <block statements> }
<initialize>; while(<boolean expression>) { <block statments> <increment>; }
- java语句总结
数组 #
- 数组能够存储相同类型的多个数据
- N个数组的数组编号为0至N-1;这种数组在Java中称为一维数组
- 创建并初始化数组
- 需要三个步骤,声明数组名字和类型,创建数组,初始化数组元素
- 声明并初始化一个数组
- 简化写法
double[] a = new double[N]; - 使用数组(访问的索引小于0或者大于N-1时会抛出ArrayIndexOutOfBoundsException)
- 典型的数组处理代码
- 起别名
- 下面的情况并没有将数组新复制一份,而是a,b指向了同一个数组
- 下面的情况并没有将数组新复制一份,而是a,b指向了同一个数组
- 二维数组
- Java中二维数组就是一堆数组的数组
- 二维数组可以是参差不齐,比如a[0]=new double[5],a[1]=new double[6]之类
- 二维数组的创建及初始化
double[][] a; a = new double[M][N]; for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) a[i][j] = 0.0;
- 精简后的代码 double[][] a=new double[M][N];
linux_韩老师_01-06
基础介绍 #
- 本套课程内容
- 基础篇: linux入门、vm和Linux的安装、linux目录结构
- 实操篇
- 远程登录(xshell,xftp)、实用指令、进程管理、用户管理
- vi和vim编辑器、定时任务调度、RPM和YUM
- 开机、重启和用户登录注销、磁盘分区及挂载、网络配置
- linux使用的地方
- 在linux下开发项目(需要把javaee项目部署到linux下运行)
- linux运维工程师(服务器规划、优化、监控等)
- linux嵌入式工程师(linux下驱动开发[c,c++])
- linux应用领域
- 个人桌面
- 服务器(免费稳定高效)
- 嵌入式领域(对软件裁剪,内核最小可达几百kb等)
linux介绍 #
- linux是一个开源免费操作系统
- linux吉祥物
tux(/tu’ks/唾可si),没找到音标,将就一下 - linux之父,linus,也是git的创作者
主要发行版:Ubuntu、RedHat,Centos,Debian等
RedHat和Centos使用同样的源码,但是RedHat收费 - Linux和Unix的关系
unix也是一个操作系统,贝尔实验室。做一个多用户分时操作系统, multics,但是没完成。其中一个后来在这基础上,完成的操作系统为unix (原本是B语言写的),后面和另一个人用unix用c语言改写了。
unix源码是公开的,后面商业公司拿来包装做成自己的系统, 后面有个人提倡自由时代用户应该对源码享有读写权利而非垄断
后面RichardStallman发起GNU计划(开源计划),Linus参加该计划,并共享出linux内核,于是大家在此基础上开发出各种软件。linux又称GNU/linux - Linux和Unix关系
VMWare安装Centos7.6 #
在windows中安装Linux系统
VM和Linux系统在pc中的关系
安装过程中,网络模式使用NAT模式
选择最小安装,且选择CompatibilityLibraries和DevelopmentTools
linux分区
一般分为三个
一般boot1G,swap分区一般跟内存大小一致,这里是2G,所以根分区就是剩下的,也就是20-1-2=17G
如图,boot,/,swap都是标准分区。且boot和/是ext4的文件格式,swap是swap的文件格式修改主机名
修改密码及增加除root外的普通用户
修改网络为固定ip(NAT模式下)
- 先在VM里面把子网ip改了,这里改成
192.168.200.0
- 然后改网关为192.168.200.200
- 使用yum install -y vim 安装文本编辑工具
- 最后在linux中改配置文件
vim /etc/sysconfig/network-scripts/ifcfg-ens33
- 其中先修改BOOTPROTO=“static”
- 然后设置ip地址、网关和DNS,
下面是添加到上面的ifcfg-ens33后面,不是直接执行代码
IPADDR=192.168.200.200 GATEWAY=192.168.200.2 DNS1=192.168.200.2
- 使用命令重启网络
service network restart # 或者直接重启电脑 reboot
- 先在VM里面把子网ip改了,这里改成
192.168.200.0
这里顺便装一下zsx
...
redis_尚硅谷_19-A
验证码模拟 #
- 首先需要一个MyRedis单例类
/**
* MyRedis单例类
*/
public class MyJedis {
private static Jedis myJedis;
public static Jedis getInstance() {
//如果是空则进行初始化
if (myJedis == null) {
//由于synchronized同步是在条件判断内,所以同步
//并不会一直都执行,增加了效率
synchronized (MyJedis.class) {
if (myJedis == null) {
//设置密码
DefaultJedisClientConfig.Builder builder = DefaultJedisClientConfig.builder()
.password("hello.lwm");
DefaultJedisClientConfig config = builder.build();
Jedis jedis = new redis.clients.jedis.Jedis("192.168.200.200", 6379, config);
return jedis;
}
}
}
return myJedis;
}
}
redis_尚硅谷_18
Jedis操作Redis6 #
- 插曲:本地项目关联github远程库
git init git add README.md git commit -m "first commit" #-m表示强制重命名 git branch -M main #使用别名 git remote add origin git@github.com:lwmfjc/jedis_demo.git #用了-u之后以后可以直接用git push替代整行 git push -u origin main
- jedis pom依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.0.1</version> </dependency>
- jedis使用
public class Main { public static void main(String[] args) { //设置密码 DefaultJedisClientConfig.Builder builder = DefaultJedisClientConfig.builder() .password("hello.lwm"); DefaultJedisClientConfig config = builder.build(); Jedis jedis = new Jedis("192.168.200.200", 6379, config); //ping String value = jedis.ping(); System.out.println(value); //返回所有key Set<String> keys = jedis.keys("*"); System.out.println("key count: " + keys.size()); for (String key : keys) { System.out.printf("key--:%s---value:%s\n", key, jedis.get(key)); } System.out.println("操作list"); //操作list jedis.lpush("ly-list", "java", "c++", "css"); List<String> lrange = jedis.lrange("ly-list", 0, -1); for (String v : lrange) { System.out.println("value:" + v); } //操作set System.out.println("操作set"); jedis.sadd("ly-set", "1", "3", "3", "5", "1"); Set<String> smembers = jedis.smembers("ly-set"); for (String v : smembers) { System.out.println("value:" + v); } //操作hash System.out.println("操作hash"); jedis.hset("ly-hash", "name", "lidian"); jedis.hset("ly-hash", "age", "30"); jedis.hset("ly-hash", "sex", "man"); Map<String, String> lyHash = jedis.hgetAll("ly-hash"); for (String key : lyHash.keySet()) { System.out.println(key + ":" + lyHash.get(key)); } //操作zset System.out.println("操作zset"); jedis.zadd("person", 100, "xiaohong"); jedis.zadd("person", 80, "xiaoli"); jedis.zadd("person", 90, "xiaochen"); List<String> person = jedis.zrange("person", 0, -1); for (String name : person) { System.out.println(name); } //结束操作 jedis.flushDB(); jedis.close(); } }
redis_尚硅谷_12-17
Redis配置文件 #
- redis中单位的设置,支持k,kb,m,mb,g,gb,且不区分大小写
- include (包含其他文件,比如公共部分)
- bind
bind 127.0.0.1 ::1 #listens on loopback IPv4 and IPv6
- 后面这个::1,相当于ipv6版的127.0.0.1。在redis配置文件中,整句表示只允许本地网卡的某个ip连接(但是它并不能指定某个主机连接到redis中。比如本机有两个网卡,两个ip,可以限定只有其中一个ip可以连接)
- 如果注释掉了/或者bind 0.0.0.0,表示允许所有主机连接
- protected-mode
protected-mode yes
- 设置保护模式为yes,protected是redis本身的一个安全层,这个安全层在同时满足下面三个条件的时候会开启,开启后只有本机可以访问redis
- protected-mode yes
- 没有bind指令(bind 0.0.0.0不属于这个条件)
- 没有设置密码 (没有设置requirepass password)
- 只要上面一个条件不满足,就不会开启保护模式。换言之,只要设置了bind 0.0.0.0或者没有设置bind,且不满足上面三个条件之一,就能够进行远程访问(当然,linux/windows的6379端口要开放)
- 设置保护模式为yes,protected是redis本身的一个安全层,这个安全层在同时满足下面三个条件的时候会开启,开启后只有本机可以访问redis
- tcp-backlog 表示未连接队列总和
- timeout 秒为单位,时间内没操作则断开连接
- tcp-keepalive 300 心跳检测,每隔300s检测连接是否存在
- pidfile /var/run/redis_6379.pid 将进程号保存到文件中
- loglevel 表示日志的级别/debug/verbose/notice/warning
- logfile "" 设置日志的路径
- database 16 默认有16个库
- requirepass password 设置密码
- maxclients 设置最大连接数
- maxmemory 设置最大内存量,达到则会根据移除策略进行移除操作
Redis的发布和订阅 #
- 发布订阅,pub/sub,是一种消息通信模式:发送者pub发送消息,订阅器sub接收消息
- 发布者能发布消息,订阅者可以订阅/接收消息
- 操作
subscribe channel1 #客户端A订阅频道
此时订阅channel1频道的客户端就会接收到消息publish channel1 helloly #向频道发送消息
redis新数据类型 #
Bitmaps #
进行二进制操作
...
redis_尚硅谷_06-11
Redis针对key的基本操作 #
- 常用命令
keys * #查找当前库所有库 exists key1 #key1是否存在 1存在;0不存在 type key2 #key2的类型 del key3 #删除key3 unlink key3 #删除key3(选择非阻塞删除。会先从元数据删除,而真正删除是异步删除) expire key1 10 #设置key1的过期时间,单位秒 ttl key1 #获取key1的剩余存活时间,-2表示key已过期或不存在,-1表示永不过期 select 1 #切换到1号库(redis中有15个库,默认在库1) dbsize #查找当前redis库中有多少个key flushdb #清空当前库 flushall #清空所有库
Redis中常用数据类型 #
字符串(String) #
- String是二进制安全的,可以包含jpg图片或序列化的对象
- 一个Redis中字符串value最多可以只能是512M
- 常用命令
set key1 value1 get key1 set key1 value11 #将覆盖上一个值 append key1 abc #在key1的值追加"abc" strlen key1 #key值的长度 setnx key1 value #当key不存在时才设置key incr n1 #将n1的值加一,,如果n1不存在则会创建key n1 并改为1(0+1) decr n1 #将n1的值减一,如果n1不存在则会创建key n1 并改为-1(0-1) incrby n1 20 #将n1的值加20,其他同上 decrby n1 20 #将n1的值减20,其他同上
- redis原子性
incr具有原子性操作
java中的i++不是原子操作 - 其他命令
mset k1 v1 k2 v2 mget k1 k2 msetnx k1 v1 k2 v2 #仅当所有的key都不存在时才会进行设置 getrange name 0 3 #截断字符串[0,3] setrange name 3 123 #从下标[3]开始替换字符串(换成123) setex k1 20 v1 #设置过期时间为20s expire k1 30 #设置过期时间为30s getset k1 123 #获取旧值,并设置一个新值
- 数据结构,SimpleDynamicString,SDS,简单动态字符串,内部结构类似Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配
列表 (List) #
- 单键多值
- 底层是双向链表
- 从左放
lpush k1 v1 v2 v3 #从左边放(从左往右推) lrange k1 0 -1 #从左边取(v3 v2 v1)
- lpush:
- 从右放
rpush k2 v1 v2 v3
- brpush:
- lpop/rpop
lpop k2 #从左边弹出一个值 lpop k2 2 #从左边弹出两个值,当键没有包含值时,键被删除
- rpoplpush
lpush a a1 a2 a3 rpush b b1 b2 b3 rpoplpush a b #此时a:a1 a2,b:a3 b1 b2 b3
- lrange
lrange b 1 2 #获取b中下标[1,2]的所有值 lrange b 1 -1 #获取所有值[1,最大下标]的所有值
- lindex,llen
lindex b 1 #直接取第一个下标的元素 llen b #获取列表的长度
- linsert
linsert b before b2 myinsert linsert b after b2 myinsert #在某个列表的值(如果重复取第一个)的位置之前/之后插入值
- lrem,lset
lrem b 2 a #从b列表中,删除两个a(从左往右) lset b 2 AA #把下标2的值设置为AA
- list数据结构是一个快速列表,quicklist
当元素较少的时候,会使用连续的内存存储,结构时ziplist,即压缩列表;当数据多的时候会有多个压缩列表,然后会链接到一起(使用双向指针)
集合(Set) #
- 特点:无序,不重复
- Set:string类型的无序集合,底层是一个value为null的hash表;添加/删除时间复杂度为O(1)
- 常用命令
sadd k1 v1 v2 v3 v2 v2 v1 #设置集合中的值 smembers k1 #取出集合中的值 sismember k1 v3 #k1是否存在v3,存在返回1,不存在返回0 scard k1 #返回集合中元素的个数 srem k1 v2 v3 #删除集合中的v2和v3 spop k1 #从k1中随机取出一个值 srandmember k1 2 #从k1中随机取出2个值
smove a k a1 #从a中将a1移动到k中 sinter a k #取a,k的交集 sunion a k #取a,k的并集 sdiff a k #返回两个集合的差集(从集合a中,去除存在集合k中的元素,即a-k)
- Set数据结构时dict字典,字典使用哈希表实现的
哈希(Hash) #
- 是String类型的field和value的映射表,用来存储对象,类似java中的Map<String,Object>
- 常用命令
hset user:1001 id 1 #设置(对象)user:1001的id属性值 hset user:1001 name zhangsan hget user:1001 name #取出user:1001的name hmset user:1001 id 1 name zhangsan #批量设置(现在hset也可以批量设置了,hmset已弃用) hexists user:1001 id 1 #判断属性id是否存在 hkeys user:1001 #查看hash结构中的所有filed hvals user:1001 #查看hash结构中所有value hincrby user:1001 age 2 #给hash结构的age属性值加2 hsetnx user:1001 age 10 #给hash结构的age属性设置值为10(如果age属性不存在)
- hash类型数据结构,当field-value长度较短时用的是ziplist,否则使用的是hashtable
有序集合(ZSet) #
- 与set很相似,但是是有序的
- 有序集合的所有元素(成员)都关联一个评分(score),score用来从最低到最高方式进行排序,成员唯一但评分是重复的
- 常用命令
zadd topn 100 xiaoming 120 xiaohong 60 xiaochen #添加key并为每个成员添加评分 zadd topn xiaoli 200 zrange topn 0 -1 #查找出所有成员(按排名由小到大) zrange topn 0 -1 withscores #从小到大查找所有成员并显示分数 zrangebyscore topn 130 200 #查找所有在130-200的成员 zrevrangebyscore topn 200 130 #从大到小查找所有成员(注意,从大到小时第一个值必须大于等于第二个) zincrby topn 15 xiaohong #给小红添加15分 zrem topn xiaohong #删除元素 zcount topn 10 200 #统计该集合,分数区间内的元素个数 zrank topn xiaohong #xiaohong的排名,从0开始
- zset底层数据结构
- hash结构
- 跳跃表 给元素value排序,根据score的范围获取元素列表
- 对比有序链表和跳跃表
- 查找51元素
- 跳跃表
按图中的顺序查找,查找四次就能找到
- 查找51元素
- hash结构
- End
redis_尚硅谷_01-05
课程简介 #
NoSQL数据库简介、Redis概述与安装、常用五大数据结构、配置文件详解、发布与订阅、Redis6新数据类型、Redis与spring boot整合、事务操作、持久化之RDB、持久化之AOF、主从复制及集群、Redis6应用问题(缓存穿透、击穿、雪崩以及分布式锁)、Redis6新增功能
NoSQL数据库简介 #
- Redis属于NoSQL数据库
- 技术分为三大类
- 解决功能性问题:Java、Jsp、RDBMS、Tomcat、Linux、JDBC、SVN
- 解决扩展性问题:Struts、Spring、SpringMVC、Hibernate、Mybatis
- 解决性能问题:NoSQL、Java线程、Nginx、MQ、ElasticSearch
- 缓存数据库的好处
- 完全在内存中,速度快,结构简单
- 作为缓存数据库:减少io的读操作
- NoSQL=Not Only SQL,不仅仅是SQL,泛指非泛型数据库
- 不支持ACID(但是NoSQL支持事务)
- 选超于SQL的性能
- NoSQL适用场景
- 对数据高并发的读写
- 海量数据的读写
- 对数据高可扩展性
- NoSQL不适用的场景
- 需要事务支持
- 基于sql的结构化查询存储
- 多种NoSQL数据库介绍
- Memcache 不支持持久化,数据类型单一,一般作为辅助持久化的数据库
- Redis 支持持久化,除了k-v模式还有其他多种数据结构,一般作为辅助持久化的数据库
- MongoDB,是文档型数据类型;k-v模型,但是对value提供了丰富的查询功能;支持二进制数据及大型对象;替代RDBMS,成为独立数据库
- 大数据时代(行式数据库、列式数据库)
- 行式数据库
查询某一块数据的时候效率高 - 列式数据库
查询某一列统计信息快 - 其他
Hbase,Cassandra,图关系数据库(比如社会关系,公共交通网等)
- 行式数据库
- 小计
NoSQL数据库是为提高性能而产生的非关系型数据库
Redis概述与安装 #
- 简单概述
- Redis是一个开源的kv存储系统
- 相比Mencached,支持存储的数据类型更多,包括string,list,set,zset以及hash,这些类型都支持(pop、add/remove及取交并集和差集等),操作都是原子性的
- Redis数据都是缓存在内存中
- Redis会周期性地把数据写入磁盘或修改操作写入追加的记录文件
- 能在此基础上实现master-slave(主从)同步
- Redis功能
- 配合关系型数据库做高速缓存
- Redis具有多样的数据结构存储持久化数据
- 其他部分功能
- Redis安装
- 从官网中下载redis-6.xx.tar.gz包(该教程在linux中使用redis6教学)
- 编译redis需要gcc环境
- 使用gcc –version查看服务器是否有gcc环境
- 如果没有需要进行安装
apt install -y gcc 或者 yum install -y gcc
- 将redis压缩文件进行解压
tar -zxvf redis-6xx.tar.gz
- 进入解压后的文件夹,并使用make命令进行编译
make
- 如果报错了,需要先用下面命令清理,之后再进行编译
make distclean
- 安装redis
make install
- 进入/usr/local/bin目录,查看目录
- Redis启动
- 前台启动
redis-server
- 后台启动
- 在刚才解压的文件夹中,拷贝出redis.conf文件(这里拷贝到/etc/目录下)
cp redis.conf /etc/redis.conf
- 到etc中修改redis.conf文件
将no改为yes并保存vim /etc/redis.conf # 进入编辑器后使用下面命令进行搜索并回车 /daemonize no
- 在刚才解压的文件夹中,拷贝出redis.conf文件(这里拷贝到/etc/目录下)
- 进入/usr/local/bin目录启动redis
redis-server /etc/redis.conf
- 查看进程,发现redis已经启动
ps -ef | grep redis
- 使用redis-cli 客户端连接redis
redis-cli keys *
- 前台启动
相关知识 #
- Redis6379的由来
- 人名Merz 在九宫格对应的数字就是6379
- 人名Merz 在九宫格对应的数字就是6379
- Redis默认有15个库,默认数据都在数据库0中,所有库的密码都是相同的
- Redis是单线程+多路复用技术
- Redis是串行操作
- 火车站的例子
当1,2,3没有票的时候,不用一直等待买票,可以继续做自己的事情,黄牛买到票就会通知123进行取票
- Redis是串行操作
- Memcached和Redis区别
- Memcached支持单一数据类型,Redis支持多数据类型
- Memcached不支持持久化
- Memcached用的多线程+锁的机制,Redis用的是单线程+多路复用程序