当前位置: 首页 > news >正文

软考-数据库系统工程师(15万词+400张图片)(一)

软考-数据库系统工程师(一)

    • 上午题
    • 下午题
  • 计算机系统知识
    • 计算机系统的组成
      • 计算机硬件组成
      • 中央处理单元
      • 计算机周期
    • 计算机数据表示
      • 存储单位
      • R进制
      • 算数逻辑运算
      • 数据在计算机中的表示方法(机器码和码制)
      • 定点数和浮点数
      • 校验码(不考)
      • crc冗余校验码
      • 海明校验码
    • 计算机体系结构
      • 指令流数据流
      • 指令系统
      • 指令与操作数的寻址方式
      • CISC/RISC
      • 流水线
    • 存储系统
      • 概念
      • cache
        • 直接映像
        • 全相联映像
        • 组组相连映像
        • cache的性能分析
      • 存储单位
      • 存储器分类
      • 随机访问存储器
      • 外存储器
      • 虚拟存储器
      • 相联存储器
    • 输入输出技术(外设)
      • I/O设备
      • 总线结构
      • 输入输出控制
        • 程序控制方式
        • 中断方式
        • 直接内存存取(DMAC)方式
        • IO通道方式和外围处理机(IOP)方式
      • 数据传输方式
      • 生物特征认证技术
    • 安全性、可靠性、性能评价
      • 计算机可靠性
        • 可靠性指标
        • 串并联系统可靠性
        • 并联系统可靠性
        • N模元余系统
      • 计算机系统性能评价
      • 信息安全
      • 加密技术
        • 对称(私钥)加密技术
        • 非对称加密技术(公钥)
        • 对称和非对称加密算法的区别
        • 数字信封原理
        • 数字签名
        • 信息摘要
        • 公钥基础设施PKI
    • 多媒体知识
      • 媒体分类
      • 文件格式
      • 声音频率问题
      • 像素问题
      • 多媒体内容接口标准问题
      • 彩色打印机所用的颜色空间
      • mpeg视频编码
  • 程序语言基础
    • 程序设计语言的基本概念
    • 程序设计语言的基本成分
    • 编译程序基本原理
  • 数据结构与算法
    • 线性表
      • 基本概念
      • 顺序表
      • 链表
        • 单链表
        • 双链表
        • 静态链表
      • 有序表
    • 栈与队列
        • 顺序栈
        • 顺序共享栈
        • 链栈
      • 栈的应用
      • 队列
        • 顺序队
        • 顺序循环(环形)队
        • 链队
      • 队列的应用
      • 栈与队列的区别
      • 串的基本概念
      • 串的存储结构
      • 模式匹配算法
    • 数组矩阵
      • 数组
      • 矩阵
    • 树与二叉树
      • 树和森林
        • 树的性质(重点)
        • 树的遍历
        • 树的存储结构
      • 二叉树
        • (完全)二叉树的性质
        • 二叉树遍历
        • 二叉树和树和森林的转换
        • 二叉树的存储结构
        • 二叉树的构造
      • 线索二叉树
      • 二叉排序树
      • 平衡二叉树
      • 哈夫曼树
      • 并查集
      • 图的基本概念
      • 图的存储结构及基本算法
        • 邻接矩阵
        • 邻接表
      • 图的遍历
        • 深度优先遍历DFS
          • 算法
          • 遍历次序(重要)
        • 广度优先遍历BFS
          • 算法
          • 遍历次序(重要)
      • 最小生成树
        • 生成树概念
        • 普里姆(Prim)算法
        • 克鲁斯卡尔(Kruskal)
      • 最短路径
          • 迪杰斯特拉(Dijkstra)求单源最短路径
        • 弗洛伊德(Floyd)求各顶点之间最短路径问题
      • 有向无环图描述表达式(节省空间)
      • 拓扑排序
      • 关键路径
        • 概念
        • 几个变量
        • 关键路径计算
    • 查找
        • 概念
          • 平均查找长度ASL(重点)
        • 线性表查找
          • 顺序查找
          • 折半(二分)查找
          • 分块(索引)查找
        • 树表查找
          • 二叉排序树BST
          • 平衡二叉树AVL
        • 散列(哈希)查找 - HashTable
          • 概念
          • 哈希函数的构造方法
          • 哈希冲突的解决办法
          • 除留余数画出哈希表
          • 拉链法画出哈希表
    • 排序(重点)
        • 插入排序
          • 直接插入排序(增量法)
          • 折半插入排序
          • 希尔排序(Shell Sort)
        • 交换排序
          • 冒泡排序
          • 快速排序
        • 选择排序
          • 简单选择(直接选择)排序
          • 堆排序
        • 归并排序
        • 基数排序
        • 各排序的比较
  • 操作系统基础
    • 进程管理
      • 进程三态图
      • 前驱图
      • 进程资源图
      • 进程同步与互斥
      • 进程的信号量的pv操作
      • 死锁
      • 线程
      • 进程调度
    • 存储管理
      • 分区存储管理
      • 分页存储管理
        • 分页
        • 页面置换算法
        • 快表(快速的页表)
      • 分段存储管理
      • 段页式存储管理
    • 设备管理
      • 设备管理概述
      • I/O软件
      • 设备管理技术
    • 文件管理
      • 文件管理概述
      • 索引文件结构
      • 文件目录
      • 文件存储空间管理
      • 作业调度算法
  • 网络基础知识
    • 计算机网络概述
      • 网络功能和分类
      • OSI七层模型
    • 网络硬件基础
      • 传输介质(网线)
      • 物理层互联设备
      • 数据链路层的互联设备
      • 网络层互联设备
      • 应用层互联设备
    • 网络的协议与标准
      • 局域网和广域网协议
      • TCP/IP协议(四层模型)
      • 各层协议
        • 网络层协议
        • 传输层协议
        • 应用层协议
        • 会话层
        • 协议端口号对照表
    • internet基础知识
      • 通信方式和交换方式
      • ip地址表示
        • 分类ip
        • 无分类ip
        • 私有ip
      • 域名
      • 子网划分
      • IPv6
      • NAT技术
      • DNS
      • 动态地址分配
      • ping命令
    • 网络安全概述
      • 网络安全威胁
      • 防火墙技术
      • 入侵检测与防御
      • 恶意代码(病毒)
      • 计算机安全等级
      • 计算机安全十大原则
      • 信息安全
      • 加密技术

上午题

img

image-20240330141555858

image-20240330141609494

下午题

image-20240403154303893

image-20240403154334909

image-20240330142052528

image-20240330141617846

计算机系统知识

image-20240322093241860

计算机系统的组成

计算机硬件组成

计算机系统由硬件系统和软件系统组成。硬件由运算器、控制器、存储器、输入设备、输出设备5部分组成;软件由系统软件、应用软件组成。

  • **cpu的组成:**运算器,控制器,寄存器(64位)和内部总线等部件组成

CPU的基本功能:

a) 程序控制。CPU通过执行指令来控制程序的执行顺序,这是CPU的重要功能。

b) 操作控制。一条指令功能的实现需要若干操作信号配合来完成,cpu产生每条指令的操作信号并将操作信号送往对应的部件,控制相应的部件按指令的功能要求进行操作。

c) 时间控制。CPU对各种操作进行时间上的控制,即指令执行过程中操作信号的出现时间、持续时间及出现的时间顺序都需要进行严格控制。

以上三个都是控制器,下面是运算器

d) 数据处理——CPU的根本任务,算数运算逻辑运算

此外,cpu还需要对系统内部和外部的中断(异常)做出响应,进行相应的处理

中央处理单元

运算器:对数据进行处理的部件,主要完成算术和逻辑运算

运算器包含:

  • 算数逻辑单元ALU(Arithmetic and logic unit):数据的算数运算和逻辑运算

  • 累加寄存器AC(Accumulator):为ALU提供一个工作区,用来暂存数据(运算结果或源操作数的存放区)

    以上两个常考

  • 数据缓冲寄存器DR(Data Register):写内存时,暂存指令或数据

  • 状态条件寄存器PSW(Program Status Word):存状态标志与控制标志(条形码内如,如溢出标志等)

控制器:从主存中取出指令,并指出下一条指令在主存中的位置,取出的指令经指令寄存器送往指令译码器,经过对指令的分析发出相应的控制和定时信息;

控制器的组成部分为:

  • 程序计数器(pc)Program Counter:存储下一条要执行指令的地址(指针)

  • 指令寄存器(ir)Instruction Register:存储即将执行的指令(操作码和地址码)

    以上两个常考

  • 指令译码器(id)Instruction Decoder:对操作进行分析解释

  • 地址寄存器(ar)Address Register:保存当前cpu所访问的内存地址

  • 计算机硬件的典型结构
    • 单总线结构
    • 双总线结构(以cpu为中心、以存储器为中心)
    • 采用通道的大型系统结构。

计算机周期

各种计算机周期

  1. 时钟频率:xx Ghz

  2. 总线周期:cpu完成一次内存访问(读写)或IO接口操作所需要的时间;一个总线周期通常由n个时钟周期组成

  3. 时钟(振荡)周期:时钟频率(xx Ghz)的倒数,是计算机中最基本、最小的时间单位。如2.4Ghz的时钟周期为1/2.4

  4. 机器(cpu)周期:指完成一个基本操作(如取指、读存储器),以读取一个指令的最短时间来规定cpu周期。其包含多个时钟周期

  5. 指令周期:包含 取值-》分析-》执行 的时间,其可能包含0-多条总线周期

  6. 存储周期:主存储器两次启动操作之间需要的最小时间间隔,即存储器周期时间

其中:时钟周期 < 机器(cpu)周期 ~= 总线周期 < 指令周期

计算机数据表示

存储单位

数据的最小存储单位是bit(比特/位),一个b为一个二进制位(做存储空间的题时一定要转换成二进制先),一个字节(B)为8个二进制位

k、m、g是数量单位,每个单位相差1024倍

b,B是存储单位

即1B=8bit,1kB=8kb

运算方式:不要硬算,化简为2 的幂指数来计算

做题步骤:①先将十六进制的多少位(字节)算出来

②将该十六进制数用2^n n次方的十进制形式表示出来

③根据题目再进行相应的乘法除法运算

R进制

二进制0b十六0x或H

基本概念

  • 数制:r进制
  • 基数:就是每一位的数码可以有多少个数字来表示。其实就是所谓的进制,十进制,基数为十,数码可以取的值有10个,分别是0~9。
  • 数码:该r进制可以使用的符号
  • 数位:个位十位百位
  • 位权:个位数上的1 的权值为 10^0,十位数上的1 的权值为 10^1 ,百位数上的1 的权值为 10^2 。
  • 二进制转八/十六进制:分3/4个一组

    相反同理

  • r进制转十进制:位权展开法,从0,1,2,3…累加

  • 十进制转r进制:取余后从下往上取值

算数逻辑运算

  • 加减乘除

    二进制的除法运算,属于模二运算,模二运算的特点是:没有进位

    模二加法:0+0=0 0+1=1 1+0=1 1+1=0

    模二减法:0-0=0 0-1=1 1-0=1 1-1=0

    模二乘法:0x0=0 0x1=0 1x0=0 1x1=1

  • 二进制的与运算(逻辑乘),用**^**,and,-表示

  • 或运算(逻辑加),用v,+,or表示

  • 异或用一个用O包围的+,**xor,^**表示

    上述的是位运算符,异则是1,编程里,^表示的是异或运算,&才是并

    逻辑运算符

    • 与:^
    • 或:v
    • 非: ¬ \neg ¬

    位运算符

    • 与:&
    • 或:|
    • 异或:^

数据在计算机中的表示方法(机器码和码制)

各种数据在计算机中表示的形式称为机器数0开头表示正号,1开头表示负号小数点隐含表示且不占位置机器数对应的实际数据称为真值。机器数分为无符号数(unsigned)和有符号数(正和负数)。无符号数表示正数。

  • 原码:真值,0开头正,1开头负,默认是8位,没有添0

  • 反码:负数就取反(开头1不动),正数相同

  • 补码:正数相同,负数为反码+1

    负数的补码=原码取反+1;负数的原码同样=补码+1

    补码是为了消除+0和-0

    常用于加减法

  • 移码:=补码,但是开头符号位取反

    常用于浮点数的阶码

机器码能够表示的不同的有符号整数(定点小数)个数
原码2^n - 1 = 2^(n-1) + 2^(n-1) + 1
反码2^n - 1
补码2^n
移码2^n

因为补码负数时+了1,所以原码和反码比补码和移码少一位,补码比他们多一位

例:用8位二进制表示

  • 原码:-127-127共有254+相同的两个0=255个数 = 2^n - 1
  • 反码:-127-127共有254+相同的两个0=255个数 = 2^n - 1
  • 补码:-128-127共有255+两个0=256个数 = 2^n

定点数和浮点数

  • 定点整数:符号真值.(小数点在最右)

  • 顶点小数:符号.真值(小数点在真值前面)

  • 浮点数:N=M*R^e

    N是数符,M是尾数,e是指数(阶码),R是基数(阶码的底)

    浮点数计算方法:

    • 对阶:使次方相同(规则:小变大,增加几位,末尾就移除几位)
    • 尾数计算相加减
    • 结果格式化(负数变成1.0xxxx或正数变成0.1xxxx)

    浮点数所能表示的数值范围是由阶码确定的,所表示的数值精度由尾数决定

    image-20240330185624552

校验码(不考)

  • 码距:就单个编码A:00而言,其码距为1,因为其只需要改变一位就变成另一个编码。在两个编码中,从A码到B码转换所需要改变的位数称为码距,如A:00要转换为B:11,码距为2。一般来说,码距越大,越利于纠错和检错。
  • 奇偶校验码:在编码中增加1位校验位来使编码中1的个数为奇数(奇校验)或者偶数(偶校验),从而使码距变为2(一个是校验码另一个是本身的错误)。例如:
  • 奇校验:编码中,含有奇数个1,发送给接收方,接收方收到后,会计算收到的编码有多少个1,如果是奇数个,则无误,是偶数个(+0),则有误(+1)。
  • 偶校验同理,只是编码中有偶数个1,由上述,奇偶校验只能检1位错,并且无法纠错。

crc冗余校验码

  • CRC的全称是循环冗余校验(Cyclic Redundancy Check)。**CRC只能检错,不能纠错。使用CRC编码,需要先约定一个生成多项式G(x)。**生成多项式的最高位和最低位必须是1。假设原始信息有m位,则对应多项式M(x)。生成校验码思想就是在原始信息位后追加若干校验位,使得追加的信息能被G(x)整除。接收方接收到带校验位的信息,然后用G(x)整除。余数为0,则没有错误;反之则发生错误。

    例:假设原始信息串为10110,CRC的生成多项式为G(x)=x^4+x+1,求CRC校验码。

    (1)在原始信息位后面添0,假设生成多项式的阶为r,则在原始信息位后添加r个0,本题中,G(x)阶为4,则在原始信息串后加4个0,得到的新串为101100000,作为被除数

    (2)由多项式得到除数,多项中x的幂指数存在的位置1,不存在的位置0。本题中,x的幂指数为0,1,4的变量都存在,而幂指数为2,3的不存在,因此得到除数10011。

    (3)生成CRC校验码,将前两步得出的被除数和除数进行模2除法运算(即不进位也不借位的除法运算)。**除法过程(好像是异或运算)**如下图所示。

    得到余数1111(余数的位数要和阶数要和r相同)。

    注意:余数不足r,则余数左边用若干个0补齐。如求得余数为11,r=4,则补两个0得到0011。

    该余数也就是crc的校验位

    (4)生成最终发送信息串,将余数(校验位)添加到原始信息后(变成校验码)。上例中,原始信息为10110,添加余数1111后,结果为101101111。发送方将此数据发送给接收方。

    (5)接收方进行校验。接收方的CRC校验过程与生成过程类似,接收方接收了带校验和的帧后,用多项式G(x)来除。余数为0,则表示信息无错;否则要求发送方进行重传。

    注意:收发信息双方需使用相同的生成多项式。

    image-20240330170308072

海明校验码

  • 海明码:本质也是利用奇偶性来检错和纠错的检验方法,构成方法实在数据位之间的确定位置上插入k个校验位,通过扩大码距实现检错和纠错

    设数据位是s位,校验位是j位,则s和j必须满足以下关系:2^j-1>=s+j

    比如一个有10位数海明码,那么它的校验位最大的位数为8

    又比如一个有10位的数据,则至少需要添加4位的校验位才能成为海明校验码

例:求信息1011的海明码

  • 1.校验位的位数和具体的数据位的位数之间的关系

    所有位都编号,从最低位编号(最右边开始),从1开始递增,校验位处于2的n(n=012.....)次方中即处于第1,2,4,8,16,32,.....位上,其余位才能填充真正的数据位,若信息数据为1011,则可知,第1,2,4位为校验位,第3,5,6,7位为数据位,用来从高位开始存放1011,得出信息位和校验位分布如下:

    因此可以得知所有的校验码都比信息位中位数最大的位数要小

  • 2.计算校验码

    将所有信息位的编号都拆分成二的n次表示后,校验位的值=校验的信息位的异或运算,如下图所示:

    上图中,7=4+2+1,表示7由第4位校验位(r2)和第2位校验位(r1)和第1位校验位(ro) 共同校验,同理,第6位数据位6=4+2,第5位数据位5=4+1,第3位数据位3=2+1,

    前面知道,这些2的n次方都是校验位,可知,第4位校验位校验第765三位数据 位,因此,第4位校验位r2等于这三位数据位的值异或,第2位和第1位校验位计 算原理同上.

    计算出三个校验位后,可知最终要发送的海明校验码为1010101(校验位穿插在中间,和信息位组成校验码。不像crc校验位在末尾)

  • 3.检错和纠错原理

    接收方收到海明码之后,会将每一位校验位与其校验的位数分别异或,即做如下三组运算:

    如果是偶校验,那么运算得到的结果应该全为0,如果是奇校验,应该全为1,才是正确,假设是偶校验,且接收到的数据为1011101(第四位出错),此时,运算的结果为:

    这里不全为0,表明传输过程有误(用了偶检验),并且按照r2r1r0排列为二进制100,这里指出的就是错误的位数,表示第100,即第4位出错,找到了出错位,纠错方法就是将该位逆转。

image-20240330165955622

计算机体系结构

指令流数据流

  • 处理机的数量进行分类:单处理系统(一个处理单元和其他设备集成)、并行处理系统(两个以上的处理机互联)分布式处理系统(物理上远距离且松合的多计算机系统)。

  • Flynn分类法:分类有两个因素,即指令流和数据流,指令流由控制部分处理,每一个控制部分处理一条指令流,多指令流就有多个控制部分;数据流由处理器来处理,每一个处理器处理一条数据流,多数据流就有多个处理器;至于主存模块,是用来存储的,存储指令流或者数据流,因此,无论是多指令流还是多数据流,都需要多个主存模块来存储,对于主存模块,指令和数据都一样

    指令流is(instruction stream)指机器执行的指令序列

    数据流ds指指令流调用的数据序列

  • 依据计算机特性,是由指令来控制数据的传输,因此,一条指令可以控制一条或多条数据流,但一条数据流不能被多条指令控制,否则会出错,就如同上级命令太多还互相冲突不知道该执行哪个,因此多指令单数据MISD不可能,如下图所示

Single Instruction Single Data stream

M就是Multiple

单指令流都是一个控制器,多指令流都是多个控制器,表示的是执行单条指令还是不同指令

单数据流都是一个处理器,多数据流都是多个数据器,数据流表示的是同步进行还是异步进行

主存模块只有两个“单”才是单,否则都是多

image-20240330165139332

image-20240330165111669

指令系统

计算机指令的组成:一条指令由操作码和操作数两部分组成

  • 操作码决定要完成的操作,操作数指参加运算的数据及其所在的单元地址。在计算机中,操作要求和操作数地址都由二进制数码表示,分别称作操作码和地址码,整条指令以二进制编码的形式存放在存储器中。

    该二进制数码的前面的是操作码,后面是地址码

  • 计算机指令执行过程:取指令——分析指令——执行指令三个步骤,首先将程序计数器PC中的指令地址取出,送入地址总线, CPU依据指令地址去内存中取出指今内容存入指今寄存器IR:而后由指今译码哭进行分析,分析指会损作码·最后执行指令,取出指令执行所需的源操作数。

指令与操作数的寻址方式

指令寻址方式

  • 顺序寻址方式:当执行一段程序时,是一条指令接着一条指令地顺序执行。

  • 跳跃寻址方式:指吓一跳指令的地址码不是由程序计数器给出而是由本条指令直接给出。程序跳跃后,按新的指令地址开始顺序执行。因此,程序计数器的内容也必须相应改变,以便及时跟踪新的指令地址。

指令一般存在主存里

指令操作数的寻址方式

  • 立即寻址方式指令的地址码字段指出的不是地址,而是操作数本身

    如一个数字:45

  • 直接寻址方式:在指令的地址字段中直接指出操作数在主存中的地址

  • 相对寻址:指令地址码给出的是一个偏移量(可正可负),操作数地址等于本条指令的地址加上偏移量

  • 间接寻址方式:指令地址码字段所指向的存储单元中存储的是操作数的地址

经过中点站

  • 基址寻址方式:将基址寄存器的内容加上指令中的形式地址而形成操作数的有效地址,其优点是可以扩大寻址能力。

  • 变址寻址方式:变址寻址方式计算有效地址的方法与基址寻址方式很相似,它是将变址寄存器的内容加上指令中的形式地址而形成操作数的有效地址。

操作数可能在寄存器可能在其他地方

  • 寄存器寻址:操作数存放在某一寄存器中,指令中给出存放操作数的寄存器名

    如:MOV RI,其中RI表示RIGISTER寄存器

  • 寄存器间接寻址:操作数存放在内存单元中,操作数所在存储单元的地址在某个寄存器中

CISC/RISC

CISC(Complex Instruction Set Computer)是复杂指令系统计算机,兼容性强,指令繁多、长度可变,由微程序实现;

RISC(Reduced Instruction Set Computer)是精简指令系统计算机,指令少,使用频率接近,主要依靠硬件实现(通用寄存器、硬布线逻辑控制)。

具体区别如下:

