http://www.javashuo.com/article/p-adhbaize-ew.htmlhtml
由于哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,因此不少时候须要用到一种数组链表来作,也就是拉链法。拉链法是数组结合链表的一种结构,较早前的hashMap底层的存储就是采用这种结构,直到jdk1.8以后才换成了数组加红黑树的结构。mysql
图是一种比较复杂的数据结构,在存储数据上有着比较复杂和高效的算法,分别有邻接矩阵 、邻接表、十字链表、邻接多重表、边集数组等存储结构linux
栈:特色就是一个先进后出的结构。
队列:特色就是一个先进先出的结构。c++
栈的应用:很是普遍,在CPU内部就有提供栈这个机制。主要用途:函数调用和返回,数字转字符,表达式求值,走迷宫等等。在CPU内部栈主要是用来进行子程序调用和返回,中断时数据保存和返回。在编程语言中:主要用来进行函数的调用和返回。能够说在计算机中,只要数据的保存知足先进后出的原理,都优先考虑使用栈,因此栈是计算机中不可缺的机制。git
队列的应用:队列主要用在和时间有关的地方,特别是操做系统中,队列是实现多任务的重要机制。windows中的消息机制就是经过队列来实现的。进程调度也是使用队列来实现,因此队列也是一个重要的机制。只要知足数据的先进先出原理就可使用队列。程序员
不一样:redis
相同:两种结构都可实现数据的顺序存储,构造出来的模型呈线性结构。算法
区别一:物理地址存储的连续性
数组的元素在内存中是连续存放的。
链表的元素在内存中不必定是连续存放的,一般是不连续的。
区别二:访问速度
数组的访问速度很快,由于数组能够根据数组能够根据下标进行快速定位。
链表的访问速度较慢,由于链表访问元素须要移动指针。
区别三:添加、删减元素速度
数组的元素增删速度较慢,由于须要移动大量的元素。
链表的元素增删速度较快,由于只须要修改指针便可。sql
前缀树也叫字典树,经常使用语字符串的查找。数据库
字典树==前缀树==Trie树:
查询某个单词(前缀)在全部单词中出现次数的一种数据结构
查询和插入时间复杂度都是O(n),是一种以空间换时间的方法。
详细介绍参考于: http://www.javashuo.com/article/p-zwukhaty-cz.html (须要详细看)
https://blog.csdn.net/aiphis/article/details/48247469
应用:
前缀树有着普遍的应用,例如自动补全,拼写检查、搜索单词、搜索前缀等等
线程池是一种多线程处理形式,处理过程当中将任务添加到队列,而后在建立线程后自动启动这些任务。
通俗点讲,线程池就是一个容器,集中管理线程。线程使用完毕不会销毁,而是会先存储在线程池内。
一、判断线程池里的核心线程是否都在执行任务,若是不是(核心线程空闲或者还有核心线程没有被建立)则建立一个新的工做线程来执行任务。若是核心线程都在执行任务,则进入下个流程。
二、线程池判断工做队列是否已满,若是工做队列没有满,则将新提交的任务存储在这个工做队列里。若是工做队列满了,则进入下个流程。
三、判断线程池里的线程是否都处于工做状态,若是没有,则建立一个新的工做线程来执行任务。若是已经满了,则交给饱和策略来处理这个任务。
https://blog.csdn.net/jiao1902676909/article/details/88980110
一、线程是稀缺资源,使用线程池能够减小建立和销毁线程的次数,每一个工做线程均可以重复使用。
二、能够根据系统的承受能力,调整线程池中工做线程的数量,防止由于消耗过多内存致使服务器崩溃。
建立的线程池具体配置为:核心线程数量为5个;所有线程数量为10个;工做队列的长度为5
刚开始都是在建立新的线程,达到核心线程数量5个后,新的任务进来后不再建立新的线程,而是将任务加入工做队列,任务队列到达上限5个后,新的任务又会建立新的普通线程,直到达到线程池最大的线程数量10个,后面的任务则根据配置的饱和策略来处理。咱们这里没有具体配置,使用的是默认的配置AbortPolicy:直接抛出异常。
一个应用场景
linux高并发的实现,线程池的实现思想,怎样处理高并发就好比说,用迅雷看电影。一边下载,一边播放。这个时候下载进程和播放进程,他们两个就有同步的机制,例如:只能播放视频文件中已经下载完成的部分,没有下载的不能播放。
https://blog.csdn.net/chenkaifang/article/details/81428799
并发是轮流处理多个任务,并行是同时处理多个任务
https://www.jianshu.com/p/cbf9588b2afb
①一个函数在他的函数体内调用他自身称为递归调用,执行递归函数将反复调用其自身,每执行一次进入新的一层。
②为防止递归函数无休止的进行,必须在函数内有终止条件。
③对于一个函数只要知道他的递归定义式和边界条件,就能够编递归函数。
层数不能太多,在递归调用的过程中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易形成栈溢出等。
递归算法解题一般显得很简洁,但递归算法解题的运行效率较低。因此通常不提倡用递归算法设计程序。
充分必要条件是:问题具备某种可借用的类同自身的子问题描述的性质;某一有限步的子问题(也称本原问题)有直接的解存在。
递归算法就是经过解决同一问题的一个或多个更小的实例来最终解决一个大问题的算法。为了在C语言中实现递归算法,经常使用递归函数,也就是说能调用自身的函数。递归程序的基本特征:它调用自身(参数的值更小),具备终止条件,能够直接计算其结果。
在使用递归程序时,咱们须要考虑编程环境必须可以保持一个其大小与递归深度成正比例的下推栈。对于大型问题,这个栈须要的空间可能妨碍咱们使用递归的方法。
一个递归模型为分治法,最本质的特征就是:把一个问题分解成独立的子问题。若是子问题并不独立,问题就会复杂的多,主要缘由是即便是这种最简单算法的直接递归实现,也可能须要不可思议的时间,使用动态规划技术就能够避免这个缺陷。
能够按照从最小开始的顺序计算全部函数值来求任何相似函数的值,在每一步使用先前已经计算出的值来计算当前值,咱们称这项技术为自底向上的动态规划。只要有存储已经计算出的值的空间,就能把这项技术应用到任何递归计算中,就能把算法从指数级运行时间向线性运行时间改进。
性质:动态规划下降了递归函数的运行时间,也就是减小了计算全部小于或等于给定参数的递归调用所要求的时间,其中处理一次递归调用的时间为常量。
具体详见于:https://blog.csdn.net/DeepIT/article/details/6530282
在自顶向下的动态规划中,咱们存储已知的值;在自底向上的动态规划中,咱们预先计算这些值。咱们经常选择自顶向下的动态规划而不选自底向上动态规划,其缘由以下:
1 自顶向下的动态规划是一个天然的求解问题的机械转化。
2 计算子问题的顺序能本身处理。
3 咱们可能不须要计算全部子问题的解。
咱们不能忽视相当重要的一点是,当咱们须要的可能的函数值的数目太大以致于不能存储(自顶向下)或预先计算(自底向上)全部值时,动态规划就会变得低效。自顶向下动态规划确实是开发高效的递归算法实现的基本技术,这类算法应归入任何从事算法设计与实现所需的工具箱。
http://www.javashuo.com/article/p-phajxaty-ds.html
https://blog.csdn.net/qq_35556064/article/details/82503076
连表查询
from 多个表,使用where筛选条件
分页查询
select * from student limit 2,3
limit 2,3表明从第2条(不包含第2条) 数据开始查询出3条记录
嵌套查询
将一个查询块嵌套在另外一个查询块的 WHERE 子句或 HAVING 短语的条件中的查询称为 嵌套查询。
http://www.javashuo.com/article/p-bwgxltnu-dx.html
http://www.javashuo.com/article/p-eisyufyw-dy.html
https://www.runoob.com/design-pattern/singleton-pattern.html
https://www.jianshu.com/p/3bfd916f2bb2
https://blog.csdn.net/u011109589/article/details/80519863
log2(n)取整后 +1
协程不是进程或线程,其执行过程更相似于子例程,或者说不带返回值的函数调用。
一个程序能够包含多个协程,能够对比与一个进程包含多个线程,
于是下面咱们来比较协程和线程。咱们知道多个线程相对独立,有本身的上下文,切换受系统控制;而协程也相对独立,有本身的上下文,可是其切换由本身控制,由当前协程切换到其余协程由当前协程来控制。
协程和线程区别:协程避免了无心义的调度,由此能够提升性能,但也所以,程序员必须本身承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力。
http://www.javashuo.com/article/p-osgohrxy-ee.html
https://blog.csdn.net/jason_cuijiahui/article/details/82587076
http://www.javashuo.com/article/p-aeomaiju-eg.html
http://www.javashuo.com/article/p-hbufqghd-ek.html
一、病毒木马形成。 二、打开的网页过多,可形成短期CPU占用率高。 三、看视频时因为硬盘读写慢、网速慢,也可引发CPU占用率高。 四、玩大型游戏时,也可引发CPU占用率高。 五、有时自启动项过多(其中包括与系统不兼容的程序),引发响应慢引发CPU占用率高。
怎么判断一个元素是否是数组?
霍夫曼树:带权路径最短的二叉树称为哈夫曼树或最优二叉树
https://blog.csdn.net/qq_29519041/article/details/81428934
https://www.jianshu.com/p/d632b7e8f003
http://c.biancheng.net/view/3398.html
http://www.javashuo.com/article/p-epsgovkv-em.html
https://blog.csdn.net/qq_34793133/article/details/80087727
http://www.javashuo.com/article/p-pzhpbcel-mu.html
(1)进程栈大小时执行时肯定的,与编译连接无关
(2)进程栈大小是随机确认的,至少比线程栈要大,但不会超过2倍
(3)线程栈是固定大小的,可使用ulimit -a 查看,使用ulimit -s 修改。通常默认是8M。
(4)通常默认状况下,线程栈是在进程的堆中分配栈空间,每一个线程拥有独立的栈空间,为了不线程之间的栈空间踩踏,线程栈之间还会有以小块guardsize用来隔离保护各自的栈空间,一旦另外一个线程踏入到这个隔离区,就会引起段错误。
https://blog.csdn.net/elfprincexu/article/details/78779158
函数模板不能进行隐式类型转换
若是出现函数重载,优先调用普通函数
若是想强制使用函数模板,则可使用空参数列表
函数模板也能够发生重载
若是函数模板能够产生更好的匹配,那么优先使用函数模板
https://blog.csdn.net/XUCHEN1230/article/details/86370292
编译器会对函数模板进行两次编译:
1,对模板代码自己进行编译;
1,检查函数模板自己有无语法错误等;
2,对参数替换后的代码进行编译;
1,调用函数模板的时候,编译器要根据实际的参数类型获得真正的函数,这个时候编译器会对这个函数进行第二次编译;
匿名函数
好比你代码里有一些小函数,而这些函数通常只被调用一次(好比函数指针),这时你就能够用lambda表达式替代他们,这样代码看起来更简洁些,用起来也方便