计算机保研er必备

数据库中的选择操作,什么时候应该用到索引?

答:是不是只要在这个列上有索引,就应该去用索引。我说不是这样,这是数据库系统内部的事情,它可以选择用索引,也可以选择不用。老师继续追问,如果让你去设计一个数据库系统,你会选择什么时候用索引,什么时候不用。我答数据量很大的时候我们用索引是比较划算的,比如说从一万个数据里面选一个数据,而它恰好又有索引,这时你就可以用索引,但是如果从一万个数据里面选9999个,像这种极端情况,就没必要用索引了,直接遍历就可以了。一般来说,选取的数据的个数是总个数的10%以下,用索引是比较划算的,因为索引也是有代价的。
数据库范式
https://www.cnblogs.com/lca1826/p/6601395.html
第一范式(1NF):属性不可分。
第二范式(2NF):符合1NF,并且,非主属性完全函数依赖于码。
第三范式(3NF):符合2NF,并且,消除非主属性对码的传递依赖。
BC范式(BCNF):符合3NF,并且,消除主属性对码的部分与传递依赖。

为什么多路归并用败者树不用胜者树?

https://blog.csdn.net/ReDreamme/article/details/107286378
胜者树

胜者树每上升一次需要访问两个节点:父节点和兄弟节点。
败者树

败者树在重构的过程中只与父节点进行比较而不涉及兄弟节点之间的比较。

败者树不用获取胜者,每次只需访问父节点。
因为败者树是专用于k路归并的数据结构,每次只需要(且只能)修改原来的总冠军(而且修改后的优先级不高于原来的),所以每轮比较只要判断是“新人上位”还是“原来的亚军上位”,根本不需要另外找原来的胜者。相当于原来的总冠军“退役”了,新来的徒弟只要能打败他师傅打败的每个亚军,就是新的总冠军了。
关键就是,败者树不支持修改任意叶子,每次只能修改原来的总冠军。(胜者树是可以的,但k路归并的时候用不到)。

AVL RL
n0 = n2 + 1
Floyd

汉诺塔

不断将n个盘子的汉诺塔问题转换为2个n-1个盘子的汉诺塔问题。

稳定排序的意义

除非要排序的内容是一个复杂对象的多个数字属性,且其原本的初始顺序存在意义,那么我们需要在二次排序的基础上保持原有排序的意义,才需要使用到稳定性的算法,例如要排序的内容是一组原本按照价格高低排序的对象,如今需要按照销量高低排序,使用稳定性算法,可以使得想同销量的对象依旧保持着价格高低的排序展现,只有销量不同的才会重新排序。(当然,如果需求不需要保持初始的排序意义,那么使用稳定性算法依旧将毫无意义)。
快排为什么快,硬件方面
 一方面是参考位置,计算机硬件经过优化,访问彼此靠近的内存位置往往比访问散落在内存中的内存位置要快。quicksort中的分区步骤通常具有很好的位置性,因为它访问的是靠近前面和后面的连续阵列元素。因此,quicksort的性能往往比其他排序算法(如heapsort)好得多,即使它经常做大致相同数量的比较和交换,因为在heapsort的情况下,访问是比较分散的。
 另外还有就地操作,不需要创建任何辅助数组来保存临时值。
归并排序的最坏时间复杂度优于快排,为什么还选快排
 快排查找的常量要比归并小。
 绝大多数情况下,快排遇到的都是平均情况,也就是最佳情况,只有极个别的时候会是最坏情况,因此往往不考虑这种糟糕的情况。
希尔排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

桶排序

假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序。

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

 基数排序:根据键值的每位数字来分配桶。
 计数排序:每个桶只存储单一键值。
 桶排序:每个桶存储一定范围的数值。
排序复杂度

In-place: 占用常数内存,不占用额外内存
Out-place: 占用额外内存
希尔 n^1.3