指令系统类型指令寻址方式实现方式其它
CISC(复杂数量,使用频率流到士可变长格式支持微程序控制技术(微码)研制周期
RISC(精简数量,使用频率接近,定长格式,大部分为单周期指令,操作寄存器,只有Load/Store操作内存支持方式增加了通用寄存器;硬布线逻辑控制为主:效支持高级语适合采用流水线优化编译,效支持高级语言

扩展:

  1. X86架构由Intel公司设计并长期使用,原属于CISC(复杂指令集)型架构。
  2. ARM架构由ARM公司设计,广泛用于移动设备等低功耗场景,是RISC(精简指令集)型架构。arduino,stm32,树莓派都是arm。
  3. RISC-V,如其名,是一种开源的RISC(精简指令集)型架构。
  4. MIPS架构一般用于嵌入式系统或微控制器,也是RISC(精简指令集)型架构。
  5. 树莓派:cisc:不是芯片,而是一个集成的电路板,是基于linux的一个微型计算机。
  6. 单片机是把非常微小的CPU,内存,定时器,和各种外部接口集成在一个芯片上,形成了芯片级别的微型计算机。
  7. Arduino一般认为是使用avr系列8位单片机的开发板和atmel公司的arm开发板,当然现在也有其他开发板,比如esp8266,esp32,stm32系列,飞思卡尔的k系列,这里我们说Arduino就单只8位单片机。

流水线

指令流水线原理:将指令分成不同段,每段由不同的部分去处理,因此可以产生叠加的效果,所有的部件去处理指令的不同段

如果不采用流水线就是串行的方式

复杂指令系统计算机没有流水线

流水线采用异步控制反而会增加控制电路的复杂性,并且不会带来性能改善

RISC中的流水线技术:

(1)超流水线(Super Pipe Line)技术。它通过细化流水、增加级数和提高主频,使得在每个机器周期内能完成一个甚至两个浮点操作。其实质是以时间换取空间

原本指令分3步,现在分更多的步骤

(2)超标量(Super Scalar)技术。它通过内装多条流水线来同时执行多个处理,其时钟频率虽然与一般流水接近,却有更小的CPI。其实质是以空间换取时间

加硬件

(3)超长指令字(Very Long Instruction Word,VLIW)技术。 VLIW和超标量都是20世纪80年代出现的概念,其共同点是要同时执行多条指令,其不同在于超标量依靠硬件来实现并行处理的调度,VLIW则充分发挥软件的作用,而使硬件简化,性能提高。

流水线的时间计算

  • 流水线周期:指令分成不同执行段,其中执行时间最长(最慢)的段为流水线周期。

  • 流水线执行时间:1条(段)指令总执行时间+(总指令条数-1)*流水线周期。

  • 实际流水线吞吐率计算:吞吐率即单位时间内执行的指令条数。公式:总指令条数/流水线执行时间。

  • 流水线的最大吞吐率计算:流水线的最长周期的倒数,即1/最长周期

  • **流水线的加速比计算:**加速比即使用流水线后的效率提升度,即比不使用流水线快了多少倍,越高表明流水线效率越高,公式:不使用流水线执行时间/使用流水线执行时间。

流水线的加速比值结果>1

1s=103nm=106us(微秒)=10^9ns

当缓冲区的数量少于执行任务中出现的缓冲区的数量时,需要把任务里有缓冲区的合并起来,直至满足目前所有的缓冲区数量

image-20240324170242006

流水线采用异步控制不会明显增高其性能

存储系统

概念

上面的梯形表示:上面是速度快,容量小,价格高;下面是慢大低

cpu的寄存器一般是为单位,如32位

cache:m为单位,如3m

主存储器(内存):G

联机硬盘存储器:g或t,外盘

脱机光盘、磁盘存储器,外盘

  • 计算机采用分级存储体系的主要目的是为了解决存储容量、成本和速度之间的矛盾问题

  • 两级存储:Cache-主存(cache缓冲和内存)、主存-辅存(虚拟存储体系)

  • 局部性原理:总的来说,在CPU运行时,所访问的数据会超向于一个较小的局部空间地址内,包括下面两个方面:

    时间局部性原理:如果一个数据项正在被访问,那么在近期它很可能会被再次访问,即在相邻的时间里会访问同一个数据项

    空间局部性原理:在最近的将来会用到的数据的地址和现在正在访问的数地址很可能是相近的,即相邻的空间地址会被连续访问。

cache

  • 高速缓存Cache用来存储当前最活跃的程序和数据,直接与CPU交互位于CPU和主存之间,容量小,速度为内存的5-10倍,由半导体材料构成。其内容是主存内存的副本贝,对于程序员来说是透明的。

  • Cache由控制部分和存储器组成存储器存储数据,控制部分判断CPU要访问的数据是否在Cache中,在则命中,不在则依据一定的算法从主存中替换。

  • 地址映射:在CPU工作时,送出的是主存单元的地址,而应从Cache存储器中读/写信息。这就需要将主存地址转换为Cache存储器地址,这种地址的转换称为地址映像,由硬件自动完成映射,分为下列三种方法:

    考点:由硬件自动完成映射,不需要程序员自己去设定

直接映像

将cache存储器等分成块,主存也等分成块并编号。主存中的块与Cache中的块的对应关系是固定的,也即二者块号相同才能命中。地址变换简单但不灵活,容易造成资源浪费。 (如图所示)

考点:

  1. 优点:地址变化简单、访问速度快

  2. 缺点:块冲突率最高、cache空间得不到充分利用

  3. 主存地址构成:

    主存区号区内块号块内地址

    注:这里每个区号都占一个编址地址,也就是说,主存总块数就是主存占的多少位的位数

  4. Cache的块数(区内块号位数)=高速缓存容量 / 每一块的大小

  5. 主存区号个数(主存占多少位):主存容量 / 高速缓存容量

  6. 块内地址占位数:块的大小转换成2的n次方

  7. 主存地址位数=主存区号+主存块号+块内地址(即上述三项相加)

    image-20240412141243357

全相联映像

同样都等分成块并编号。主存中任意一块都与cache中任意一块对应。因此可以随意调入Cache任意位置(不用担心类似哈希冲突那样,他会自动跑去空的位置),但地址变换复杂,速度较慢。因为主存可以随意调入Cache任意块,只有当Cache满了才会发生块冲突,是最不容易发生块冲突的映像方式。

考点:

  1. 优点:灵活,块冲突率最低,只有在cache中的快全部装满后才会出现冲突,cache利用率高

  2. 缺点:无法从主存块号中直接获得所对应的cache的块号,变换比较复杂,地址变换速度慢,成本高

  3. 主存地址构成:

    主存区号块内地址
组组相连映像

前面两种方式的结合将Cache存储器先分块再分组,主存也同样先分块再分组,组间采用直接映像,即主存中组号与Cache中组号相同的组才能命中,但是组内全相联映像,也即组号相同的两个组内的所有块可以任意调换。

考点:

  1. 组组相连映像冲突概率位于直接映像和全相联映像中
  2. 主存地址位数=区号+组号+主存块号+块内地址
  3. cache地址位数(块内地址位数)=组号+组内块号+块内地址

一组多少块是没用的信息。

主存地址的位数=块的大小*主存的块数量 (结果取2的n次方)

主存区号的位数=主存块数量/cache块数量

cache的性能分析

Hc为cache的命中率,tc为cache的存取时间,tm为主存的访问时间,则cache存储器的等效加权平均访问时间ta为:

ta=Hctc+(1-Hc)tm

也就是:等效加权平均访问时间=cache命中率*cache存取时间+cache未命中率*访问主存时间

存储单位

数据的最小存储单位是bit(比特/位),一个b为一个二进制位(做存储空间的题时一定要转换成二进制先),一个字节(B)为8个二进制位

k、m、g是数量单位,每个单位相差1024倍

b,B是存储单位

即1B=8bit,1kB=8kb

运算方式:不要硬算,化简为2 的幂指数来计算

存储器分类

  1. 按存储器所处位置分类

    • 内存:…
    • 外存:…
  2. 按存储器构成材料分类

    • 磁存储器
    • 半导体存储器
    • 光存储器
  3. 按存储器工作方式分类

    • 读写存储器(Random Access Memory,RAM,就是随机存储器)。其是既能读取数据也能存入数据的 存储器。
    • 只读存储器。根据数据的写入方式,这种存储器又可分为ROM、PROM、EPROM和EEPROM等类型。
      • 固定只读存储器(read Only Memory,ROM)。这种存储器的内容是在厂家生产时就写好的,其内容只能读出,不能改变。一般用于存放系统程序BIOS以及用于微程序控制。
      • 可编程的只读存储器(Programmable read Only Memory,PROM)。其中的内容可以由 用户一次性地写入,写入后不能再修改。
      • ③可擦除可编程的只读存储器(Erasable Programmable read Only Memory,EPROM)。其 中的内容既可以读出,也可以由用户写入,写入后还可以修改。改写的方法是写入之前先用紫外线照射15~20分钟以擦去所有信息,然后再用特殊的电子设备写入信息。
      • ④电擦除可编程的只读存储器(Electrically Erasable Programmable read Only Memory, EEPROM)。与EPROM相似,EEPROM中的内容既可以读出,也可以进行改写。只不过这种存储器是用电擦除的方法进行数据的改写。
      • ⑤闪速存储器(Flash Memory)。其简称闪存,闪存的特性介于EPROM和EEPROM之 间,类似于EEPROM,也可使用电信号进行信息的擦除操作。整块闪存可以在数秒内删除,速度远快于EPROM。
  4. 按访问方式分类

    存储器按访问方式可分为按地址访问的存储器和按内容访问的存储器。

  5. 按寻址方式分类

    存储器按寻址方式可分为随机存储器、顺序存储器和直接存储器。

    (1)随机存储器(Random Access Memory,RAM)。这种存储器可对任何存储单元存入 或读取数据,访问任何一个存储单元所需的时间是相同的。

    (2)顺序存储器(Sequentially Addressed Memory,SAM)。访问数据所需要的时间与数据 所在的存储位置相关,磁带是典型的顺序存储器。

    (3)直接存储器(Direct Addressed Memory,DAM)。介于随机存取和顺序存取之间的一 种寻址方式。磁盘是一种直接存取存储器,它对磁道的寻址是随机的,而在一个磁道内则是顺序寻址。

    不是dma数据交互方式,而是dam存储器

随机访问存储器

随机访问存储器(ram)分为静态ram和动态ram两类。静态比动态更快也更贵

  • sram:常用来做高速缓存存储器
  • dram:用来作为主存及图形系统的帧缓冲存储区

外存储器

详细参考:

数字存储完全指南 02:机械硬盘的原理与参数详解 - 少数派 (sspai.com)

存储技术详解,有这一篇就够了 - 知乎 (zhihu.com)

  1. 磁盘存储器(硬盘)

    • 磁盘结构和参数

      磁盘有正反两个盘面,每个盘面有多个同心圆,每个同心圆是一个磁道(从外到里编号,最外一圈是0道,每个同心圆又被划分为多个扇区,数据就被存放在一个个扇区中

      磁头首先要寻找到对应的磁道,然后等待磁盘进行周期旋转,旋转到指定的扇区,才能读取到对应的数据,因此,会产生寻道时间(寻磁道)和等待时间(转到数据)

      公式为:存取时间=寻道时间+等待时间(平均定位时间+转动延迟)。

      注意:寻道时间是指磁头移动到磁道所需的时间;等待时间为等待读写的扇区转到磁头下方所用的时间。

  2. 光盘存储器

    • co-rom
    • worm

不考,但是是硬盘的相关知识

  1. 文件系统

    用来管理目录和文件的系统叫做文件系统,它规定了文件和目录数据如何储存到储存设备上,Windows 用的文件系统是 NTFS。

    因为我们很少有只占用一个扇区以下的文件,所以文件系统会将磁盘面上相邻的若干个扇区合并为一个簇(又叫分配单元,Unix 类系统叫块,反正都是一个意思)文件系统进行读写操作的基本单位就是簇。

    可以看到大小和占用空间两个属性,后面跟着的容量是不同的。「大小」就是文件的实际大小,「占用空间」就是这个文件在磁盘上占用的簇大小 ,因为 10.2 KB > 8KB,而 NTFS 文件系统的簇大小是 4KB,所以他必须要占三个簇,也就是 12KB。比较大的文件看着大小和占用空间可能一样,但仔细观察后面的字节数,也会发现相差了簇以内的字节。

虚拟存储器

实际上是一种逻辑存储器

​ 在概念上,可以将主存存储器看作一个由若干个字节构成的存储空间,每个字节(称为一个存储单元)有一个地址编号,主存单元的该地址称为物理地址(physicaladdress)。当需要访问主存中的数据时,由CPU给出要访问数据所在的存储单元地址,然后由主存的读写控制部件定位对应的存储单元,对其进行读(或写)操作来完成访问操作。
​ 现代系统提供了一种对主存的抽象,称为虚拟存储(virtualmemory),使用虚拟地址(viraladdress,由CPU生成)的概念来访问主存,使用专门的MMU(Memory Management unit)将虚拟地址转换为物理地址后访问主存。设主存容量为4GB,则其简化后的访问操作和内存模型如图1-13所示。

转换检测缓冲区:将虚拟地址映射到物理地址的硬件机制

​ **虚拟存储器实际上是一种逻辑存储器,实质是对物理存储设备进行逻辑化的处理,并将统的逻辑视图呈现给用户。**因此,用户在使用时,操作的是虚拟设备,无需关心底层的物理环境,从而可以充分利用基于异构平台的存储空间,达到最优化的使用效率。

真题

虚拟存储管理系统的基础是程序的局部性理论,这个理论的基本含义是指程序执行时往往会不均匀地访问主存储器单元。根据这个理论,Denning提出了工作集理论。工作集是进程运行时被频繁地访问的页面集合。在进程运行时,如果它的工作集页面都在主存储器内,能够使该进程有效地运行,否则会出现频繁的页面调入/调出现象

image-20240324200354998

相联存储器

相联存储器是一种按内容访问的存储器

输入输出技术(外设)

主存与外设之间的相互联系

I/O设备

IO设备可分为块设备和字符设备两类。块设备把信息存放在固定大小的块中,每个块都有自己的地址,独立于其他块,可寻址例如磁盘、USB闪存、CD-ROM等。字符设备以字符为单位接收或发送一个字符流字符设备不可以寻址例如打印机、网卡、鼠标键盘等

IO设备一般都包含设备控制器,一般以芯片的形式出现,如南桥芯片。不同的控制器可以控制不同的设备。南桥芯片中包含了多种设备的控制器,如硬盘控制器、USB控制器、网卡、声卡控制器等。IO设备通过总线以及卡槽与计算机其他部件进行连接,如PCI、PCI-E、SATA、

  • 计算机系统中存在多种内存与接口地址的编址方法,常见的是下面两种:

    • 1)内存与接口地址独立编址方法

      内存地址和接口地址是完全独立的两个地址空间访问数据时所使用的指令也 完全不同,用于接口的指令只用于接口的读/写,其余的指令全都是用于内存的。 因此,在编程序或读程序时很易使用和辨认。这种编址方法的缺点是用于接口 的指令太少、功能太弱。

    • 2)内存与接口地址统一编址方法

      内存地址和接口地址统一在一个公共的地址空间里,即内存单元和接口共用地 址空间。优点是原则上用于内存的指令全都可以用于接口,这就大大地增强了 缺点就在于整个地址空间被分成两部分,其中一部分分配给接口使用,剩余的 为内存所用,这经常会导致内存地址不连续。

  • 计算机和外设间的数据交互方式:(常考)

    • 程序控制(查询/直接)方式:CPU主动查询外设是否完成数据传输,效率极低

      等到外设传输完成后,cpu才能做别的,相当于串行

    • **程序中断方式:**外设完成数据传输后,向cpu发送中断,等待cpu处理数据效率相对较高。**中断响应时间指的是从发出中断请求到开始进入中断处理程序; 中断处理时间指的是从中断处理开始到中断处理结束。中断向量提供中断服务 程序的入口地址。**多级中断嵌套,使用堆栈来保护断点和现场。

      可以同时进行

    • DMA方式(direct memory access,直接主存存取):cpu秩序完成必要的初始化等操作,数据传输的整个过程都由DMA控制器来完成,在主存和外设之间建立直接的数据通路, 效率很高。

      cpu不参与,dma自己完成

    在一个总线周期结束后,CPU会响应DMA请求开始读取数据;CPU响应程序中 断方式请求是在一条指令执行结束时。

总线结构

总线(Bus),是指计算机设备和设备之间传输信息的公共数据通道。总线是 连接计算机硬件系统内多种设备的通信线路,它的一个重要特征是由总线上的 所有设备共享,因此可以将计算机系统内的多种设备连接到总线上。

一条总线同一时刻仅允许一个设备发送,但允许多个设备接收。

总线:连接多个部件的信息传输线,是各部件共享的传输介质

  • 从广义上讲,任何连接两个以上电子元器件的导线都可以称为总线,通常分 为以下三类:

    • 内部总线(电路板上):内部芯片级别的总线,芯片与处理器之间通信的总线。

      书上没这种,不考

      系统总线(内部线):是板级总线 用于计算机内各部分之间的连接,具体分为

      • 数据总线Data Bus DB(并行数据传输位数,如32位)

      • 地址总线AB(系统可管理的内存空间的大小(32位系统最大只能支持2^32=4gb内存))

      • 控制总线 CB(传送控制命令)。代表的有ISA总线、EISA总线、PCI总线。

      系统总线目的在于增减外设(更换内存条等),同时减少信息传输线(注意是线)的数量;但缺点在于降低了信息传输的并行性、信息的传输速度

      • 优点:
        • 简化了系统结构,便于系统设计制造
        • 大大减少了连线数目,便于布线,减小体积,提高系统的可靠性
        • 便于接口设计,所有与总线连接的设备均采用类似的接口
        • 便于系统的扩充、更新与灵活配置,易于实现系统的模块化
        • 便于设备的软件设计,所有接口的软件就是对不同的接口地址进行操作
        • 便于故障诊断和维修,同时也降低了成本

      特点:在某一时刻,只允许有一个不见向总线发生信息,但多个部件可同时从总线接受相同信息。总线的信息传输可以串行和并行

    • 外部总线:设备一级的总线,微机和外部设备的总线。代表的有RS232(串行总 线)、SCSI(并行总线)、USB(通用串行总线,即插即用,支持热插拔)。

      书上没这种,不考

      总线的性能指标:

      带宽、位宽、工作频率

    image-20240330171300916

    总线宽度指的是总线的位数,即数据信号的并行传输能力,也体现总线占用的物理空间和成本;总线的带宽指总线最大数据传输率,即每秒传输的数据总量,总线宽度和始终频率共同决定了总线的带宽:总线带宽=时钟频率/时钟周期*总线宽度

单总线:只有一条线,很多设备挂载在这一条线上,上面的设备都能同时接受数据,但同一时刻,只能由一台设备接受数据,不同时刻才能多台

输入输出控制

程序控制方式

(1)无条件传送:外设总是准备好的,无条件,随时接收和提供数据。
(2)程序查询方式:CPU利用程序来查询外设的状态,准备好了再传数据。

中断方式

CPU不等待,也不执行程序去查询外设的状态,而是由外设在准备好以后,向CPU发出中断请求信号通知CPU,CPU收到中断请求信号以后,保存正在执行程序的现场,转入I/0中断服务程序的执行,然后再返回到被打断的程序继续执行
在有多个中断源的情况下,常用的处理方法有中断信号线法、中断软件查询法、菊花链法,总线仲裁法,中断向量表法。可以按中断源的优先级来安排服务的先后顺序

(1)多中断信号线法。每个中断源都有属于自己的一根中断请求信号线向CPU提出中断
请求。
(2)中断软件查询法。当CPU检测到一个中断请求信号以后,即转入到中断服务程序去轮询每个中断源以确定是谁发出了中断请求信号。对各个设备的响应优先级由软件设定。
(3)菊花链法。软件查询的缺陷在于花费的时间太多。菊花链法实际上是一种硬件查询法所有的IO模块共享一根共同的中断请求线,而中断确认信号则以链式在各模块间相连。当CPU检测到中断请求信号时,则发出中断确认信号。中断确认信号依次在IO模块间传递,直到发出请求的模块,该模块则把它的I送往数据线由CPU读取
(4)总线仲裁法。一个IO设备在发出中断请求之前,必须先获得总线控制权,所以可由总线仲裁机制来裁定谁可以发出中断请求信号。当CPU发出中断响应信号后,该设备即把自己的ID发往数据线
(5)中断向量表法。中断向量表用来保存各个中断源的中断服务程序的入口地址。当外设发出中断请求信号(INTR)以后,由中断控制器(INTC)确定其中断号,并根据中断号查找中断向量表来取得其中断服务程序的入口地址,同时INTC把中断请求信号提交给CPU

image-20240408193536831

中断嵌套:在一个中断中调用了另一个中断(优先级更高

优先级情况:

  1. 多个中断源则选择优先级高的
  2. 中断嵌套问题
直接内存存取(DMAC)方式

数据的传输是在 主存和外设之间直接进行的,不需要cpu的干预,只需要cpu在过程开始和结束时发出一些命令,实际操作是由DMA硬件之间执行完成的,期间cpu可以处理别的任务

IO通道方式和外围处理机(IOP)方式

更进一步减轻了CPU对IO操作的控制,更进一步提高了CPU的工作效率,但是是以增加更多硬件为代价的

数据传输方式

控制方式特点内容子分类备注
cpu程序查询CPU主动,轮询外设,原理简单,CPU效率低外设主动,无条件传送不考虑外设状态,假定它们随时可收发数据
程序中断外设主动,耗时
CPU需先新停当前工作,执行中断,然后返回
查询(有条件传送)执行/操作前先查询设备状态,空闲时操作
DMACDMA速度快
CPU不参与DMAC临时接管
1、DMA需CPU控制传输块大小和内存地址,IO通道不需要
2、DMA控制1台设备与内存传输,/0通道则控制多台
适合少量数据
IO通道类似DMACPU干预更少DMAC只负责传输,管理和控制/设备仍由CPU负
是对DMA控制方式的发展

生物特征认证技术

指通过计算机利用人体固有生物特征(先天)或行为特征(后天)鉴别个人身份

人体特征转换为数字形式存储到计算机中,通过匹配算法完成验证和识别个人身份

  • 生物特征(先天)
    • 人脸识别
    • 指纹识别
    • 虹膜识别
    • 掌静脉识别
    • 声纹识别
  • 行为特征(后天)
    • 笔记识别
    • 步态识别

安全性、可靠性、性能评价

计算机可靠性

可靠性指标

平均无故障时间MTTF(mean time to failure)=1/失效率。

平均故障修复时间MTTR(Mean Time To Repair)=1/修复率。

平均故障间隔时间MTBF(Mean Time Between Failure)=MTTF+MTTR

F:failure;

R:repair;

B:between;

系统可用性=MTTF/(MTTF+MTTR)*100%。

串并联系统可靠性

无论什么系统,都是由多个设备组成的,协同工作,而这多个设备的组合方式可以是串联、并联,也可以是混合模式, 假设每个设备的可靠性为R1,R2…Rn则不同的系统的可靠性公式如下:

  • *串联系统 个设备不可靠,整个系统崩溃,整个系统可靠性R=R1R2Rn。

并联系统可靠性

所有设备都不可靠,整个系统才崩溃,整个系统可靠性R=1-(1-R1)(1-R2).*(1-Rn)。

N模元余系统
  • N模余系统由N个(N=2n+1)相同的子系统和一个表决器组成,表决器把N个子系统中占多数相同结果的输出作为输出系统的输出,如图所示。在N个子系统中,只要有n+1个或n+1个以上子系统能正常工作,系统就能正常工作,输出正确的结果

    少数服从多数:一般以上可靠能正常工作

image-20240330170237220

计算机系统性能评价

  • 性能评测的常用方法
    (1)时钟频率。一般来讲,主频越高,速度越快
    (2)指令执行速度。计量单位KIPS 每秒千万条指令、MIPS 每秒百万条指令(Million Instruction Per Second)。
    (3)等效指令速度法。统计各类指令在程序中所占比例,并进行折算,是一种固定比例法。
    (4)数据处理速率(ProcessingDataRate,PDR)法。采用计算PDR值的方法来衡量机器性能,PDR值越大,机器性能越好。PDR与每条指令和每个操作数的平均位数以及每条指令的平均运算速度有关。
    (5)核心程序法(属于基准程序法)把应用程序中用得最频繁的那部分核心程序作为评价计算机性能的标准程序,也简称为基准程序法,在不同的机器上运行,测得其执行时间,作为各类机器性能评价的依据
  • **基准程序法(Benchmark)**是目前被用户一致承认的测试性能的较好方法,有多种多样的基准程序,包括:
    (1)整数测试程序。同一厂家的机器,采用相同的体系结构,用相同的基准程序测试,得到的MIPS值越大,一般说明机器速度越快
    (2)浮点测试程序。指标MFLOPS(理论峰值浮点速度)
    (3)SPEC基准程序(SPECBenchmark)。重点面向处理器性能的基准程序集将被测计算机的执行时间标准化,即将被测计算机的执行时间除以一个参考处理器的执行时间
    (4)TPC基准程序。用于评测计算机在事务处理、数据库处理、企业管理与决策支持系统等方面的性能。其中,TPC-C是在线事务处理(On-lineTransactionProcessing,OLTP)的基准程序,TPC-D是决策支持的基准程序。TPC-E作为大型企业信息服务的基准程序

信息安全

  • 信息安全含义及属性:保护信息的保密性、完整性、可用性,另外也包括其他属性,如:真实性可核查性、不可抵赖性和可靠性

  • 保密性:信息不被泄漏给未授权的个人、实体和过程或不被其使用的特性包括:(1)最小授权原则(2)防暴露(3)信息加密(4)物理保密:①物理设备②电磁波(拦截)

  • 完整性:信息未经授权不能改变的特性。影响完整性的主要因素有设备故障误码、人为攻击和计算机病毒等。保证完整性的方法包括

    • (1)协议:通过安全协议检测出被删除、失效、被修改的字段

    • (2)纠错编码方法:利用校验码完成检错和纠错功能。

    • (3)密码校验和方法。

    • (4)数字签名:能识别出发送方来源。

    • (5)公证:请求系统管理或中介机构证明信息的真实性

  • 可用性:需要时,授权实体可以访问和使用的特性。 一般用系统正常使用时间和整个工作时间之比来度量

其他属性:

  • 真实性:指对信息的来源进行判断,能对伪造来源的信息予以鉴别

  • 可核查性:系统实体的行为可以被独一无二的追到该实体的特性,这个特性就是要求该实体对其行为负责,为探测和调查安全违规事件提供了可能性。

  • 不可抵赖性:是指建立有效的责任机制,防止用户否认其行为,这一点在电子商务中是极其重要的

    相对重要

  • 可靠性:系统在规定的时间和给定的条件下,无故障地完成规定功能的概率

安全需求

  • 可划分为物理线路安全、网络安全 系统安全和应用安全;从各级安全需求字面上也可以理解:

  • 物理线路就是物理设备 物理环境

  • 网络安全指网络上的攻击、入侵

  • 系统安全指的是操作系统漏洞、补丁

  • 应用安全就是上层的应用软件,包括数据库软件

加密技术

对称(私钥)加密技术

数据的加密和解密的密钥(密码)是相同的,属于不公开密钥加密算法。其缺点是加密强度不高(因为密钥位数少),且密钥分发困难(因为密钥还需要传输给接收方,也要考虚保密性等问题)。优点是加密速度快,适合加密大数据

  • 常见的**对称密钥加密算法(私密)**如下:

    DES(data encryption standard):数据加密标准,是分组加密算法。替换+移位、56(比特)位密钥、64位数据块、速度快,密钥易产生

    3DES:三重DES,两个56位密钥K1、K2。

  • 加密:K1加密->K2解密->K1加密

  • 解密:K1解密->K2加密->K1解密

    AES(advanced encryption standard):高级加密标准,是美国联邦政府采用的一种区块加密标准,这个标准用来替代原先的DES。对其的要求是“至少像3DES一样安全”

    RC-5:RSA数据安全公司的很多产品都使用了RC-5。

    IDEA(international data encryption algorithm):国际数据加密算法,**128位密钥,64(明文和密文都是64比特)**位数据块,比DES的加密性好,对计算机功能要求相对低,主要用于PGP

安全和效率是对立的,无法两全其美

密钥位数为128以内

RC5:适合大量数据的加密

非对称加密技术(公钥)
  • 数据的加密和解密的密钥是不同的,分为公钥和私钥。公开密钥加密算法其缺点是加密速度慢。优点是安全性高,不容易破解
    非对称技术的原理是:发送者发送数据时,使用接收者的公钥作加密密钥,私钥作解密密钥,这样只有接收者才能解密密文得到明文。安全性更高,因为无需传输密钥。但无法保证完整性。如下:

用b的公钥发送,这样只有b的私钥能解开,保证了数据的安全

  • 常见的非对称加密算法如下:
    RSA:三个科学家联名发出,非对称算法,512位(或1024位)密钥,计算机量极大,难破解。
  • DSA:也可以用于数字签名
  • Elgamal、EcC(圆曲线算法,用于比特币加密)、背包算法、Rabin、D-H等。

(对称加密和非对称加密的联合使用)

对称和非对称加密算法的区别
对称加密算法(带E:encrption)不对称加密算法
AESRSA(三个人)、DSA
DESElgamal
3DESEcC(圆曲线算法,用于比特币加密)、
RC系列背包算法、Rabin、D-H等

相比较可知,对称加密算法密钥一般只有56位,因此加密过程简单适合加密大数据,也因此加密强度不高:而非对称加密算法密钥有1024位,相应的解密计算量庞大,难以破解,却不适合加密大数据,一般用来加密对称算法的密钥

因此对称算法的算法效率比较高

image-20240324153106371

将两个技术组合使用了,这也是数字信封的原理

数字信封原理

(保证了数据的安全性)

数字信封原理:信是对称加密的密钥,数字信封就是对此密钥进行非对称加密,具体过程:发送方将数据用对称密钥加密传输而将对称密钥用接收方公钥加密发送给对方。接收方收到数字信封,用自己的私钥解密信封,取出对称密钥解密得原文。

相当于套了层娃;数字信封运用了对称加密技术和非对称加密技术本质是使用对称密钥加密数据,非对称密钥加密对称密钥,解决了对称密钥的传输问题

image-20240324162414882

数字签名

唯一标识一个发送方,用到了哈希函数,与非对称加密步骤相反

  • 保证了完整性和不可抵赖性,却失去了数据安全性

    通过公钥私钥发送者发送数据时,使用发送者的私钥进行加密,接收者收到数据后,只能使用发送者的公钥进行解密,这样就能唯一确定发送方,这也是数字签名的过程但无法保证机密性。如下:

用途可能就是需要确保是某一方发送的,但同时数据内容不重要,可以公之于众那种

image-20240324162528513

信息摘要

(哈希函数,摘要算法,杂凑算法,密码散列),可以检测数据是否进行了修改,保证了数据的完整性

  • 所谓信息摘要,就是一段数据的特征信息,当数据发生了改变,信息摘要也会发生改变,发送方会将数据和信息摘要一起传给接收方,接收方会根据接收到的数据重新生成一个信息摘要,若此摘要和接收到的摘要相同,则说明数据正确。信息摘要是由哈希函数生成的
  • 信息摘要的特点:不算数据多长,都会产生固定长度的信息摘要;任何不同的输入数据,都会产生不同的信息摘要;单向性,即只能由数据生成信息摘要不能由信息摘要还原数据。
  • 信息摘要算法:
    • MD2
    • MD4
    • MD5:信息摘要算法message-digest algorithm,产生128位的输出
    • SHA-1:安全散列算法1secure Hash Algorithm-1,产生160位的输出,安全性更高
公钥基础设施PKI

公钥基础设施PKI:是以不对称密钥加密技术为基础,以数据机密性、完整性身份认证和行为不可抵赖性为安全目的,来实施和提供安全服务的具有普适性的安全基础设施

  • (1)数字证书:一个数据机构,是一种由一个可信任的权威机构签署的信息集合。在不同的应用中有不同的证书。如×.509证书必须包含下列信息:(1)版本号(2)序列号(3)签名算法标识符(4)认证机构(5)有效期限(6)主题信息(7)认证机构的数字签名(8)公钥信息

  • 公钥证书主要用于确保公钥及其与用户绑定关系的安全。这个公钥就是证书所标识的那个主体的合法的公钥。任何一个用户只要知道签证机构的公钥,就能检查对证书的签名的合法性。如果检查正确,那么用户就可以相信那个证书所携带的公钥是真实的,而且这个公钥就是证书所标识的那个主体的合法的公钥。例如驾照

  • (2)签证机构CA(Certificate Authority):负责签发证书、管理和撤销证书。是所有注册用户所信赖的权威机构,CA在给用户签发证书时要加上自己的数字签名,以保证证书信息的真实性。任何机构可以用CA的公钥来验证该证书的合法性。

image-20240324161745482


image-20240324161904751

多媒体知识

媒体分类

国际电话电报咨询委员会(CCITT将媒体分为感觉媒体、表示媒体、表现媒体、存储媒体和传输媒体5类

  • 感觉媒体指直接作用于人的感觉器官,使人产生直接感觉的媒体,如引起听觉反应的声音,引起视觉反应的图像
  • 传输媒体指传输表示媒体的物理介质,如电缆、光缆、电磁波等;
  • 表示媒体指传输感觉媒体的中介媒体,即用于数据交换的编码如图像编码、文本编码和声音编码
  • 表现媒体是指进行信息输入和输出的媒体,如键盘、鼠标、话筒,以及显示器打印机、喇叭
  • 存储媒体指用于存储表示媒体的物理介质,如硬盘、光盘

总结

感觉媒体:感觉,那就是声音图像这些

传输:顾名思义

表示:编码

表现:主机外设

存储:顾名思义

文件格式

  • wav是声音文件格式
  • bmp是图像格式
  • mov是和视频文件格式

声音频率问题

音频数字化过程中采样频率应为声音最高频率2倍。本题采样频率为8KHz,所以其语音的最高频率应不超过4KHz

像素问题

图像分辨率是指组成一幅图像的像素密度;也是水平和垂直的像素表示;即用每英寸多少点(dpi)表示数字化图像的大小。
300dpi来扫描一幅3*4英寸的彩色照片,那么得到一幅900*1200=3003 * 3004个像素点的图像

多媒体内容接口标准问题

彩色打印机所用的颜色空间

CMY颜色空间

mpeg视频编码

程序语言基础

image-20240322093604201

程序设计语言的基本概念

  • 程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算过程进行描述、组织和推导。

  • 低级语言(面向机器):机器语言(计算机硬件只能识别和1的指令序列),汇编语言。

    何为低级(底级)?

    接近计算机硬件的就是低级,用的是二进制

    何为汇编?

    符号表示的如add,sub之流叫做汇编指令,而汇编语言和高级语言编写的程序称为源程序

  • 高级语言:功能更强,抽象级别更高,与人们使用的自然语言比较接近。

  • 程序设计语言特点

Fortran语言:科学计算,执行效率高
Pascal语言:为教学开发,表达能力强。
C语言:指针操作能力强,可以开发系统级软件,高效结构化语言
C++语言:面向对象,高效。
Java语言:面向对象,中间代码,跨平台
C#语言:面向对象,中间代码,Net框架,微软开发

Python是一种面向对象、解释型、脚本计算机程序设计语言
Prolog是逻辑型程序设计语言。

  • 汇编:将汇编语言翻译成目标程序执行,针对汇编语言

  • 解释和编译:将高级语言来进行执行(不生成可执行文件)。不同之处在于编译程序生成独立的可执行文件,直接运行,运行时无法控制源程序,效率高。而解释程序不生成可执行文件,可以逐条解释执行,用于调试模式,可以控制源程序,因为还需要控制程序,因此执行速度慢,效率低。

    如c语言进行编译有产生exe执行文件

    python是解释,所有没有exe文件

  • 程序设计语言定义四要素:语法、语义、语用和语境。

  • 语法是指由程序设计语言的基本符号组成程序中的各个语法成分(包括程序)的组规则,其中由基本字符构成的符号(单词)书写规则称为词法规则,由符号构成语法成分的规则称为语法规则。

    单词(符号)叫词法,符号就做语法

  • 语义是程序设计语言中按语法规则构成的各个语法成分的含义,可分为静态语义和动态语义。静态语义指编译时可以确定的语法成分的含义,而运行时刻才能确定的含义是动态语义。一个程序的执行效果说明了该程序的语义,它取决于构成程序的各个组成部分的语义。

    image-20240430180040435

  • 语用表示了构成语言的各个记号和使用者的关系,涉及符号的来源使用和影响

  • 语言的实现则有个语境问题。语境是指理解和实现程序设计语言的环境,包括编译环境和运行环境。

程序设计语言定义总结

  1. 词法分析:编译的第一阶段,从中识别出一个个“单词”符号
  2. 语法分析:确定整个输入串是否构成一个语法上正确的程序。一般通过编译的程序,不存在语法上的错误
  3. 语义分析:主要是检查源程序进行类型分析和检查,并收集类型信息供后面的代码生成阶段使 用
  4. 中间代码生成根据语义分析的输出生成中间代码
  5. 目标代码生成:编译的最后一个阶段。是把中间代码转换成机器上的绝对指令代码、可重定位的指令代码或汇编指令代码
  • 程序设计语言的分类
    (1)命令式和结构化程序设计语言,包括Fortran、PASCAL和C语言。

    结构化:自顶向下

    (2)面向对象程序设计语言,包括C++、JAVA和Smalltalk语言。
    (3)函数式程序设计语言,包括LISP、Haskell、Scala、Scheme、APL等。
    (4)逻辑型程序设计语言,包括PROLOG。

    image-20240322093604201

程序设计语言的基本成分

1.数据成分:指一种程序设计语言的数据和数据类型数据分为常量(程序运行时不可改变)、变量(程序运行时可以改变)、全局量(存储空间在静态数据区分配)、局部量(存储空间在堆栈区分配)。数据类型有整型、字符型、双精度、单精度浮点型、布尔型、结构体等。

2.运算成分:指明允许使用的运算符号及运算规则。包括算术运算、逻辑运算关系运算、位运算等。

3.控制成分:指明语言允许表述的控制结构包括顺序结构、、选择结构、循环结构。如下图所示。

​ 4.传输成分:指明语言允许的数据传输方式。 如赋值处理 数据的输入输出等

​ 5.函数:C程序由一个或多个函数组成,每个函数都有一个名字,其中有且仅有个名字为main的函数作为程序运行时的起点。函数的使用涉及3个概念:函数定义、函数声明和函数调用

  • 函数的定义包括两部分:函数首部和函数体。函数的定义描述了函数做什么和怎么做。函数定义的一般形式为:

    返回值的类型函数名(形式参数表)//函数首部

    {

    函数体;

    }

    函数首部说明了函数返回值的数据类型、函数的名字和函数运行时所需的参数及类型。函数所实现的功能在函数体部分进行描述。

  • 函数应该先声明后引用如果程序中对一个函数的调用在该函数的定义之前进行,则应该在调用前对被调用函数进行声明。函数原型用于声明函数。函数声明的一般形式为:

    返回值类型函数名(参数类型表)

  • 函数调用的一般形式为
    函数名(实参表);
    函数调用时实参与形参间交换信息的方法有值调用和引用调用两种。
    (1)值调用(callbyValue)。若实现函数调用时将实参的值传递给相应的形参,则称为是传值调用。在这种方式下形参不能向实参传递信息。
    在C语言中,要实现被调用函数对实参的修改,必须用指针作为参数。即调用时需要先对实参进行取地址运算,然后将实参的地址传递给指针形参。

    其本质上仍属于值调用。这种方式实现了间接内存访问。

    (2)引用调用(CallbyReference)引用是C++中引入的概念,当形式参数为引用类型时,形参名实际上是实参的别名,函数中对形参的访问和修改实际上就是针对相应实参所做的访问和改变。

31

编译程序基本原理

  • 编译程序对高级语言源程序进行编译的过程中,要不断收集、记录和使用源程序中一些相关符号的类型和特征等信息,并将其存入符号表中,编译过程如下:

  • 词法分析:是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)

    输入是字符流

  • 语法分析:是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确

    输入是记号流

    有括号匹配

  • 语义分析:是编译过程的一个逻辑阶段.语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查,进行类型审查如类型匹配、除法除数不为0等。又分为静态语义错误(在编译阶段能够查找出来)和动态语义错误(只能在运行时发现)。

    32

  • 中间代码和目标代码:中间代码是根据语义分析产生的,需要经过优化链接最终生成可执行的目标代码。引入中间代码的目的是进行与机器无关的代码优化处理。常用的中间代码有后缀式(逆波兰式)、三元式(三地址码)、四元式和树等形式。需要考虑三个问题(一是如何生成较短的目标代码;二是如何充分利用计算机中的寄存器,减少目标代码访问存储单元的次数;三是如何充分利用计算机指令系统的特点,以提高目标代码的质量)

    出错分为动态错误和静态错误,动态错误是指程序运行时发生的错误,如input输入一个0后作为除数;静态错误则是运行之前,如标点符号错误等

33

34

数据结构与算法

image-20240322093552812

线性表


无论是线性表的顺序存储还是链式存储,其元素可以是任意数据类型,包括简单的整数、字符,也可以是复杂的如结构体、类的实例

基本概念

线性表是一个具有相同特性的数据元素的有限序列。

一致性(相同特性):所有元素属于同一数据类型。

有穷性:数据元素个数是有限的。

序列:数据元素由逻辑序号唯一确定。一个线性表中可以有相同值的元素。一个线性表中所有元素之间的相对位置是线性的

线性表的入和出的操作都要考虑元素是否满|空

顺序表

随机存取

按逻辑顺序依次存储到存储器中一片连续的存储空间中。

  • 定义

    typedef struct 
    {  ElemType data[MaxSize];
       int length;
    } SqList;    	//顺序表类型  
    

    说明:注意逻辑位序和物理位序相差1。

  • 各算法实现:

    插⼊数据要判满,删除数据要判空

    插⼊删除有可能移动数据

    顺序表中插入一个元素平均移动n/2次,删除一个元素平均移动(n-1)/2,两者的时间复杂度都是O(n)

链表

每个物理结点增加一个指向后继结点的指针域为单链表。

每个物理结点增加一个指向后继结点的指针域和一个指向前驱结点的指针域为双链表。

链表的存储是无序的,但是链表的查找还是得用顺序查找,叫做顺序存取

单链表
  • 单链表的考察(存储密度)

    存储密度=数据占用的空间/结点总占用空间

  • 定义

    typedef int ElemType;
    typedef struct LNode{
    	ElemType data;
    	struct LNode * next;
    }LinkNode; //LNode强调的是结点,LinkNode强调的是链表
    
  • 创建

    创建有头插法和尾插法

    头插法可以同于链表的逆置。逆序

    尾插法正序

双链表

与单链表大同小异,下面只写有区别的

  • 定义

    typedef int ElemType;
    typedef struct LNode{
    	ElemType data;
    	struct LNode * next,*prior;
    }LinkNode; 
    
静态链表

有序表

注意区分顺序表和有序表的概念:有序表要求数据是有序存放的,顺序表没有这个要求

很显然,有序表是线性表的一个子集。

有序表也可以用顺序存储实现或链式存储实现

栈与队列

栈和队列是操作受限制的线性表

LIFO

栈的顺序存储结构入栈都是指针先,出栈都是指针后

顺序栈

演示:Array Stack Visualization (usfca.edu)

  • 定义:

    typedef struct{ 
        Elemtype data[Maxsize]; 
        int top; 
    }SqStack;
    
    • 栈空(初始化):s->top==-1

    • 栈满:s->top==Maxsize-1

    • 进栈:指针先加1

    • 出栈:先取出来,指针再减1

    注意看题目需求条件,也可以栈空从top==0开始,然后入栈就是后指针,出栈就是先指针

    n个元素的合法出栈序列个数**(卡特兰数):**

    Cn 2n/(n+1) == An 2n/(n! * (n+1))

    例如n=4时,=876*5/(4! * 5)=14

因为入栈与出栈不需要移动表中元素,因此入栈出栈时间复杂度都是O(1)

顺序共享栈

是为了节省普通顺序栈中浪费的空间

  • 定义:

    typedef struct{ 
        Elemtype data[Maxsize]; 
        int top,top2; //top是左边下标从0开始的栈,top2是右边下标从Maxsize开始的栈 
    }SqStack;
    
    • 栈空(初始化):栈1空为top1==-1;栈2空为top2==Maxsize

    • 栈满:top1==top2-1

    • 进栈:先动指针

    • 出栈:先取出来,再动指针

  • 算法的实现:多了一个变量用来判断是对哪个栈进行操作,了解即可

链栈

Linked List Stack Visualization (usfca.edu)

  • 定义:

    typedef struct linknode{ 
        Elemtype data; 
        struct linknode *next; 
    }LinkStNode;
    
    • 栈空(初始化):s->next==NULL

    • 栈满:不会栈满

    • 进栈:新建结点头插法

    • 出栈:取出第一个值后删除结点

      p=head->next;e=p->data;head->next=p->next;free§;

    栈底存在时,栈底->next==NULL

栈的应用

  • 括号匹配
  • 表达式求值
  • 递归
  • 求解迷宫
  • (二)进制转换
  • c语言中临时变量
  • 表达式求值

    • 前缀表达式==先序遍历

    • 中缀表达式(加括号)==中序遍历

    • 后缀表达式==后序遍历

      前缀表达式也叫波兰表达式,后缀表达式也叫逆波兰表达式

      转换规则:转换后的运算数的相对位置不能变,但是运算符号可以改变位置,意味着一个中缀表达式可能有多个后缀表达式或前缀表达式。但如果按相同运算符等级从左到右则转换的结果唯一

      转化成后缀表达式后的运算符的从左到右的顺序就是原本中缀表达式中运算符的执行顺序

      前缀:运算符在中缀表达式的操作数的前面;后缀:运算符在中缀表达式的操作数的后面;也就是遵循就近原则

      如中缀:1+2*3

      • 前缀:+1*2 3
      • 后缀:1 2 3 * +

      后缀表达式是从左到右入栈

      前缀表达式是从右到左入栈

队列

FIFO

尾进头出

入动rear

出动front

顺序队

Array Queue Visualization (usfca.edu)

  • 定义:

    typedef struct{ 
        elemtype data[Maxsize]; 
        int rear,front;  //头指针和尾指针的下标 
    }SqQueue;
    
    • 初始化:q->rear=q->front**=-1**

    • 队空:q->front==q->rear

      不一定==-1

    • 队满:q->rear==Maxsize-1

    • 入队:++rear

    • 出队:++front

    如果题目要求初始化从0开始,那么入队出队都是后指针

    注:front始终是首节点的前一个位置

    队的所有入队出队都是先动下标(指针)后放(拿)数据

    有n个空间的队列最多只能执行n次入队,有n个空间的循环队列,最多只能执行n-1次入队

因为入与出操作都不需要移动表中元素,因此入和出的时间复杂度都是O(1)

顺序循环(环形)队

避免空间浪费

循环队,那一定就是顺序存储的队,且该队的操作要取余(除了rear)

  • 定义:

    • 初始化:q->front=q->rear=0

      • 队空:q->rear==q->front

        那么初始化状态也算做队空

        但是队空不一定是0位置

      • 队满:(q->rear+1)%Maxsize==q->front

        队尾指针正好在队头指针的后一位,则队满

        浪费掉一个空间,用来区分队空与队满

      • 入队:q->rear=(q->rear+1)%Maxsize

      • 出队:front=(front+1)%Maxsize

  • 在尾指针头指针和元素个数中仅有两个的情况

    • 元素个数:count=(rear-front+Maxsize)%Maxsize

    • 队头位置:front=(rear-count+Maxsize)%Maxsize

      只要有减号-,那就是需要加上Maxsize再取整的

    • 队尾位置:rear=(front+count)

      注:front始终是首节点的前一个位置

      只有加号+,没有减号-,则与Maxsize无关,不用Maxsize

链队
  • 定义:

    //定义单链表的结构 
    typedef struct qnode{ 
        elemtype data; 
        struct qnode *next; 
    }Datanode;  //表示单链表结点 
    //定义链队的结构 
    typedef struct{ 
        Datanode *front; Datanode *rear; 
    }Linkqunode;  //表示链队结点
    
    • 初始化:q->front=q->rear=NULL

    • 队空:q->rearNULL q->frontNULL

    • 队满:不存在

    • 入队:分配结点,尾插入链表中(链表为空要特殊处理),动尾指针

    • 出队:动头指针(只有一个元素要特殊处理),拿出数据,释放节点空间

    • 判断链队只有一个结点:q->front==q->rear!=NULL

    注:若用无头结点的单链表实现,且此时front指向首节点,默认是头节点

队列的应用

  • 求解报数问题
  • 求解迷宫问题
  • 层次遍历
  • 计算机系统的应用
  • 缓冲区
  • 页面替换算法

栈与队列的区别

队列
主要区别仅关心top,完全不用管栈底即有rear也有front
入操作先指针rear动
出操作先先数据front动

串的基本概念

字符串是一种特殊的线性表,其数据元素都为字符

  • 空串:长度为0的字符串,没有任何字符

  • 空格串:由一个或多个空格组成的串,空格是空白字符,占一个字符长度子串(模式串):串中任意长度的连续字符构成的序列称为子串。含有子串的串称为主串,空串是任意串的子串

  • 串的模式匹配:子串的定位操作,用于查找子串在主串中第一次出现的位置的算法。

  • 串相等:指两个串长度相等且对应位置上的字符也相同

  • 串比较:两个串比较大小时以字符的ASCI码值作为依据。比较操作从两个串的第

    串的基本操作如下:
    ①赋值操作StrAssignst):将串t的值赋给串S
    ②连接操作Concatst:将串t接续在串s的尾部,形成一个新串。
    ③求串长StrLength(s):返回串s的长度。
    ④串比较SuCompare(s,t):比较两个串的大小。返回值-1、0和1分别表示s<t、st和s>t三种情况。
    求子串SubString(s.start.len):返回串s中从start开始的、长度为len的字符序列

串的存储结构

  • 字符串可以采用顺序存储和链式存储方式

    (1)顺序存储。该方式是用一组地址连续的存储单元来存储串值的字符序列。由于串中的元素为字符,所以可通过程序语言提供的字符数组定义串的存储空间(即存储空间的容量固定),也可以根据串长的需要动态申请字符串的空间(即存储空间的容量可扩充或缩减)

    (2)链式存储。字符串也可以采用链表作为存储结构,当用链表存储串中的字符时,每个结点中可以存储一个字符,也可以存储多个字符,需要考虑存储密度问题。结点大小为4的块链如图3-9所示。

模式匹配算法

朴素的模式匹配算法:也称为布鲁特一福斯算法,其基本思想是从主串的第1个字符起与模式串的第1个字符比较,若相等,则继续逐个字符进行后续的比较;否则从主串中的第2个字符起与模式串的第1个字符重新比较,直至模式串中每个字符依次和主串中的一个连续的字符序列相等时为止,此时称为匹配成功否则称为匹配失败

  • 基本模式匹配算法

    int Index(char Slchar Tint pos){
    /*查找并返回模式串T在主串S中从pOs开始的位置(下标),若不是S的子串,则返回-1*i=pos;j=0;/*  i,j分别用于指示出主串字符和模式串字符的位置(下标),若T不是s的子串,则返回—1*/
        i=pos;j=0;   /*i,j分别用于指示出主串字符和模式串字符的位置(下标)*/
    	slen=strlen(s);tlen=strlen(r)/*计算主串和模式串的长度*/
        while(i<slen&&j<tlen){
            if(s[i]==T[j]){
               i++;
               j++;
            }
           else{
               i=i-j+1;       /*主串字符的位置指针回退*/          	 j=-;       /*模式串重新从起始字符开始*/
         }
        if(j>=tlen)
         	return i-tlen;
        return -1;
    }
    

最好O(n+m)

最坏O(n*m)

  • 改进的模式匹配算法
    改进的模式匹配算法又称为KMP算法(由D.E.Knuth、VR.Pratt和J.H.Morris提出),其改进之处在于:每当匹配过程中出现相比较的字符不相等时,不需要回主串字符的位置指针而是利用已经得到的“部分匹配”的结果,将模式串向后“滑动”尽可能远的距离,再继续进行比较。此算法可在O(n+m)的时间内完成

数组矩阵

数组

  • 数组是定长线性表在维度上的扩展,即线性表中的元素又是一个线性表。N维数组是一种“同构”的数据结构,其每个数据元素类型相同、结构一致。

  • 其可以表示为行向量形式或者列向量形式线性表,单个关系最多只有一个前驱和一个后继,本质还是线性的

  • 数组结构的特点:数据元素数目固定;数据元素类型相同;数据元素的下标关系具有上下界的约束且下标有序

  • 数组数据元素固定,一般不做插入和删除运算,适合于采用顺序结构

  • 数组存储地址的计算,特别是二维数组,要注意理解,假设每个数组元素占用存储长度为len,起始地址为a,存储地址计算如下**(默认从0开始编号)**:

矩阵

稀疏矩阵:在一个矩阵中,若非零元素的个数远远少于零元素个数,且非零元素的分布没有规律。

树与二叉树

树和森林

树的性质(重点)
  1. 树总结点树=度之和+1=分支节点总和+1

    度之和=分支结点度数=0*n0+1*n1+2*n2…

  2. 第i层最多有m^(i-1)个结点

  3. 高度为h的m次树的总结点最多为(m^h-1)/(m-1)

    一定要记得高度h的总结点个数还有除数的

  4. 具有n个结点的m次树的最小高度为logm(n(m-1)+1) (上取整)*

树的遍历
  1. 先根遍历

    =森林的先根遍历=二叉树的先序遍历

    这里的意思是先转换成对应的树|二叉树在进行遍历的序列相同

  2. 后根遍历

    =森林的后根遍历=二叉树的中序遍历

  3. 层次遍历

    =图的广度优先遍历

树的存储结构
  1. 双亲存储

    typedef struct{
    	elemtype data;  //结点的值
    	int parent;  //双亲的位置
    }ptree[Maxsize];  //为双亲存储结构类型
    
  2. 孩子链存储

    typedef struct node{
    	elemtype data;
    	struct node *sons[Maxsons];  //指向孩子结点,表示每个结点最多的度数
    }TSonNode;
    

    空域:指针个数-分支个数=n*m-(n-1)

    • 设计一个求树t高度的递归算法:

      int treeheight(TSonNode * t){
      	TSonNode *p;
      	int i,h,maxh=0;
      	if(t==NULL)
      		return 0;
      	for(i=0;i<Maxsons;i++){    //p指向t的第i+1个孩子结点
      		p=t->sons[i];
      		if(p!=NULL){
      			h=treeheight(p);  //求对应子树的高度
      			if(maxh<h)
      				maxh=h;
      		}
      	}
      	return (maxh+1);  //返回树的高度
      }
      
  3. 兄弟链存储

    typedef struct tnode{
    	elemtype data;
    	struct tnode *hp;  //指向兄弟
    	struct tnode *vp;  //指向孩子结点
    }TsbNode;
    

    最重要,用于实现树与二叉树的互相转换

    左孩子右兄弟

    空域:指针个数-分支个数=2n-(n-1)=n+1

    👆因为一个节点就两个指针,相当于孩子链中m次树为2的情况

    • 设计一个求树t高度的递归算法:

      int treeheight2(TsbNode *t){
      	TsbNode *p;
      	int h,maxh=0;
      	if(t==NULL)
      		return 0;
      	p=t->vp;   //p指向第1个孩子结点
      	while(p!=NULL){
      		h=treeheight2(p);
      		if(maxh<h)
      			maxh=h;
      		p=p->hp;  //继续处理其他兄弟,即其他子树
      	}
      	return(maxh+1);
      }
      

二叉树

(完全)二叉树的性质

叶子结点仅有可能在最后两层出现

  1. n0=n2+1
  2. n2=n0-1
  3. n=2n2+1=2n0-1
  4. .i层最多有2^(i-1)个结点
  5. 深度为k的⼆叉树⾄多有2^k - 1个结点
  6. 具有n个结点的完全⼆叉树的深度为log2(n)向下取整+1
  7. n为奇数时,n1=0;n为偶数时,n1=1(因为n0+n2为奇数)
  8. 如果对⼀棵有n个结点的完全⼆叉树,可以通过⽗节点求⼦⼥结点,也可以通过⼦⼥结点 求⽗节点,不过要注意,根节点的编号是从0开始还是从1开始。下面计层序编号为i
    • 若i<=n/2,则i为分支结点,否则是叶子结点
    • 若i有左孩子,则左孩子编号是2i,右孩子为2i+1

二叉树遍历
  1. 先序(前缀表达式)

    第一个是根节点。若有左右子树,则第二个是左子树根节点,第三个是右子树根节点

    • 递归算法:

      void preOrder(btNode *b){
      	if(b!=NULL){
      		printf("%c",b->data);  //访问结点
      		preOrder(b->lchild);  //递归左子树
      		preOrder(b->rchild);  //递归右子树
      	}
      }
      
  2. 中序(中缀表达式(要加括号))

    若有左右子树,则根节点在中间,左右子树在两边

    递归算法:

    void inOrder(btNode *b){
    	if(b!=NULL){
    		inOrder(b->lchild);  //递归左子树
    		printf("%c",b->data);  //访问结点
    		inOrder(b->rchild);  //递归右子树
    	}
    }
    
  3. 后序(后缀表达式)

    最后一个是根结点

    递归算法:

    void postOrder(btNode *b){
    	if(b!=NULL){	
    		postOrder(b->lchild);  //递归左子树
    		postOrder(b->rchild);  //递归右子树
    		printf("%c",b->data);  //访问结点
    	}
    }
    
  4. 层次遍历

    非递归

    借助环形队列

先序中序后序非递归遍历需要用到临时栈

二叉树和树和森林的转换

只用知道以下四种情况,树和森林间的转换就是增加一个根或删去一个根

  1. 二叉树转树

    孩子左兄弟右:孩子在左边,兄弟在右边

    > 规则:

    1. 二叉树的左孩子是树中该结点(该左孩子的双亲)的最左孩子(第一个孩子)
    2. 二叉树的右孩子是树中该结点(该右孩子的双亲)的一个兄弟

    要求:根节点必须无右孩子,否则就是转成森林了

    方法:

    1. 将所有有右孩子的线左转45°
    2. 去掉兄弟之间的线,并连上各自的双亲
  2. 二叉树转森林

    孩子左兄弟右,并且根兄弟要切断

    > 规则:

    1. 二叉树的左孩子是树中该结点(该左孩子的双亲)的最左孩子(第一个孩子)
    2. 二叉树的右孩子是树中该结点(该右孩子的双亲)的一个兄弟

    要求:根节点一定要有右子树,否则就是树了

    方法:

    1. 将所有有右孩子的线左转45°
    2. 去掉兄弟之间的线,并连上各自的双亲
  3. 树转二叉树

    第一棵子树(如果有的话)作为左孩子,下一个兄弟(如果有的话)作为右孩子

    第一棵子树作为左孩子,下一个兄弟作为右孩子

    方法:

    1. 兄弟结点之间连接条虚线,并把所有的非最左结点(右结点)的线删去
    2. 将兄弟的线右转45°
  4. 森林转二叉树

    方法:

    1. 兄弟结点**(根节点)之间连接条虚线**,并把所有的非最左结点(右结点)的线删去
    2. 将兄弟的线右转45°
二叉树的存储结构
  1. 顺序存储

    typedef char elemtype;
    //课本上二叉树的顺序存储定义如下
    typedef elemtype sqBinTree[Maxsize];
    ---------------------------------------------
    //王道上二叉树的顺序存储定义如下
    struct TreeNode{
    	elemtype value;
    	bool isempty;  //结点是否为空
    };
    TreeNode t[Maxsize];  //定义一个长度为Maxsize的数组t,按照从上至下、从左至右的顺序依次存储完全二叉树中的各个结点
    

  2. 二叉链表

    typedef char elemtype;
    //二叉链表存储定义及各操作的实现
    typedef struct node{
    	elemtype data;
    	struct node *lchild;
    	struct node *rchild;
    }btNode;
    

    n+1个空域

  3. 三叉链表

    typedef char elemtype;
    //二叉链表存储定义及各操作的实现
    typedef struct node{
    	elemtype data;
    	struct node *lchild;
    	struct node *rchild;
        struct node *parent;
    }btNode;
    

    3n-2(n-1)=n+2个空域

二叉树的构造
  1. 先序遍历序列+中序遍历序列画出二叉树

    用先序第一个确认根的位置,在中序中找到根,左边是左子树,右边是右子树,继续递归确认

  2. 后序遍历序列+中序遍历序列画出二叉树

    用后序最后一个确认根的位置,在中序中找到根,左边是左子树,右边是右子树,继续递归确认

  3. 层次遍历序列+中序遍历序列画出二叉树

    用层次第一个确认根的位置,在中序中找到根,左边是左子树,右边是右子树,继续递归确认

线索二叉树

充分利用二叉链表的空域:

  • 左空则指向其前驱
  • 右空则指向其后继

二叉排序树

  • 考点:会给一串数列,你需要依次按顺序插入进去,组成二叉排序树

详细见树表查找篇章

方便搜索的一种树

左子树放小的,右子树放大的

平衡二叉树

要求左右子树的高度差最多是1

大根堆或小根堆

堆是一颗完全二叉树,采用数组顺序存储,有大小堆之分

堆又叫优先级队列

优先级队列是完全⼆叉树 + 堆的规则(⼤⼩根堆)

哈夫曼树

  • 构造(重点):

    1. 每次拿最小的两个结点合并成一个新结点(最多合并n-1次)

    2. 再循环拿两个最小的结点(选过的不能再选),第一步构造的新结点也可以选中

      因此需要结合n-1次

  • 带权路径计算(重点):

    1. 找出所有叶子结点
    2. 计算各个叶子结点的路径长度*叶子结点的权值
    3. 将2式相加,有几个叶子结点就有几项

哈夫曼树共有2n0-1=2n2+1个结点,且没有度为1的结点

分支结点n-1=2n0-2

huffman树是带权路径WPL(Weighed Path Length)最⼩的树,也称最优树。当哈夫曼树的度大于2时,就运用到了外存中的排序,叫最佳归并树

  • 哈夫曼编码(前缀编码)

    huffman树的左树编码为0,右树编码为1(左小右大),则每⼀个叶⼦结点将得到唯⼀的编码,即为 huffman编码,也叫做前缀编码

    所谓前缀编码就是指,任何一个编码都不是另一个编码的前缀

    哈夫曼树的字符个数=叶子结点个数

    哈夫曼树的字符长度+1=哈夫曼树的最大高度

    注意区分字符长度和字符个数!注意区分字符长度和字符个数!注意区分字符长度和字符个数!

  • 哈夫曼树的应用就是压缩存储空间

并查集

对两个集合的合并、查找操作

并查集采用双亲存储实现

图的基本概念


图(Graph)G由顶点集合V(G)和边集合E(G)构成。

图不可以为空,至少要有一个顶点,顶点集非空,只有边是可以空的

  • 图的表示

    • 无向图:

      e={(1,2),(1,3),(1,0),(2,3),(3,0),(2,4)}

    • 有向图:

      e={<1,2>,<1,3>,<0,1>,<2,3>,<0,3>}

    无向图用()表示,可以颠倒顺序。无向图边成为边

    有向图用<>表示,从左指向右,表示左边的出边是右边,不可颠倒。有向图边成为弧

    有向图中所有顶点的入度之和等于所有顶点的出度之和。

  • 边与度的关系

    边数e=n个顶点的度之和 / 2

    即:n个顶点的度之和为边数的两倍

  • 完全图(顶点n与边e的关系)

    完全图指的是所有的顶点均和其他顶点有边(不仅仅是连通而已,是直接边)。有向图则要同时存在方向相反的两条弧

    • 无向完全图中,每两个顶点之间都存在着一条边,此时边数最多,称为完全无向图, 最多有e=n(n-1)/2条边

    • 有向完全图中,每两个顶点之间都存在着方向相反的两条边,此时边数最多,称为完全有向图,最多有e=n(n-1)条边。

  • 稠密图与稀疏图

    • 稠密图:接近完全图,边多
    • 稀疏图:边少
  • 子图

    子图要求选取的顶点子集与边子集在父图中能连得通

  • 连通

    • 无向图:顶点i到顶点j有路径,叫做连通图

      对于无向图,边的取值范围为0到n(n-1)/2, 如果图有n(n-1)/2条边,则⽆向称为图称⽆向完全 图,

    • 有向图:顶点i到顶点j有去和来两条路径,叫强连通图

      对于有向图,边的取值范围为0到n(n-1), 如果图有n(n-1)条边,则称向图称为有向完全图,在 有向完全图中任意两个顶点之间都存在⽅向相反的两条弧

      ⼀个顶点的⼊度为0、其余顶点的⼊度均为1的有向图,称为有向树

    • 不连通:在(极大)连通分量上多+一个顶点

  • 连通图、连通分量(无向)

    若无向图中任意两个顶点都连通(不一定有直接边),则称为连通图,否则称为非连通图

    因此连通图与无向完全图的关系是:连通图真包含于无向完全图

    无向图G中的极大连通子图称为G的连通分量。显然,任何连通图的连通分量只有一个,即本身,而非连通图有多个连通分量。

    如果只有一个顶点(没有边),那么此时该顶点也叫做连通分量

    一个有n个顶点的图,最少有1个连通分量,最多又n个连通分量

    • 实现n个顶点的无向连通图至少n-1条边

      无向连通图的最少边数,就是生成树

      若再+一条边,形成n个顶点n条边,则一定有环

      那么显然:

      • 生成树,n-1条边
      • 非连通图:<n-1条边
    • 只有非连通图才有可能有多个连通分量

    • e条边的非连通图的顶点最少=连通图的顶点+1 即:边数e=n(n-1) /2 **

      求出e条边所构成的完全图n后+1

      非连通图的边数最少是n-1,并且有n+1个顶点(自推)

  • 强连通图、强连通分量(有向图)

    若有向图中任意两个顶点都连通(不一定有直接弧),则称为强连通图,否则称为非强连通图。

    因此强连通图与有向完全图的关系是:强连通图真包含于有向完全图

    有向图G中的极大强连通子图称为G的强连通分量

    强连通图只有一个强连通分量,即本身。非强连通图有多个强连通分量。

    • 实现有向连通图至少n条边

    • n个顶点的强连通图(有向图)至少有n条边

      上述两都是形成了环,这样就连通了

图的存储结构及基本算法

邻接矩阵

顺序存储

  • 概念

对角线都是0

关于对角线对称,因此顶点为n阶矩阵的n,边为主对角线以上的1的个数

需要会根据图画出邻接矩阵

连通的话是权值(若是不带权的图,则默认是1

无穷表示不连通

01

一个图的邻接矩阵表示是唯一的。

特别适合于稠密图的存储。

*邻接矩阵的存储空间为O(n*2)

*邻接矩阵遍历的时间复杂度也是O(n*2)

  • 矩阵的地址求法

    源自邻接矩阵是顺序存储形式,所以是以a[n][m]的方式表示的

    ​ 矩阵中是按行(列)优先的顺序存储的。也就是说,二维数组的第一行的所有元素会先于第二行的所有元素被存储,第二行的所有元素会先于第三行的所有元素被存储,以此类推。

    给定一个 m x n 的二维数组 a,其首元素(即 a[0][0])的基地址是 BASE,那么元素 a[i][j] 的地址可以通过以下公式计算:

    Address of a[i][j] = BASE + ((i * n) + j) * size
    
    • i * n : 这是前 i 行元素的总数量。
    • j : 是第 i 行中,a[i][j] 前面的元素数量。
    • (i * n) + j : 这是 a[i][j] 元素在二维数组中的位置(从 0 开始计数)。
    • ((i * n) + j) * size :由于每个元素可能会占用多于一个字节的空间(如 int 类型通常会占用4个字节),我们需要将元素在数组中的位置乘以它所占用的空间大小,来得到相对于 BASE 的偏移量。
邻接表
  • 概念

采用的是顺序存储+链式存储的方式实现

用一个数组作为头结点表示每个顶点,然后每个数组内部都有个指针,指向连接的结点

边界点算的是出度

需要会根据图画出邻接表,不关于主对角线对称,顶点为n阶矩阵的n,边数为邻接表中1的个数

邻接表表示不唯一。

特别适合于稀疏图存储。

邻接表的存储空间为O(n+e)

邻接表的时间复杂度也是O(n+e)

图的遍历

注意区分树的层次遍历、先根遍历、后根遍历

二叉树的先中后序遍历

深度优先遍历DFS

优先遍历从某个结点出发的有最深层次的结点,层次必须递增,若到底则回到第二层的其他结点继续深度遍历

深度优先遍历相当于⼆叉树中的前序遍历

**邻接表求遍历序列:看到一条可以走(没有走过)路径就直接走下去,没有道路时回退 **

算法
void DFS(AdjGraph *G,int v)  //邻接表实现,实现主要都是用邻接表
{  ArcNode *p; int w;
   visited[v]=1; 		//置已访问标记
   printf("%d  ",v); 		//输出被访问顶点的编号
   p=G->adjlist[v].firstarc; 	//p指向顶点v的第一条边的边头结点
   while (p!=NULL) 
   {  w=p->adjvex;
      if (visited[w]==0) 
         DFS(G,w);   		//若w顶点未访问,递归访问它
      p=p->nextarc;  		//p指向顶点v的下一条边的边头结点
   }
}

深度优先遍历的过程体现出后进先出的特点:用栈或递归方式实现。

如何确定一个顶点是否访问过? 设置一个visited[] 全局数组, visited[i]=0表示顶点i没有访问; visited[i]=1表示顶点i已经访问过。

该算法的对领接表,该时间复杂度为O(n+e)。

对领接矩阵,该时间复杂度为O(n*e)。

遍历次序(重要)

要点:

  • 若有多条路,先选权值小的那条路

  • 掌握由一个图写出深度优先遍历序列

    如下图,若从2出发,下一步可以选1或者6,但要先去小的,所以先去1;然后以1为出发点可以去2(去过)或者5,访问5,5没有可以访问的了;然后回到2,这次从6开始,去3,然后3又可以去4,再去7,8,遍历完成。

  • 掌握由一个邻接表写出深度优先遍历序列(重点)

    邻接表写出深度优先遍历序列的要点在于要看邻接表里的,因为邻接表里多条路,并不一定是选权值最小的

    如下图,若从2出发,下一步选1,然后跳到1的那一行,2被访问了,那就去5;跳5那一行,没东西了,返回2那一行;访问下一个6,6的行可以选3(没被选中过)…以此类推,被选过的就要跳过去

    秘诀:访问一个,就到它的行去接着访问别的,若没有,则一步步向上返回

38

广度优先遍历BFS
算法

类似于层次遍历,距离起始结点近的先访问完,再访问离更远的

要会从邻接表的图来写出遍历序列

邻接表求遍历序列:考虑每一条可以走(没有走过)的路径,尝试走每条道路

void BFS(AdjGraph *G,int v)
{  int w, i;
   ArcNode *p;
   SqQueue *qu;			//定义环形队列指针
   InitQueue(qu);			//初始化队列
   int visited[MAXV];        		//定义顶点访问标记数组
   for (i=0;i<G->n;i++) 
     visited[i]=0;	  		//访问标记数组初始化
   printf("%2d",v); 			//输出被访问顶点的编号
   visited[v]=1;             		//置已访问标记
   enQueue(qu,v);
   while (!QueueEmpty(qu))       		//队不空循环
   {  deQueue(qu,w);				//出队一个顶点w
      p=G->adjlist[w].firstarc; 		//指向w的第一个邻接点
      while (p!=NULL)				//查找w的所有邻接点
      {  if (visited[p->adjvex]==0)		//若当前邻接点未被访问    
         {  printf("%2d",p->adjvex);		//访问该邻接点
            visited[p->adjvex]=1;		//置已访问标记
            enQueue(qu,p->adjvex);		//该顶点进队
         }
         p=p->nextarc;              		//找下一个邻接点
      }
    }
    printf("\n");
}

广度优先搜索遍历体现先进先出的特点,用队列实现。

对于连通图,调用一次DFS或BFS,能够访问到图中的所有顶点

无向非连通图:调用一次DFS或BFS,只能访问到初始点所在连通分量中的所有顶点,不可能访问到其他连通分量中的顶点。

所以非连通图,需要调用连通分量个数次的DFS或BFS才能遍历所有结点

对领接表,该时间复杂度为O(n+e)。

对领接矩阵,该时间复杂度为O(n*e)。

遍历次序(重要)

要点:

  • 若有多条路,先选权值小的那条路

  • 掌握由一个图写出广度优先遍历序列

    如下图,若从2出发,下一步可以选1或者6,但要先去小的,所以先去1,再去6;然后以1或6为出发点可以去3、5或者7,访问5(因为上一级1比较小),然后3、7;然后以5、3、7为起点访问其他的,遍历完成。

  • 掌握由一个邻接表写出广度优先遍历序列(重点)

    邻接表写出深度优先遍历序列的要点在于要看邻接表里的,因为邻接表里多条路,并不一定是选权值最小的

    如下图,若从2出发,下一步将该层全访问完1、6,然后跳到1的那一行,访问改行,2被访问了,那就去5,第二行的1访问完毕;之后回到2行,访问6,还是一样,跳过去,访问一行先,然后再往里深入…以此类推,被选过的就要跳过去

39

秘诀:先把一层的都访问遍,再挨个往里钻

最小生成树

从4-8都属于图的应用

可以先数一下有多少个顶点,因此边数为定点数-1

生成树概念

一个连通图的生成树是一个极小连通子图,它含有图中全部n个顶点和构成一棵树的**(n-1)**条边。

生成树是图用某种遍历方式所形成的,所以每个结点只会被访问一次,不能重复走,但必须每个结点都走完

可以看出生产树的概念是针对无向图而言的,而无向图中连通的最低要求就是要有n-1条边,所以说生成树是极小连通子图

注意:连通分量是极大联通子图,一个极大一个极小,注意区分

由广度优先遍历得到的生成树称为广度优先生成树。

由深度优先遍历得到的生成树称为深度优先生成树。

生成树是可以没有权值的,极小生成树必须要有权值

边数=顶点数-1

树形不唯一,边和权值之和唯一

  • 最小生成树(MST):边上的权值之和最小的生成树
普里姆(Prim)算法

选择最近的点,后连接边

要求:不能形成回路(本质:不能重复访问结点)

找挨着最近的点连起来,并将连起来的点加入集合中,之后按照集合里周围单位1 的范围进行查找

  • 步骤:

    (1)初始化U={v}。v到其他顶点的所有边为候选边;

    (2)重复以下步骤n-1次,使得其他n-1个顶点被加入到U中:

    ①从候选边中挑选权值最小的边输出,设该边在V-U中的顶点是k,将k加入U中;

    ②考察当前V-U中的所有顶点j,修改候选边:若(j,k)的权值小于原来和顶点k关联的候选边,则用(k,j)取代后者作为候选边。

> Prim()算法中有两重for循环,所以时间复杂度为O(n2)。

克鲁斯卡尔(Kruskal)

选择最小的边,后画点

要求:不能回路

找边最小的一条,然后将两个点连起来,如果这两点已经连通了,则不要这条边,去找另外小的一条

  • 步骤:

    (1)置U的初值等于V(即包含有G中的全部顶点),TE的初值为空集(即图T中每一个顶点都构成一个连通分量)。

    (2)将图G中的边按权值从小到大的顺序依次选取:

    Œ 若选取的边未使生成树T形成回路,则加入TE;

     否则舍弃,直到TE中包含(n-1)条边为止。

    Kruskal算法的时间复杂度为O(elog2e)

    改进:堆排序、并查集

最短路径

迪杰斯特拉(Dijkstra)求单源最短路径

类似线代里的矩阵求最短路径

34

弗洛伊德(Floyd)求各顶点之间最短路径问题

35

有向无环图描述表达式(节省空间)

36

拓扑排序

  • 1.有向无环图(DAG图)
  • 2.顶点表示活动的网络(AOV)网
  • 3.拓扑排序(DAG图中)

img

关键路径

概念
  • 1.开始顶点(源点):仅有一个入度为0的顶点
  • 2.结束顶点(汇点):仅有一个出度为0的顶点
  • 3.关键路径:具有最大路径长度的路径
  • 4.关键活动:关键路径上的活动
  • 5.最短时间:关键路径的长度
几个变量
  • 1.事件vn的最早发生时间Ve(n)

    通过从源点开始,找出每条到达汇点的每条路径,最后取最大值max

  • 2.事件Vn的最迟发生事件Vl(n)

    通过汇点逆向回去源点,最后取出最小值min

  • 3.活动Ai的最早发生时间e(i)

    =Ve(n)

  • 4.活动Ai的最迟发生时间l(i)

    l=Vl-权值c

  • 5.c路径长

    Ai的权长

  • 6.活动的差额d(i)

    d=l-Ve

关键路径计算
  • d=0 == Vl-c-Ve=0 == 逆序-权长-正序=0

查找

概念
平均查找长度ASL(重点)

- Age Search Length,这是衡量查找 算法效率的重要指标

n是表的⻓度,pi是查找第i个数据元素的概率,如果概率相等,则pi=1/n, ci是找到第i个数据 元素所需⽐较的次数。

asl越小,效率越高

线性表查找
顺序查找

从头到尾或从尾到头

折半(二分)查找
  • 顺序表描述

要求是有序表,最好是顺序表,但也可以是链式

//二分查找(升序)
int binSearch(rectype r[],int n ,keytype k){
	int low=0,high=n-1,mid;
	while(low<=high){
		mid=(low+high)/2;  //相当于向下取整
		if(k==r[mid].key)
			return mid+1;  //逻辑序号序号加1
		if (k<r[mid].key)
			high=mid-1;
		else
			low=mid+1;
	}
	return 0;  //如果while没有ruturn则没找到,返回0
}
  • 二叉树描述折半查找

    此时叫判定树或比较树,显然,判定树是一颗平衡二叉排序树(AVL)

    平衡二叉树证明:当元素个数为偶数时,mid可以选择上取整和下取整。选上取整则右子树始终比左子树多1或0个;选下取整则左子树始终比右子树多1或0个,因此构成了平衡二叉树

    失败结点个数为元素个数+1,因为n个结点相当于分成了n+1个区间,用数学的直线划分区间来理解

    需要会手动画出判定树、比较树

    如下图:

    41- 判定树,比较树

新增的叶子结点叫做外部结点,用于计算失败的平均查找长度,计算方式:*((到达外部结点经过的边数)该层个数)累计求和/外部结点个数

判定树里存在的结点叫做内部结点,用于计算成功的平均查找长度,计算方式(第i层*第i层的内部结点个数)累计求和/内部结点个数

折半查找的最大查找次数=判定树的最大高度=log2n(下取整)+1 | log2(n+1)(上取整)

折半查找的时间复杂度 为:O(log2n)

分块(索引)查找
  • 概念

    1. 分块查找又称索引顺序查找,它吸取了顺序查找和折半查找各自的优点,既有动态结构,又 适于快速查找。

    2. 分块查找的基本思想:将查找表分为若干子块。块内的元素可以无序,但块间的元素是有序 的,即第一个块中的最大关键字小于第二个块中的所有记录的关键字,第二个块中的最大关键字 小于第三个块中的所有记录的关键字,以此类推。再建立一个索引表,索引表中的每个元素含有 各块的最大关键字和各块中的第一个元素的地址,索引表按关键字有序排列。 即将n个数据的表分成b块,每一块再分成s列

    3. 分块查找的过程分为两步:第一步是在索引表中确定待查记录所在的块,可以顺序查找或折半查找索引表;第二步是在块内顺序查找(只能)。

      因此索引查找最好的情况都需要查找两次

  • 平均查找长度

    顺序查找

    但s=根号n时,ASL取极小值根号n+1

    例题:对于10000个元素的文件,用分块查找,最佳的元素个数s是100个,总的块数b=100,ASL=101

    分块查找的缺点就是增加一个索引表的存储空间和增加建立的时间

    如果分块查找采用链式存储,则可以实现动态搜索表

树表查找
二叉排序树BST
  • 据二叉排序树的定义,左子树结点值 < 根结点值 < 右子树结

对⼆叉树进⾏中序遍历,将得到从小到大的排序顺序

⼆叉搜索树最⼤的功劳在于:规定了节点的位置,因此针对BST可以有效实现查找、插 ⼊、删除,让树形结构可以进⾏动态调整

具有n个内部结点的二叉排序树,其外部结点个数为n+1

平均执行时间或者ASL=O(log2(n))

二叉排序树中的查找路径是原来二叉排序树的一部分,也一定构成一棵二叉排序树。

  • n个关键字构成的不同二叉排序树有多少棵?

    答:需要用到卡特兰数,就是出栈序列个数那个:C(n,2n)/(n+1)

    如4个关键字,则有14棵树

  • 算法

    1. 类型定义

      typedef int keytype;
      typedef char infotype;
      typedef struct node{
      	keytype key;
      	infotype data;
      	struct node *lchild,*rchild;
      }bstNode;
      
    2. 插入

      ​ 需保证插入后,仍然满足排序树需求。用到了递归,当子树为空时就会插入,如果在左边就递归左边插入,在右边就递归右边插入

      bool insertBst(bstNode *&bt,keytype k){
      	if(!bt){
      		bt=(bstNode *)malloc(sizeof(bstNode));
      		bt->key=k;
      		bt->lchild=bt->rchild=NULL;
      	}
      	else if(k==bt->key)  //不能存在关键字相同的结点
      		return false;
      	else if(k<bt->key)
      		return insertBst(bt->lchild,k);
      	else
      		return insertBst(bt->rchild,k);
      }
      
    3. 创建

      bstNode * createBst(keytype a[],int n){
      	//返回树的根节点
      	bstNode *bt=NULL;
      	int i=0;
      	while(i<n){
      		insertBst(bt,a[i]);
      		i++;
      	}
      	return bt;
      }
      
    4. 删除

      算法思想

      1. 考虑p是叶子:直接删
      2. 考虑p只有左子树:左子树代替
      3. 考虑p只有右子树:右子树代替
      4. 考虑p同时有左右子树:拿左子树最大或者右子树最小的
    5. 输出

      //递归输出排序树(中序)
      void dispBst(bstNode *bt){
      	if(bt){
      		dispBst(bt->lchild);
      		printf("%d,",bt->key);
      		dispBst(bt->rchild);
      	}
      }
      
平衡二叉树AVL

定义结点左子树与右子树的高度差为该结点的平衡因子,则平衡 二叉树结点的平衡因子的值只可能是**-1、1或0**

  • AVL插入结点

插入结点可能导致平衡二叉树不平衡,因此每次调整的对象都是最小不平衡子树,即以插入路径上离插入结点最近的平衡因 子的绝对值大于1的结点作为根的子树

  1. LL插入(右旋+移右叶到左)

    1. 将最小不平衡子树的左孩子移到根
    2. 将原本的根移到新根的右孩子
    3. 将新根原本的右孩子移到原根的左孩子

    在最小不平衡子树的左子树的左分支插入结点,使平衡二叉树不平衡

  2. RR插入(左旋+移左叶到右)

    1. 将最小不平衡子树的右孩子移到根
    2. 将原本的根移到新根的左孩子
    3. 将新根原本的的左孩子移到原根的右孩子替换

    在最小不平衡子树的右子树的右分支插入结点,使平衡二叉树不平衡

    LL和RR是对称的

    22

  3. LR插入(左旋+移左叶到右+右旋+移右叶到左)

    1. 将最小不平衡子树的左孩子的右孩子移到根
    2. 将原根的左孩子移到新根的左孩子
    3. 将原根移到新根的右孩子
    4. 将新根原本的左孩子移到新根的左孩子的右分支
    5. 将新根原本的右孩子移到原根的左分支

    23

    在最小不平衡子树的左子树的右分支插入结点,使平衡二叉树不平衡

  4. RL插入(右旋+移右叶到左+左旋+移左叶到右)

    1. 将最小不平衡子树的右孩子的左孩子移到根
    2. 将原根的右孩子移到新根的右孩子
    3. 将原根移到新根的左孩子
    4. 将新根原本的左孩子移到新根的左孩子的右分支
    5. 将新根原本的右孩子移到新根的右孩子的左分支

    24

    在最小不平衡子树的右子树的左分支插入结点,使平衡二叉树不平衡

    以上四种方式记忆:看第二的字母,左就右旋,右就左旋;然后看第一个字母,如果相同则结束,不相同则相反的操作

散列(哈希)查找 - HashTable
概念
  1. 哈希表

    通过哈希函数,直接对关键字进⾏映射访问的表就称为哈希表

    散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突,这些 发生碰撞的不同关键字称为同义词。一方面,设计得好的散列函数应尽量减少这样的冲突;另一 方面,由于这样的冲突总是不可避免的,所以还要设计好处理冲突的方法。

  2. hashTable需要解决的两个问题

    1. 映射函数 — hash函数 (除留余数法)
    2. 冲突解决 — (开放地址法、链地址法)
  3. 影响哈希表查找的因素:

    1. 装填因子:已存入的元素数n与哈希地址空间大小m的比值,即a=n/m;越小,冲突可能性越小
    2. 所采用的哈希函数
    3. 出现哈希冲突时采取的解决办法
    4. 存入的元素特性(如连续的一串、奇数、偶数…)
哈希函数的构造方法
  • 1=直接定址法

以关键字k本身加上某个常量c作为哈希地址:h(k)=k+c

如:h(学号) = 学号-201001001

适用于关键字分布的连续,否则将造成大量浪费

  • 2=除留余数法

用关键字k除以某个不大于哈希表长度m的素数p所得的余数作为哈希地址

h(k)=k % p (p<=m)

关键在于选p

p一般用的是最靠近m的素数

哈希冲突的解决办法
  • 1=开放定址法(主流)
  1. 线性探测法

    di=(d0+i) mod m (i=1,2,3…)

    只能往后去找,一次往后一位,如果到末尾就从头开始

  2. 平方探测法

    di=(d0 +|- i^2) mod m (1<=i<=m-1)

    往前或往后去找,迈的步子越来越大

两种方法总结:就是当前位置有人了,需要每次往后一步(往前往后,步子更大)的去找空位

  • 2=拉链法

拉链法就是把所有的冲突同义词用单链表连起来,哈希表的地址对应的是单链表的首结点

33

除留余数画出哈希表

​ 假设哈希表长度m=13,采用除留余数法哈希函数建立如下关键字集合的哈希表:

(16,74,60,43,54,90,46,31,29,88,77)。

并采用线性探查法解决冲突。

下标0123456789101112
k7754164331294660748890
成功探查次数21111411111
失败探查次数21109876543213
拉链法画出哈希表
  • 查找成功asl计算

    46

  • 查找失败asl计算

    47

排序(重点)

排序可视化网站:

Comparison Sorting Visualization (usfca.edu)

  • 排序的稳定性

    • 相同关键字的元素,排序后,这些相同的关键字的元素位置没有发生改变,就称这种排序方法是稳定的。
    • 相同关键字的元素,排序后,这些相同的关键字的元素位置发生了改变,就称这种排序方法是不稳定的。
  • 内排序和外排序

    外排序会相对较慢

插入排序

每次将一个待排序的元素按其关键字大小插入到前面已经排好序的有序区中的适当位置,直至全部插入完成

直接插入排序(增量法)

思想:左边分为有序区,右边分为无序区,初始化i=1,每次将一个新的元素插入到有序区的合适位置

//直接插入排序,我的
void insertSort(rectype R[],int n){
	int i=1,temp,k;
	for(;i<n;i++){   //若是0或1个则不执行
		if(R[i-1].key>R[i].key){
			temp=R[i].key;  
			//将前面大于的往后移
			k=i-1;    //升序的前一项
            for(;k>=0;k--){
                if (temp<R[k]);
                	R[k+1]=R[k];
                else
                    break;   //不需要排序
            }
			R[k+1].key=temp;
		}
	}
}
//课本 
void insertSort2(rectype R[],int n){
	int i=1,temp,k;
	for(;i<n;i++){   //若是0或1个则不执行
		if(R[i-1].key>R[i].key){
			temp=R[i].key;  
			//将前面大于的往后移
			k=i-1;    //升序的前一项
			do{
				R[k+1]=R[k];  
				k--;
			}
			while(R[k].key>temp && k>=0);
			R[k+1].key=temp;
		}
	}
}

时间:O(n^2)

空间:O(1)

折半插入排序

直接插入排序是用顺序比较去找插入的位置,这边是采用折半查找去找插入的位置,再移动元素插入

//折半插入,减少比较次数,但是移动次数还是一样的
void binInsertSort(rectype R[],int n){
	int i,temp,k,low,high,mid;
	for(i=1;i<n;i++){   //若是0或1个则不执行
		if(R[i-1].key>R[i].key){
			temp=R[i].key;  
			//将前面大于的往后移
			low=0;high=i-1;
			while(low<=high){
				mid=(low+high)/2;
				if(temp<R[mid].key)
					high=mid-1;
				else
					low=mid+1;
			}
			for(k=i-1;k>=high+1;k--)  								// high+1==low
				R[k+1]=R[k];
			R[high+1].key=temp;
		}
	}
}

仅减少了查找位置(比较)次数

时间:O(n^2)

空间:O(1)

希尔排序(Shell Sort)

​ 实际上是一种分组插入方法

​ 思想:取一个小于n的整合d1作为第一个增量,把表的全部元素分成d1个组,将所有距离为d1的倍数的元素放在同一个组中,对这一个组进行插入排序;然后取第二个增量d2,继续;直到d=1之后,最所有的元素再进行一次插入排序,算法完毕。

思路就是:从局部的一点点有序(看起来)到最后的完全有序

40

//希尔排序(牺牲了0的下标)
void shellSort(rectype R[],int n){
	int d,j,i;
	for(d=n/2;d>=1;d/=2){  //d表示的是两个数据之间的距离
		for(i=d+1;i<=n;i++){  //下标0不放数据,从1开始放,这里i=d+1就类似插入排序中i=1一样,放到第二个数上
			R[0].key=R[i].key;  //不是用的哨兵,0是暂存数据区	
			j=i-d;  //j就是第一个数
			for(;j>0 && R[j].key>R[i].key;j-=d)
				R[j+d].key=R[j].key;
			R[j+d].key=R[0].key;
		}
	}
}
//希尔排序(课本)
void shellSort2(rectype R[],int n){
	int d,j,i,temp;  //用了临时变量,而不用0下标的位置暂存,但这里第一个数据还是放的1位置
	for(d=n/2;d>=1;d/=2){
		for(i=d;i<n;i++){
			temp=R[i].key;  
			j=i-d;
			for(;j>=0 && R[j].key>R[i].key;j-=d)
				R[j+d].key=R[j].key;
			R[j+d].key=temp;
		}
	}
}

d1一般取n/2…然后n/4…以此类推

d表示的是两个数据之间的距离,也表示分成几组,比如说d=1就是整个表分成一组就是表示整个表

也称为减少增量的排序方法

时间:O(n^1.3)

空间O(1)

仅用于顺序表,不能用链表

不稳定的

哈希(散列)存储结构、哈希查找、希尔排序、哈希函数容易搞混,注意区分:哈希是查找的,希尔是插入排序的

交换排序

两两比较,交换次序

冒泡排序
void swap(int &x,int &y){
	int temp=x;x=y;y=temp;
}
//冒泡排序(从后往前.每次最小放前面)
void bubbleSort(rectype R[],int n){
	int i,j,flag=1;
	for(i=0;i<n;i++){  
		for(j=n-1;j>i;j--){
			if(R[j].key<R[j-1].key){
				swap(R[j].key,R[j-1].key);
				flag=0;
			}
		}
		if(flag)
			break;
	}
}
//冒泡排序(从前往后.每次最大放后面)
void bubbleSort2(rectype R[],int n){
	int i,j,flag=1;
	for(i=n-1;i>=0;i--){  //每次将最小的放前面
		for(j=0;j<i;++j){
			if(R[j].key>R[j+1].key){
				swap(R[j].key,R[j+1].key);
				flag=0;
			}
		}
		if(flag)
			break;
	}
}

可以采用链表实现

稳定的

快速排序
  • 基本思想:

    在待排序内的n个元素中任取一个元素(一般就是第一个元素)作为基准,把该元素放入适当位置后,数据序列被此元素划分成两部分,所有小的放前面,大的放后面,并把该元素排在这两部分的中间(称为该元素的归位),这个过程称为一趟快速排序(不完全=一趟划分)。之后再对左右划分出来的进行快速排序,实际上就是一个递归

    注意快排代码:这里是low<high为的是找到low=high的点进行插入;而二分查找是low<=high是为了找到low=high+1的low点进行插入,注意区分

    //快速排序(王)
    int partition(rectype r[],int low,int high){
    	int pivot=r[low].key;   //pivot是基准、枢轴的意思,这里每次让第一个元素作为基准
    	while(low<high){   //找出low=high的枢轴位置
            //从high先还是low先都是一样的,这边是以high先走
    		while(low<high && r[high].key>=pivot)//找出比基准小的high
    			high--;
    		r[low].key=r[high].key;  //比枢轴小的值移到枢轴左边
    		while(low<high && r[low].key<=pivot)//比low基准大时不成立
    			low++;  
    		r[high].key=r[low].key;  //比枢轴大的值移到枢轴右边
    	}
    	r[low].key=pivot; //结束循环表示,low=high,此处就是枢轴的位置,这里也可以用high
    	return low;  //返回枢轴的下标
    }
    void quickSort(rectype r[],int low,int high){
    	if(low<high){    //递归退出的条件
    		int pivot=partition(r,low,high);  //这是枢轴的下标,进行划分
    		quickSort(r,low,pivot-1);  //对枢轴左侧快速排序
    		quickSort(r,pivot+1,high);  //对枢轴右侧快速排序
    	}
    }
    

    代码(递归):重要

    不稳定的

    空间:O(nlog2n)。其中n为递归层数

    时间:O(log2n)

    与希尔排序O(n*log2(n))的比较:当n>2.5时,快排优势,小于时,希尔优势

    优化:每次选的枢轴尽量可以划分均匀的两部分

    1. 选头、中、尾三个数据元素,选中间值作为枢轴元素
    2. 随机选一个元素作为枢轴元素
    //快速排序(优化)--选择mid作为基准
    void quickSort2(rectype r[],int low,int high){
    	int mid,pivot;
    	mid=(low+high)/2;
    	if(low<high){
    		if(mid!=low)//若基准不是区间中的第一个元素,将其与第一个元素交换
    			swap(r[mid].key,r[low].key); //可能是懒得搞了,把基准放去low的位置,统一操作 
    		pivot=partition(r,low,high);
    		quickSort2(r,low,pivot-1);
    		quickSort2(r,pivot+1,high);
    	}
    }
    
选择排序

每一趟从待排序元素中选出关键字最小(最大)的元素,放在子表最后,直至完成

简单选择(直接选择)排序

分为有序区与无序区,有点类似冒泡

//简单排序(王)
void swap(int &a,int &b){
	int temp=a;
	a=b;
	b=temp;
}
void eazySort(rectype r[],int n){
	int k,min;
	for(int i=0;i<n-1;i++){
		min=i;
		for(k=i+1;k<n;k++)
			if(r[k].key<r[min].key)
				min=k;
		if(min!=i)  //表示不是原地交换
			swap(r[min].key,r[i].key);
	}
}

链表也可以

不稳定

堆排序

堆排序是一种树形选择排序方法

堆是一颗完全二叉树,采用数组顺序存储,有大小根堆之分

堆又叫优先级队列

优先级队列是完全⼆叉树 + 堆的规则(⼤⼩根堆)

左孩子2i,右孩子2i+1

父节点i/2(下取整)

  • 实现大根堆的算法(下标从1开始)

    //大根堆排序
    //筛选函数,选出最大的上浮,小元素下坠
    void sift(rectype r[],int i,int len){ 
    	//left是左孩子,i是根,len是多少个数据
    	r[0]=r[i];   //将0腾出,暂存数据
    	for(int left=2*i;left<=len;left*=2){
    		if(left<len && r[left].key<r[left+1].key)  //选出左右孩子最大的一个
    			left++;  //右孩子更大,将left指向右孩子
    		if(r[0].key<r[left].key){  //左孩子比根大
    			r[i]=r[left];  //将左孩子挪到根上
    			i=left;
    		}
    		else  //根比左右孩子都大
    			break;
    	}
    	r[i]=r[0];
    }
    //建立大根堆的方式:从最后一个分支节点开始,大的上浮,小的筛下去
    void createHeap(rectype r[],int n){
    	for(int i=n/2;i>=1;i--)
    		sift(r,i,n);
    }
    
  • 实现对大根堆排序的算法

    //堆排序的建立,每次根(最大的)和最后一个元素交换,这样每次选出最大的放末尾,就形成了升序
    void heapSort(rectype r[],int n){
    	createHeap(r,n);
    	for(int i=n;i>=2;i--){  //进行n-1躺堆排序,每一趟堆中元素个数减1
    		swap(r[1].key,r[i].key);  //将最后一个元素和根交换
    		sift(r,1,i-1);
    	}
    }
    

大根堆进行堆排序后产生的是降序序列,小根堆进行堆排序后产生的是升序序列

时间复杂度:O(nlog2n)

空间复杂度:O(1)

  • 小根堆只需改动sift即可

    void sift2(rectype r[],int i,int len){ 
    	r[0]=r[i];   
    	for(int j=2*i;j<=len;j*=2){
    		if(j<len && r[j].key>r[j+1].key)  //如果右孩子更小
    			j++;   //也就只需改动两个if的大于小于号即可
    		if(r[0].key>r[j].key){  
    			r[i]=r[j];  
    			i=j;
    		}
    		else 
    			break;
    	}
    	r[i]=r[0];
    }
    
  • 下标从0开始的大根堆排序

     void sift3(int* nums,int i,int len){
    	 int temp=nums[i];  //nums[0]=nums[i]
    	 for(int child=i*2+1;child<len;child=i*2+1){  //child=i*2;child<=len;chile*=2)
    	     if(child<len-1 && nums[child]<nums[child+1])  //child<len
    	        child++;
    	    if(temp>nums[child])  //nums[0]>=nums[left]
    	        break;
    	    else{
                nums[i]=nums[child];
                i=child;
            }
    	 }
    	 nums[i]=temp;  //=nums[0]
    }
    void heapsort(int* nums,int n){
         for(int i=n/2-1;i>=0;i--)  //i=n/2,i>=1
            sift3(nums,i,n);
        for(int i=n-1;i>=1;i--){  //i=n;i>=2
            int temp=nums[0];   //0都是1
            nums[0]=nums[i];
            nums[i]=temp;
            sift3(nums,0,i);  //sift3(nums,1,i-1)
        }
     }
    
  • 堆中插入新元素:对于小根堆,新元素放到表尾,与其父节点比较,小则一路上升,直至无法上升为止

  • 堆中删除元素:被删除的元素用堆底元素替代,让该元素不断下坠

    只有一个孩子下坠:只用对比一次关键字

    两个孩子下坠:对比两次关键字

归并排序

归并排序是多次将两个或两个以上的有序表合成一个新的有序表。一般内排序都是用的二路归并排序,即二路归并;而外排序才是k路归并排序

  • 算法思想

    将两个有序表放在同一个数组相邻的位置,并将他们放在一个暂时数组中,待合并后移回原数组去

  • 递归实现(自顶向下)

    //二路归并排序(递归式)
    void merge(rectype r[],int low,int mid,int high){
    	rectype* r1;  //辅助变量进行排序
    	int i=low,j=mid+1,k;  //i是第一段,j是第二段,k表示r的位置
    	r1=(rectype*)malloc((high-low+1)*sizeof(rectype)); //分配和r一样的空间
    	for(k=low;k<=high;k++)  //先将第一段和第二段都移去r1
    		r1[k].key=r[k].key;  
    	for(k=i;i<=mid&&j<=high;k++){
    		if(r1[i].key<=r1[j].key)
    			r[k].key=r1[i++].key;
    		else
    			r[k].key=r1[j++].key;
    	}
    	//当其中一段完了另一段没完时
    	while(i<=mid)
    		r[k++].key=r1[i++].key;
    	while(j<=high)
    		r[k++].key=r1[j++].key;
    	free(r1);
    }
    void mergeSort(rectype r[],int low,int high){
    	if(low<high){  //low=high表示就剩一个元素了?
    		int mid=(low+high)/2;  //中间划分,分别对两边递归的归并排序
    		mergeSort(r,low,mid);
    		mergeSort(r,mid+1,high);
    		merge(r,low,mid,high);  //再对上面两个归并
    	}
    }
    
  • 非递归式,自底向上(不重要)

    //非递归式
    void MergePass(rectype R[],int length,int n)	//对整个数序进行一趟归并
    {
    	int i;
    	for (i=0;i+2*length-1<n;i=i+2*length) 	//归并length长的两相邻子表
    		merge(R,i,i+length-1,i+2*length-1);
    	if (i+length-1<n-1)                		//余下两个子表,后者长度小于length
    		merge(R,i,i+length-1,n-1);  		//归并这两个子表
    }
    void MergeSort(rectype R[],int n)			//自底向上的二路归并算法
    {
    	int length;
    	for (length=1;length<n;length=2*length)//进行log2n趟归并
    		MergePass(R,length,n);
    }
    

稳定

时间:O(log2n)

空间:O(n)

基数排序

基数排序是一种不需要进行关键字比较的,借助于多关键字排序的思想对单关键字排序的方法

​ 一般元素R【i】的关键字有d位数字(或字符)组成,其中每一位的值都在0-r的范围内,r要取最大的值,其中r成为基数(index)

​ 基数排序有两种,即最低位优先(least significant digit first,LSD)和最高位优先(most significant digit first,MSD)

  • 分配:开始时,把Q,Q·····Q各个队列置成空队列,然后依次考查线性表中的每一个元素aj(j=0,1,···,n—1),如果元素aj的关键字k}=k,就把元素a,插入到Q,队列中。
  • 收集:将Q,Q1,···,Q—1各个队列中的元素依次首尾相接,得到新的元素序列,从而组成新的线性表。

例如对整数序列递增排序,由于个位数的重要性低于十位数,十位数的重要性低于百位数,一般越重要的位越放在后面排序,个位数属于最低位,所以对整数序列递增排序时应该采用最低位优先排序方法。

算法不考

时间:O(d(n+r))

空间:O(r)

稳定

擅长处理:

  • 关键字可以方便地拆分位d组,且d较小
  • r较小
  • 元素个数n较大

43

按个位收集之后,形成了个位的升序序列

按十位手机之后形成了十位的升序序列,如果十位相同,则按个位的升序序列,得到最终的排序结果

各排序的比较
排序方法平均时间复杂度空间稳定性
直接插入O(n^2)O(1)稳定
折半插入O(n^2)O(1)稳定
希尔O(n^1.3)O(1)不稳定
冒泡O(n^2)O(1)稳定
快速O(nlog2n)O(log2n)不稳定
简单选择O(n^2)O(1)不稳定
O(nlog2n)O(1)不稳定
二路归并O(nlog2n)O(n)稳定
基数O(d(n+r))O(r)稳定

稳定的优先选:直插、冒泡、归并

不稳定的优先选:快速、希尔、堆

只用记不稳定的排序4个:简单快速堆希尔排序

操作系统基础

image-20240322093318450

  • 操作系统定义:能有效地组织和管理系统中的各种软/硬件资源,合理地组织计算机系统工作流程,控制程序的执行,并且向用户提供一个良好的工作环境和友好的接口。

  • 操作系统有两个重要的作用:第一通过资源管理提高计算机系统的效率;第二,改善人机界面向用户提供友好的工作环境。

  • 操作系统的4个特征是并发性、共享性、虚拟性和不确定性

    并发不是并行

  • 操作系统的功能:
    (1)进程管理。实质上是对处理机的执行“时间”进行管理,采用多道程序等术将CPU的时间合理地分配给每个任务,主要包括进程控制 进程同步、进程通信和进程调度
    (2)文件管理。 主要包括文件存储空间管理、目录管理、文件的读/写管理和存取控制。
    (3)存储管理。存储管理是对主存储器“空间”进行管理主要包括存储分配与回收、存储保护、地址映射(变换)和主存扩充。
    (4)设备管理。实质是对硬件设备的管理,包括对输入/输出设备的分配、启动、完成和回收
    (5)作业管理。包括任务、界面管理、人机交互、图形界面、语音控制和虚拟现实等。

操作系统的分类:

  • **批处理操作系统:**单道批处理和多道批处理(主机与外设可并行)。
  • 分时操作系统:一个计算机系统与多个终端设备连接。将CPU的工作时间划分为许多很短的时间片,轮流为各个终端的用户服务。
  • 实时操作系统:实时是指计算机对于外来信息能够以足够快的速度进行处理并在被控对象允许的时间范围内做出快速反应。实时系统对交互能力要求不高但要求可靠性有保障。
  • 网络操作系统:是使联网计算机能方便而有效地共享网络资源,为网络用户提供各种服务的软件和有关协议的集合。三种模式:集中模式、客户端/服务器模式(cs|bs)、对等模式。
  • 分布式操作系统:分布式计算机系统是由多个分散的计算机经连接而成的计算机系统,系统中的计算机无主、次之分,任意两台计算机可以通过通信交换信息。
  • 微型计算机操作系统:简称微机操作系统,常用的有Windows、MacsLinux。

嵌入式操作系统主要特点:

  • (1)微型化。从性能和成本角度考虑,希望占用的资源和系统代码量少,如内存少、字长短、运行速度有限、能源少(用微小型电池)。
  • (2)可定制。从减少成本和缩短研发周期考虑,要求嵌入式操作系统能运行在不同的微处理器平台上,能针对硬件变化进行结构与功能上的配置,以满足不司应用需要。
  • (3)实时性。嵌入式操作系统主要应用于过程控制、数据采集、传输通信、媒体信息及关键要害领域需要迅速响应的场合,所以对实时性要求较高。
  • (4)可靠性。系统构件、模块和体系结构必须达到应有的可靠性,对关键要害应用还要提供容错和防故障措施
  • (5)易移植性。为了提高系统的易移植性,通常采用硬件抽象层和板级支撑包的底层设计技术。
  • 嵌入式系统初始化过程按照自底向上、从硬件到软件的次序依次为:片级初始化→板级初始化→系统初始化

进程管理

进程三态图

  • 进程的组成:进程控制块PCB(process control block)(唯一标志)、程序(描述进程要做什么)、数据(存放进程执行时所需数据)

    任务控制块TCB(Task Control Block)

    FCB:文件控制块

  • 进程基础的状态是下左图中的三态图。需要熟练掌握左下图中的进程三态之间的转换。

    阻塞也叫等待

    阻塞不能直接进入运行状态,就绪状态也不能直接进入阻塞

前驱图

反映了进程之间的关系,每一条代表一个信号量S。每一个进程执行完就会释放掉信号量

  • 用来表示哪些任务可以并行执行,哪些任务之间有顺序关系,具体如下图可知,ABC可以并行执行,但是必须ABC都执行完后,才能执行D,这就确定了两点:任务间的并行、任务间的先后顺序

进程资源图

用来表示进程和资源之间的分配和请求关系,如下图所示:

  • P(process)代表进程,R(resource)代表资源,R方框中有几个圆球就表示有几个这种资源,在上图中,R1指向P1,表示R1有一个资源已经分配给了P1,P1指向R2,表示P1还需要请求一个R2资源才能执行。

    看进程p(⚪),入度是有的资源(R资源已分配给P),出度是需要请求的资源

  • 阻塞节点:某进程所请求的资源已经全部分配完毕,无法获取所需资源,该进程被阻塞了无法继续。如上图中P2。

  • 非阻塞节点:某进程所请求的资源还有剩余,可以分配给该进程继续运行。如上图中P1、P3。

    进程出度的请求用完会回收,进行释放

  • 当一个进程资源图中所有进程都是阻塞节点时,即陷入死锁状态

是否能化简什么意思?

定要先执行不阻塞节点;p3先执行完后,释放会R1和R2,此时p1和p2就不阻塞了

进程同步与互斥

  • 临界资源:各进程间需要以互斥方式对其进行访问的资源

  • 临界区:指进程中对临界资源实施操作的那段程序。本质是一段程序代码。

  • 互斥:某资源(即临界资源)在同一时间内只能由一个任务单独使用,使用时需要加锁,使用完后解锁才能被其他任务使用:如打印机。

  • 同步:多个任务可以并发执行,只不过有速度上的差异,在一定情况下停下等待,不存在资源是否单独或共享的问题;如自行车和汽车。

  • 互斥信号量S:对临界资源采用互访问,使用互信号量后其他进程无法访问,初值为1

  • 同步信号量S:对共享资源的访问控制,初值一般是共享资源的数量

    共享资源有上限

    image-20240324200549965

进程的信号量的pv操作

  • P操作:申请资源,S=S-1,若S>=0,则执行P操作的进程继续执行;若S<0,则置该进程为阻塞状态(因为无可用资源),并将其插入阻塞队列。

    s>=0:表示资源的可用个数

    s<0:则绝对值s表示阻塞队列中等待该资源的进程数,也表示当前为阻塞状态,要尽量避免这种情况

  • V操作:释放资源,S=S+1,若S>0,则执行V操作的进程继续执行;若S<=0,则从阻塞状态唤醒一个进程,并将其插入就绪队列(此时因为缺少资源被P操作阻塞的进程可以继续执行),然后执行V操作的进程继续

    S:信号量

    s>=0:表示资源的可用个数

    s<0:则绝对值s表示阻塞队列中等待该资源的进程数,也表示当前为阻塞状态,要尽量避免这种情况

  • 经典问题(上述的应用):生产者和消费者的问题
    三个信号量:互压信号量So(仓库独立使用权),同步信号量S1(仓库空闲个数),同步信号量S2(仓库商品个数)。
    生产者流程: 消费者流程:
    生产一个商品S PSO)
    PISO P(S2)
    P(S1) 取出一个商品
    将商品放入仓库中 V(S1)
    V(S2) VSO)
    VSO)

    如何判断vp哪个先哪个后?

    若信号量初值为>0,则先p后v

    若信号量初值为<=0,则先v后p

    看前驱图,区分哪条线对应的是S几;

    前驱图的出度就是释放空间,即V,入读就是占用空间,即P

    上图因为初值都是0,所以为了使不进入阻塞状态,就先执行v的操作来进行+1

    一个进程的信号量不管是同步还是互斥,他都有一个v一个p

    根据一个信号量一个v和p与先v后p的两个条件前后推论

    做题方法:大胆假设,小心求证

