1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-11-03 13:53:45 +08:00

将除号和乘号规范化

This commit is contained in:
Didnelpsun
2021-05-31 23:35:44 +08:00
parent cb6e0bd0dd
commit 220d5b726a
15 changed files with 81 additions and 86 deletions

View File

@@ -120,7 +120,7 @@
由于快速排序使用了递归,所以需要递归工作栈,空间复杂度与递归层数相关,所以为$O(递归层数)$。
每一层划分只需要处理剩余的待排序元素,时间复杂度不超过$O(n)$,所以时间复杂度为$O(n*递归层数)$。
每一层划分只需要处理剩余的待排序元素,时间复杂度不超过$O(n)$,所以时间复杂度为$O(n\times\text{递归层数})$。
而快速排序会将所有元素组织成为二叉树,二叉树的层数就是递归调用的层数。所以对于$n$个结点的二叉树,最小高度为$\lfloor\log_2n\rfloor+1$,最大高度为$n$。
@@ -306,7 +306,7 @@ $n$个元素二路归并排序,归并一共要$\log_2n$趟,每次归并时
#### 桶排序的性能
桶排序最好情况下使用线性时间$O(n)$,桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为$O(n)$。桶排序的平均时间复杂度为线性的$O(n+C)$,其中$C=n*(\log n-\log m)$,其中$m$代表桶划分的数量。
桶排序最好情况下使用线性时间$O(n)$,桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为$O(n)$。桶排序的平均时间复杂度为线性的$O(n+C)$,其中$C=n\times(\log n-\log m)$,其中$m$代表桶划分的数量。
很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。
@@ -385,7 +385,7 @@ $k$路平衡归并:最多只能有$k$个段归并为一个;每一趟归并
#### 最佳归并树的衡量
每个初始归并段可以看作一个叶子结点,归并树的长度作为结点权值,则归并树的带权路径长度WPL等于读写磁盘的次数。从而归并过程中的磁盘IO次数=归并树的WPL*2。
每个初始归并段可以看作一个叶子结点,归并树的长度作为结点权值,则归并树的带权路径长度WPL等于读写磁盘的次数。从而归并过程中的磁盘IO次数=归并树的WPL×2。
#### 最佳归并树的构造

View File

@@ -34,7 +34,7 @@
### 表达式求值
一般使用的都是中缀表达式,例如:4+2×3-10/5,按照运算法则,我们应当先算2×3然后算10/5 ,再算加法,最后算减法。
一般使用的都是中缀表达式,例如:4+2×3-10÷5,按照运算法则,我们应当先算2×3然后算10÷5 ,再算加法,最后算减法。
表达式分为三个部分:操作数、运算符、界限符。

View File

@@ -37,7 +37,7 @@
+ 匹配成功的最好时间复杂度:$O(m)$:刚好第一个就匹配上了,总对比次数为子串长度。
+ 匹配失败的最好时间复杂度:$O(n-m+1)=O(n-m)=O(n)$:匹配成功之前,每一个与第一个字符都匹配失败。
+ 匹配失败的最坏时间复杂度:$O(nm-m^2+m)= O(nm)$:子串除了最后一个对不上,其余的都能对上,则每次遍历完一边后,又要走回头路;直到匹配成功/失败一共需要比较$m*(n-m+1)$次。m:每次需要移动m次,i需要移动$n-m+1$次。
+ 匹配失败的最坏时间复杂度:$O(nm-m^2+m)= O(nm)$:子串除了最后一个对不上,其余的都能对上,则每次遍历完一边后,又要走回头路;直到匹配成功/失败一共需要比较$m\times(n-m+1)$次。m:每次需要移动m次,i需要移动$n-m+1$次。
### KMP算法

View File