冒泡排序改进

 设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
 双向冒泡排序,首先从前往后把最大数移到最后,然后反过来从后往前把最小的一个数移动到数组最前面,这一过程就是第一轮,然后重复这一过程,最终就会把整个数组从小到大排列好。双向冒泡排序要稍微优于传统的冒泡排序,因为双向排序时数组的两头都排序好了,我们只需要处理数组的中间部分即可,而单向即传统的冒泡排序只有尾部的元素是排好序的,这时每轮处理都需要从头一直处理到已经排好序元素的前面一个元素。虽然它在效率上有了点改进,但它也不能大幅度提高其排序的效率,这是由冒泡排序的基本过程所决定了的。
快排改进
 只对长度大于k的子序列递归调用快速排序,让原序列基本有序,然后再对整个基本有序序列用插入排序算法排序。实践证明,改进后的算法时间复杂度有所降低,且当 k取值为 8 左右时,改进算法的性能最佳。
 三数取中做枢轴,一般是使用左端、右端和中心位置上的三个元素的中值作为基准元。
哈希表除留取余法的桶个数为什么是质数

贪心算法 vs 动态规划 vs 分治法

都需要将问题划分为一个个子问题,然后通过解决这些子问题来解决最终问题。
分治法:将原问题划分成 n 个规模较小而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。
分治模式在每一层递归上都有三个步骤:
 分解(Divide):将原问题分解成一系列子问题;
 解决(Conquer):递归地解各个子问题。若子问题足够小,则直接求解;
 合并(Combine):将子问题的结果合并成原问题的解。

动态规划:适用于子问题重叠的情况,也就是各子问题包含公共的子问题。在这种情况下,若用分治法则会做许多不必要的工作,即重复地求解公共的子问题。动态规划算法对每个子子问题只求解一次,将其结果保存在一张表中,从而避免每次遇到各个子问题时重新计算答案。
动态规划算法的设计可以分为如下 4 步骤:
 描述最优解的结构
 递归定义最优解的值
 按自底向上的方式计算最优解的值
 由计算出的结果构造一个最优解
最优子结构性质和子问题重叠性质是该问题可用动态规划算法求解的基本要素:
1.最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。在动态规划算法中,利用问题的最优子结构性质,以自底向上的方式递归地从子问题的最优解逐步构造出整个问题的最优解。
2.重叠子问题:在用递归算法自顶向下求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要此子问题时,只要简单地用常数时间查看一下结果。通常,不同的子问题个数随问题的大小呈多项式增长。因此,用动态规划算法通常只需要多项式时间,从而获得较高的解题效率。

贪心法:贪心算法是使所做的选择看起来都是当前最佳的,期望通过所做的局部最优选择来产生出一个全局最优解。
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
 问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
 贪心选择性质。是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法与动态规划算法的主要区别。
求拓扑排序的几种方法
删边(有向图是入度为0的结点,无向图是入度为1的结点,度为0是孤立节点)

判断图是否存在环

1、 拓扑
2、 DFS + 后退边
用DFS(深度优先遍历),判断是否有后退边,若有,则存在环。具体来说,在遍历顶点的每一条边时,判断一下这个边的顶点是不是在栈中,如果在栈中,说明之前已经访问过了,这里再次访问,说明有环存在。
判断后退边时,借助一个栈和一个数组。栈:即可以用来输出环。数组:inStack判断是否在栈中。
链表的环
 如何判断是否存在环?
使用追赶的方法,设定两个指针 slow、fast,从头指针开始,每次分别前进 1 步、2 步。如存在环,则两者相遇;如不存在环,fast 遇到 NULL 退出。
 如何知道环的长度?
记录下问题1的碰撞点 p,slow、fast 从该点开始,再次碰撞所走过的操作数就是环的长度s。
 如何找出环的连接点在哪里?
碰撞点 p 到连接点的距离 = 头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
 带环链表的长度是多少?