死锁

  • 当一个进程在等待永远不可能发生的事件时,就会产生死锁若系统中有多个进程处于死锁状态,就会造成系统死锁

  • 死锁产生的四个必要条件:

    • 资源互斥

    • 每个进程占有资源并等待其他资源

    • 系统不能夺进程资源

      但是强制剥夺资源可以破坏

    • 进程资源图是一个环路。

死锁产生后,解决措施是打破四大条件,有下列方法:

  • 死锁预防:采用某种策略限制并发进程对于资源的请求,破坏死锁产生的四个条件之一,使系统任何时刻都不满足死锁的条件

  • 死锁避免:一般采用银行家算法来避免,银行家算法,就是提前计算出一条不会死锁的资源分配方法,才分配资源,否则不分配资源,相当于借贷,考虑对方还得起才借钱,提前考虑好以后,就可以避免死锁

    重点:银行家算法

    银行家算法步骤:

    1. 求剩余可用的资源数:拿可用资源数-已分配的资源数
    2. 求每个进程的还需资源数:每个进程的最大需求量-已分配的资源数
    3. 拿1求出的资源数去2里找是否能够执行该进程,若能执行则执行完后将已分配资源数加到1的剩余资源数里去,如果不能执行就是死锁了,以此类推


    image-20240324201134437

    例如上面该题

    ①剩余资源=210

    ②:

    进程已分配资源②的资源
    p1121531
    p2211010
    p32106 -1 1
    p4120001
    p5113231

    ③:剩余资源数210根据②的资源数只能执行p2,执行完后,210+p2对应的已分配资源211,最后是421

    ④:421不能执行p1,只能执行p4,所以根据选项就是c了

  • 死锁检测:允许死锁产生,但系统定时运行一个检测死锁的程序,若检测到系统中发生死锁,则设法加以解除。

  • 死锁解除:即死锁发生后的解除方法,如强制夺资源,撤销进程等

  • 死锁资源计算:系统内有n个进程,每个进程都需要R个资源,那么其发生死锁的最大资源数为n(R-1)。其不发生死锁的最小资源数为n*(R-1)+1。*

    公式重要 👆

    s**>0是有的资源数量,s<0是当前系统有多少进程正在等待资源**

    由此得出最大值是初值:打印机的数量,最小值就是等待的资源:3个资源-n个进程,

    image-20240429164933116

    注:上图中分配资源必须是每个进程都1个才能有一个是2,也就是说进程最大资源数和最小资源数最多差1