@@ -14,7 +14,7 @@
各数组元素大小相同,且物理上连续存放。
数组元素a[i]的存放地址=起始地址LOC+i*sizeof(ElemType)。数组下标从0开始。
数组元素a[i]的存放地址=起始地址LOC+i×sizeof(ElemType)。数组下标从0开始。
### 二维数组
@@ -25,7 +25,7 @@
已知二维数组b[M][N]。
若按行存储,b[i][j]的存储地址=起始地址LOC+(i\*N+j)*sizeof(ElemType)。
若按行存储,b[i][j]的存储地址=起始地址LOC+(i×N+j)×sizeof(ElemType)。
### 十字链表法
@@ -41,7 +41,7 @@
若对一个$n$阶方阵$A[0,n-1][0,n-1]$中的任意一个元素$a_{ij}$都有$a_{ij}=a_{ji}$,即主对角线对称元素相等的矩阵,就是对称矩阵。
其中元素可以分为上三角区域、主对角线和下三角区域,上下三角区域元素相等。所以可以将$A$存放在一维数组$B[n(n+1)/2]$中,从而$a_{ij}=b_k$,只存放下三角部分与主对角线部分元素。从而$a_{ij}$对应的$k=1+2+\cdots+(i-1)+j-1=\dfrac{i(i-1)}{2}+j-1$。
其中元素可以分为上三角区域、主对角线和下三角区域,上下三角区域元素相等。所以可以将$A$存放在一维数组$B[n(n+1)\div2]$中,从而$a_{ij}=b_k$,只存放下三角部分与主对角线部分元素。从而$a_{ij}$对应的$k=1+2+\cdots+(i-1)+j-1=\dfrac{i(i-1)}{2}+j-1$。
+ 当$i\geqslant j$时,即下三角区域与主对角线元素:$k=\dfrac{i(i-1)}{2}+j-1$。
+ 当$i<j$时,即上三角区域:$k=\dfrac{j(j-1)}{2}+i-1$。
@@ -50,7 +50,7 @@
#### 下三角矩阵
下三角矩阵指上三角区域的元素均为同一常量,其存储思想与对称矩阵一样,但是需要最后多一个存储空间存储上三角的常量。所以可以将$A$存放在一维数组$B[n(n+1)/2+1]$中。
下三角矩阵指上三角区域的元素均为同一常量,其存储思想与对称矩阵一样,但是需要最后多一个存储空间存储上三角的常量。所以可以将$A$存放在一维数组$B[n(n+1)\div2+1]$中。
+ 当$i\geqslant j$时,即下三角区域与主对角线元素:$k=\dfrac{i(i-1)}{2}+j-1$。
+ 当$i<j$时,即上三角区域:$k=\dfrac{n(n-1)}{2}$。

View File