问题 3 中已经求出连接点距离头指针的长度,加上问题 2 中求出的环的长度,二者之和就是带环单链表的长度。
10G数据,1G内存排序
 分别排序:根据内存1G,数据10G,将10G数据切分成10份,通过内存调用磁盘的方式,每1G进行排序。
 归并:多路归并过程可以使用败者树或最小堆。为方便起见用最小堆,原理是一样的。
 内存中开辟一个大小为10的最小堆,和一个缓冲区(小于1G,不要太小)。
 取10份排序好的数据的首位进入最小堆。则最小的数位于堆顶,移除堆顶元素并写入缓冲区,然后从移除元素的元素所属数组中的下一位进入最小堆,在次移除堆顶进入缓冲区…直到缓冲区满,缓冲区回写磁盘,清空缓冲区,再次将数据置入最小堆…
 直到10份数据全部写完,然后将最小堆的元素按顺序回写磁盘即可。

内核级线程、用户级线程

  1. 内核级(KLT)线程:
     切换由内核控制,当线程进行切换的时候,由用户态转化为内核态。切换完毕要从内核态返回用户态。可以很好的运用多核CPU。
     优点:一个进程中的线程被阻塞了,还可以调用该进程中的其他线程。在多处理器中,内核可以调用同一个进程中的多个线程同时进行处理。
     缺点:线程在用户态的运行,而线程的调度和管理在内核实现,在控制权从一个线程传送到另一个线程需要用户态到内核态再到用户态的模式切换,比较占用系统资源。

  2. 用户级(ULT)线程 :
     把整个线程实现部分放在用户空间中,内核对线程一无所知,内核看到的就是一个单线程进程。整个用户级线程的切换发生在用户空间,这样的线程切换至少比陷入内核要快一个数量级(不需要陷入内核、不需要上下文切换、不需要对内存高速缓存进行刷新,这就使得线程调度非常快捷)。但是它不能像内核级线程一样更好的运用多核CPU。
     如果一个线程开始运行,那么该进程中其他线程就不能运行,除非第一个线程自动放弃CPU。因为在一个单独的进程内部,没有时钟中断,所以不能用轮转调度(轮流)的方式调度线程。
     优点:线程之间的切换不需要转换到内核态,节省了内核空间、也节省了时间。用户级线程的实现和操作系统无关。
     缺点:一个进程中有一个线程被阻塞了,该进程就被阻塞了。一个进程只能在一个CPU上获得执行。

  3. 为什么会这样呢?
     答:是因为操作系统内核根本不知道线程的存在,他只看得到进程,所以在他眼中是进程被阻塞了。

  4. 多线程模型
     多对一模型:将多个用户级线程有映射到一个内核级线程,线程管理在用户空间完成。
    特点:线程管理在用户态,效率高;一个线程再使用内核服务被阻塞的时候其他的线程都会被阻塞,多线程不能并行的运动在多处理机的系统中。
     一对一模型:一个用户级线程映射一个内核级线程
    特点:当一个线程被阻塞后,别的还可以继续执行,并发能力强,多核CPU可以运行多个线程;每创建一个用户级线程就会创建一个内核级线程,创建开销大,浪费资源
     多对多模型:n个用户级线程映射到m个内核级线程上去,n>m
    特点:以上两者的优点
    交换和覆盖

分段和分页

  1. 基本分段式和基本分页式的区别在于:基本分页存储管理是站在计算机的角度考虑的,不具备逻辑性,以增加内存利用率为主,地址的变换由硬件决定。
  2. 但是基本分段式是站在用户程序员的角度来的,是具备逻辑性的,有利于信息的共享,只需要在段表中增加一个段表项即可进行共享段。

梯度、方向导数

方向导数:本质是一个数值,简单来说其定义为: 一个函数沿指定方向的变化率。
梯度:梯度与方向导数是有本质区别的,梯度其实是一个向量,其定义为: 一个函数对于其自变量分别求偏导数,这些偏导数所组成的向量就是函数的梯度
https://www.ebaina.com/articles/140000012912
函数在某点的梯度是这样一个向量,它的方向与取得最大方向导数的方向一致,而它的模为方向导数的最大值。
傅里叶变换和时域频域
时域:自变量是时间,即横轴是时间,纵轴是信号的变化。其动态信号x(t)是描述信号在不同时刻取值的函数。
频域:自变量是频率,即横轴是频率,纵轴是该频率信号的幅度,也就是通常说的频谱图。从频域图中,可以一眼看出正弦波的频率和峰值振幅。