线程

一个实体,基本不含资源,而是共享进程的资源,线程有pcb(线程控制块),比进程有的更小的单位

在一个进程里可以创建多个线程

  • 传统的进程有两个属性:可拥有资源的独立单位;可独立调度和分配的基本单位。

  • 引入线程的原因是进程在创建、撤销和切换中,系统必须为之付出较大的时空开销,故在系统中设置的进程数目不宜过多,进程切换的频率不宜太高,这就限制了并发程度的提高。引入线程后,将传统进程的两个基本属性分开,线程作为调度和分配的基本单位,进程作为独立分配资源的单位。用户可以通过创建线程来完成任务,以减少程序并发执行时付出的时空开销。

  • 线程分为用户级线程和内核支持线程

    1. 用户级线程不依赖于内核。创建、撤销和切换都不利用系统调用来实现
    2. 内核支持线程依赖于内核都利用系统调用来实现
  • 线程是进程中的一个实体,是被系统独立分配和调度的基本单位。线程基本上不拥有资源,只拥有一点运行中必不可少的资源(如程序计数器、一组寄存器和栈),它可与同属一个进程的其他线程共享进程所拥有的全部资源,例如进程的公共数据、全局变量、代码、文件等资源,但不能共享线程独有的资源,如线程的栈指针等标识数据

