这里写目录标题 一、基础知识1.1 堆基础知识1.2 优先队列 / C++priority_queue 一、基础知识 1.1 堆基础知识 堆一般指二叉堆,其实就是首先是个完全二叉树,然后父节点大于子节点或者父节点小于子节点(前者叫大顶堆,后者叫小顶堆);
堆排序是一种算法,把数据排序;
而优先队列是一种数据结构,是把数据和排序算法封装起来的一种数据结构,而其中的排序算法可以是堆排序(这也是最常用的)。
关于堆和堆排序:请去看B站视频
对于此视频注意一点:
一开始写的heapify函数是从顶部开始向下的,所以会出现最大数在最底下冒不上来的情况,但是up写的第二个build_heap函数包含了heapify并且是从底层开始的,所以能生成堆[微笑]。
其实就是up主说的:
我有提到过一个前提:对一个节点做heapify的时候,必须保证它的所有子树都已经是堆。
所以,在这个前提下,如果要做heapify的节点已经符合“父节点 子节点”的性质,那么这就已经是一个堆了;就没有必要往下走了。
另外,我们的build_heap函数是从最后一个不是叶节点的点开始往前做heapify操作的,所以最后是可以形成一个堆。
我的代码实现:
#include <iostream> #include <algorithm> using namespace std; //heapify()函数,其前提是:对一个节点做heapify的时候,必须保证它的所有子树都 已经 是堆。 void heapify(int tree[],int n,int i){ if(i >= n){ return; } int c1 = 2 * i + 1; int c2 = 2 * i + 2; int max = i; if(c1 < n && tree[c1] > tree[max]){ max = c1; } if(c2 < n && tree[c2] > tree[max]){ max = c2; } if(max !
此时我们在xterm下运行qemu虚拟机,命令行如下:
$ qemu -s -S -hda ~/linux-0.2.img -kernel /home/xxx/linux-2.6.28-obj/arch/x86/boot/bzImage -append root=/dev/hda
我解释一下这个命令行上的参数。
-s 选项表示我们运行虚拟机时将1234端口开启成调试端口,供eclipse网络调试时使用
-S 选项表示我们启动虚拟机时要“冻住”虚拟机,等待调试器发出继续运行的命令。
-hda ~/linux-0.2.img 表示我们要运行时的硬盘 (这个文件可以在http://wiki.qemu.org/Download下到)
-kernel /home/xxx/linux-2.6.28-obj/arch/x86/boot/bzImage 表示我们要调试的内核镜像
-append root=/dev/hda 表示我们要传递给内核的参数(这里你可能感觉有点奇怪为啥是/dev/hda而不是/dev/hda1或是/dev/hda2呢?因为这个镜像仅仅是一个分区的二进制镜像,不是整个硬盘的镜像)
启动后,你会看到屏幕黑黑的啥也没有。因为我们指定了-S参数把虚拟机给“冻”住了。
继续回到eclipse中,这时候我们在菜单中选择Run -> Debug Configurations ,这时候打开一个配置页面。然后我们在C/C++ Application上双击鼠标,这时在右侧的页面弹出了debug配置选项,然后我们在project一栏选择 linux-kernel ,在下面的C/C++ Application中填入/home/xxx/linux-2.6.28-obj/vmlinux,如下图所示:
然后我们单击Debugger选项页,将Debugger改为 GdbServer Debugger . 将Stop on startup at 改为start_kernel,将Connection子选项页下的Type改为TCP将Port number改为1234,最终如下图所示:
然后单击Debug按钮开始调试!这时候Eclipse会提示我们切换 Perspective ,选择是,不再提示。
这时候就开始调试内核,而且是源码级的调试!如下图:
后面的啥查看寄存器,查看变量,都不用我多说了吧。享受调试内核的乐趣吧!
import 'dart:math'; import 'package:flutter/material.dart'; class UiTabBar extends StatefulWidget { UiTabBar({ Key? key, this.width, this.height, this.padding = const EdgeInsets.symmetric(horizontal: 8), this.direction = Axis.horizontal, this.physics = const BouncingScrollPhysics(), this.style, this.unselectedStyle, required this.tabs, required this.currentIndex, }) : super(key: key); final List<UiTab> tabs; final Axis? direction; final double? height; final double? width; final EdgeInsets? padding; final TextStyle? style; final TextStyle? unselectedStyle; final ScrollPhysics physics; final int currentIndex; @override _UiTabBarState createState() => _UiTabBarState(); } class _UiTabBarState extends State<UiTabBar> with TickerProviderStateMixin { ScrollController _scroll = ScrollController(); late AnimationController _animation; late Point _size; @override void initState() { super.
Flutter沉浸式状态栏 void main() { if (Platform.isAndroid) { // 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后,是为了在渲染后进行set赋值,覆盖状态栏,写在渲染之前MaterialApp组件会覆盖掉这个值。 SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent); SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); } } Flutter修改状态栏字体颜色 使用AnnotatedRegion包裹Scaffold,可以使得状态栏颜色改变,有dark和light两种
// An highlighted block @override Widget build(BuildContext context) { return AnnotatedRegion<SystemUiOverlayStyle>( value: SystemUiOverlayStyle.light, child: Material(child:Scaffold(),),); }
题目描述:
KiKi和BoBo玩 “井”字棋。也就是在九宫格中,只要任意行、列,或者任意对角线上面出现三个连续相同的棋子,就能获胜。请根据棋盘状态,判断当前输赢。
输入描述:
三行三列的字符元素,代表棋盘状态,字符元素用空格分开,代表当前棋盘,其中元素为K代表KiKi玩家的棋子,为O表示没有棋子,为B代表BoBo玩家的棋子。
输出描述:
如果KiKi获胜,输出“KiKi wins!”;
如果BoBo获胜,输出“BoBo wins!”;
如果没有获胜,输出“No winner!”。
示例1
输入:
K O B
O K B
B O K
输出:
KiKi wins!
import java.util.Scanner; public class HelloWorld { public static void main(String[] args) { Scanner in=new Scanner(System.in); //读入井字棋 String [][] tic = new String [3][3]; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ tic[i][j]=in.next(); } } boolean kwin=kikiwin(tic); boolean bwin=bobowin(tic); if(kwin==true){ System.out.println("KiKi wins!"); } else if (bwin==true){ System.out.println("BoBo wins!"); } else if(kwin==true && bwin==true){ System.
版本 Ubuntu 20.04 LTS
Bochs 2.6.10
异常 bochs: symbol lookup error: /usr/local/lib/bochs/plugins/libbx_x.so: undefined symbol: XOpenDisplay异常
原因 在新版本中,配置文件.bochsrc中display_library项用sdl代替x,所以需要重新配置bochs。
解决方案 apt-get install libsdl-dev编译./configure时加上 --with-sdl然后重新make和make install在.bochsrc中修改 display_library: sdl如果sdl不行, 可以尝试libsdl2-dev,然后相应的把sdl改成sdl2
linux通过grep根据关键字查找日志文件上下文
1、在标准unix/linux下的grep命令中,通过以下参数控制上下文的显示:
grep -C 10 keyword catalina.out 显示file文件中匹配keyword字串那行以及上下10行
grep -B 10 keyword catalina.out 显示keyword及前10行
grep -A 10 keyword catalina.out 显示keyword及后10行
2、查找的结果比较大时,为了方便定位问题,也可以重定向到文件中,比如:
grep -C 10 keyword catalina.out > aaa.txt
3、统计包含某个关键字的个数
grep -o keyword catalina.out| wc -l
4、如果一行最多一个关键字,可以简写为:
grep -c keyword catalina.out
5、查看grep版本的方法是
grep -V
Grep命令详细说明:
Usage: grep [OPTION]... PATTERN [FILE]...
Search for PATTERN in each FILE or standard input.
PATTERN is, by default, a basic regular expression (BRE).
Example: grep -i 'hello world' menu.
37.1 线程清理和控制函数
#include void pthread_cleanup_push(void (* rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);
函数参数
rtn:清理函数指针
arg:调用清理函数传递的参数
execute:值 1 时,执行线程清理函数;值 0 时,不执行线程清理函数
返回值
成功,返回 0;否则,返回错误编号
触发线程调用清理函数的工作
调用 pthread_exit
响应取消请求
用非零 execute 参数调用 thread_cleanup_pop 时
#include #include #include /** 定义线程清理函数 */
void clean_fun(void *arg)
{
char *s = (char *)arg;
printf("clean_fun: %s\n", s);
}
void *th_fun(void *arg)
{
int execute = (int )arg;
pthread_cleanup_push(clean_fun, "first clean func");
pthread_cleanup_push(clean_fun, "second clean func");
题目描述:
KiKi知道什么叫杨辉三角之后对杨辉三角产生了浓厚的兴趣,他想知道杨辉三角的前n行,请编程帮他解答。杨辉三角,本质上是二项式(a+b)的n次方展开后各项的系数排成的三角形。其性质包括:每行的端点数为1, 一个数也为1;每个数等于它左上方和上方的两数之和。
输入描述:
第一行包含一个整数数n。 (1≤n≤30)
输出描述:
包含n行,为杨辉三角的前n行,每个数输出域宽为5。
示例1
输入:
6
输出:
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 import java.util.Scanner; public class HelloWorld { public static void main(String[] args) { Scanner in=new Scanner(System.in); int n=in.nextInt(); int [][] triangle=new int [n][n]; for(int i=0;i<n;i++){ for(int j=0;j<i+1;j++){ //第一个数和最后一个数都为1 if(j==0 || j==i){ triangle[i][j]=1; } else{ triangle[i][j]=triangle[i-1][j]+triangle[i-1][j-1]; } //设置域宽为5 System.
在Linux中使用配置文件时,有时需要将诸如配置参数之类的文本附加到现有文件。
在这篇文章中,你将学习在Linux中将文本追加到文件结尾的不同方法。
使用> >运算符追加文本
>>运算符将输出重定向到文件,如果文件不存在,则创建该文件,但如果存在,则输出将追加到文件末尾。
例如,您可以使用echo命令将文本附加到文件的末尾,如图所示。# echo"/mnt/pg_master/wal_archives 10.20.20.5(rw,sync,no_root_squash)" >> /etc/exports
或者,你可以使用printf命令(不要忘记使用n字符来添加下一行)。# printf"/mnt/pg_master/wal_archives 10.20.20.5(rw,sync,no_root_squash)n" >> /etc/exports
也可以使用cat命令连接一个或多个文件中的文本,并将它附加到另一个文件。
在以下示例中,/etc/exports配置文件中的共享被添加到名为shares.txt的文本文件中。# cat /etc/exports
# cat shares.txt
# cat shares.txt >> /etc/exports
# cat /etc/exports
将文件附加到/etc/exports
此外,你还可以使用以下文档将配置文本附加到文件的末尾,如下所示。# cat /etc/exports
# cat >>/etc/exports
> /backups 10.20.20.0/24(rw,sync)
> /mnt/nfs_all 10.20.20.5(rw,sync)
> EOF
# cat /etc/exports
注意:不要为>重定向操作符错误>>;使用>将删除文件的内容,然后覆盖它,这可能导致数据丢失。
使用tee命令附加文本
tee命令从标准输入复制文本,并将它粘贴/写入标准输出和文件,可以使用它-a标志将文本追加到文件的末尾,如下所示。# echo"/mnt/pg_master/wal_archives 10.20.20.5(rw,sync,no_root_squash)" | tee -a /etc/exports
OR
# cat shares.txt | tee -a /etc/exports
使用Tee命令附加文本
还可以通过tee命令使用here文档。# cat <
您可以使用mmap(2)系统调用将设备文件映射到用户进程内存。通常,设备文件是物理内存到文件系统的映射。
否则,您必须编写一个内核模块来创建这样的文件,或者提供一种将所需内存映射到用户进程的方法。
另一种方法是将/ dev / mem的部分重新映射到用户存储器。
编辑:
mmaping / dev / mem的示例(此程序必须能够访问/ dev / mem,例如具有root权限):
#include #include #include #include #include int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s \n", argv[0]);
return 0;
}
off_t offset = strtoul(argv[1], NULL, 0);
size_t len = strtoul(argv[2], NULL, 0);
// Truncate offset to a multiple of the page size, or mmap will fail.
size_t pagesize = sysconf(_SC_PAGE_SIZE);
off_t page_base = (offset / pagesize) * pagesize;
拉莫斯之舞
您可以使用mmap(2)系统调用将设备文件映射到用户进程内存。通常,设备文件是物理内存到文件系统的映射。否则,您必须编写一个内核模块来创建此类文件或提供一种将所需内存映射到用户进程的方法。另一种方法是将/ dev / mem的部分重新映射到用户内存。编辑:mmaping / dev / mem的示例(此程序必须有权访问/ dev / mem,例如具有root权限):#include #include #include #include #include int main(int argc, char *argv[]) { if (argc < 3) { printf("Usage: %s \n", argv[0]); return 0; } off_t offset = strtoul(argv[1], NULL, 0); size_t len = strtoul(argv[2], NULL, 0); // Truncate offset to a multiple of the page size, or mmap will fail. size_t pagesize = sysconf(_SC_PAGE_SIZE); off_t page_base = (offset / pagesize) * pagesize; off_t page_offset = offset - page_base; int fd = open("
busybox devmem
busybox devmem是mmaps的小型CLI实用程序/dev/mem。
您可以通过以下方式在Ubuntu中获取它: sudo apt-get install busybox
用法:从物理地址读取4个字节0x12345678:
sudo busybox devmem 0x12345678
写入0x9abcdef0该地址:
sudo busybox devmem 0x12345678 w 0x9abcdef0
来源:https : //github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85
mmap MAP_SHARED
映射时/dev/mem,您可能要使用:
open("/dev/mem", O_RDWR | O_SYNC);
mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)
MAP_SHARED 使写操作立即进入物理内存,这使观察起来更容易,并且对硬件寄存器写操作更有意义。
CONFIG_STRICT_DEVMEM 和 nopat
要/dev/mem查看和修改内核v4.9上的常规RAM,必须首先:
禁用CONFIG_STRICT_DEVMEM(在Ubuntu 17.04上默认设置)
传递nopatx86 的内核命令行选项
没有这些端口,IO端口仍然可以工作。
另请参见:/ dev / mem的mmap失败,且virt_to_phys地址的参数无效,但是地址是页面对齐的
缓存刷新
如果您尝试写入RAM而不是寄存器,则CPU可能会缓存内存:如何在Linux中刷新CPU缓存以获取地址空间区域?而且我看不到一种非常方便/简便的方法来刷新它或将该区域标记为不可缓存:
如何使用O_DIRECT将内核空间内存(物理地址)写入文件?
如何在Linux中刷新地址空间区域的CPU缓存?
是否可以在用户空间上在Linux上分配不可缓存的内存块?
因此,也许/dev/mem不能可靠地用于将内存缓冲区传递给设备吗?
不幸的是,这在QEMU中无法观察到,因为QEMU不模拟缓存。
如何测试
现在是有趣的部分。以下是一些不错的设置:
用户区内存
volatile在用户态进程上分配变量
使用/proc//maps+ 获取物理地址/proc//pagemap
使用修改物理地址上的值devmem,并观察用户态过程的反应
内核内存
用以下方式分配内核内存 kmalloc
Spring新版本aop失效的探究 1.背景2.探究3.解决 1.背景 把spring从4.0升级到4.3.29后,自定义一个注解,至于方法上,切面中定义的规则是注解代理,升级后工程运行不走代理方法而是走注解下的方法。
2.探究 Spring开启注解的配置是通过AnnotationConfigWebApplicationContext,向该context中添加一个configuration,该configuration需要有@EnableAspectJAutoProxy注解,并且如果不用@ComponentScan,则默认扫描同一个包下的切面。在切面中需要声明被代理的bean,否则也不生效。查看工程,有对应的configuration,且也添加进了AnnotationConfigWebApplicationContext,该configuration中的注解和bean的声明也都有,结果还是不走代理方法。
3.解决 后来在context初始化的代码中发现在调用context的register方法注册configuration的方法是在refresh方法之后调用的,新版本的refresh方法会初始化aop容器,register方法放在refresh方法之后,初始化的aop就用不上register的configuration了,所以切面代理没生效。
题目描述:
KiKi有一个矩阵,他想知道经过k次行变换或列变换后得到的矩阵。请编程帮他解答。
输入描述:
第一行包含两个整数n和m,表示一个矩阵包含n行m列,用空格分隔。 (1≤n≤10,1≤m≤10)
从2到n+1行,每行输入m个整数(范围-231~231-1),用空格分隔,共输入n*m个数,表示第一个矩阵中的元素。
接下来一行输入k,表示要执行k次操作(1≤k≤5)。接下来有k行,每行包括一个字符t和两个数a和b,中间用空格格分隔,t代表需要执行的操作,当t为字符’r’时代表进行行变换,当t为字符’c’时代表进行列变换,a和b为需要互换的行或列(1≤a≤b≤n≤10,1≤a≤b≤m≤10)。
输出描述:
输出n行m列,为矩阵交换后的结果。每个数后面有一个空格。
示例1
输入:
2 2
1 2
3 4
1
r 1 2
输出:
3 4
1 2
import java.util.Scanner; public class HelloWorld { public static void main(String[] args) { Scanner in = new Scanner(System.in); //输入原始二维矩阵 int n = in.nextInt(); int m = in.nextInt(); int[][] rec = new int[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { rec[i][j] = in.
一、数据库级及SQL语言简介
1、目前主流数据库
微软:sql server、access
瑞典:mysql
ibm: db2
sybase:sybase
ibm: informix
oracle: oracle
2、SQL语言
DQL-------------数据查询语言
select … From … Where
DML-------------数据操纵语言
insert、update、delete
DDL-------------数据定义语言
create、alter、drop
DCL-------------数据控制语言
commit、rollback、savepoint
二、基本Sql语句
1、表设计 创建表:
create table 表名 (字段 字段类型); 复制表结构及数据:
create table 新表 as select * from 旧表 复制表结构不需要数据:
create table 新表 as select * from 旧表 where 2<>2 查看表结构:desc 表名.
复制表数据:
insert into 目标表 select * from 参考表 伪表:系统中保留的虚拟表,不能更改,也不能删除。
名称:dual 通过伪表显示当前系统时间:select sysdate from dual; 查看指定用户下所有的表
misfire阈值 1.背景2.misfire阈值2.1misfireThreshold2.2作为nextFireTime的下界生效2.3作为nextFireTime的上界生效 3.总结 1.背景 在使用quartz时有时候会发现任务并不是准时执行的,而是有一些延迟,但是为什么不算是misfire呢
2.misfire阈值 在Quartz执行逻辑(六)misfire的处理中说了Misfire的处理是由JobStoreSupport中的一个线程MisfireHandler来处理的,此外在JobStoreSupport中还有一个字段misfireThreshold,它表示misfire的阈值,任务的执行的延迟时间不大于这个值都不算misfire。
2.1misfireThreshold 该字段在getMisfireTime方法中被使用:
可以看到在计算misfireTime的时候使用当前时间减去misfireThreshold的值,也就是延迟在这个阈值范围内的都不算misfire。那么这个getMisFireTime方法在哪被使用呢?怎么发挥作用的呢?
2.2作为nextFireTime的下界生效 在acquireNextTrigger方法中有调用:
可以看到在执行数据库查询操作的时候第三个参数传递的是getMisfireTime的返回值,这个参数代表的是noEarilerThan,映射到sql语句中就是nextFireTime要大于等于它的,小于等于前面的noLaterThan+timeWindow。结合前面说的执行时间延迟misfireThreshold范围内的都不算misfire,所以getMisfireTime的返回值应该作为下界,上届是noLaterThan+timeWindow。noLaterThan默认是当前时间加30s,timeWindow的值是三个值中最小的一个。具体逻辑在QuartzSchedulerThread中,可以参考Quartz执行逻辑(一)QuartzSchedulerThread介绍,quartz执行流程简介。
2.3作为nextFireTime的上界生效 那么上界是如何保证的呢,getMisfireTime方法在另外一个方法recoverMisfiredJobs中也有调用:
这个getMisfireTime方法返回值参数映射到要执行的sql语句中就是nextFireTime小于getMisfireTime方法的返回值。这也不难理解,如果nextTime小于了这个当前时间减去misfireThreshold的值,说明以当前为基准,misfireThreshold这么长时间之前该任务就该触发了,如果现在让它触发,那么该任务的触发延迟时间就大于了misfireThreshold的值了,是不合理的。至此misfireThreshold对于上下界的生效过程就说完了。关于misfire的处理可以参考Quartz执行逻辑(六)misfire的处理
3.总结 misfireThreshold值的生效有两个方面,一个是在获取下次要触发的触发器的时候,这时作为nextFireTime的下界生效。另一方面在判断任务是否misfire,此时作为nextFireTime的上界生效。
mysql数据库建表失败 一开始COLUMN_TRIGGER字段的值为trigger,用hibernate建表,数据库中一直没有表,于是对hibernate进行配置。
打印出执行的sql语句,找到了create语句后用MySQL的command line执行,有以下报错:
经过搜索了解到trigger是MySQL的保留关键字,不能作为列名,于是把COLUMN_TRIGGER的值改为taskTrigger解决问题。
获取jira任务的信息 1.背景2.探究3.解决4.总结 1.背景 最近做一个demo项目,需要能够显示jira任务的状态信息,所以就稍微探究了一下jira的api和一些发请求的方法。
2.探究 一开始发现jira提供的jira-client-api中有jiraclient类,通过它很容易就可以获取到对应的任务的信息,但是如果依赖jar,存在一个问题,就是该jar中依赖到的jar都必须要依赖,所以只引入一个client-api.jar是远远不够的,运行时会报错,之后就根据报错去maven仓库搜,再这样操作引入了十几个jar之后终于报错中有一个类找不到是那个第三方库中的,这样就依赖不到对应的jar,功能也就实现不了,于是决定舍弃该方案。
方案二决定采用发请求的方式,去解析返回值。在查找资料后发现了jira的api接口为:https://域名/rest/api/2/issue/。所以向该接口发送POST请求即可获取到任务的信息。经过操作发现直接在api后加上对应的任务id即可获取对应任务的所有信息。然后解析其返回值即可获取到想要的信息。
3.解决 data即为得到的响应数据,是一个json,通过解析这个json即可获取到目标信息。
4.总结 这种发请求的方式除了在本场景中可以用于获取任务信息,也可以用同样的方式去爬取信息。
面向对象 面向过程思想:
步骤清晰简单面向过程适合处理一些较为简单的问题 面向对象思想:
物以类聚,分类的思维模式,思考问题首先会决绝哪些问题需要哪些分类,然后对这些分类进行单独思考,最后,才对某个分类下的细节进行面向过程的思索面向对象适合处理复杂的问题,适合处理需要多人协作的问题 面向对象的本质就是:以类的方式组织代码,以对象的组织(封装)数据
三大特性:封装 继承 多态
方法调用 public class Demo2 { //静态方法 static public static void main(String[] args){ //静态方法的调用 Demo2.say(); //非静态方法的调用 需要通过new关键字实例化 new Demo2().come(); } //静态方法 public static void say(){ System.out.println("学生说话了"); } //非静态方法 public void come(){ System.out.println("学生来了"); } //两个非静态方法之间调用 public void a(){ b();//直接调用 } public void b(){ } //两个静态方法之间调用 public static void c(){ d();//可以直接调用 } public static void d(){ //a(); //直接调用会报错,非静态类实例化之后才存在 } } 值传递 public class Demo4 { public static void main(String[]args){ int a = 1; System.