傅里叶变换:傅里叶变换的目的是可将时域上的信号转变为频域上的信号,任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。
应用:图像去噪:设计一个低通滤波器(高斯函数),去掉图像中的高频噪声。
泰勒展开
泰勒公式是一个用函数在某点的信息描述其附近取值的公式。如果函数足够平滑的话,在已知函数在某一点的各阶导数值的情况下,泰勒公式可以用这些导数值做系数构建一个多项式来近似函数在这一点的邻域中的值。
应用:
①计算机的数值计算领域。matlab数学库中就包含很多的初等函数,像sin(x),cos(x)等,
②深度学习中牛顿法是一种二阶梯度方法。牛顿法的前提其实是泰勒展开。

非零子式的最高阶数就是秩
行列式
行列式是线性变换的伸缩因子
即旋转放缩后无法回到原来状态
而正负号的作用是告诉我们是左手系还是右手系
相当于把标准正交基A旋转伸缩到这个平行四边形B = TA

矩阵乘和线性变换

矩阵乘的意义,是将一个向量,经过某个函数(矩阵)之后,变换成另外一个向量。
线性变换,也就是在变换的基础上,再加一个条件,线性的,也就是原来的一条直线,在变换了之后还应该是直线。
(线性变换通过指定基下的矩阵A表示)
一个向量,在经过一个矩阵A的变换之后,改变的是组成向量的基,而这个向量关于基的线性组合方式是没有变化的。
矩阵相乘其实就意味着对向量(空间)进行两次变换的叠加效果。并且先变换A后变换B和先变换B后变换A是不一样的,因此AB和BA不相等。

线性空间

一个向量组的线性组合构成一个线性空间,我们称“该向量组张成了这个线性空间”,这个线性空间就是该向量组的向量空间。
线性空间是这么一个空间,里面的所有向量都满足:乘一个常数后或者和其它向量相加后(除法和减法可以看作另类的乘法和加法)后仍然在这个空间里。
线性空间一定包含零元素。
极大无关组
极大无关组言简意赅,就是一个向量组中所有线性无关向量的集合,那么剩下的什么?剩下的就是线性相关的,这个线性相关不是指它们线性相关,是指剩下的向量都可以由无关组的向量线性表示出来。

相似矩阵

同一个线性变换,不同基下的矩阵,称为相似矩阵
v->Av 或 Bv 是一个线性变换,由于Av和Bv相同,所以是同一个线性变换
但A是在基V1中变换的,B是在基V2中变换,则A和B就是相似矩阵。

正定矩阵

合同矩阵

同一个二次曲线,在不同基下需要用不同的二次型矩阵表示。这两个二次型矩阵就称为合同矩阵。

集合的大小

如果集合A能和集合B的元素之间存在一一对应关系,则两者一样大。如果集合A能和集合B的子集一一对应,但不能和集合B一一对应,则集合A比集合B小。
双射、单射、满射
 单射:集合A一个对应B的一个,但是有可能B中有的元素没有A中元素对应。
 满射:可以集合A和集合B可以多对一也可以一对一,B中元素都有A中元素对应,A中元素也总能对应B中元素。
 双射:A、B之间一一对应。
欧拉回路、哈密顿回路
(1)欧拉回路:经过图G中每条边一次且仅一次的回路,称为欧拉回路。
(2)欧拉路径:经过图G中每条边一次且仅一次的路径,称为欧拉路径。
(3)存在欧拉回路的图称为欧拉图。
无向图 G 有欧拉回路,当且仅当 G 是连通图且无奇度顶点;
无向图 G 有欧拉路径,当且仅当 G 是连通图且恰好有两个奇度顶点。这两个奇度顶点是欧拉路径的端点。
(4)哈密顿图:经过图中每个顶点一次且仅一次的回路称为哈密顿回路。存在哈密顿回路的图称为哈密顿图。同理也有哈密尔顿路径。

完全图、平面图

在无向图中,若每对顶点之间都有一条边相连,则称该图为完全图
在有向图中,若每对顶点之间都有二条有向边相互连接,则称该图为完全图
平面图:图G中的边与边之间只在顶点处交叉。
判断一个平面图是否连通可以用欧拉公式:任意一张连通平面的节点数(V)、边数(E)和面数(F)的关系可以有公式V – E + F = 2表示。