多个线程之间的共享内容问题

线程共享资源线程独享资源
地址空间程序计数器
全局变量寄存器
打开的文件
子进程状态字
闹铃
信号及信号服务程序
记账信息

进程调度

算法说明备注
先来先服务
(First Come First Serve)
先来先得先后最简单,先来的任务先服务
优点:对长任务和繁忙CPU有利缺点:对短任务和繁忙VO任务不利
**短作业优先<**br/> (Shortest Job First)谁小谁先爱幼对长任务不利;不能保障紧急任务被及时处理;任务长短只是主观估算
优点:最短的平均等待时间和平均周转时间
缺点:对长任务不利,未考虑紧追性会导致机(长任务得不到资源)
优先权调度
Priority Scheduling)
看优先级权重根据优先级把资源分配给优先级最高的静态优先权+动态优先权
优点:可灵活调整任务偏好程度
缺点:高优先级太多,导致(低优先级无法得到资源
时间片轮转
Round Robin)
一视同仁公平将作业排成队列,每份作业分段,轮流获取运行时间
进程阻塞,未用完也要让出;不考虑任务长短受系统处理能力和负载影响
优点:公平,响应快,适用于分时操作系统
缺点:高频率切换带来开销,不区分任务紧急程度
多级反馈调度是时间片轮转和优先级的综合优点:照顾了短进程以提高系统吞吐量,缩短了平均周转时间