@@ -38,7 +38,7 @@ ASL查找失败为$\dfrac{1+2+3+\cdots+n+n}{n+1}=\dfrac{n}{2}+\dfrac{n}{n+1}$。
#### 折半查找的结构
定义三个指针,low指向查找范围的最小值,high指向查找范围的最大值,mid指向查找范围的中间值,$mid=\lfloor(low+high)/2\rfloor$。(也可以向上取整,过程会有所不同)
定义三个指针,low指向查找范围的最小值,high指向查找范围的最大值,mid指向查找范围的中间值,$mid=\lfloor(low+high)\div2\rfloor$。(也可以向上取整,过程会有所不同)
#### 折半查找的过程
@@ -94,7 +94,7 @@ ASL查找成功失败的情况都十分复杂,所以一般不会考。
#### B树的定义
为了保证m叉查找树中每个结点都能被有效利用,避免大量结点浪费导致树高过大,所以规定m叉查找树中,除了根结点以外,任何结点至少有$\lceil m/2\rceil$个分叉,即至少包含$\lceil m/2\rceil-1$个结点。
为了保证m叉查找树中每个结点都能被有效利用,避免大量结点浪费导致树高过大,所以规定m叉查找树中,除了根结点以外,任何结点至少有$\lceil\dfrac{m}{2}\rceil$个分叉,即至少包含$\lceil\dfrac{m}{2}\rceil-1$个结点。
为了保证m叉查找树是一棵平衡树,避免树偏重导致树高过大,所以规定m叉查找树中任何一个结点,其所有子树的高度都要相同。
@@ -107,7 +107,7 @@ B树即多路平衡查找树,所有结点的孩子个数的最大值就是B树
+ 树的每个结点至多包含m棵子树,至多包含m-1个关键字。
+ B树最底端的失败的不存在的结点就是常说的叶子结点,而最底端的存在数据的结点就是终端结点。(一般的树的叶子结点和终端结点都是指最底端的有数据的结点)
+ 若根结点不是终端结点,则至少有两颗子树,任意结点的每棵子树都是绝对平衡的。
+ 除根结点以外的所有非叶结点至少有$\lceil m/2\rceil$棵子树,即至少包含$\lceil m/2\rceil-1$个结点。
+ 除根结点以外的所有非叶结点至少有$\lceil\dfrac{m}{2}\rceil$棵子树,即至少包含$\lceil\dfrac{m}{2}\rceil-1$个结点。
+ 所有叶结点都出现在同一个层次上且不带信息。
+ 每个结点中的关键字是有序的。子树0 < 关键字1 < 子树2 < ...。
@@ -115,14 +115,14 @@ B树即多路平衡查找树,所有结点的孩子个数的最大值就是B树
+ 最小高度:让每个结点尽可能满,有$m-1$个关键字,$m$个分叉,则一共有$(m-1)(m^0+m^1+m^2+\cdots+m^{h-1})$个结点,其中$n$小于等于这个值,从而求出$h\geqslant\log_m(n+1)$。
+ 最大高度:
+ 让各层分叉尽可能少,即根结点只有两个分叉,其他结点只有$\lceil m/2\rceil$个分叉,所以第一层1个,第二层2个,第$h$层$2(\lceil m/2\rceil)^{h-2}$个结点,而$h+1$层的叶子结点有$2(\lceil m/2\rceil)^{h-1}$个,且$n$个关键字的B树必然有$n+1$个叶子结点,从而$n+1\geqslant2(\lceil m/2\rceil)^{h-1}$,即$h\leqslant\log_{\lceil m/2\rceil}\dfrac{n+1}{2}+1$。
+ 让各层关键字尽可能少,记$k=\lceil m/2\rceil$。第一层最少结点数和最少关键字为1;第二层最少结点数为2,最少关键字为$2(k-1)$,第三层最少结点数为$2k$,最少关键字为$2k(k-1)$,第$h$层最少结点数为$2k^{h-2}$,最少关键字为$2k^{h-2}(k-1)$,从而$h$层的m阶B数至少包含关键字总数$1+2(k-1)(k^0+k^1+\cdots+k^{h-2})=1+2(k^{h-1}-1)$,若关键字总数小于这个值,则高度一定小于$h$,所以$n\geqslant 1+2(k^{h-1}-1)$,则$h\leqslant\log_{\lceil m/2\rceil}\dfrac{n+1}{2}+1$。
+ 让各层分叉尽可能少,即根结点只有两个分叉,其他结点只有$\lceil\dfrac{m}{2}\rceil$个分叉,所以第一层1个,第二层2个,第$h$层$2(\lceil\dfrac{m}{2}\rceil)^{h-2}$个结点,而$h+1$层的叶子结点有$2(\lceil\dfrac{m}{2}\rceil)^{h-1}$个,且$n$个关键字的B树必然有$n+1$个叶子结点,从而$n+1\geqslant2(\lceil\dfrac{m}{2}\rceil)^{h-1}$,即$h\leqslant\log_{\lceil\dfrac{m}{2}\rceil}\dfrac{n+1}{2}+1$。
+ 让各层关键字尽可能少,记$k=\lceil\dfrac{m}{2}\rceil$。第一层最少结点数和最少关键字为1;第二层最少结点数为2,最少关键字为$2(k-1)$,第三层最少结点数为$2k$,最少关键字为$2k(k-1)$,第$h$层最少结点数为$2k^{h-2}$,最少关键字为$2k^{h-2}(k-1)$,从而$h$层的m阶B数至少包含关键字总数$1+2(k-1)(k^0+k^1+\cdots+k^{h-2})=1+2(k^{h-1}-1)$,若关键字总数小于这个值,则高度一定小于$h$,所以$n\geqslant 1+2(k^{h-1}-1)$,则$h\leqslant\log_{\lceil\dfrac{m}{2}\rceil}\dfrac{n+1}{2}+1$。
#### B树的插入
新元素插入一定是插入到最底层的终端结点,使用B树的查找来确定插入位置。
若导致原结点关键字数量超过上限溢出,就从中间位置$\lceil m/2\rceil$分开,将左部分包含的关键字放在原来结点,右部分包含的关键字放在一个新结点,并插入到原结点的父结点的后一个位置上,而在原结点的父结点连接后的结点后移一个连接让位给分割出来的右半部分结点,中间的一个结点$\lceil m/2\rceil$插入到原结点的父结点上,并考虑在父结点的顺序。
若导致原结点关键字数量超过上限溢出,就从中间位置$\lceil\dfrac{m}{2}\rceil$分开,将左部分包含的关键字放在原来结点,右部分包含的关键字放在一个新结点,并插入到原结点的父结点的后一个位置上,而在原结点的父结点连接后的结点后移一个连接让位给分割出来的右半部分结点,中间的一个结点$\lceil\dfrac{m}{2}\rceil$插入到原结点的父结点上,并考虑在父结点的顺序。
若父结点插入时也溢出了,则同理在父结点的中间进行分割,左半部分在原来父结点;右半部分新建一个父结点,并把中间结点右边开始的所有连接移动到新父结点上;中间的结点上移到祖父结点,如果没有就新建,然后建立两个指针分别指向原父结点和新父结点。
@@ -159,7 +159,7 @@ B+树考的并不是很深。
一个m阶的B+树需要满足以下条件:
1. 每个分支结点最多有m棵子树或孩子结点。
2. 为了保持绝对平衡,非叶根结点至少有两棵子树,其他每个分支结点至少有$\lceil m/2\rceil$棵子树。(不同于B树,B+树又重新将最下面的保存的数据定义为叶子结点)
2. 为了保持绝对平衡,非叶根结点至少有两棵子树,其他每个分支结点至少有$\lceil\dfrac{m}{2}\rceil$棵子树。(不同于B树,B+树又重新将最下面的保存的数据定义为叶子结点)
3. 结点的子树个数与关键字个数相等。(B树结点子为树个数与关键字个数加1)
4. 所有叶结点包含所有关键字以及指向记录的指针,叶结点中将关键字按大小排序,并且相邻叶子结点按大小顺序相互连接起来。所以B+树支持顺序查找。
5. 所有分支结点中仅包含其各子结点中关键字的最大值以及指向其子结点的指针(即分支结点只是索引)。
@@ -180,7 +180,7 @@ B+树可以顺序查找,在叶子结点的块之间定义指向后面叶子结
:--:|:--:|:--:
结点的n个关键字对应的子树个数|$n$|$n+1$
根结点的关键字数|$[1,m]$|$[1,m-1]$
其他结点的关键字数|$[\lceil m/2\rceil,m]$|$[\lceil m/2\rceil-1,m-1]$
其他结点的关键字数|$[\lceil\dfrac{m}{2}\rceil,m]$|$[\lceil\dfrac{m}{2}\rceil-1,m-1]$
关键字分布|叶子结点包含所有关键字,非叶结点包含部分重复关键字|所有结点的关键字不重复
结点作用|叶子结点包含信息,非叶子结点是索引作用|所有结点都包含信息
结点存储内容|叶子结点包含关键字与对应记录的存储地址,非叶子结点包含对应子树的最大关键字和指向该子树的指针|所有结点都包含关键字与对应记录存储地址
@@ -197,7 +197,7 @@ B+树可以顺序查找,在叶子结点的块之间定义指向后面叶子结
关键字与地址通过散列函数(哈希函数)来实现映射。即记录位置=散列函数(记录关键字)。
+ 直接定址法:可表示为散列函数(关键字)=a*关键字+b,其中a、b均为常数。这种方法计算特别简单,并且不会发生冲突,但当关键字分布不连续时,会出现很多空闲单元,会将造成大量存贮单元的浪费。
+ 直接定址法:可表示为散列函数(关键字)=a×关键字+b,其中a、b均为常数。这种方法计算特别简单,并且不会发生冲突,但当关键字分布不连续时,会出现很多空闲单元,会将造成大量存贮单元的浪费。
+ 数字分析法:分析关键字的各个位的构成,截取其中若干位作为散列函数值,尽可能使关键字具有大的敏感度,即最能进行区分的关键字位,这些位数都是连续的。
+ 平方取中法:先求关键字的平方值,然后在平方值中取中间几位为散列函数的值。因为一个数平方后的中间几位和原数的每一位都相关,因此,使用随机分布的关键字得到的记录的存储位置也是随机的。适用于关键字的每位取值都不够均匀或均小于散列地址所需的位数。
+ 折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为散列函数的值,称为折叠法。例如,假设关键字为某人身份证号码430104681015355,则可以用4位为一组进行叠加,即有5355+8101+1046+430=14932,舍去高位,则有H(430104681015355)=4932。
@@ -252,6 +252,6 @@ $H_i=RH_i(Key)\,i=1,2,\cdots,k$。
若散列函数设计得足够好,散列查找时间复杂度可以达到$O(1)$,即不存在冲突。
**装填因子**=表中记录数/散列表长度。装填因子代表一个散列表中的满余情况,越大则查找效率越低。
**装填因子**=表中记录数÷散列表长度。装填因子代表一个散列表中的满余情况,越大则查找效率越低。
若只给出了装填因子$\alpha$,则此时平均查找长度为:$ASL=\dfrac{1}{2}(1+\dfrac{1}{1-\alpha})$。