等价关系和偏序关系

极大似然估计

极大似然估计,就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值。
极大似然估计提供了一种给定观察数据来评估模型参数的方法,即:“模型已定,参数未知”。

先验概率和后验概率

先验概率是指根据以往经验和分析得到的概率,如全概率公式,它往往作为"由因求果"问题中的"因"出现。
后验概率是指依据得到"结果"信息所计算出的最有可能是那种事件发生,如贝叶斯公式中的,是"执果寻因"问题中的"因"。
https://blog.csdn.net/qq_42851114/article/details/89150383
因特网中的两大类路由选择协议
(1)域内路由选择协议IGP:RIP(UDP,用的路由选择算法是距离向量,最多15跳)、OSPF(IP,用的路由选择算法是链路状态,其中用到了迪杰斯特拉最短路径求解算法。
(2)域间路由选择协议EGP:BGP(TCP)
浏览器请求一个网址的过程?
(1)首先是解析域名,DNS进行,获得IP地址。然后端口号发送端随机分配,服务器是固定的80端口。
(2)知道IP和端口号之后就可以建立3次握手建立TCP连接。
(3)发送HTTP请求报文。
(4)服务器处理浏览器发来的请求,返回要显示的页面html信息。
(5)传输结束,4次握手释放连接。
(6)显示页面。

意向锁

1)意向锁的作用:对关系加显示锁就相当于对该关系的所有元组都加了相同的锁(多粒度封锁,分成树,每个结点被加锁相当于其后裔结点也被加了锁)。但是这意味着每次我想要对某个结点加锁时,都不仅需要检查该结点上被加的锁,还需要检查他的所有前结点以及后裔结点上被加的锁,这太麻烦了。
2) 引出意向锁的目的:意向锁是指,当你对某个结点加显示锁(X/S)时,就意味这你对该结点所有的上层结点都加了意向锁(IX/IS)。所以某个结点上有意向锁就意味着,该节点存在后继结点上加了X/S锁。
3)好处在哪?假如你想对某个结点加显示锁,那么你除了查看该结点上加的显示锁之外,只需要看该结点加的意向锁即可,比如你想给该结点加X锁,但是该结点已经有了一个意向锁IX,说明他的子结点存在加X锁的,那你就不能给结点加X,会冲突。
4)申请锁自上往下进行,释放锁自下往上进行。

中间代码优化

1)目的:优化后的代码运行快、存储空间需求小。这也正是我们优化代码的目的,从时空两个维度尽可能让代码效率高。在时间和空间两个维度优化代码,尽可能以较小的代价取得最优的优化结果。
2)技术:消除公共子表达式、复写传播、删除无用代码、代码外提(在循环中一直没有改变的值,我们把它提到循环外面去)、强度削弱(乘除变加减)、删除归纳变量。
五级流水线
将指令的执行分成五个阶段:分别是取指、译码、执行、访存、写回。

K-means

针对 K-means 算法的缺点,我们可以有很多种调优方式:如数据预处理(归一化、去除异常点),合理选择 K 值,高维映射等。
核聚类方法的主要思想是通过一个非线性映射,将输入空间中的数据点映射到高位的特征空间中,并在新的特征空间中进行聚类。非线性映射增加了数据点线性可分的概率,从而在经典的聚类算法失效的情况下,通过引入核函数可以达到更为准确的聚类结果。

KNN

KNN 算法是有监督学习中的分类算法,它看起来和另一个机器学习算法 K-means 有点像(K-means 是无监督学习算法)。KNN 的最终目的是分类,而 K-means 的目的是给所有距离相近的点分配一个类别,也就是聚类。

KNN 的原理就是当预测一个新的值 x 的时候,根据它距离最近的 K 个点是什么类别来判断 x 属于哪个类别。
 如何确定 K 取多少值好呢?
答案是通过交叉验证(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如6:4拆分出部分训练数据和验证数据),从选取一个较小的 K 值开始,不断增加 K 的值,然后计算验证集合的方差,最终找到一个比较合适的 K 值。
LSTM