image-20240429161544096

时间片流转(轮转)是用于交互式系统的

  • 进程调度方式是指当有更高优先级的进程到来时如何分配CPU。分为可夺和不可夺两种,可剥夺指当有更高优先级进程到来时,强行将正在运行进程的CPU分配给高优先级进程;不可夺是指高优先级进程必须等待当前进程自动释放CPU。

  • 在某些操作系统中,一个作业(一组进程)从提交到完成需要经历高、中、低三级调度。

    (1)高级调度。高级调度又称“长调度”“作业调度”或“接纳调度” 它决定处于输入池中的哪个后备作业可以调入主系统做好运行的准备,成为一个或组就绪进程。在系统中一个作业只需经过一次高级调度。
    (2)中级调度。中级调度又称“中程调度”或“对换调度 它决定处于交换区中的哪个就绪进程可以调入内存,以便直接参与对CPU的竞争。
    (3)低级调度。低级调度又称“短程调度”或“进程调度”,它决定处于内存中的哪个就绪进程可以占用CPU。低级调度是操作系统中最活跃、最重要的调度程序,对系统的影响很大

调度算法:

  • 先来先服务FCFS:先到达的进程优先分配CPU。用于宏观调度
  • 时间片轮转(分时):分配给每个进程CPU时间片,轮流使用CPU,每个进程时间片大小相同,很公平,用于微观调度
  • 优先级调度:每个进程都拥有一个优先级,优先级大的先分配CPU。
  • 多级反馈调度:时间片轮转和优先级调度结合而成,设置多个就绪队列,每个队列分别赋予不同的优先级,分配不同的时间片长度;新进程先进入队列1的未尾,按FCFS原则,执行队列1的时间片;若未能执行完进程,则转入队列2的未尾,如此重复

存储管理

分区存储管理

  • 所谓分区存储管理,就是整存,将某进程运行所需的内存整体一起分配给它,然后再执行。有三种分区方式:

  • 固定分区:静态分区方法,将主存分为若干个固定的分区,将要运行的作业装配进去,由于分区固定,大小和作业需要的大小不同,会产生内部碎片

    类似数组

  • 可变分区:动态分区方法,主存空间的分区是在作业转入时划分,正好划分为作业需要的大小,这样就不存在内部碎片,但容易将整片主存空间切割成许多块,会产生外部碎片。可变分区的算法如下

  • 系统分配内存的算法有很多,如下图所示,根据分配前的内存情况,还需要分配9kb空间,对不同算法的结果介绍如下:

    • 首次适应法:按内存地址顺序从头查找,找到第一个>=9k空间的空闲块,即切割9k空间分配给进程

    • 最佳适应法:将内存中所有空闲内存块按从小到大排序,找到第一个>=9K空间的空闲块,切割分配,这个将会找到与9K空间大小最相近的空闲块

    • 最差适应法:和最佳适应法相反,将内存中空闲块空间最大的,切割9k空间分配给进程,这是为了预防系统中产生过多的细小空闲块

    • 循环首次适应法:按内存地址顺序查找,找到第一个>=9K空间的空闲块,而后若还需分配,则找下一个,不用每次都从头查找,这是与首次适应法不同的地方

  • 可重定位分区:可以解决碎片问题,移动所有已经分配好的区域,使其成为个连续的区域,这样其他外部细小的分区碎片可以合并为大的分区,满足作业要求。只在外部作业请求空间得不到满足时进行

分页存储管理

分页

要掌握逻辑地址看页表转化为物理地址

分区存储是整存

分页存储不用一次性存进去,一步一步的,现在计算机常用的

有内部碎片

逻辑页分为页号和页内地址页内地址就是物理偏移地址(页号的后xx位),而页号(位于高位)与物理块号并非按序对应的,需要查询页表,才能得知页号对应的物理块号,再用物理块号加上偏移地址才得出了真正运行时的物理地址

  • 分页系统(逻辑地址(页))的地址结构:
高位低位
页号页内地址(偏移地址)

优点:利用率高,碎片小,分配及管理简单
缺点:增加了系统开销,可能产生抖动现象

页的个数增加,但算法没有提升,导致原本不会下降的速度,速度下降

页的逻辑地址组成:页号,内存(偏移)地址组成

物理地址:页框(页帧),外存地址组成

页号:假设有4GB的内存,每一页的大小为4KB,那么总共有2^20页,即有20位的页号,由页号查页表(存逻辑地址和物理地址之间的对应关系)才能将页号转换成物理块号,即从逻辑地址转换成物理地址

页内地址(页面大小):和页的大小相关,一页大小为4KB,那么页内地址为2^12,页内地址和物理地址都是不变的

页面置换算法

请求分页是在纯分页系统的基础上增加了请求调页功能、**页面置换功能所形成的页式虚拟存储系统,它是日前常用的一种虚拟存储器的方式。在进程运行过程中,如果发生缺页,此时主存中又无空闲块时,为了保证进程能正常运行,必须从主存中调出一页程序或数据送磁盘的对换区。**但究竞将哪个页面调出,需要根据一定的页面置换算法来确定。置换算法的好坏将直接影响系统的性能,不适当的算法可能会导致系统发生“抖动”(thrashing)。即刚被换出的页很快又被访问,需重新调入,导致系统频繁地更换页面,以至于一个进程在运行中把大部分时间花费在完成页面置换的工作上,这种现象称为系统发生了“抖动”(也称)。请求分页系统的核心问题是选择合适的页面置换算法,常用的页面置换算法如下所述。

  • 最优算法:OPT,理论上的算法,无法实现,是在进程执行完后进行的最佳效率计算,用来让其他算法比较差距。原理是选择未来最长时间内不被访问的页面置换,这样可以保证未来执行的都是马上要访问的
  • 先进先出算法:FIFO,先调入内存的页先被置换淘汰,会产生抖动现象,即分配的页数越多,缺页率可能越多(即效率越低)
  • 最近最少使用:LRU(Least Recently Used),在最近的过去,进程执行过程中,过去最少使用的页面被置换淘汰,根据局部性原理,这种方式效率高,且不会产生动现象,使用大量计数器,,但是没有LFU多
  • 淘汰原则:优先淘汰最近未访问的,而后淘最近未被修改的页面

用了最近最少使用LRU算法,第一看访问位,看有没有访问,第二看修改位,看有没有修改

快表(快速的页表)
  • 是一块小容量的相联存储器,由快速存储器组成,按内容访问,速度快,并且可以从硬件上保证按内容并行查找,一般用来存放当前访问最频繁的少数活动页面的页号

    相联存储器是一种按内容访问的存储器

  • 快表是将页表存于cache中慢表是将页表存于内存上。慢表需要访问两次内存才能取出页,而快表是访问一次cache和一次内存,因此更快

分段存储管理

分页是每页固定分(固定大小),分段每段不是固定的大小,是根据逻辑整体分段的

将进程空间分为一个个段,每段也有段号(从0开始)和段内地址,与页式存储不同的是,每段物理大小不同,分段是根据逻辑整体分段的

分页是页号和页内地址

因此,段表也与页表的内容不同,页表中直接是逻辑页号对应物理块号,而下图所示,段表有段长和基址两个属性,才能确定一个逻辑段在物理段中的位置。

段表寄存器由段表地址地址(基址)和段长组成

段的逻辑地址的两个位:段号,段内地址。因此逻辑地址必须在段长内(不能超出段长)

  • 分段系统的地址结果,段表(逻辑地址):
段号段内地址(偏移地址)
  • 段表寄存器的组成:

    段表起始地址(基址、起始地址)段表长度(>=段内地址)

    逻辑地址转换成物理地址:段表的起始地址+段内地址

    优点:多道程序共享内存,各段程序修改互不影响。
    缺点:内存利用率低,内存碎片浪费大

分页之间有逻辑地址与物理地址之间的转换,分段也有

分页是偏移地址不变,页号转换成物理号

分段是段内地址不变,段号转换成物理号

段页式存储管理

  • 对进程空间先分段,后分页,具体原理图和优缺点如下

  • 优点:空间浪费小、存储共享容易、存储保护容易、能动态链接

  • 缺点:由于管理软件的增加,复杂性和开销也随之增加,需要的硬件以及占用的内容也有所增加,使得执行速度大大下降

设备管理

设备管理概述

  • 设备是计算机系统与外界交互的工具,具体负责计算机与外部的输入/输出工作所以常称为外部设备(简称外设)。在计算机系统中,将负责管理设备和输入/输出的机构称为I/O系统。因此,I/O系统由设备、控制器、通道(具有通道的计算机系统)、总线和O软件组成

    设备的分类

  • 按数据组织分类:块设备、字符(字符流)设备。

  • 按照设备功能分类:输入设备、输出设备、存储设备、网络联网设备、供电设备。

  • 资源分配角度分类:独占设备(互斥)、共享设备(同步)和虚拟设备

  • 数据传输速率分类:低速设备、中速设备、高速设备。

  • 设备管理的任务是保证在多道程序环境下,当多个进程竞争使用设备时,按一定的策略分配和管理各种设备,控制设备的各种操作,完成IO设备与主存之间的数据交换。

  • 设备管理的主要功能是动态地掌握并记录设备的状态、设备分配和释放、缓冲

  • 区管理、实现物理IO设备的操作、提供设备使用的用户接口及设备的访问和控制

I/O软件

  • I/0设备管理软件的所有层次及每一层功能如下图:

  • 实例:当用户程序试图读一个硬盘文件时,需要通过操作系统实现这一操作。与设备无关软件检查高速缓存中有无要读的数据块(设备无关软件),若没有,则调用设备驱动程序,向IO硬件发出一个请求(设备驱动程序)。然后,用户进程阻塞并等待磁盘操作的完成。当磁盘操作完成时,硬件产生一个中断,转入中断处理程序(中断处理程序)。中断处理程序检查中断的原因,认识到这时磁盘读取操作已经完成,于是唤醒用户进程取回从盘读取的信息,从而结束此次IO请求。用户进程在得到了所需的硬盘文件内容之,后继续运行。

    重点:

    设备无关软件

    设备驱动程序

    中断处理程序

image-20240330185241396

设备管理技术

  • 一台独占设备,在同一时间只能由一个进程使用,其他进程只能等待,且不知道什么时候打印机空闲,此时,极大的浪费了外设的工作效率。

  • (虚拟设备)引入SPOOLING(外围设备联机操作)技术(将独占的设备转变成共享设备),就是在外设上建立两个数据缓冲区,分别称为输入井和输出井,这样,无论多少进程,都可以共用这一台打印机,只需要将打印命令发出,数据就会排队存储在缓冲区中,打印机会自动顺序打印,实现了物理外设的共享,使得每个进程都感觉在使用一个打印机这就是物理设备的虚拟化。如下图所示

    所谓独占就是原本打印机如果多个提交就会提示目前占用,无法使用;共享就是可以照常提交,但是你得排队

文件管理

文件管理概述

  • 文件是具有符号名的、在逻辑上具有完整意义的一组相关信息项的集合

  • 信息项是构成文件内容的基本单位,可以是一个字符,也可以是一个记录,记录可以等长,也可以不等长。一个文件包括文件体和文件说明。文件体是文件真实的内容。文件说明是操作系统为了管理文件所用到的信息,包括文件名文件内部标识、文件的类型、文件存储地址、文件的长度、访问权限、建立时间和访问时间等

  • 文件管理系统,就是操作系统中实现文件统一管理的一组软件和相关数据的集合,专门负责管理和存取文件信息的软件机构,简称文件系统。文件系统的功能包括按名存取;统一的用户接口;并发访问和控制;安全性控制;优化性能;差错恢复。

  • 文件的类型

    (1)按文件性质和用途可将文件分为系统文件、库文件和用户文件
    (2)按信息保存期限分类可将文件分为临时文件、档案文件和永久文件。(3)按文件的保护方式分类可将文件分为只读文件、读/写文件、可执行文件和不保护文件。
    (4)unI系统将文件分为普通文件、目录文件和设备文件(特珠文件)。

  • 文件的逻辑结构可分为两大类:有结构的记录式文件:无结构的流式文件

  • 文件的物理结构是指文件在物理存储设备上的存放方法,包括:
    (1)连续结构。连续结构也称顺序结构,它将逻辑上连续的文件信息(如记录)依次存放在连续编号的物理块上
    (2)链接结构。链接结构也称串联结构,它是将逻辑上连续的文件信息(如记录)存放在不连续的物理块上,每个物理块设有一个指针指向下一个物理块。

    (3)索引结构。将逻辑上连续的文件信息(如记录)存放在不连续的物理块中,系统为每个文件建立一张索引表。索引表记录了文件信息所在的逻辑块号对应的物理块号,并将索引表的起始地址放在与文件对应的文件目录项中。
    (4)多个物理块的索引表。索引表是在文件创建时由系统自动建立的,并与文件一起存放在同一文件卷上。根据一个文件大小的不同,其索引表占用物理块的个数不等,一般占一个或几个物理块

索引文件结构

  • 如图所示,系统中有13个索引节点,0-9为直接索引,即每个索引节点存放的是内容,假设每个物理盘(磁盘数据块)大小为4KB,共可存4KB*10=40KB数据

    若没有告诉地址项是从什么数字开始的,则默认是从0开始的

  • 10号索引节点为一级间接索引节点,大小为4KB,存放的并非直接数据,而是链接到直接物理盘块的地址,假设每个索引地址占4B,则共有1024个地址,对应1024个物理盘,可存1024*4KB=4096KB数据

    一个盘块可以存的索引数量=盘块的大小/每一个盘块的地址的大小

  • 二级索引节点类似,直接盘存放一级地址,一级地址再存放物理盘快地址,而后链接到存放数据的物理盘块,容量又扩大了一个数量级,为1024*1024*4KB数据

磁盘索引块是用作算索引数量的除数

磁盘数据块的用来计算长度的,长度就是数据块

文件目录

  • 文件控制块(FCB,文件目录)中包含以下三类信息:基本信息类、 存取控制信息类和使用信息类

    (1)基本信息类。例如文件名、文件的物理地址、文件长度和文件块数等。

    (2)存取控制信息类。文件的存取权限,像unIX用户分成文件主、同组用户和一般用户三类,这三类用户的读/写执行RWX权限。

    (3)使用信息类。文件建立日期、、最后一次修改日期、最后一次访问的日期、当前使用的信息(如打开文件的进程数、在文件上的等待队列)等。

  • 文件控制块的有序集合称为文件目录。

  • 相对路径:是从当前路径开始的路径。

  • 绝对路径:是从根目录开始的路径。

  • 全文件名=绝对路径+文件名要注意,绝对路径和相对路径是不加最后的文件名的,只是单纯的路径序列。

文件存储空间管理

  • 文件的存取方法是指读/写文件存储器上的一个物理块的方法。通常有顺序存取和随机存取两种方法。顺序存取方法是指对文件中的信息按顺序依次进行读写;随机存取方法是指对文件中的信息可以按任意的次序随机地读/写
  • 文件存储空间的管理

(1)空闲区表。将外存空间上的一个连续的未分配区域称为“空闲区”。操作系统为磁盘外存上的所有空闲区建立一张空闲表,每个表项对应一个空闲区适用于连续文件结构。

18-22都是空的

29-36…

(2)位示图。 这种方法是在外存上建立一张位示图(Bitmap),记录文件存储器的使用情况。 每一位bit对应文件存储器上的一个物理(磁盘)块,取值0和1分别表示空闲和占用。假如计算机系统中字长为32位那么在位示图中的第0个字(位)(逻辑编号)对应文件存储器上的0,1,2,,31号物理块:第1个字(位)对应文件存储器上的32,33,34,63号物理块,以此类推。

位示图的大小对应的就是多少个物理块,单位是b

磁盘个数(b)=磁盘容量/一块磁盘(物理)块大小

(3)空闲块链。每个空闲物理块中有指向下一个空闲物理块的指针,所有空闲物理块构成一个链表,链表的头指针放在文件存储器的特定位置上(如管理块中),不需要磁盘分配表,节省空间
(4)成组链接法。例如,在实现时系统将空闲块分成若干组,每100个空闲块为一组,每组的第一个空闲块登记了下一组空闲块的物理盘块号和空闲块总数。假如某个组的第一个空闲块号等于0,意味着该组是最后一组,无下一组空闲块

作业调度算法

算法说明备注
先来先服务
(First Come First Serve)
先来先得先后最简单,先来的任务先服务
优点:对长任务和繁忙CPU有利缺点:对短任务和繁忙VO任务不利
**短作业优先<**br/> (Shortest Job First)谁小谁先爱幼对长任务不利;不能保障紧急任务被及时处理;任务长短只是主观估算
优点:最短的平均等待时间和平均周转时间
缺点:对长任务不利,未考虑紧追性会导致机(长任务得不到资源)
响应比高优先响应比高的作业优先启动响应比r=作业响应时间/作业执行时间
=(作业等待时间+作业执行时间)/作业执行时间
优先权调度
Priority Scheduling)
看优先级权重根据优先级把资源分配给优先级最高的静态优先权+动态优先权
优点:可灵活调整任务偏好程度
缺点:高优先级太多,导致(低优先级无法得到资源
均衡调度算法根据系统的运行情况和作业本身的特性对作业分类,力求均衡地使用系统的各种资源,即注意发挥系统效率,使用户满意
时间片轮转
Round Robin)
一视同仁公平将作业排成队列,每份作业分段,轮流获取运行时间
进程阻塞,未用完也要让出;不考虑任务长短受系统处理能力和负载影响
优点:公平,响应快,适用于分时操作系统
缺点:高频率切换带来开销,不区分任务紧急程度

image-20240430175349234

image-20240429161544096

时间片流转(轮转)是用于交互式系统的

  • 进程调度方式是指当有更高优先级的进程到来时如何分配CPU。分为可夺和不可夺两种,可剥夺指当有更高优先级进程到来时,强行将正在运行进程的CPU分配给高优先级进程;不可夺是指高优先级进程必须等待当前进程自动释放CPU。

  • 在某些操作系统中,一个作业(一组进程)从提交到完成需要经历高、中、低三级调度。

    (1)高级调度。高级调度又称“长调度”“作业调度”或“接纳调度” 它决定处于输入池中的哪个后备作业可以调入主系统做好运行的准备,成为一个或组就绪进程。在系统中一个作业只需经过一次高级调度。
    (2)中级调度。中级调度又称“中程调度”或“对换调度 它决定处于交换区中的哪个就绪进程可以调入内存,以便直接参与对CPU的竞争。
    (3)低级调度。低级调度又称“短程调度”或“进程调度”,它决定处于内存中的哪个就绪进程可以占用CPU。低级调度是操作系统中最活跃、最重要的调度程序,对系统的影响很大

调度算法:

  • 先来先服务FCFS:先到达的进程优先分配CPU。用于宏观调度
  • 时间片轮转(分时):分配给每个进程CPU时间片,轮流使用CPU,每个进程时间片大小相同,很公平,用于微观调度
  • 优先级调度:每个进程都拥有一个优先级,优先级大的先分配CPU。
  • 多级反馈调度:时间片轮转和优先级调度结合而成,设置多个就绪队列,每个队列分别赋予不同的优先级,分配不同的时间片长度;新进程先进入队列1的未尾,按FCFS原则,执行队列1的时间片;若未能执行完进程,则转入队列2的未尾,如此重复

网络基础知识

image-20240322093410114

计算机网络概述

网络功能和分类

计算机网络是计算机技术与通信技术相结合的产物,它实现了远程通信、远程信息处理和资源共享。

计算机网络的功能:数据通信、资源共享、负载均衡、高可靠性。

计算机网络按分布范围和拓扑结构划分如下图所示:

Local Area Network

Metropolitan Area Network

Wide Area Network

互联网就是一个广域网

一个局域网的基本组成主要有网络服务器、网络工作站、网络适配器和传输介质;决定局域网特性的主要技术有三个方面:用以传输数据的传输介质;用以连接各种设备的拓扑结构:用以共享资源的介质访问控制方法

例如电信的100兆M每秒,实际就是100Mbit/s,实际要除以8=12.5MB/s

总线型(利用率低、干扰大、价格低)、星型(交换机形成的局域网、中央单元负荷大)、环型(流动方向固定(顺或逆)、效率低扩充难)、树型(总线型的扩充、分级结构)、分布式(任意节点连接,管理难成本高)

总线型特点:只能一个发送。可以多个接受

星型常用:交换机

OSI七层模型

(Open System Interconnect),即开放式系统互连参考模型

记忆口诀:物链网传输应用

层次(低到高)功能单位协议设备
1.物理层在链路上透明地传输位(bit)。需要完成的工作包括线路配置、确定数据传输模式、确定信号形式、对信号进行编码、连接传输介质。为此定义了建立、维护和拆除物理链路所具备的机械特性、电气特性、功能特性以及规程特性。比特bitEIA/TIA RS-232、RS-449、V.35、RJ-45、FDDI中继器(集线器)集成器(hub、usb多口)
2.数据链路层把不可靠的信道变为可靠的信道。为此将比特组成,在链路上提供点到点的传输,并进行差错控制、流量控制等。SDLC、HDLC、LAPB、PPP、STP、中继等、IEEE802、ATM交换机、网桥
3.网络层**在源节点目的节点之间进行路由选择、拥塞控制、顺序控制、传送包,保证报文的正确性。**网络层控制着通信子网的运行,因而它又称为通信子网层IP分组IP、 ICMP、IGMP、ARP、RARP、IPsec路由器
4.传输层提供端-端间可靠的、透明的数据传输,保证报文顺序的正确性、数据的完整性。报文段TCPUDP网关
5.会话层建立通信进程的逻辑名字与物理名字之间的联系,提供进程之间建立、管理和终止会话的方法,处理同步与恢复问题。PDURPC、SQL、NFS网关
6.表示层实现数据转换(包括格式转换、压缩、加密等),提供标准的应用接口、公用的通信服务、公共数据表示方法JPEG、ASCII、GIF、MPEG、DES网关
7.应用层对用户不透明的提供各种服务,如E-mail。数据Telnet、 FTP、 HTTP、SMTPPOP3、DNS、DHCP网关
  • 第①层的设备每个代表一个冲突域
  • 第②层的设备每个都能隔离冲突域,即几个主机就是几个冲突域
  • 第③层的设备每个都能隔离广播域,即连接几个设别就是几个广播域

局域网就是数据链路层,不能接入互联网(网络层),可以连在一起,但不能通网

以太网(以太网是一种计算机局域网技术。以太网有两类:第一类是经典以太网,第二类是交换式以太网,使用了一种称为交换机的设备连接不同的计算机。以太网是一种计算机局域网技术。以太网有两类:第一类是经典以太网,第二类是交换式以太网,使用了一种称为交换机的设备连接不同的计算机。)是局域网的一个具体应用

以太网位于传输层

网络硬件基础

传输介质(网线)

  • 双绞线:将多根铜线按规则缠绕在一起,能够减少干扰;分为无屏双绞线UTP和屏双绞线STP,都是由一对铜线组成。也即我们常说的网线;双绞线的传输距离在100m以内。

  • 无屏蔽双绞线UTP:价格低安装简单,但可靠性相对较低,分为CAT3(3类UTP,速率为10Mbps)、CAT4(4类UTP,与3类差不多,无应用)、-CAI5(5类UTP,速率为100Mbps,用于快速以太网)CAI5E(超5类UTP,速率为1000Mbps)、CAT6(6类UTP,用来替代CAT5E,速率也是1000Mbps)
  • 屏蔽双绞线STP:比之UTP增加了一层屏蔽层,可以有效的提高可靠性,但对应的价格高,安装麻烦,一般用于对传输可靠性要求很高的场合。
  • 多模光纤的特点:成本低、宽芯线、聚光好、耗散大、低效,用于低速短距离的通信。
  • 单模光纤的特点:成本高、窄芯线、需要激光源、耗散小、高效,用于高速长距离的通信。

网线标准:

  • A:绿白绿 橙白蓝 蓝白橙 棕白棕

  • B:橙白橙 绿白蓝 蓝白绿 棕白棕

    两者相同:蓝和蓝白,棕白棕

    交换次序:绿白绿与橙白橙

    绿了先A

    交叉线接法:一端A一端B则可以用于,网卡连网卡;或交换机连交换机/hub,主机连路由器

    直通线接法:两头都是b或a,网卡与交换机\hub

  • 光纤:由纤芯和包层组成,传输的光信号在纤芯中传输,然而从PC端出来的信号都是电信号,经过光纤传输的话,就必须将电信号转换为光信号

  • 多模光纤MMF:纤芯半径较大,因此可以同时传输多种不同的信号,光信号在光纤中以全反射的形式传输,采用发光二极管LED为光源,成本低,但是传输的效率和可靠性都较低,适合于短距离传输,其传输距离与传输速率相关,速率为100Mbps时为2KM, 速率为1000Mbps时为550m

  • 单模光纤SMF:纤芯半径很小,一般只能传输一种信号,采用激光二极管LD作为光源,并且只支持激光信号的传播,同样是以全反射形式传播,只不过反射角很大,看起来像一条直线,成本高,但是传输距离远,可靠性高。传输距离可达5KM。

  • 无线电波与红外光波:

物理层互联设备

物理层的互联设备有中继器(Repeater)和集线器(Hub)。
1)中继器
它是在物理层上实现局域网网段互联的,用于扩展局域网网段的长度**。由于中继器只在两个局域网网段间实现电气信号的恢复与整形,因此它仅用于连接相同的局域段。
理论上说,可以用中继器把网络延长到任意长的传输距离,但是,局域网中接入的中继器的数量将受时延和衰耗的影响,因而必须加以限制。**中继器的主要优点是安装简便、使用方便、价格便宜。

2)集线器
​ 可以看成是一种特殊的多路中继器,也具有信号放大功能。使用双绞线的以太网多用Hub扩大网络,同时也便于网络的维护。**以集线器为中心的网络优点是当网络系统中某条线路或某节点出现故障时,不会影响网上其他节点的正常工作。集线器可分为无源(passive)集线器、有源(active)集线器和智能(intelligent)集线器
​ 无源集线器只负责把多段介质连接在一起,不对信号做任何处理,每一种介质段只允许展到最大有效距离的一半:有源集线器类似于无源集线器,但它具有对传输信号进行再生和放大从而扩展介质长度的功能;智能集线器除具有有源集线器的功能外,还可将网络的部分功能集成到集线器中,如网络管理、选择网络传输线路等

广播域与冲突域

集线器所有连接主机的端口组成一个冲突域集线器不可以起到自动寻址的作用

交换机所有连接主机的端口各个形成一个冲突域

路由器所有连接主机的端口各个形成一个冲突域

在这里插入图片描述

数据链路层的互联设备

数据链路层的互联设备有网桥(Bridge)和交换机(Switch)
1)**网桥
用于连接两个局域网网段,工作于数据链路层。**网桥要分析帧地址字段,以决定是否把收到的帧转发到另一个网络段上。确切地说,网桥工作于MAC子层,只要两个网络MAC子层以上的协议相同,都可以用网桥互联
2)**交换机
交换机是一个具有简化、低价、高性能和高端口密集特点的交换产品,它是按每一个包中的MAC地址相对简单地决策信息转发,而这种转发决策一般不考虑包中隐藏的更深的其他信息。**交换机转发数据的延退很小,操作接近单个局域网性能,远远超过了普通桥接的转发性能交换技术允许共享型和专用型的局域网段进行带宽调整,以减轻局域网之间信息流通出现的瓶颈问题。

交换机的工作过程为:当交换机从某一节点收到一个以太网后,将立即在其内存中的地址表(端口号-MAC地址)进行查找,以确认该日的MAC的网卡连接在哪一个节点上,然后将该转发至该节点。如果在地址表中没有找到该MAC地址,也就是说,该日的MAC地址是首次出现,交换机就将数据包广播到所有节点。拥有该MAC地址的网卡在接收到该广播后,将立即做出应答,从而使交换机将其节点的“MAC地址”添加到MAC地址表中。

交换机是一种多端口网桥,且各个端口形成一个广播域,但不是冲突域,集线器才组成冲突域

​ 交换机的三种交换技术:端口交换、交换和信元交换
​ (1)端口交换技术用于将以太模块的端口在背板的多个网段之间进行分配、平衡。
​ (2)交换技术对网络顿的处理方式分为直通交换和存储转发。其中,直通交换方式可提供线速处理能力,交换机只读出网络顿的前14个字节,便将网络顿传送到相应的端口上;存储转发方式通过对网络的读取进行验错和控制。
​ (3)信元交换技术采用长度(53个字节)固定的信元交换,由于长度固定,因而便于用硬件实现。

网络层互联设备

路由器(Router)是网络层互联设备,用于连接多个逻辑上分开的网络。逻辑网络是指一个单独的网络或一个子网,当数据从一个子网传输到另一个子网时,可通过路由器来完成。
路由器具有很强的异种网互联能力,互联的网络最低两层协议可以互不相同,通过驱动软件接口到第三层上而得到统一。对于互联网络的第三层协议,如果相同,可使用单协议路由器进行互联:如果不同,则应使用多协议路由器。多协议路由器同时支持多种不同的网络层协议,并可以设置为允许或禁止某些特定的协议。所谓支持多种协议,是指支持多种协议的路由,而不是指不同类协议的相互转换。
通常把网络层地址信息叫作网络逻辑地址,把数据链路层地址信息叫作物理地址。**路由器最主要的功能是选择路径。在路由器的存储器中维护着一个路径表,记录各个网络的逻辑地址用于识别其他网络。**在互联网络中,当路由器收到从一个网络向另一个网络发送的信息包时,将丢弃信息包的外层,解读信息包中的数据,获得目的网络的逻辑地址,使用复杂的程序来决定信息经由哪条路径发送最合适,然后重新打包并转发出去。路由器的功能还包括过滤、存储转发、流量管理和介质转换等。一些增强功能的路由器还可有加密、数据压缩、优先和容错管理等功能。由于路由器工作于网络层,它处理的信息量比网桥要多,因而处理速度比网桥慢。

应用层互联设备

​ **网关(Gateway)是应用层的互联设备。在一个计算机网络中,当连接不同类型而协议差别又较大的网络时,则要选用网关设备。**网关的功能体现在OSI模型的最高层,它将协议进行转换,将数据重新分组,以便在两个不同类型的网络系统之间进行通信。由于协议转换是一件复杂的事,一般来说,网关只进行一对一转换,或是少数几种特定应用协议的转换,网关很难实现通用的协议转换

网络的协议与标准

局域网和广域网协议

  • 以太网规范IEEE802.3是重要的局域网协议(电气电子工程师学会IEEE的英文全称是the Institute of Electrical and Electronics Engineers**)**,包括:

    IEEE802.3 标准以太网 10Mb/s 传输介质为细同轴电缆

    IEEE802.3u 快速以太网 100Mb/s 双绞线

    IEEE802.3z 千兆以太网 1000Mb/s 光纤或双绞线

    EEE802.3ae 万兆以太网 10Gb/s 光纤

  • 无线局域网WLAN技术标准:IEEE802.11

  • 广域网协议包括: PPP**(Point-to-Point Protocol,如拨号上网)**点对点协议、ISDN综合业务数字网、XDSL、DSL数字用户线路的统称:HDSL、SDSL、MVL、ADSL)、DDN(Digital Data Network)数字专线、X.25、FR中继、ATM异步传输模式

TCP/IP协议(四层模型)

传输控制协议(英语:Transmission Control Protocol)

Internet Protocol( 网际互连协议 )

网络协议三要素:语法、语义、时序。其中语法部分规定传输数据的格式,语义部分规定所要完成的功能,时序部分规定执行各种操作的条件、顺序关系等

TCP协议与OSI模型的对应关系:

OSITCP
1.物理层网络接口层
2.数据链路层
3.网络层网际层
4.传输层运输层
5.会话层应用层
6.表示层
7.应用层

TCP与UDP:

用户数据报协议(UDP,User Datagram Protocol)

动态主机配置协议(Dynamic Host Configuration Protocol)

TCPUDP
ftp(20、21)tftp(69)
pop3(110)dns(53)
http(80)dhcp(67)
smtp(25)、发送邮件snmp(161)
telnet(23)VOIP

**iP电话(VoIP)**是一种基于传输层中用户数据报协议(UDP)所提供服务的应用层协议。

各层协议

网络层协议
  • IP:网络层最重要的核心协议,在源地址和目的地址之间传送数据报,无连接、不可靠。

  • ICMP(Internet Control Message Protocol):因特网控制报文协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。

  • ARP(Address Resolution Protocol)RARP(Reverse Address Resolution Protocol):地址解析协议,ARP是将IP地址转换为物理地址

  • RARP是将物理地址转换为IP地址

  • IGMP(Internet Group Management Protocol):网络组管理协议,允许因特网中的计算机参加多播,是计算机用做向相邻多目路由器报告多目组成员的协议,支持组播

  • IPsec(Internet Protocal Security):互联网安全协议,是保护IP协议的网络传输协议簇

    ipsec属于第三层vpn协议

传输层协议
  • TCP:整个TCP/IP协议族中最重要的协议之一,在IP协议提供的不可靠数据数据基础上,采用了重发技术,为应用程序提供了一个可靠的、面向连接的、全双工的数据传输服务。一般用于传输数据量比较少,且对可靠性要求高的场合。

    建立连接:三次握手,源主机发送一个,目标主机愿意通信,源主机确认相应目标主机的TCP包

    断开连接:四次挥手,

  • UDP:是一种不可靠、无连接的协议,有助于提高传输速率,一般用于传输数据量大,对可靠性要求不高,但要求速度快的场合

  • SSH(secure shell protocal):安全外壳协议,为远程登录会话提供安全

应用层协议

基于TCP的FTP、HTTP等都是可靠传输。基于UDP的DHCP、DNS等都是不可靠传输。

TCP

  • FTP(FileTransferProtocol,FTP):文件传输协议,用于因特网上的控制文件的双向传输

    **匿名FTP用户名是anonymous,密码通常是guest或者使用者E-mail地址。出于安全目的,多数名FTP服务器不允许上传、修改和删除操作。**数据不加密

    FTP在客户端与服务器内部建立两条TCP连接:

    (1)21端口负责控制连接,主要用于传输命令和参数

    (2)20端口负责数据连接,主要用于传送文件

    注意:推荐使用被动模式,在同一局域网内可以使用主动模式

    1安全性:客户端通常配置本地防火墙,服务器20端口很难连接到指定端口
    2.连通性:NAT网络时需配置局域网端口映射

  • SFTP(SSH File Transfer Protocol, 也称SecretFileTransferProtocol):SFTP是基于网络协议SSH(安全外壳)的协议。数据加密

  • FTPS:FTPS是在FTP协议上增加了SSL协议。FTPS是为FTP添加传输层安全CTLS和安全套接层SSL加密协议支持的扩展协议

    sftp>ftps

  • TFTP(TrivialFileTransferProtocol):简单文件传输协议, 是TCP/IP协议族中,基于UDP协议用来在客户端与服务端之间简单文件传输的协议,提供不复杂、开销不天的文件传输服务。端口号为69。

  • HTTP:超文本传输协议,用于从WWW服务器传输超文本到本地浏览器的传输协议。使用SSL加密后的安全网页协议为HTTPS。

    ssh:secure shell,终端设备与远程站点之间建立安全连接的协议

  • SHTTP(Secure HyperText ) :安全超文本转换协,shttp和https区别:shttp以http 加密数据;https全程加密;

  • PGP、MOSS、PEM、MIME:邮件的应用

  • SMTP(发送邮件应用)和POP3:简单邮件传输协议,是一组用于由源地址到的地址传送邮件的规则,邮件报文采用ASCII格式表示。

  • Telnet:远程连接协议,是因特网远程登录服务的标准协议和主要方式

  • Kerberos:网络安全授权协议,对个人通信以安全手段进行身份认证。UDP

  • SNMP:简单网络管理协议,由一组网络管理的标准协议,包含一个应用层协议、数据库模型和一组资源对象。该协议能够支持网络管理系统,泳衣监测连接到网络上的设备是否有任何引起管理师行关注的情况。

    管理站和代理站必须具有相同的团体名才能互相通信

    image-20240324164654665

  • DHCP:动态主机配置协议,基于UDP,基于C/S模型,为主机动态分配IP地址,有三种方式

    固定分配、动态分配、自动分配

    动态ip地址协议

  • DNS:域名解析协议,通过域名解析出IP地址