LSTM中的三个门是用的sigmoid作为激活函数,主要方便把门的开度限制在01,生成候选记忆时候用的才是tanh,门j的激活函数如果用relu的话会有个问题,就是relu是没有饱和区域的,那么就没法起到门的作用。候选记忆用tanh是因为tanh的输出在-11,是0中心的,并且在0附近的梯度大,模型收敛快。

SVM

https://blog.csdn.net/LY_ysys629/article/details/72980834
距离超平面最近的且满足一定条件的几个训练样本点被称为支持向量。SVM模型由支持向量决定,支持向量距离超平面的距离是小于等于1的(原因后边有解释),假如SVM能够找出一个超平面或者超曲面使得支持向量能够尽可能的分类正确,且距离超平面或超曲面的距离尽可能的远,则非支持向量点,也能被正确分类且距离最远,该处距离的含义可认为分类正确的置信度,距离越远置信度越大。

https://blog.csdn.net/qq_40587575/article/details/90271611
(软硬分隔的可视描述)

总线

总线是一组能为多个部件分时共享的公共信息传送线路。
共享也就是多个设备公用同一套总线,即总线上可以挂多个部件。指同一时刻只允许一个部件向总线发送信息,如果有多个部件想要向总线传送信息,则必须一个一个来,也就是分时发送。
总线是为了增加外部设备与主机的连接灵活性而出现的。
总线分为三大类:片内总线、系统总线(数据总线双向+控制总线单向+地址总线)、通信总线。
https://blog.csdn.net/qq_52109814/article/details/123336973

内存管理

文件管理
如果一个文件有n个索引块,那么连续分配访问磁盘1次;链接分配访问磁盘n次;m级索引访问m+1次。
空闲表法:空闲表法是连续的分配方式,他与内存的动态分配方式相似。为文件划分一块连续的空间。系统为外存上的所有空闲区域建立一张空闲盘块表(序号,空闲盘块的第一块号,空闲盘块数)。同样可以使用首次适应,最佳适应等算法。

C++多态

在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数,如果对象类型是派生类,就调用派生类的函数,如果对象类型是基类,就调用基类的函数。
1、静态多态:从技术上来讲就是函数重载。
2、动态多态:动态多态依赖于虚函数的实现,虚函数是指在类中用virtual关键字标识的成员函数。对于虚函数,可以在继承类中对父亲类中的虚函数进行重载的(要求函数参数列表完全一致)。

调度层次

 作业调度(高级调度):按照一定的原则,从外存中处于后备状态的作业中选取一个作业,为其分配内存、I/O设备等资源。并且建立进程。主要是外存于内存之间的调度。
注意:只调度进内存一次,调出一次
 中级调度(内存调度):为了提高内存的利用率,与系统的吞吐量。将那些暂时不能运行的进程调度到外存进行等待。当需要这些进程的时候,又会把它们从外存中调度回来到就绪队列中等待使用
注意:中级调度可以发生多次
 进程调度(低级调度):按照某种方式与策略从就绪态选取一个进程,将处理机分配给它。
注意:进程调度的频率最高

死锁

 互斥条件:进程请求的资源只能一个进程使用。比如打印机资源。
 不剥夺条件:当一个进程在处理机上执行的时候,别的进程不能剥夺它的处理机权限。
 请求并保持条件:进程申请某一资源的时候,如果得不到回复,必须保持请求这一资源的状态。
 循环条件:存在一种进程资源循环等待链,链中的进程请求同一种资源。
死锁预防
 破坏互斥条件:这里有一个新的技术,SpooLing技术可以解决。比如进程A、B同时求打印机,这时候会有一个输出进程来接受A、B的请求,然后依次让打印机去工作。在A、B看来打印机好像是一个共享的资源。
 破坏不剥夺条件:法一:当一个进程请求的资源很久都得不到的时候,他必须放弃现有的资源(哲学家问题)。法二:系统可以根据优先级将优先级低的资源调给高优先级的资源。
 破坏请求并保持条件:采用预先资源分配法,当一个进程申请完所有资源的时候才能投入运行,在运行过程中这些资源都归他所有。
 破坏循环条件:可以采用顺序资源分配法,首先给系统中的所有资源编号,规定每个进程必须按编号递增的顺序申请资源。同一类资源一次申请完毕,也就是说,该进程第一次申请的资源必须是他所需要所有资源中编号最小的,他以后每次申请的资源编号必须比前一次大。这样的好处在于编号大的优先级资源总会被使用完毕,然后给别的优先级使用。

死锁避免

 银行家

进程

进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。进程一般由程序,数据集合和进程控制块三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块包含进程的描述信息和控制信息是进程存在的唯一标志。

线程

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。 一个标准的线程由线程 ID,当前指令指针 PC,寄存器和堆栈组成。而进程由内存空间(代码,数据,进程空间,打开的文件)和一个或多个线程组成。

程序内存区域

  1. 栈区
    由编译器自动分配释放 ,存放函数的参数值,局部变量的值等,内存的分配是连续的,类似于平时我们所说的栈,如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器会自动接着当前栈区的结尾来分配内存。
  2. 堆区
    由 new 分配的内存块,由应用程序控制,需要程序员手动利用 delete 释放,如果没有,程序结束后,操作系统自动回收。
    类似于链表,在内存中的分布不是连续的,它们是不同区域的内存块通过指针链接起来的。如果我们申请到了某一块内存,那么这一块内存区将会从连续的(通过链表连接起来的)内存块上断开,如果我们在使用完后,不及时的对它进行释放,那么它就会被孤立开来,由于没有任何指针指向它,所以这个区域将成为内存碎片。
  3. 全局区/静态区
    全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。
  4. 文字常量区
    常量字符串就是放在这里的。 程序结束后由系统释放。
  5. 程序代码区
    存放函数体的二进制代码。

编译与解释

翻译高级语言编写的程序的方式有编译和解释两种。
编译 (compile) 是用编译器 (complier) 程序把高级语言所编写的源程序 (source code) 翻译成用机器指令表达的目标代码,使目标代码和源程序在功能上完全等价,通过连接器 (linker) 程序将目标程序与相关连接库连接成一个完整的可执行程序。其优点是执行速度快,产生的可执行程序可以脱离编译器和源程序存在,反复执行。
解释 (interpret) 是用解释器 (interpreter) 程序将高级语言编写的源程序逐句进行分析翻译,解释一句,执行一句。当源程序解释完成时目标程序也执行结束,下次运行程序时还需要重新解释执行。其优点是移植到不同平台时不用修改程序代码,只要有合适的解释器即可。

new、delete、malloc、free

  1. 前者是关键字,需要编译器支持,后者是库函数,需要头文件支持
  2. 前者无需指定内存块大小
  3. 前者返回对象指针,或bad_alloc异常,后者返回void*指针或NULL
  4. new先调用operator new函数,申请内存,然后调用构造函数初始化成员变量,最后返回指针;delete调用析构函数,然后调用operator delete释放内存。malloc/free 是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
  5. C++ 允许自定义 operator new 和 operator delete 函数控制动态内存的分配。
  6. 内存泄漏对于 new 和 malloc 都能检测出来,而 new 可以指明是哪个文件的哪一行,malloc 确不可以。
    虚函数、虚函数表
    https://blog.csdn.net/weixin_43595277/article/details/120659984

数组名和数组首地址

静态数组中,数组名在进行地址操作时,&arr 和 arr 值虽相同,但意义不同:&arr 移动的单位是整个数组,而 arr 移动的单位是数组元素。
const和define
 const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应) 。
 有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。

计算机启动