会话层
  • Socks(protocal for sessions traversal across firewall securely):防火墙安全会话转换协议,是应用程序透明的穿过网络防火墙
  • Kerberos:网络安全授权协议,对个人通信以安全手段进行身份认证

协议端口号对照表
端口服务端口服务
20文件传输协议(数据),ftp80超文本传输协议(http)
21文件传输协议(控制),ftp110POP3服务器(邮箱接受服务器)
23Telnet终端仿真协议(远程连接)69简单文件传输协议(Tftp)
67DHCP(服务端)68DHCP(客户端)
25SMTP简单邮件发送协议161SNMP(轮询)
53域名服务器(DNS)162SNMP(陷阱)
22sftp

简单邮件传输协议(Simple Mail Transfer Protocol)

简单网络管理协议(Simple Network Management Protocol)

动态主机配置协议(Dynamic Host Configuration Protocol)

域名系统(Domain Name System)

文件传输协议(File Transfer Protocol)

internet基础知识

通信方式和交换方式

设备与网关之间要处于用一个子网才能进行互通

  • 通信方向

    • 单工总线:只能在一个方向上传输信息
    • 半双工总线:可以在两个方向上传输信息,但同一时刻,只能一个方向
    • 全双工总线:可以同时在不同方向传输信息
  • 同步方式

    • 异步传输:发送方每发送一个字符,需要约定一个起始位和停止位插入到字符的起始和结尾处这样当接收方接收到该字符时能够识别,但是这样会造成资源浪费,传输效率降低
    • 同步传输:以数据块为单位进行传输,当发送方要发送数据时,先发送一个同步顿,接收方收到后做好接收准备,开始接收数据块,结束后又会有结束确认,这样一次传输一个数据块,效率高
    • 串行传输:一次只能1位1位的发送,适合长距离,速度慢,价格低
    • 并行传输:1此能n位n位的发送,适合短距离,速度快,价格高
  • 3g通信标准

    TD-SCDMA

ip地址表示

机器中存放的IP地址是32位的二进制代码,每隔8位插入一个空格,可提高可读性,为了便于理解和设置,一般会采用点分十进制方法来表示:将32位二进制代码每8位二进制转换成十进制,就变成了4个十进制数,而后在每个十进制数间隔中插入,如下所示,最终为128.11.3.31

因为每个十进制数都是由8个二进制数转换而来,因此每个十进制数的取值范围为1-254(掌握二进制转十进制的快速计算方法, 牢记2的幕指数值,实现快速转换)

255是广播地址,专门用于向网络中所有工作站进行发送的一个地址。例如网关的主机位部分就是255,同时子网掩码也可以达到255。只有ip不能取255

分类ip
  • 分类IP地址:IP地址分四段,每段八位,共32位二进制数组成
    在逻辑上,这32位P地址分为网络号和主机号,依据网络号位数的不同,可以将P地址分为以下几类:

    如何判断ip地址是否是同一个网段的?

    同一个网段的ip的网络号必须相同,比如说无分类ip/20,那么只需看前20位的二进制网络号是否相同就可以

类别点分十进制表示最小地址最大地址
A类0.0.0.0 - 127.255.255.25500000000.00000000.00000000.0000000001111111.11111111.11111111.11111111
B类128.0.0.0 - 191.255.255.25510000000.00000000.00000000.0000000010111111.11111111.11111111.11111111
C类192.0.0.0 - 223.255.255.25511000000.00000000.00000000.0000000011011111.11111111.11111111.11111111
D类组播224.0.0.0 - 239.255.255.25511100000.00000000.00000000.0000000011101111.11111111.11111111.11111111
E类保留240.0.0.0 - 255.255.255.25511110000.00000000.00000000.0000000011111111.11111111.11111111.11111111

A类前缀必须是0开头,最多可以有2^24-2个主机

B类前缀必须是10开头,最多可以有2^16-2个主机

C类前缀必须是110开头,最多可以有2^8-2个主机

注:主机地址数量都需要-2

组播协议应用有VOD、Netmeeting、cscw

无分类ip
  • 无分类编址:即不按照ABC类规则,自动规定网络号,无分类编址格式为:IP地址/网络号,示例:128.168.0.11/20表示的IP地址为128.168.0.11,其网络号占20位,因此主机号占32-20=12位,也可以划分子网

    /后面表示的是网络号

私有ip
  • 特殊IP地址
    公有地址:通过它直接访问因特网。是全网唯一的IP地址。
    私有地址:属于非注册地址,专门为组织机构内部使用,不能直接访问因特网,下表所示为私有地址范

    如果私有地址要上网则要通过nat协议

    类别ip地址范围网络号网络数
    A10.0.0.0~10.255.255.255101
    B172.16.0.0~172.31.255.255172.16~172.3116
    C192.168.0.0~192.168.255.255192.168.0~192.168.255256

    特殊地址如下图:

    网络号主机号源地址使用目的地址使用代表的意思例子
    0可以不可在本网络上的本主机192.168.0.0/24
    全1不可可以在本网络上进行广播192.168.1.1/16
    net-ID全1不可可以对net-ID上的所有主机进行广播
    127非全0或全1的数可以可以用作本地软件环回测试之用127.0.0.1
    169.254非全0或全1的数可以可以Windows主机DHCP服务器故分配169.254.0.0/16

域名

域名(DomainName)通常是用户所在的主机名字或地址。域名格式是由若干部分组成的每个部分又称子域名,它们之间用“.”分开,每个部分最少由两个字母或数字组成。域名通常按分层结构来构造,每个子域名都有其特定的含义。通常情况,一个完整、通用的层次型主机域名由如下4部分组成:
计算机主机名.本地名.组名.最高层域名
从右到左,子域名分别表示不同的国家或地区的名称(只有美国可以省略表示国家的顶级域名)、组织类型、组织名称、分组织名称和计算机名称等。域名地址的最后一部分子域名称为高层域名(或顶级域名),它大致可以分成两类:一类是组织性顶级域名:另一类是地理性顶级域名。

子网划分

  • 子网划分:一般公司在申请网络时,会直接获得一个范围很大的网络,如一个B类地址,因为主机数之间相差的太大了,不利于分配,我们一般采用子网划分的方法来划分网络,即自定义网络号位数,就能自定义主机号位数,就能根据主机个数来划分出最适合的方案,不会造成资源的浪费。

  • 因此就有子网的概念,一般的IP地址按标准划分为ABC类后,可以进行再一步的划分,将主机号拿出几位作为子网号,就可以划分出多个子网,此时IP地址组成为:网络号+子网号+主机号

    无分类ip后面 /x 的位数由网络号和子网号组成,32-x就是主机号

  • 网络号和子网号都为1,主机号都为0,这样的地址为子网掩码

    如255.255.255.0;子网掩码不等同于子网地址

    要注意的是:子网号可以为全0和全1,主机号不能为全0或全1,因此,主机数需要-2,而子网总个数不用-2,就是2^n个

  • 还可以聚合网络为超网,就是划分子网的逆过程,将网络号取出几位作为主机号,此时,这个网络内的主机数量就变多了,成为一个更大的网络。

image-20240322201302483

子网个数的计算:2(新划分的网络号-原网络号)

IPv6

  • 主要是为了解决IPv4地址数不够用的情况而提出的设计方案,IPv6具有以下特性:
  • IPv6地址长度为128位,地址空间增大了2^96倍
  • 灵活的IP报文头部格式,使用一系列固定格式的扩展头部取代了IPV4中可变长度的选项字段。IPv6中选项部分的出现方式也有所变化,使路由器可以简单播过选项而不做任何处理,加快了报文处理速度;IPv6简化了报文头部格式,加快报文转发,提高了吞吐量;
  • 提高安全性,身份认证和隐私权是IPv6的关键特性;
  • 支持更多的服务类型
  • 允许协议继续演变,增加新的功能,使之适应未来技术的发展
  • IPv4和IPv6的过渡期间,主要采用三种基本技术

(1)双协议栈:主机同时运行IPv4和IPv6两套协议栈,同时支持两套协议,一般来说IPv4和IPv6地址之间存在某种转换关系,如IPv6的低32位可以直接转换为IPv4地址,实现互相通信。
(2)隧道技术:这种机制用来在IPv4网络之上建立一条能够传输IP6数据报的隧道,例如可以将IPv6数据报当做IPv4数据报的数据部分加以封装,只需要加一个IPv4的首部,就能在IP4网络中传输IPv6报
文。
(3)翻译技术:利用一台专门的翻译设备(如转换网关),在纯IPV4和纯IPV6网络之间转换IP报头的地址,同时根据协议不同对分组做相应的语义翻译,从而使纯IPV4和纯IPV6站点之间能够透明通信

NAT技术

​ 因特网面临IP地址短缺的问题。这个问题有所谓长期的或短期的两种解决方案。长期的解决方案就是使用具有更大地址空间的IPv6协议,网络地址翻译(NetworkAddressTranslatorsNAT)是许多短期的解决方案中的一种
​ NAT技术最初提出的建议是在子网内部使用局部地址,而在子网外部使用少量的全局地址,通过路由器进行内部和外部地址的转换。NAT的实现主要有两种形式。
第一种应用是动态地址翻译(DynamicAddressTranslation)。为此,首先引入存根域的概念。所谓存根域(ShibDomain),就是内部网络的抽象,这样的网络只处理源和目标都在子网内部的通信。任何时候存根域内只有一部分主机要与外界通信,甚至还有许多主机可能从不与外界通信,所以整个存根域只需共享少量的全局IP地址。存根域有一个边界路由器,由它来处理域内与外部的通信。

DNS

  • DNS的解析顺序:

    本地host文件->本地DNS缓存->本地DNS服务器->根域名服务器

  • DNS的查询顺序:

    本地缓存->本地DNS服务器->服务器的缓存->根域名DNS服务器

  • DNS负载均衡:

DNS负载均衡是通过启动循环,添加每个web服务器的主机记录来实现的

image-20240322200102499

DNS故障问题:

  • 本地的DNS服务器工作不正常
  • 本地DNS服务器网络连接中断
  • 直接将该计算机的DNS服务器设置错误也会导致DNS无法解析域名,从而出现使用域名不能访问该网站,但是使用该网站的IP地址可以访问该网站。

但是该计算机与DNS服务器不在同一子网不会导致DNS无法解析域名的现象发生,通常情况下大型网络里面的上网计算机与DNS服务器本易就不在一个子网,只要路由可达DNS都可以正常工作

动态地址分配

即DHCP

ping命令

判断用户与外部站点的连通性,

  1. ping(本地循环地址),无法ping则说明本机TCP/IP协议不能正常工作,
  2. ping+本机IP不通则说明网络适配器(网卡/MODEM)出现故障
  3. ping+同一网段计算机的IP不通则说明网络线路出现故障
  4. netstat命令:用于显示TCP、UDP、IP、ICMP协议相关统计数据,一般用于检验本机网络端口的连接情况
  5. ARP命令:可以查看和修改本地计算机的ARP表项,和查看ARP缓存和解决地址解析问题非常使用。
  6. Tracert命令:可以跟踪网络连接,Tracert(路由跟踪)是路由跟踪程序,用于确定IP数据报访问目标所采取的路径,可以查看哪段路由出现连接问题。

网络安全概述

image-20240322093453246

网络安全威胁

  • 一般认为,目前网络存在的威主要表现在以下5个方面:

    ​ (1)非授权访问:没有预先经过同意,就使用网络或计算机资源则被看作非授权访问,如有意避开系统访问控制机制,对网络设备及资源进行非正常使用,或擅自扩大权限,越权访问信息。它主要有以下几种形式:假冒、身份攻击、非法用户进入网络系统进行违法操作、合法用户以未授权方式进行操作等。

    ​ (2)信息泄露或丢失:指敏感数据在有意或无意中被泄露出去或丢失,它通常包括信息在传输中丢失或泄露、信息在存储介质中丢失或泄露以及通过建立隐蔽隧道等窃取敏感信息等如黑客利用电磁泄露或搭线窃听等方式可截获机密信息,或通过对信息流向、流量、通信频度和长度等参数的分析,推测出有用信息,如用户口令、账号等重要信息。

    ​ (3)破坏数据完整性:以非法手段得对数据的使用权,删除、修改、插入或重发某些重要信息,以取得有益于攻击者的响应:恶意添加,修改数据,以干扰用户的正常使用

    ​ (4)拒绝服务攻击:它不断对网络服务系统进行干扰,改变其正常的作业流程,执行无关

    程序使系统响应减慢甚至换,影响正常用户的使用,甚至使合法用户被排而不能进入计算机网络系统或不能得到相应的服务。

    ​ (5)利用网络传播病毒:通过网络传播计算机病毒,其破坏性大大高于单机系统,而且用户很难防范

  • 计算机网络面临以下的四种威胁:截获(interception),中断(interruption),算改(modification),伪造(fabrication)。
    (1)重放攻击:攻击者发送一个目的主机已接收过的包,达到欺骗系统的目的,主要用于身份认证过程
    (2)拒绝服务:攻击者向因特网上的服务器不停地发送大量分组,使因特网或服务器无法提供正常服务
    (3)访问控制:也叫做存取控制或接入控制。必须对接入络的权限加以控制,并规定每个用户的接入权限
    (4)流量分析:通过观察PDU的协议控制信息部分,了解正在通信的协议实体的地址和身份,研究PDU的长度和传输的频度,以便了解所交换的数据的某种性质
    (5)恶意程序:恶意程序(rogueprogram)通常是指带有攻击意图所编写的一段程序

image-20240324165005289

防御技术

蜜罐技术是一种主动防御技术,是入侵检测技术的一个重要发展方向。
蜜罐是一种在互联网上运行的计算机系统,是专门为吸引并透骗那些试图非法间入他人计算机系统的人而设计的。蜜罐系统是一个包含漏洞的诱骗系统,它通过摸拟一个或多个易受攻击的主机和服务,给攻击者提供一个容易攻击的目标。
由于蜜罐并没有向外界提供真正有价值的服务,因此所有试图与其进行连接的行为均可认为是可疑的。

防火墙技术

​ 防火墙(Firewall)是建立在内外网络边界上的过滤封锁机制,它认为内部网络是安全和可信赖的,而外部网络是不安全和不可信赖的。防火墙的作用是防止不希望的、未经授权地进出被保护的内部网络,通过边界控制强化内部网络的安全策略。

​ 防火墙技术经理了包过滤、应用代理网关和状态检测技术三个发展阶段:

  • VPN技术:通过隧道将两个内部网络通过公共网络进行连接使其成为一个总体网络。
  • 防火墙技术:包过滤防火墙(屏蔽路由器):将路由器放置于内部网络中,网络层安全
  • 应用代理防火墙:也就是双宿主机防火墙,应用层安全
  • 状态检测技术防火墙:以上两种技术的综合,屏蔽路由器置于外部网络,双宿主机置于内部网络。
  • 屏蔽子网防火墙:设置DMZ(非军事区)由屏蔽路由器置于内部网络和双宿主机构成。

image-20240324162628031

包过滤防火墙和代理服务防火墙的叙述:包过滤技术对应用和用户是透明的

image-20240322200220521

入侵检测与防御

入侵检测系统(Imtusion Detection System,IDS)作为防火墙之后的第二道安全屏障,通过从计算机系统或网络中的若干关键点收集网络的安全日志、用户的行为、网络数据包和审计
记录等信息并对其进行分析,从中检查是否有违反安全策略的行为和遭到入侵攻击的迹象,入
侵检测系统根据检测结果,自动做出响应。IDS的主要功能包括对用户和系统行为的监测与分析、系统安全漏洞的检查和扫描、重要文件的完整性评估、已知攻击行为的识别、异常行为模式的统计分析、操作系统的审计跟踪,以及违反安全策略的用户行为的检测等。入侵检测通过实时地监控入侵事件,在造成系统损坏或数据丢失之前阻止入侵者进一步的行动,使系统能尽可能地保持正常工作。与此同时,IDS还需要收集有关入侵的技术资料,用于改进和增强系统抵抗入侵的能力。
入侵检测系统有效地弥补了防火墙系统对网络上的入侵行为无法识别和检测的不足,入侵检测系统的部署,使得在网络上的入侵行为得到了较好的检测和识别,并能够进行及时的报警然而,随着网络技术的不断发展,网络攻击类型和方式也在发生着巨大的变化,入侵检测系统
也地暴露出如漏报、误报率高、灵活性差和入侵响应能力较弱等不足之处

被动攻击的概念:只拿数据,不修改、破坏数据

主动攻击的概念:将干扰通讯或导致信息传输不正确。

攻击行为

  1. DDOS(Distributed Denial of Service分布式阻断服务):黑客利用DDOS攻击器控制多台机器同时攻击来达到“碍正常使用者使用服务”的目的。

    image-20240324164513426

  2. TCP会话动持:是劫持通信双方已建立的TCP会话连接,假冒其中一方(通常是客户端)的身份,与另一方进行进一步通信。

  3. SQL注入:是一种类型的SQL注入攻击,询问数据库真或假的问题,并确定基于该应用程序的响应的答复

    SQL注入防范措施有
    1、通过正则表达校验用户输入
    2、通过参数化存储过程进行数据查询存取
    3、参数化SQL语句
    4、采用预编译语句集
    5、字符串过滤
    6、使用安全函数

  4. ARP欺骗攻击:是针对以太网地址解析协议(ARP)的一种攻击技术。由攻击者发送假的ARP数据包到网上,其目的是要让送至特定的IP地址的流量被错误送到攻击者所取代的地方

  5. 重放攻击:攻击者发送一个目标主机已接受过的包,来达到欺骗系统的目的,主要用于身份认证过程

恶意代码(病毒)

恶意代码(MaliciousCode):违背目标系统安全策略的程序代码

传播种类说明特征&类型备注
被动(触发)计算机病毒Computer Virus 复制一组具有自我复制、传播能力的程序代码,有宿主隐性:附加在正常软件或文档中
传染性:能进行自我复制(区别普通程序)
潜伏性:触发条件满足才执行(如某日)
④破坏性:危害程度取决于设计者
文档:Melissa(梅丽莎)病毒
邮件:爱虫病毒、求职信病毒
照片:库尔尼科娃
网页:NIMDA病毒
①引导型病毒:磁盘杀手病毒、AntiExe病毒
宏病毒:word宏病毒(批量处理程序命令)
③多态病毒:逃避静态特征扫描,需启发式杀毒
④隐藏病毒:隐藏文件大小和时间、加密等
特洛伊木马Trojan Horse 潜伏具有伪装能力、隐执行非法功能的恶意程序
需要宿主
本地特洛伊木马:只运行在本地,盗用多用户口令,修改复制整个硬盘资料,达到控制计算机的目的
网络特洛伊木马:远程木马控制端+木马肉鸡
红色代码、广外女生、冰河、Rootkit、Netspy、YAI、SubSeven、Netbus、Back Office、sniffer
①文件绑法:将木马绑到常用软件包
②邮件附件:将木马程序伪装成邮件附件
③Web网页:木马程序隐藏在html文件中
间谋软件
Spyware
刺探
在用户不知情时被安装的软件,执行用户非期望的功能弹出广告、浏览器重定向、记录击键、浏览习惯、窃取用户隐私2345浏览器、2345压缩软件;驱动精灵、驱动人生弹广告、360等
间谋软件
Spyware
刺探
依附在其他软件中,具有触发执行破坏能力的程序代码计数器触发、时问触发、文件触发、特定用户访问触发等若管理员一个月没有登录系统,则清除服务器数据
主动陷门(非授权访问)特权允许用户开系统安全机制而访问系统的代码软件开发商为调试和维护系统而设定的功能若允许特定用户识别码登录系统
网络蠕虫Worms
传播
具有自我复制和传播能力、可独立自动运行的恶意程序通过有漏洞的网络主机节点传播
①随机扫描:IP段随机扫描(Slammer虫)
②顺序扫描:所在网段扫描(W32.Blaster)
③选择性扫描:有选择性去扫描感染目标主机(病毒发展方向)
WannaCry勒索病毒、震荡波、Nimda、worm.、熊猫烧香
僵尸网络(Botnets)傀儡攻击者将户程序植入目标主机,进而操控受害机执行恶意活动的网络构建方式:远程漏洞攻击;弱口令扫描入侵;邮件附件;恶意文档;文件共享;
早期:类蟠虫病毒主动扫描+远程漏洞攻击
目前:网页挂马(主流)
细菌(消耗具有自我复制功能的独立程序通过复制本身来消耗系统CPU、内存和磁盘资源
  • 普通病毒与蠕虫病毒区别

    1、普通病毒需要寄生到其他程序(宿主)内部;而虫是一种独立智能程序,不需要附着宿主,通过复制自身传播
    2、普通病毒主要感染文件系统,蟠虫病毒目标是感染互联网上所有计算机

  • 僵尸网络与蠕虫病毒区别

    僵尸网络拥有同意的高度可控的系统,且僵尸网络追求规模,需要认为控制。而蠕虫病毒是自发性的,不需要人为的参与,且蠕虫病毒的目标是感染所有数字签名

image-20240324164817579

计算机安全等级

安全级别定义
A1可验证安全设计。提供B3级保护,同时给出系统的形式化隐秘通道分析,非形式化代码一致性验证
B3安全域。该级的TCB必须满足访问监控器的要求,提供系统恢复过程
B2结构化安全保护。建立形式化的安全策略模型,并对系统内的所有主体和客体实施自主访问和强制访问控制
B1标记安全保护。对系统的数据加以标记,并对标记的主体和客体实施强制存取控制
C2受控访问控制。实际上是安全产品的最低档次,提供受控的存取保护,存取控制以用户为单位
C1只提供了非常初级的自主安全保护,能实现对用户和数据的分离,进行自主存取控制,数据的保护以用户组为单位
D1最低级别,保护措施很小,没有安全功能

计算机安全十大原则

  1. 机制的经济性:着重强调在设计和实现安全措施时的简洁性
  2. 故障安全默认配置:所设计系统的默认配置应该具有保守的安全机制
  3. 完备调停:对于资源的每次访问必须检查以确保不违背安全机制
  4. 开放设计:系统设计和安全体系结构应该公开,安全仅依赖于对的保密
  5. 特权分离:为了访问受限资源或者让程序执行某些操作,多个条件需要被同时满足最小特权:要求每个用户和程序在操作时应当使用尽可能少的特权
  6. 最少公共机制:在多用户系统中,允许多个用户共享资源的机制应该最小化
  7. 心理可接受性:用户接口应该精心设计且非常直观,所有与安全相关的设置都按普通用户的期望进行配置
  8. 工作因素:在设计安全方案时,绕过安全机制的代价应与攻击者的资源做对比
  9. 危害记录:有时候记录入侵细节比采用更复杂的措施来预防入侵更为理想

信息安全

  • 信息安全

加密技术

  • 加密技术

相关文章:

  • SFM/MVS_NERF_3DGAUSS三维重建
  • linux内核升级
  • 行业案例 | SAS 基于 SQL 托管实例构建高弹性安全的数据平台
  • 低频rfid手持机,助力动物耳标智能化管理
  • 管理大规模监控技术栈的最佳实践
  • 【数据结构与算法】包装类初识泛型
  • 拓扑排序 —— 2. 力扣刷题207. 课程表
  • 14.1 - VDMA彩条显示实验之固定分辨率
  • 【Javascript】在canvas中加载shader着色器的方法(开箱即用)
  • 102.二叉树的层序遍历- 力扣(LeetCode)
  • JavaScript Number 对象
  • Unity中使用FMETP STREAM传输实时画面
  • python全栈-vue框架
  • Hibernate:让对象与数据库无缝对话的全自动ORM框架
  • CesiumEarth能够本地浏览的三维倾斜模型切片(3DTiles)
  • GESP2025年3月认证C++七级( 第三部分编程题(2)等价消除)
  • 图像形态学操作对比(Opencv)
  • VSCode中选择Anaconda的Python环境
  • java数组06:Arrays类
  • 数据结构--线性表
  • 站内优化包括哪些/今天的新闻 联播最新消息
  • 郑州最好的网站建设/汕头网站排名
  • 网站定位案例/seo短视频保密路线
  • 做网站流量怎么赚钱吗/网站优化推广哪家好
  • 怎么给网站做seo/源码交易平台
  • 网站二级栏目数量/企查查在线查询