BIOS上电自检、查找启动设备、MBR引导程序、加载OS内核、OS取得系统控制权
 按下电源开关后,主板各个器件会供电,CPU 供电完成后会进行一段复位的操作。复位完成后会从主板上的存储芯片(BIOS 芯片)里读取一段启动代码进行上电自检。如果硬件设备都检测正常的话,它就会进行下一步:检测启动设备。
 假设它查找的启动设备是一块硬盘。接下来,它会到硬盘的第一个扇区去读取一段程序(主引导记录 Master Boot Record,512 字节——引导程序 + 硬盘分区表、分区表数据 + 结束标志 AA55)。
 当 BIOS 程序找到 MBR 这段数据的时候,它会把数据加载到内存中,然后把系统的控制权交给 MBR 中的那段引导程序。
 MBR 的引导程序取得系统的控制权之后,它会把操作系统的内核加载到内存,然后把系统的控制权交给操作系统的内核。这个时候,操作系统就取得了系统的控制权。接下来的过程就是操作系统正常启动的过程。

Java程序编译过程

java不是纯编译的,可能是先编译后解释,也可能是两次编译。

Python解释过程

Java很特殊,Java程序也需要编译,但是没有直接编译称为机器语言,而是编译称为字节码,然后在Java虚拟机上用解释方式执行字节码。Python的也采用了类似Java的编译模式,先将Python程序编译成Python字节码,然后由一个专门的Python字节码解释器负责解释执行字节码。

当我们在命令行中输入pythonhello.py时,其实是激活了Python的"解释器",告诉"解释器":你要开始工作了。可是在"解释"之前,其实执行的第一项工作和Java一样,是编译。当python程序运行时,编译的结果则是保存在位于内存中的PyCodeObject中,当Python程序运行结束时,Python解释器则将PyCodeObject写回到pyc文件中。当python程序第二次运行时,首先程序会在硬盘中寻找pyc文件,如果找到,则直接载入,否则就重复上面的过程。pyc文件其实是PyCodeObject的一种持久化保存方式。

Pyc是为了重用,我们需要编译成pyc文件的应该是那些可以重用的模块。Python的解释器认为:只有import进来的模块,才是需要被重用的模块。Python解释器只把我们可能重用到的模块持久化成pyc文件。

链接

https://blog.csdn.net/zhengnianli/article/details/104321056
链接就是目标文件与一些库文件 生成可执行文件的过程。
 静态链接
编译时完成链接。链接器是一个独立程序,将一个或多个库或目标文件链接到一起,生成可执行程序。这里的库指的是静态链接库,Windows下以.lib为后缀,Linux下以.a为后缀。
编译时用到静态链接,编译时的链接就是静态链接,所以链接程序ld/collect2,也可以称为静态链接器。
 动态链接
在编译的时候只留下调用接口,当程序真正运行时,才去链接执行,动态链接不是在编译时发生的,是在程序动态运行时发生的,所以叫称为动态链接。
动态链接库,Windows下以.dll为后缀,Linux下以.so为后缀。在Windows下的动态链接也可以用到.lib为后缀的文件,但这里的.lib文件叫做导入库,是由.dll文件生成。

CSMA/CA和CSMA/CD的工作原理和区别

无线局域网802.11标准的CSMA/CA和802.3协议中的CSMA/CD两种机制都是为了解决数据传输过程中的网络上的冲突问题。

  1. CSMA/CD (Carrier Sense MultIPle Access with Collision Detection)
    先听后发,边听边发,冲突停发,随机重发。采用二进制指数退避算法,可以检测冲突,但无法“避免”。
    2.CSMA/CA (Carrier Sense Multiple Access with Collision Avoidance)
    在无线局域网中,冲突检测存在一定问题,这是由于要检测冲突,设备必须能够一边接受数据信号一边传送数据信号,而这在无线系统中是无法办到的。CSMA/CA利用ACK信号来避免冲突的发生,也就是说,只有当客户端收到网络上返回的ACK信号后才确认送出的数据已经正确到达目的。
  2. 两者区别:
    检测方式不同:CSMA/CD通过电缆中电压的变化来检测,当数据发生碰撞时,电缆中的电压就会随着发生变化;而CSMA/CA采用能量检测(ED)、载波检测(CS)和能量载波混合检测三种检测信道空闲的方式。
    牛顿法

二分法

二分法能够求出方程的单根(不是重(chong)根)或者奇重根,但却不能求得方程的偶重根。因为f(x)若有偶重根,它在偶重根两侧不会变号。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值