[{"content":"第一三章 分层 解释 翻译 微程序级 - 传统机器语言级 - 操作系统级 ==汇编语言级== - 高级语言级 - 应用语言级 翻译：用转换程序把高一级机器上的程序转换为低一级机器上的等效程序，然后再在这低一级机器上运行。速度快、占用空间大。 解释：对于高一级机器上程序中的每一条语句或指令，转换为低级语言的一段等效程序执行，执行完后再去高一级机器取下一条语句或指令。速度慢、占用空间小。 定义 计算机系统结构的定义：\n计算机系统结构是指传统机器程序员所看到的计算机属性，即==概念性结构、功能特性。== 计算机系统结构的实质：确定计算机系统中软硬件的界面，界面之上是软件实现的功能，界面之下是硬件和固件实现的功能。 透明性：一种本来存在的事物或属性，从某种角度看好像不存在或看不到。低层机器的属性对高层机器程序员来说通常是透明的。 广义系统结构定义：包括指令系统结构、组成、硬件。 指令集 ARM：RISC（精简指令集） X86：CISC（复杂指令集）\nFlynn分类法 按照指令流和数据流的多倍性\n冯氏分类法 （字，位） x （串，并）\nHandler分类法 三元组：控制器（乘流水部件数）、ALU/PE（乘流水部件）、字长（乘流水部件）\n系统结构的发展 冯诺依曼结构：输入设备、输出设备、控制器、运算器、存储器。指令与数据同等对待（一条总线）。 冯诺伊曼以==运算器==为中心，核心思想是==存储器== 哈佛结构：冯诺依曼基础上，指令与数据分离。现代计算机都是哈佛结构。 系统结构设计 方向（中间：传统机器级 - 操作系统级） 兼容性 模拟（实现==虚拟机的指令集==） 仿真（用宿主机的==微程序去解释实现另一台机器的指令集==） 并行性从低到高： 指令内部 指令见 线程间 任务/过程级（子程序/进程为调度单元） 作业/程序级 提高并行性的途径： 时间重叠：==轮流使用==同一套硬件的==各个部分==。 资源重复：重复设置硬件资源。 资源共享：按顺序轮流使用==同一套硬件==设备。 原理和公式 局部性原理： 时间、空间相对地簇集 Amdahl定律 ![[Pasted image 20260413161910.png]] 扩展Amdahl：分母为单个部件提升之和，分子不变\nCPU性能公式 符号 含义 IC 指令时钟周期数 MIPS 百万指令每秒 CPI CLOCK per Instruction CPU时间：时钟周期数 * 时钟周期时间==（越小越好，衡量CPU性能）== CPI越小性能越高 MIPS = 主频（每秒时钟周期数）/ CPI（每条指令时钟周期数） ==（百万单位）== 程序执行时间 = 指令数 / 主频 ==（MHz -\u0026gt; 单位毫秒）== ","date":"2026-04-13T00:00:00+08:00","permalink":"https://invalidval.github.io/p/%E7%B3%BB%E7%BB%9F%E7%BB%93%E6%9E%84chapter-1-3-%E5%A4%8D%E4%B9%A0/","title":"【系统结构】Chapter 1-3 复习"},{"content":"树状数组模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 n,m = map(int,input().split()) t = list(map(int,input().split())) c = [0] * (n+1) def lowbit(x): return x \u0026amp; (-x) def add(idx,d): while idx \u0026lt;= n: c[idx] += d idx += lowbit(idx) def query(idx): res = 0 while idx \u0026gt; 0: res += c[idx] idx -= lowbit(idx) return res def rs(l,r): return query(r) - query(l) for i,v in enumerate(t, start = 1): add(i,v) for i in range(m): k,a,b = map(int,input().split()) if k == 0: print(rs(a-1,b)) #注意需要包含第a个元素 else: add(a,b) 操作 普通数组 前缀和数组 树状数组 单点更新 O(1) O(n) O(log n) 区间查询 O(n) O(1) O(log n) ","date":"2026-04-11T00:00:00+08:00","permalink":"https://invalidval.github.io/p/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84%E5%92%8C%E7%BA%BF%E6%AE%B5%E6%A0%91/","title":"树状数组和线段树"},{"content":"xx Intel Pentium 的段页式 ","date":"2025-11-16T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter-8-%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/","title":"Chapter 8 内存管理"},{"content":"讲什么了 语法制导定义和翻译方案\nS属性定义的自底向上实现\nL属性定义的自底向上实现\n关键概念 综合属性 继承属性 S属性定义和L属性定义的LR分析实现 翻译思路 根据翻译目标确定产生式的语义（含义） 根据产生式的含义，分析，每个符号的语义 把语义以属性的形式附加到相应文法符号上 设计语义规则，从而形成语法制导定义 翻译目标决定语义规则，翻译结果依赖于语义规则\n翻译目标-\u0026gt;语义规则-\u0026gt;翻译结果\n把语义动作插入到产生式的适当位置，形成翻译方案\n翻译方案规定了语义动作的执行时机\n语法制导翻译的一般步骤 1. 语法制导定义 综合属性：\n产生式左部符号的综合属性是从该产生式右部文法符号的属性值计算出来的；\n在分析树中，一个内部结点的综合属性是从其子结点的属性值计算出来的。\n虚拟综合属性：将过程调用或程序段（print）的语义规则看成左部的虚拟综合属性\n继承属性： 产生式右部某文法符号的继承属性是从其所在产生式的左部符号和/或右部文法符号的属性值计算出来的；\n在分析树中，一个结点的继承属性是从其父结点和/或兄弟结点的属性值计算出来的。\n2. 依赖图 3. 拓扑排序 由前指向后\n4. S L属性定义 注意，Xj的继承属性不能依赖于其右边的符号！\n5. 翻译方案 对于S属性，把这个动作放在相应的产生式右边末尾\n对于L属性，动作不能引用其右边文法符号的综合属性，左部符号的综合属性应放在产生式右端末尾；右部某符号的继承属性必须放在这个符号之前\nS属性的自底向上实现 ","date":"2025-11-15T00:00:00+08:00","image":"https://invalidval.github.io/p/chapter-5-%E8%AF%AD%E6%B3%95%E5%88%B6%E5%AF%BC%E5%92%8C%E7%BF%BB%E8%AF%91%E6%8A%80%E6%9C%AF/cp5_hu_acc40b76f31e0dca.png","permalink":"https://invalidval.github.io/p/chapter-5-%E8%AF%AD%E6%B3%95%E5%88%B6%E5%AF%BC%E5%92%8C%E7%BF%BB%E8%AF%91%E6%8A%80%E6%9C%AF/","title":"Chapter 5 语法制导和翻译技术"},{"content":"为什么需要贪心算法 在算法设计中，贪心算法是一种通过在每一步选择中都采取在当前状态下最好或最优（即最有利）的选择，从而希望导致结果是全局最好或最优的算法。贪心算法通常用于解决优化问题。\n贪心算法的核心思想是通过局部最优选择来达到全局最优解。它适用于那些具有“最优子结构”和“贪心选择性质”的问题。\n与动态规划的区别：动态规划通常用于解决具有重叠子问题和最优子结构的问题，而贪心算法则侧重于通过局部最优选择来构建全局最优解。动态规划通常需要保存中间结果，而贪心算法则不需要。贪心不依赖子问题的解决策，而动态规划依赖。\n贪心算法的步骤 选择策略：确定在每一步中如何选择当前的最优解。这通常涉及定义一个贪心选择标准。 可行性检查：确保每次选择都不会违反问题的约束条件。 构建解：通过不断应用选择策略，逐步构建最终的解决方案。 验证最优性：在某些情况下，可能需要证明贪心选择确实能导致全局最优解。 证明贪心选择性质的方法：\n存在整体最优解 修改最优解，是其以贪心选择开始 该问题转化为规模更小的相同形式的子问题 数学归纳法证明每一步都如此 k = 1 时，该解就是最优解 k \u0026gt; 1 时，令活动1替换活动k（因为活动1结束时间最早），得到新的解仍然是最优解\n反证法？\n最优子结构性质证明的方法：\n假设一个问题的最优解包含其子问题的解。 通过构造或反证法证明，如果子问题的解不是最优的，那么整个问题的解也不会是最优的。 纸币找零问题 假设你是一个收银员，需要找零给顾客。你有面值为1元、5元、10元和20元的纸币。顾客需要找零37元。使用贪心算法，你会选择尽可能大的面值，直到达到所需的金额。\n选择一张20元纸币，剩余17元。 选择一张10元纸币，剩余7元。 选择一张5元纸币，剩余2元。 选择两张1元纸币，剩余0元。 最终，你会使用1张20元、1张10元、1张5元和2张1元纸币来找零37元。\n为什么贪心算法在这个问题中有效？因为每次选择最大的面值都能确保剩余金额最小，从而减少了总的纸币数量。\n但是！如果纸币的面值是1元、3元和4元，顾客需要找零6元。使用贪心算法：\n选择一张4元纸币，剩余2元。 选择两张1元纸币，剩余0元。 最终，你会使用1张4元和2张1元纸币，共3张纸币。 然而，最优解是使用两张3元纸币，共2张纸币。 这说明贪心算法并不总是能找到最优解。 但是可以找到近似解。\n活动选择问题 活动选择问题是指在给定一组活动的开始和结束时间的情况下，选择尽可能多的互不冲突的活动。贪心算法在这个问题中表现出色。\n排序活动：首先，根据活动的结束时间对活动进行排序。 选择活动：选择第一个活动，然后选择下一个与已选择活动不冲突且结束时间最早的活动，重复此过程直到没有更多活动可以选择。 代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include \u0026lt;iostream\u0026gt; #include \u0026lt;vector\u0026gt; #include \u0026lt;algorithm\u0026gt; using namespace std; struct Activity { int start; int end; }; bool compare(Activity a1, Activity a2) { return a1.end \u0026lt; a2.end; } void greedyActivitySelector(vector\u0026lt;Activity\u0026gt;\u0026amp; activities) { sort(activities.begin(), activities.end(), compare); int n = activities.size(); cout \u0026lt;\u0026lt; \u0026#34;Selected activities: \u0026#34; \u0026lt;\u0026lt; endl; int lastEndTime = -1; for (int i = 0; i \u0026lt; n; i++) { if (activities[i].start \u0026gt;= lastEndTime) { cout \u0026lt;\u0026lt; \u0026#34;Activity(\u0026#34; \u0026lt;\u0026lt; activities[i].start \u0026lt;\u0026lt; \u0026#34;, \u0026#34; \u0026lt;\u0026lt; activities[i].end \u0026lt;\u0026lt; \u0026#34;)\u0026#34; \u0026lt;\u0026lt; endl; lastEndTime = activities[i].end; } } } int main() { vector\u0026lt;Activity\u0026gt; activities = { {1, 3}, {2, 5}, {4, 6}, {6, 7}, {5, 8}, {8, 9} }; greedyActivitySelector(activities); return 0; } 复杂度分析：排序活动的时间复杂度为O(n log n)，选择活动的时间复杂度为O(n)，因此总的时间复杂度为O(n log n)。\n霍夫曼编码 霍夫曼编码是一种用于无损数据压缩的贪心算法。它通过为频率较高的符号分配较短的编码，而为频率较低的符号分配较长的编码，从而实现数据的压缩。\n构建优先队列：将所有符号及其频率插入一个优先队列（最小堆）。 构建霍夫曼树：重复以下步骤直到队列中只剩一个节点： 从队列中取出两个频率最小的节点。 创建一个新节点，其频率为这两个节点频率之和，并将这两个节点作为新节点的子节点。 将新节点插入队列中。 生成编码：从根节点开始，为每个左子节点分配一个“0”，为每个右子节点分配一个“1”，直到到达叶节点，生成每个符号的编码。 代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include \u0026lt;iostream\u0026gt; #include \u0026lt;queue\u0026gt; #include \u0026lt;vector\u0026gt; #include \u0026lt;unordered_map\u0026gt; using namespace std; struct Node { char ch; int freq; Node* left; Node* right; Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; struct compare { bool operator()(Node* l, Node* r) { return l-\u0026gt;freq \u0026gt; r-\u0026gt;freq; } }; void generateCodes(Node* root, string str, unordered_map\u0026lt;char, string\u0026gt;\u0026amp; codes) { if (!root) return; if (!root-\u0026gt;left \u0026amp;\u0026amp; !root-\u0026gt;right) { codes[root-\u0026gt;ch] = str; } generateCodes(root-\u0026gt;left, str + \u0026#34;0\u0026#34;, codes); generateCodes(root-\u0026gt;right, str + \u0026#34;1\u0026#34;, codes); } void huffmanCoding(vector\u0026lt;pair\u0026lt;char, int\u0026gt;\u0026gt;\u0026amp; frequencies) { priority_queue\u0026lt;Node*, vector\u0026lt;Node*\u0026gt;, compare\u0026gt; minHeap; for (auto\u0026amp; freq : frequencies) { minHeap.push(new Node(freq.first, freq.second)); } while (minHeap.size() \u0026gt; 1) { Node* left = minHeap.top(); minHeap.pop(); Node* right = minHeap.top(); minHeap.pop(); Node* newNode = new Node(\u0026#39;\\0\u0026#39;, left-\u0026gt;freq + right-\u0026gt;freq); newNode-\u0026gt;left = left; newNode-\u0026gt;right = right; minHeap.push(newNode); } Node* root = minHeap.top(); unordered_map\u0026lt;char, string\u0026gt; codes; generateCodes(root, \u0026#34;\u0026#34;, codes); cout \u0026lt;\u0026lt; \u0026#34;Huffman Codes: \u0026#34; \u0026lt;\u0026lt; endl; for (auto\u0026amp; code : codes) { cout \u0026lt;\u0026lt; code.first \u0026lt;\u0026lt; \u0026#34;: \u0026#34; \u0026lt;\u0026lt; code.second \u0026lt;\u0026lt; endl; } } int main() { vector\u0026lt;pair\u0026lt;char, int\u0026gt;\u0026gt; frequencies = { {\u0026#39;a\u0026#39;, 5}, {\u0026#39;b\u0026#39;, 9}, {\u0026#39;c\u0026#39;, 12}, {\u0026#39;d\u0026#39;, 13}, {\u0026#39;e\u0026#39;, 16}, {\u0026#39;f\u0026#39;, 45} }; huffmanCoding(frequencies); return 0; } ","date":"2025-11-12T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter-4-%E8%B4%AA%E5%BF%83/","title":"Chapter 4 贪心"},{"content":"Functional-Dependency Theory SQL for judging FDs Closure of a Set of Functional Dependencies The set of all functional dependencies logically implied by F is the closure of F, which is denoted as F+. It is the set of all functional dependencies that can be inferred from F using Armstrong\u0026rsquo;s axioms.\nArmstrong\u0026rsquo;s Axioms Armstrong\u0026rsquo;s axioms are a set of rules used to infer all the functional dependencies in a relational database. They are sound (i.e., they only produce valid dependencies) and complete (i.e., they can produce all valid dependencies).\nReflexivity: If Y is a subset of X, then X → Y holds. Augmentation: If X → Y holds, then XZ → YZ holds for any Z. Transitivity: If X → Y and Y → Z hold, then X → Z holds. Additional Rules Union: If X → Y and X → Z hold, then X → YZ holds. Decomposition: If X → YZ holds, then X → Y and X → Z hold. Pseudotransitivity: If X → Y and YZ → W hold, then XZ → W holds. （可由先argumentation和transitivity推导出） 属性集闭包 属性集X在函数依赖集F下的闭包，记为X+，是指在F中可以由X推导出的所有属性的集合。 计算X+的算法：\n初始化X+为X。 重复以下步骤，直到X+不再变化： 对于F中的每个函数依赖A → B，如果A是X+的子集，则将B添加到X+中。 例子 设有关系R(A, B, C, D)和函数依赖集F = {A → B, B → C}，计算属性集A的闭包A+：\n初始化A+ = {A}。 应用A → B，因为A是A+的子集，添加B到A+，得到A+ = {A, B}。 应用B → C，因为B是A+的子集，添加C到 A+，得到A+ = {A, B, C}。 没有更多的函数依赖可以应用，算法终止。 最终，A+ = {A, B, C}。 Canonical Cover【最简函数依赖集】 函数依赖集F的规范覆盖（Canonical Cover），记为Fc，是一个等价于F的最小函数依赖集。 A canonical cover for F is a set of dependencies Fc such that:\nF logically implies all dependencies in Fc Fc logically implies all dependencies in F (F+ = Fc+)\nno functional dependency in Fc contains an extraneous attribute each left side of functional dependency in Fc is unique. That is, there are no two dependencies in Fc, with the same left side i.e. X → Y and X → Z cannot both be in Fc 计算规范覆盖的步骤 1 2 3 4 do{ 1、使用Union rule结合右侧 2、去除Fc中的冗余属性 }while(Fc不变) 例子 F、F+、Fc Extraneous Attributes（冗余属性） 在函数依赖X → Y中，如果存在属性A ∈ X，使得在去掉A后，X - {A} → Y仍然成立，则称A是冗余属性。\n例子 设有函数依赖集F = {AB → C, A → B}，检查属性A在AB → C中是否冗余：\n计算B的闭包B+： 初始化B+ = {B}。 没有函数依赖可以应用，B+ = {B}。 检查是否B+包含C： B+不包含C，因此A不是冗余属性。 最终，属性A在AB → C中不是冗余属性。 对于右端冗余属性的检查： 在函数依赖X → Y中，如果存在属性B ∈ Y，使得在去掉B后，X → Y - {B}仍然成立，则称B是冗余属性。\n移除左端冗余属性，得到更强的函数依赖【所需左端前提条件更少】\n移除右端冗余属性，得到更弱的函数依赖【结论更少】\n一个依赖关系under F的意思是可以从F中推导出该依赖关系\nDependency Preservation（依赖保持） 在关系模式分解中，如果分解后的每个子模式的函数依赖集的联合能够推导出原始模式的所有函数依赖，则称该分解是依赖保持的。\n与holds on的区别在于， holds on是指某个具体的关系实例满足某个函数依赖， 而dependency preservation是指分解后的模式在所有可能的关系实例中都能保持原始模式的函数依赖。\nFi： 7.5 Algorithms for Decomposition Using Functional Dependencies 本节内容 BCNF\nTesting for BCNF /判断关系模式是否是BCNF Testing Decomposition for BCNF/ 判断分解后的子模式是否是BCNF BCNF decomposition algorithm/将关系模式分解为BCNF的方法 3NF\nTesting for 3NF 3NF decomposition algorithm Comparison of BCNF and 3NF Testing for BCNF To check if a non-trivial dependency $\\alpha$ causes a violation of BCNF\ncompute $\\alpha^+$ (the attribute closure of $\\alpha$), and verify that it includes all attributes of R, that is, $\\alpha$ is a superkey of R. Simplified but Incorrect test: To check if a relation schema R is in BCNF, it suffices to check only the dependencies in the given set F for violation of BCNF, rather than checking all dependencies in F+.\nIf none of the dependencies in F causes a violation of BCNF, then none of the dependencies in F+ will cause a violation of BCNF either.\nHowever, simplified test using only F is incorrect when testing a relation in a decomposition of R\n也就是说判断BCNF可以使用F作为充分条件，因为F无违例说明F+也无违例，但是判断子模式（a decomposition of R）只用F是错的！！！\nTesting Decomposition for BCNF Note:\nthe restriction of F to Ri 的意思是： 将函数依赖集F中的所有函数依赖限制在子模式Ri上，即只保留那些在Ri中有效的函数依赖。 举例子： 设有关系模式R(A, B, C)和函数依赖集F = {A → B, B → C}，将R分解为子模式R1(A, B)和R2(B, C)。 the restriction of F to R1是{A → B}，因为B → C在R1中无效。 测试由R分解后的子模式Ri是否BCNF，不能仅凭R上的F，应该采用F+\nDecomposition Algorithm for BCNF 检查关系模式R是否是BCNF。如果是，则返回R作为分解结果。（to determine whether or not Ri is in BCNF, the restriction of F to Ri and the candidate keys of Ri need to be computed）\n如果R不是BCNF，找到一个违反BCNF的函数依赖X → Y，其中X不是R的超键。\n将R分解为两个子模式R1和R2：\nR1 = X ∪ Y R2 = R - Y + X 递归地对R1和R2应用步骤1-3，直到所有子模式都是BCNF。\nNote:\n3中R1的意思是包含X和Y的所有属性的子模式，R2的意思是R中去掉Y属性后再加上X属性的子模式 该算法可能不会产生依赖保持的分解。 该算法确保每个子模式都是BCNF。 BCNF分解不保证依赖保持 Testing for 3NF Need to check only FDs in F, no checking all FDs in F+.\nStep1. Use attribute closure to check for each dependency $\\alpha$, if $\\alpha$ is a superkey\n检查每个函数依赖左端是否为超键\nStep2. If $\\alpha$ is not a superkey, we have to verify if each attribute in $\\beta$ is contained in a candidate key of R\n如果左端不是超键，检查右端属性是否包含在某个候选键中\nThis test is rather more expensive, since it involve finding all candidate keys\nTesting for 3NF has been shown to be NP-hard!\nInterestingly, decomposition into third normal form (described shortly) can be done in polynomial time\nDecomposition Algorithm for 3NF 为什么需要3NF分解算法？ 因为BCNF分解不保证依赖保持，而3NF分解算法可以保证依赖保持。\n算法步骤：\n计算函数依赖集F的规范覆盖Fc。 对于Fc中的每个函数依赖X → Y，创建一个子模式R_i = X ∪ Y。 如果没有子模式包含R的候选键，则添加一个子模式R_k，该子模式包含R的一个候选键。 返回所有子模式作为分解结果。 Note:\n只要有一个候选键包含在第2步构造出的某个子模式Ri中，就无需在第3步中，为候选键单独构造子模式。 任意挑选R的一个候选键【只需挑选一个】，对该候选健单独构造一个关系模式；无需考虑全部候选键!!! Example of 3NF Decomposition 设有关系模式R(A, B, C, D)和函数依赖集F = {A → B, B → C}，应用3NF分解算法：\n计算规范覆盖Fc = {A → B, B → C}。 创建子模式： R1 = {A, B}（对应A → B） R2 = {B, C}（对应B → C） （R1、R2都是BCNF） R的候选键是{A, D}，没有子模式包含它，因此添加R3 = {A, D}。 返回子模式R1, R2, R3作为分解结果。 对比记忆BCNF和3NF算法 3NF合成：依赖于一个预先处理好的、最小化的规范覆盖Fc来“合成”模式。Fc是它的输入。\nBCNF分解：是一个递归的、基于验证的分解过程，它直接使用当前模式上成立的函数依赖（来自原始F或其投影）来指导分解。它不关心F是否最小化。\n因此，计算BCNF分解一般不需要计算Fc。\nAppendix 7-1 Computing Candidate Keys 计算候选键的步骤：\nstep1. 将R的所有属性分为四类：\nL类：仅出现在F中函数依赖左部的属性 R类：仅出现在F中函数依赖右部的属性 N类：在F中函数依赖左右两边均未出现的属性 LR类：在F中函数依赖左右两边均出现的属性 令X_set=L类 ∪ N类，Y_set=LR类 step2. 求X_set +，\n如果X_set+ =R，则X_set为R的唯一候选键，转step5；否则转step3 step3.\n在Y_set中取一属性A，求(X_set ∪ A)+，若它包含了R的所有属性，则转step4; 否则，调换一属性反复进行这一过程，直到试完所有Y_set中的属性 step4.\n如果已找出所有的候选键，则转step5; 否则，在Y_set中依此取两个、三个，…，求其属性闭包，直至其闭包包含R的所有的属性 step5. 停止，输出结果 最后，为什么需要4NF 在某些情况下，关系模式可能存在多值依赖（MVD），这会导致数据冗余和更新异常。4NF通过消除非平凡的多值依赖，进一步规范化关系模式，从而提高数据的完整性和一致性。\n考题类型 判断最高范式 计算候选键，从BCNF向下找\n","date":"2025-11-11T00:00:00+08:00","image":"https://invalidval.github.io/p/chapter7-%E5%88%86%E8%A7%A3%E7%AE%97%E6%B3%95%E5%A4%A7%E6%A6%82%E6%98%AF7.4-7.5/c7_hu_fb6054ba954a2733.png","permalink":"https://invalidval.github.io/p/chapter7-%E5%88%86%E8%A7%A3%E7%AE%97%E6%B3%95%E5%A4%A7%E6%A6%82%E6%98%AF7.4-7.5/","title":"Chapter7 分解算法(大概是7.4-7.5)"},{"content":"Chapter 4 语法分析 本章非常之杂乱，所以需要对语法分析先进行分类\n自顶向下 递归的 非确定的：有回溯，叫递归下降分析 确定的：无回溯，叫递归调用预测分析 非递归的 非递归预测分析：第一个需要构造分析表的分析法，我们希望它是LL(1)文法。有左递归/左公因子的一定不是LL(1)文法，如果不放心，可以构造分析表，存在多重表项就不是LL(1) 自底向上 优先分析法 移进-归约分析法：LR(0) SLR(1) LR(1) LALR(1) 自底向上分析无需特殊处理左公因子，也无需处理左递归！！！！！！ ","date":"2025-11-10T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter-4-%E8%AF%AD%E6%B3%95%E5%88%86%E6%9E%90/","title":"Chapter 4 语法分析"},{"content":"最优子结构性质 重叠子问题性质 (期末一章一个大题，就这么问)\n矩阵连乘、最长公共子序列、最大子段和、背包 最优质、极大极小、全局最优\n引言 使用动态规划可以优化分治算法解决Fabonacci数列的问题。分治算法的时间复杂度为O(2^n)，而动态规划通过保存中间结果将时间复杂度降低到O(n)。\n零、矩阵连乘问题 矩阵连乘问题是指给定一系列矩阵，求它们的最优乘法顺序，以使得计算所需的标量乘法次数最少。设有n个矩阵A1, A2, \u0026hellip;, An，矩阵Ai的维数为pi-1 × pi。定义一个n维数组dp，其中dp[i][j]表示矩阵Ai到Aj的最优乘法次数。\n2 动态规划解法 2.1 递归结构 $$dp[i][j] = \\begin{cases}\r0 \u0026 , i = j \\\\\r\\min_{i \\leq k \u003c j} \\{dp[i][k] + dp[k+1][j] + p_{i-1}p_kp_j\\} \u0026 , i \u003c j\r\\end{cases}$$2.2 代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void MatrixChainOrder(int p[], int n){ int dp[n][n]; for(int i = 1; i \u0026lt; n; i++) dp[i][i] = 0; for(int l = 2; l \u0026lt; n; l++){ // l is chain length for(int i = 1; i \u0026lt; n - l + 1; i++){ int j = i + l - 1; dp[i][j] = INT_MAX; for(int k = i; k \u0026lt;= j - 1; k++){ int q = dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j]; if(q \u0026lt; dp[i][j]) dp[i][j] = q; } } } } 复杂度分析：时间复杂度为$O(n^{3})$，空间复杂度为$O(n^{2})$。\n一、凸多边形最优三角剖分 凸n边形的三角剖分与n-1个叶子的语法树之间存在一一对应关系。由于n个矩阵的完全加括号乘积与n个叶子的语法树之间存在一一对应关系，因此n个矩阵的完全加括号乘积也与凸(n+1)边形的三角剖分之间存在一一对应关系。 事实上，矩阵连乘积的最优计算次序问题是凸多边形最优三角剖分问题的一个特殊情形。 对于给定的矩阵链A1A2..An，定义一个与之相应的凸(n+1)边形P={v0 ,v1 ,… ,vn}，使得矩阵Ai与凸多边形的边vi-1vi一一对应。若矩阵Ai的维数为pi-1×pi,i=1,2,…,n，则定义三角形vivjvk上的权函数值为： ω(vivjvk)=pipjpk。依此权函数的定义，凸多边形P的最优三角剖分所对应的语法树给出矩阵链A1A2..An的最优完全加括号方式。\n1 最优子结构性质 2 递归结构 二、最大子段和 最大子段和问题是指在一个给定的一维数列中，找出一个连续子段，使得该子段的元素和最大。\n1 分治解法 2 动态规划解法 2.1 递归结构 $$dp[i] = \\max_{0 \\leq j \\leq i} \\left\\{ \\sum_{k=j}^{i} a[k] \\right\\} \\quad i \\leq n$$$$dp[i] = \\begin{cases} a[i] + dp[i-1] \u0026 , dp[i-1] \u003e 0 \\\\\ra[i] \u0026 , dp[i-1] \\leq 0 \\end{cases}$$$$rec[i] = \\begin{cases} rec[i-1] \u0026 , dp[i-1] \u003e 0 \\\\\ri \u0026 , dp[i-1] \\leq 0 \\end{cases}$$2.2 代码（从前向后）\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void MAXSUB(int a[], int n){ int *b = new int[MAX]; int *rec = new int[max]; b[0] = a[0]; rec[0] = 0; int max = b[0]; for(int i = 1; i \u0026lt; n; i++){ if(b[i-1] \u0026gt; 0) { b[i] = b[i-1] + a[i]; rec = rec[i-1]; } else{ b[i] = a[i]; rec = i; } if(b[i] \u0026gt; max) max = b[i]; } } 三、最长公共子序列 1 递归结构 设有两个序列X=x1,x2,…,xm和Y=y1,y2,…,yn，定义X的前i个元素组成的序列为Xi=x1,x2,…,xi，Y的前j个元素组成的序列为Yj=y1,y2,…,yj。设LCS[i][j]表示序列Xi和Yj的最长公共子序列的长度，则有如下递归关系：\n$$\rLCS[i][j] = \\begin{cases}\rLCS[i-1][j-1] + 1 \u0026 , X[i] = Y[j] \\\\\r\\max(LCS[i-1][j], LCS[i][j-1]) \u0026 , X[i] \\neq Y[j]\r\\end{cases}\r$$2 动态规划解法 2.1 递归结构 $$dp[i][j] = \\begin{cases}\rdp[i-1][j-1] + 1 \u0026 , X[i] = Y[j] \\\\\r\\max(dp[i-1][j], dp[i][j-1]) \u0026 , X[i] \\neq Y[j]\r\\end{cases}$$2.2 代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void LCS(char X[], char Y[], int m, int n){ int dp[m+1][n+1]; for(int i = 0; i \u0026lt;= m; i++) dp[i][0] = 0; for(int j = 0; j \u0026lt;= n; j++) dp[0][j] = 0; for(int i = 1; i \u0026lt;= m; i++){ for(int j = 1; j \u0026lt;= n; j++){ if(X[i-1] == Y[j-1]){ dp[i][j] = dp[i-1][j-1] + 1; } else{ dp[i][j] = max(dp[i-1][j], dp[i][j-1]); } } } } 四、0-1背包问题 1 递归结构 设有n件物品和一个容量为W的背包。每件物品i有一个重量wi和一个价值vi。定义dp[i][j]表示前i件物品在背包容量为j时的最大价值，则有如下递归关系： $$\rdp[i][j] = \\begin{cases}\rdp[i-1][j] \u0026 , j \u003c w_i \\\\\r\\max(dp[i-1][j], dp[i-1][j-w_i] + v_i) \u0026 , j \\geq w_i\r\\end{cases}\r$$2 动态规划解法 2.1 递归结构 $$dp[i][j] = \\begin{cases}\rdp[i-1][j] \u0026 , j \u003c w_i \\\\\r\\max(dp[i-1][j], dp[i-1][j-w_i] + v_i) \u0026 , j \\geq w_i\r\\end{cases}\r$$$$dp[0][j] = 0, \\quad 0 \\leq j \\leq W$$2.2 代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void Knapsack(int w[], int v[], int n, int W){ int dp[n+1][W+1]; for(int i = 0; i \u0026lt;= n; i++) dp[i][0] = 0; for(int j = 0; j \u0026lt;= W; j++) dp[0][j] = 0; for(int i = 1; i \u0026lt;= n; i++){ for(int j = 1; j \u0026lt;= W; j++){ if(j \u0026lt; w[i-1]){ dp[i][j] = dp[i-1][j]; } else{ dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1]); } } } } 五、完全背包问题 六、最优二叉搜索树 七、流水作业调度 八、图像压缩 ","date":"2025-11-05T00:00:00+08:00","image":"https://invalidval.github.io/p/chapter-3-%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/head_hu_3c1a04fd71a5f59e.png","permalink":"https://invalidval.github.io/p/chapter-3-%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/","title":"Chapter 3 动态规划"},{"content":"Chapter 2 形式语言与自动机基础 真TMD气死老子了，考这个b编译原理期中，其他题一分没扣，就这b自动机两个大题几乎分扣完了，CTMD，SB自动机，编译原理你考自动机还考两个是吧，害老子白丢2分总分，正则文法有你这么诡异的吗？？？你看看往年题呢？？\r自动机是非常好的发明，在编译原理中有重要作用，我们一定要学好自动机理论\n「大水课」の 复习 与这学期有关的自动机理论减少到了正则文法和有限自动机，而且考试还考的是确定有限自动机DFA。\n语言和文法 分清0型、1型、2型、3型。\n2型是CFG，3型是「正规文法」「线性文法」，所产生的语言叫「正规语言」\n所以我们一定要上正规大学\n正规文法在所有产生式的右侧，最多只有一个非终结符，并且如果存在，它必须出现在最右端。\n至于左线性文法，构造出的DFA是镜像的，我们不管它。\n文法变换 消除二义性 消除左递归 自顶向下的语法分析不能识别左递归文法\n提取左公因子 预测分析法不能识别左公因子文法，在填预测分析表时会出现多重表项 总之，消除左递归和提取左公因子只有改写为LL(1)文法时才需要！！\n正规文法与有限自动机的等价性 实际上主要考右线性文法与确定有限自动机(DFA)的等价性\n定理2.3 对每一个右线性文法G或左线性文法G，都存在一个等价的有限自动机M\n定理2.4 对每一个DFA M，对存在一个等价的右线性文法G和一个等价的左线性文法G'\n推论2 对任何一个有限自动机M，对存在一个等价的正规文法G，反之亦然\n推论3 对任何一个右线性文法G，都存在一个等价的左线性文法G\u0026rsquo;，反之亦然\n右线性文法 -\u0026gt; 有限自动机（不一定是DFA）： 这是非常简单的，因为只管将B-\u0026gt;aB写成$\\delta(B,a) = {B}$就行了，注意只有终结符的对应终结状态。但这不一定是确定的！！！\n有限自动机（不一定是DFA）-\u0026gt; 右线性文法 ：\n按左侧写法空串消不完全就导致了B状态少识别一个0?是这个原因吗？一点也不直观，操\n有限自动机 -\u0026gt; 正规表达式：\n正规表达式 -\u0026gt; 有限自动机：\n正规表达式 -\u0026gt; 正规文法：\n正规文法 -\u0026gt; 正规表达式：\n","date":"2025-11-04T00:00:00+08:00","image":"https://invalidval.github.io/p/chapter-2-%E5%BD%A2%E5%BC%8F%E8%AF%AD%E8%A8%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E6%9C%BA%E5%9F%BA%E7%A1%80/cp2_hu_cf7d0f128f6e0101.png","permalink":"https://invalidval.github.io/p/chapter-2-%E5%BD%A2%E5%BC%8F%E8%AF%AD%E8%A8%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E6%9C%BA%E5%9F%BA%E7%A1%80/","title":"Chapter 2 形式语言与自动机基础 "},{"content":"信号量有关的同步问题 有限缓冲 1、分析需要的信号量个数\n1 2 3 Binary semaphore mutex = 1；//互斥信号量，实现对缓冲区的互斥访问 semaphore empty = n；//同步信号量，表示空闲缓冲区的数量 semaphore full = 0；//同步信号量，表示产品的数量，也即非空缓冲区的数量 2、类c代码 互斥信号量一定要放在同步信号量之后\n复杂读者-写者 普通 1 2 3 4 int r_cnt = 0; Semaphore wrt = 1; r_mutex = 1; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 writer(){ wait(wrt); //w signal(wrt); } reader(){ wait(r_mutex); r_cnt++; if(r_cnt == 1) wait(wrt); signal(r_mutex); //r wait(r_mutex); r_cnt--; if(r_cnt == 0) signal(wrt); signal(r_mutex); } 带队列的读-写 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Semaphore q = 1; writer(){ wait(q); //逻辑不变 signal(q); } reader(){ wait(q); wait(r_mutex); r_cnt++; if(r_cnt == 1) wait(wrt); signal(r_mutex); signal(q); // 完成读计数之后就signal队列，之后你慢慢读没人管你 //r wait(r_mutex); r_cnt--; if(r_cnt == 0) signal(wrt); signal(r_mutex); } 扩展的读写者问题——最多允许M个读者同时读 四出生之家 可扩展到更多水果，核心是处理第一个和最后一个，保证盘内品种唯一\n哲学家吃屎 管程写法模板\n1 2 3 4 5 6 Monitor M{ enum {THINKING, EATING, HUNGRY} states[5]; condition self[5]; // void ... // void initialize(); } （期中）计数范围 三状态最大、最小值： 可以都在waiting，但是最多时必须有cpus个进程在running，所以ready_max = total - cpus\n","date":"2025-11-04T00:00:00+08:00","image":"https://invalidval.github.io/p/chapter-6-%E8%BF%9B%E7%A8%8B%E5%90%8C%E6%AD%A5/1_hu_3014106c611501b9.jpg","permalink":"https://invalidval.github.io/p/chapter-6-%E8%BF%9B%E7%A8%8B%E5%90%8C%E6%AD%A5/","title":"Chapter 6 进程同步"},{"content":"关系数据库设计步骤 无损连接 有损连接：拆分再恢复时出现多余错误记录 如果R1、R2没有公共属性，则join时会退化成笛卡尔积\n规范化理论 数据依赖 在逻辑DBS设计过程中，将E-R图转换，得到面向特定应用领域的初始关系模式集。这些初始关系模式集中可能存在多种作为完整性约束的关系模式属性间的数据依赖 (Data Dependencies) 关系\n函数依赖 (Functional Dependencies, FD, §7.2) 多值依赖 (Mutivalued Dependencies, MVD, §7.4, 7.6) 连接依赖 (Join Dependencies, JD) （略） 函数依赖是特殊的多值依赖 多值依赖又是连接依赖的特例\n范式关系 保证关系模式的函数无损连接性、函数依赖保持性进行关系规范化处理即模式分解 1NF 原子属性\n2NF 由1NF消除非主属性对键的部分（函数）依赖得到 不包含非主属性对键的部分依赖\n3NF 由2NF消除非主属性对键的传递依赖得到 不包含非主属性的对键的部分、传递依赖\nBCNF 由3NF消除主属性对键的部分和传递依赖得到 不包含主属性、非主属性对键的部分和传递依赖\n4NF 由BCNF消除非平凡且非函数依赖的多值依赖得到\n5NF 由4NF消除非平凡的连接依赖得到\n概念 函数依赖 可参考 Chapter 7 函数依赖\n函数依赖保持 区分satisfy与holds on 满足是局部满足，保持是所有合法关系实例都必须满足此FD 平凡FD 主属性与传递依赖 部分依赖 左端非最小化\n函数依赖闭包$F^{+}$ 目的：从已知函数依赖，推导出全部隐含函数依赖\n函数依赖定义的无损连接分解 范式 1NF 所有属性都是原子的 A relational schema R is in first normal form if the domains of all attributes of R are atomic. 比如应该把学院放进属性列而非使用学号编码\n2NF 不存在非主属性对候选键的部分依赖 非主属性要么不依赖，要么完全依赖于候选键\nBCNF 不存在非主属性、主属性对候选键的部分、传递依赖 A relation schema R is in BCNF with respect to a set F of functional dependencies, if for all functional dependencies in $F^{+}$ of the form $\\alpha \\rightarrow \\beta$ where $\\alpha \\subset \\beta $ R and $\\beta \\subseteq R$, at least one of the following holds: $\\alpha \\rightarrow \\beta$ is trivial (i.e., $\\beta \\subseteq \\alpha$) $\\alpha$ is a superkey for R 如何分解成BCNF？ 说白了就是让不属于原模式超键的属性都变为新模式的主键，并从原模式中去掉依赖式右端的属性\n分解BCNF也存在函数依赖保持和非保持 总之就一句话： the functional dependency s_ID, dept name → i_ID can only be checked by computing the join of the decomposed relations\n3NF Because it is not always possible to achieve both BCNF and dependency preservation, we consider a weaker normal form, known as third normal form (3NF). A relation schema R is in third normal form with respect to a set F of functional dependencies, if for all functional dependencies in $F^{+}$ of the form $\\alpha \\rightarrow \\beta$ where $\\alpha \\subset \\beta $ R and $\\beta \\subseteq R$, at least one of the following holds: $\\alpha \\rightarrow \\beta$ is trivial (i.e., $\\beta \\subseteq \\alpha$) $\\alpha$ is a superkey for R Each attribute A in $\\beta - \\alpha$ is part of some candidate key for R If a relation is in BCNF, it is also in 3NF (since in BCNF one of the first two conditions above must hold). Third condition is a minimal relaxation（放宽） of BCNF to ensure dependency preservation (will see why later) 3NF缺点 Redundancy in 3NF【缺点:数据冗余】\n3NF对比BCNF Advantages to 3NF over BCNF\nIt is always possible to obtain a 3NF design without sacrificing losslessness or dependency preservation 3NF分解可以保证无损连接、函数依赖保持 BCNF分解保证无损连接，但不保证函数依赖保持 Disadvantages to 3NF\nWe may have to use null values to represent some of the possible meaningful relationships among data items. There is the problem of repetition of information 分解目标 分解要求：从函数依赖角度 1. 分解为2NF, 3NF, BCNF 2. 必修保证无损连接分解，尽可能保证函数依赖保持\n","date":"2025-11-01T00:00:00+08:00","image":"https://invalidval.github.io/p/chapter7-%E5%85%B3%E7%B3%BB%E8%A7%84%E8%8C%83%E5%8C%967.1-7.3/c7_hu_d59080f89273aa03.png","permalink":"https://invalidval.github.io/p/chapter7-%E5%85%B3%E7%B3%BB%E8%A7%84%E8%8C%83%E5%8C%967.1-7.3/","title":"Chapter7 关系规范化(7.1-7.3)"},{"content":"ISA关系（6.8） ISA Relationship 指的是一种特定的数据建模技术，用于在概念模型（如ER图）中表示实体之间的继承关系。\nISA 是 “IS-A” 的缩写，例如 “A Manager IS-AN Employee”（一个经理 是 一个员工）。它描述了一种父类型（超类型） 和子类型 之间的层次关系。\n核心概念 在数据库设计中，ISA关系用于捕捉现实世界中存在的分类结构。\n超类型 / 父类： 一个更一般化、更抽象的实体。 例如：人(Person)、账户(Account)、车辆(Vehicle) 子类型 / 子类： 一个更具体、更特化的实体，它是超类型的一种。 例如：员工(Employee) 和 学生(Student) 是 人(Person) 的子类型。 储蓄账户(SavingsAccount) 和 支票账户(CheckingAccount) 是 账户(Account) 的子类型。 ISA关系的两个关键约束 当你在设计中使用ISA关系时，必须定义两个重要的约束：\n1. 重叠约束（Disjoint/Overlapping Constraint） 规定一个超类型的实例是否可以同时属于多个子类型。\n不允许重叠： 一个超类实例只能属于一个子类型。 例如：一个 账户(Account) 要么是 储蓄账户(SavingsAccount)，要么是 支票账户(CheckingAccount)，但不能同时是两者。用 “OR” 表示。 允许重叠： 一个超类实例可以同时属于多个子类型。 例如：一个 人(Person) 可以同时是 员工(Employee) 和 学生(Student)。用 “AND” 表示。 2. 完备性约束（Completeness constraint） 规定超类型中的每一个实例是否都必须至少属于一个子类型。\n全完备性（total）： 超类型的每一个实例都必须是某个子类型的实例。 例如：公司规定，每一个 员工(Employee) 都必须是 小时工(HourlyEmployee) 或 月薪工(SalariedEmployee) 中的一种。超类型 员工(Employee) 不会存在不属于任何子类的“孤例”。在ER图中，用双线表示。 部分完备性（partial）： 超类型的实例可以不属于任何子类型。 例如：一个 人(Person) 可以只是普通人，既不是 员工(Employee)，也不是 学生(Student)。在ER图中，用单线表示。 在数据库中的实现方式 ISA层次结构在物理数据库中主要有三种实现方式：\r1. 每个具体类一张表 方法： 忽略超类型，只为每个子类型创建一张表。这张表包含该子类型特有的属性，以及从超类型继承来的所有属性。 举例： 创建 学生表(Students) 和 员工表(Employees)，没有 人表(Persons)。Students表中有 student_id, name, age, major 等字段。 优点： 查询特定子类型的数据时速度快。 缺点： 数据冗余（如果一个人既是学生又是员工，他的name和age信息会在两张表中重复存储）。 难以对所有人进行统一查询（需要UNION操作）。 无法表示不属于任何子类的人。 2. 单张表 方法： 将整个层次结构“扁平化”为一张表。这张表包含超类型和所有子类型的所有属性。同时，增加一个“类型鉴别”字段来标识每一行属于哪个子类型。 举例： 创建一张 人表(Persons)，包含字段：person_id, name, age, person_type, major, salary, department。 如果 person_type = ‘Student’，那么 major 字段有意义，salary 字段为NULL。 如果 person_type = ‘Employee’，那么 salary 字段有意义，major 字段为NULL。 优点： 统一查询非常简单，不需要JOIN操作。 缺点： 表中存在大量NULL值，浪费存储空间。 表结构会随着子类型的增加而变得非常庞大和复杂。 3. 超类型和子类型分别建表 方法： 为超类型和每一个子类型都创建一张表。 超类型表包含所有实例共享的公共属性（和一个主键）。 子类型表只包含其特有的属性，并共享超类型表的主键（即子类型表的主键同时也是引用超类型表的外键）。 举例： 人表(Persons)：person_id (PK), name, age 学生表(Students)：person_id (PK, FK references Persons), major 员工表(Employees)：person_id (PK, FK references Persons), salary, department 优点： 设计规范，消除了数据冗余。 易于添加新的子类型。 能很好地支持重叠约束（一个人可以同时在Students和Employees表中有记录）。 缺点： 查询数据时需要频繁使用JOIN操作，性能可能成为瓶颈。 总结 在数据库领域中，ISA Relationship 是一个强大的概念建模工具，它清晰地表达了 “是一个” 的继承关系。理解并正确定义其重叠约束和完备性约束至关重要，因为它直接影响到最终数据库表结构的设计选择（每种实现方式都有其优缺点，需要根据具体应用场景进行权衡）。\n","date":"2025-10-23T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter-6.8-isa/","title":"Chapter 6.8 ISA"},{"content":"Chapter 6 The Entity-Relationship Model Entity Sets（实体集，实体型） 一张学生表是一个实体集，一个学生是一个实体（一行记录）\nRelationship Sets(关系集) 选课表就是一个关系集。它定义了“学生”和“课程”之间的“选修”这种关系。关系表示特定实体之间的一次具体关联。它对应的是联系表中的一行记录。 关系集也可以拥有自己的属性（关系集属性），用于描述关系的特征。它同样对应联系表中的列。选课表这个关系集可以有成绩、选修日期等属性，这些属性不属于学生，也不属于课程，而是属于“选修”这个行为本身。\nChoice of Primary key for Binary Relationship 在多的那一端把一的主键拿过来当外键\n多元联系(non-binary) 先转成多个二元联系再转表：将其他实体集的主键和关系自身属性建成表，各实体集不存放多余属性。\nE-R图（概念设计结果） Representing Cardinality Constraints in ER Diagram →：一 —：多 (one,many) x (one,many) = 4 种\n参与约束(Participant Constraints) 完全参与、部分参与\n逻辑设计阶段 E-R图转关系模式 实体、联系、属性（单值属性、多值属性、复合属性）如何转表？ 多值属性单独转表 复合属性拆开（如时间、地址）\n弱实体集、强实体集； 用实体还是属性？ Not to use the primary-key of an entity set as an attributes of another entity set (to represent implicitly association between these two entity sets), it is better to use an relationship set to explicitly show this association e.g. for the entity student, do not use instructor.id as its attribute, in stead of, representing association among student and instructor using relationship advisor.\n用实体还是关系？“动作”对应“联系”\n弱实体集理解\n扩展ER （详情看ISA那篇） 面向对象ER：Object-oriented (OO) E-R specialization （特化，特殊化，例化） 自上而下，底层实体集是高层实体集的真子集 高层：超类；底层：子类\ngeneralization (概括化，泛化，普遍化) 自底向上\nattributes inheritance （属性继承） 联系也可以继承\nAggregation relationship on relationship（联系的联系）\nER图记号总结 ","date":"2025-10-23T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter6-er%E6%A8%A1%E5%9E%8B/","title":"Chapter6 ER模型"},{"content":" 一、 基础查询 (Basic Queries) 1. SELECT \u0026amp; FROM 1 2 SELECT * FROM employees; SELECT name, salary FROM employees; 2. WHERE 条件筛选 1 2 3 4 5 SELECT * FROM employees WHERE salary \u0026gt; 5000; SELECT * FROM employees WHERE department = \u0026#39;IT\u0026#39; AND salary \u0026gt; 6000; SELECT * FROM employees WHERE name LIKE \u0026#39;A%\u0026#39;; -- 名字以A开头 SELECT * FROM employees WHERE age BETWEEN 25 AND 35; SELECT * FROM employees WHERE department IN (\u0026#39;IT\u0026#39;, \u0026#39;HR\u0026#39;, \u0026#39;Finance\u0026#39;); 3. ORDER BY 排序 1 2 SELECT * FROM employees ORDER BY salary DESC; SELECT * FROM employees ORDER BY department ASC, salary DESC; 4. DISTINCT 去重 1 SELECT DISTINCT department FROM employees; 二、 聚合函数与分组 (Aggregation \u0026amp; Grouping) 5. 聚合函数 1 2 3 4 5 6 7 SELECT COUNT(*) as total_employees, AVG(salary) as avg_salary, MAX(salary) as max_salary, MIN(salary) as min_salary, SUM(salary) as total_salary FROM employees; 6. GROUP BY 分组 1 2 3 4 5 6 SELECT department, COUNT(*) as emp_count, AVG(salary) as avg_salary FROM employees GROUP BY department; 7. HAVING 分组后筛选 1 2 3 4 5 6 SELECT department, COUNT(*) as emp_count FROM employees GROUP BY department HAVING COUNT(*) \u0026gt; 5; 三、 多表连接 (Joins) 8. INNER JOIN 1 2 3 SELECT e.name, d.department_name FROM employees e INNER JOIN departments d ON e.department_id = d.id; 9. LEFT/RIGHT JOIN 1 2 3 SELECT e.name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.id; 10. FULL OUTER JOIN 1 2 3 SELECT e.name, d.department_name FROM employees e FULL OUTER JOIN departments d ON e.department_id = d.id; 11. 多表连接 1 2 3 4 SELECT e.name, d.department_name, p.project_name FROM employees e JOIN departments d ON e.department_id = d.id JOIN projects p ON e.id = p.leader_id; 四、 子查询 (Subqueries) 12. 标量子查询 1 2 3 SELECT name, salary, (SELECT AVG(salary) FROM employees) as company_avg FROM employees; 13. IN 子查询 1 2 3 4 5 SELECT name FROM employees WHERE department_id IN ( SELECT id FROM departments WHERE budget \u0026gt; 100000 ); 14. EXISTS 子查询 1 2 3 4 5 6 SELECT name FROM employees e WHERE EXISTS ( SELECT 1 FROM projects p WHERE p.leader_id = e.id ); 15. 关联子查询 1 2 3 4 5 6 7 SELECT name, salary, department FROM employees e1 WHERE salary \u0026gt; ( SELECT AVG(salary) FROM employees e2 WHERE e2.department = e1.department ); 五、 高级查询技术 (Advanced Techniques) 16. CTE (公用表表达式) 1 2 3 4 5 6 7 8 WITH department_stats AS ( SELECT department, AVG(salary) as avg_salary FROM employees GROUP BY department ) SELECT * FROM department_stats WHERE avg_salary \u0026gt; 6000; 17. 递归 CTE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 WITH RECURSIVE org_chart AS ( -- 基础情况 SELECT employee_id, name, manager_id, 1 as level FROM employees WHERE manager_id IS NULL UNION ALL -- 递归情况 SELECT e.employee_id, e.name, e.manager_id, oc.level + 1 FROM employees e JOIN org_chart oc ON e.manager_id = oc.employee_id ) SELECT * FROM org_chart; 18. 窗口函数 1 2 3 4 5 6 7 8 SELECT name, department, salary, RANK() OVER (PARTITION BY department ORDER BY salary DESC) as dept_rank, AVG(salary) OVER (PARTITION BY department) as dept_avg_salary, LAG(salary) OVER (ORDER BY salary) as prev_salary FROM employees; 19. PIVOT 行列转换 1 2 3 4 5 6 7 8 9 10 -- SQL Server SELECT * FROM ( SELECT department, salary FROM employees ) AS SourceTable PIVOT ( AVG(salary) FOR department IN ([IT], [HR], [Finance]) ) AS PivotTable; 六、 数据操作 (Data Manipulation) 20. INSERT 1 2 3 4 5 6 INSERT INTO employees (name, salary, department) VALUES (\u0026#39;John Doe\u0026#39;, 5000, \u0026#39;IT\u0026#39;); -- 插入查询结果 INSERT INTO high_paid_employees (name, salary) SELECT name, salary FROM employees WHERE salary \u0026gt; 8000; 21. UPDATE 1 2 3 4 5 6 7 8 9 10 UPDATE employees SET salary = salary * 1.1 WHERE department = \u0026#39;IT\u0026#39;; -- 使用子查询更新 UPDATE employees SET salary = ( SELECT AVG(salary) FROM employees ) WHERE salary IS NULL; 22. DELETE 1 2 3 4 5 6 7 DELETE FROM employees WHERE salary \u0026lt; 3000; -- 使用子查询删除 DELETE FROM employees WHERE department_id IN ( SELECT id FROM departments WHERE active = 0 ); 23. MERGE/UPSERT 1 2 3 4 5 -- PostgreSQL INSERT INTO employees (id, name, salary) VALUES (1, \u0026#39;John\u0026#39;, 5000) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, salary = EXCLUDED.salary; 七、 事务控制 (Transaction Control) 24. 事务处理 1 2 3 4 5 6 7 8 9 10 BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 如果一切正常 COMMIT; -- 如果出现错误 ROLLBACK; 八、 性能优化相关 25. 索引使用 1 2 CREATE INDEX idx_employee_department ON employees(department); CREATE INDEX idx_employee_name_salary ON employees(name, salary); 26. 分页查询 1 2 3 4 5 -- MySQL SELECT * FROM employees ORDER BY id LIMIT 10 OFFSET 20; -- SQL Server SELECT * FROM employees ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY; 27. 查询性能分析 1 2 3 4 5 6 -- 查看执行计划 EXPLAIN SELECT * FROM employees WHERE salary \u0026gt; 5000; -- SQL Server SET STATISTICS TIME ON; SELECT * FROM employees WHERE salary \u0026gt; 5000; 九、 实用函数 28. 字符串函数 1 2 3 4 5 6 7 SELECT UPPER(name) as upper_name, LOWER(name) as lower_name, LENGTH(name) as name_length, SUBSTRING(name, 1, 3) as name_prefix, CONCAT(first_name, \u0026#39; \u0026#39;, last_name) as full_name FROM employees; 29. 日期函数 1 2 3 4 5 6 SELECT CURRENT_DATE as today, EXTRACT(YEAR FROM hire_date) as hire_year, DATE_ADD(hire_date, INTERVAL 1 YEAR) as anniversary, DATEDIFF(CURRENT_DATE, hire_date) as days_employed FROM employees; 30. 条件表达式 1 2 3 4 5 6 7 8 9 10 SELECT name, salary, CASE WHEN salary \u0026lt; 3000 THEN \u0026#39;Low\u0026#39; WHEN salary BETWEEN 3000 AND 7000 THEN \u0026#39;Medium\u0026#39; ELSE \u0026#39;High\u0026#39; END as salary_level, COALESCE(bonus, 0) as bonus_amount FROM employees; 这份指南涵盖了 SQL 从基础到高级的大部分常用语法。建议在实际工作中根据需要查阅相关部分，并通过练习来熟练掌握。\n","date":"2025-10-01T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter-3-5-sql-%E8%BF%9B%E9%98%B6%E6%9F%A5%E8%AF%A2%E8%AF%AD%E6%B3%95%E5%A4%A7%E5%85%A8/","title":"Chapter 3-5 SQL 进阶查询语法大全"},{"content":"NOT EXISTS 和 EXCEPT 是 SQL 中用于处理集合差集的高级操作，它们在不同场景下非常有用。\n一、 NOT EXISTS 用法 1. 基本语法 1 2 3 4 5 6 7 SELECT columns FROM table1 t1 WHERE NOT EXISTS ( SELECT 1 FROM table2 t2 WHERE t1.related_column = t2.related_column ); 2. 实际例子 例1：找出没有项目的员工 1 2 3 4 5 6 7 SELECT e.employee_id, e.name FROM employees e WHERE NOT EXISTS ( SELECT 1 FROM projects p WHERE p.leader_id = e.employee_id ); 例2：找出没有订单的客户 1 2 3 4 5 6 7 SELECT c.customer_id, c.customer_name FROM customers c WHERE NOT EXISTS ( SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id ); 例3：找出从未被订购的产品 1 2 3 4 5 6 7 SELECT p.product_id, p.product_name FROM products p WHERE NOT EXISTS ( SELECT 1 FROM order_items oi WHERE oi.product_id = p.product_id ); 3. 复杂例子：找出没有下属的管理者 1 2 3 4 5 6 7 8 SELECT e1.employee_id, e1.name FROM employees e1 WHERE e1.is_manager = 1 AND NOT EXISTS ( SELECT 1 FROM employees e2 WHERE e2.manager_id = e1.employee_id ); 二、 EXCEPT 用法 1. 基本语法 1 2 3 SELECT column1, column2 FROM table1 EXCEPT SELECT column1, column2 FROM table2; 2. 实际例子 例1：找出只在A表不在B表的记录 1 2 3 4 -- 找出在employees表但不在former_employees表的员工 SELECT employee_id, name FROM employees EXCEPT SELECT employee_id, name FROM former_employees; 例2：找出有库存但从未被订购的产品 1 2 3 SELECT product_id FROM inventory EXCEPT SELECT product_id FROM order_items; 例3：多列比较 1 2 3 4 -- 找出在2023年有销售但2024年没有的客户 SELECT customer_id, product_id FROM sales_2023 EXCEPT SELECT customer_id, product_id FROM sales_2024; 三、 NOT EXISTS vs EXCEPT 对比 相同需求的不同实现 需求：找出没有项目的部门 使用 NOT EXISTS:\n1 2 3 4 5 6 7 SELECT d.department_id, d.department_name FROM departments d WHERE NOT EXISTS ( SELECT 1 FROM projects p WHERE p.department_id = d.department_id ); 使用 EXCEPT:\n1 2 3 4 5 6 SELECT department_id, department_name FROM departments EXCEPT SELECT d.department_id, d.department_name FROM departments d JOIN projects p ON d.department_id = p.department_id; 四、 高级应用场景 1. 多层 NOT EXISTS（复杂逻辑） 找出所有产品都库存充足的产品类别 1 2 3 4 5 6 7 8 9 SELECT c.category_id, c.category_name FROM categories c WHERE NOT EXISTS ( -- 找出该类别中库存不足的产品 SELECT 1 FROM products p WHERE p.category_id = c.category_id AND p.current_stock \u0026lt; p.minimum_stock ); 2. EXCEPT 用于数据验证 验证两个表的结构一致性 1 2 3 4 -- 找出在source_table中存在但在target_table中不存在的记录 SELECT id, name, value FROM source_table EXCEPT SELECT id, name, value FROM target_table; 3. 组合使用 NOT EXISTS 和 EXISTS 找出只订购过一次的客户 1 2 3 4 5 6 7 8 9 10 11 12 13 14 SELECT c.customer_id, c.customer_name FROM customers c WHERE EXISTS ( -- 至少有一个订单 SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id ) AND NOT EXISTS ( -- 没有第二个订单 SELECT 1 FROM orders o1, orders o2 WHERE o1.customer_id = c.customer_id AND o2.customer_id = c.customer_id AND o1.order_id \u0026lt;\u0026gt; o2.order_id ); 五、 性能考虑和最佳实践 1. NOT EXISTS 通常性能更好 1 2 3 4 5 6 7 -- 推荐：使用NOT EXISTS SELECT * FROM table1 t1 WHERE NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.id = t1.id); -- 不推荐：使用NOT IN（对NULL值处理有问题） SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2 WHERE id IS NOT NULL); 2. EXCEPT 自动去重 1 2 3 4 -- EXCEPT 会自动去除重复记录 SELECT department FROM employees EXCEPT SELECT department FROM former_employees; 3. 处理NULL值 1 2 3 4 5 6 -- NOT EXISTS 能正确处理NULL值 SELECT * FROM products p WHERE NOT EXISTS ( SELECT 1 FROM discontinued_products dp WHERE dp.product_id = p.product_id ); 六、 实际业务场景 场景1：电商平台 - 找出从未被浏览的商品 1 2 3 4 5 6 7 SELECT product_id, product_name FROM products WHERE NOT EXISTS ( SELECT 1 FROM user_browsing_history WHERE product_id = products.product_id ); 场景2：学校系统 - 找出没有选课的学生 1 2 3 4 5 6 SELECT student_id, student_name FROM students EXCEPT SELECT s.student_id, s.student_name FROM students s JOIN enrollments e ON s.student_id = e.student_id; 场景3：银行系统 - 找出有账户但从未交易的客户 1 2 3 4 5 6 7 8 SELECT c.customer_id, c.customer_name FROM customers c JOIN accounts a ON c.customer_id = a.customer_id WHERE NOT EXISTS ( SELECT 1 FROM transactions t WHERE t.account_id = a.account_id ); 总结 NOT EXISTS: 更适合关联查询，性能通常较好，能正确处理NULL值 EXCEPT: 更适合比较两个结果集的差异，语法更直观，自动去重 选择依据: 需要关联条件时用 NOT EXISTS 直接比较两个查询结果时用 EXCEPT 考虑数据库优化器和具体数据量进行测试 两者都是处理\u0026quot;在A中但不在B中\u0026quot;这类需求的强大工具！\n","date":"2025-10-01T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter3-sql%E9%9B%86%E5%90%88%E6%93%8D%E4%BD%9C/","title":"Chapter3 SQL集合操作"},{"content":"SQL 语法 SELECT distinct 去重 1 2 select `distinct/all` dept_name from instructor 四则运算和重命名 1 select ID, name, salary/12 as monthly_salary FROM natural join 自然连接 1 2 3 4 select name, course_id from instructor natural join teaches where instructor. dept_name = ‘Art’ // 等价于加上 where instructor.ID = teaches.ID and WHERE SQL allows the use of the logical connectives and, or, and not The operands of the logical connectives can be expressions involving the comparison operators \u0026lt;, \u0026lt;=, \u0026gt;, \u0026gt;=, =, and \u0026lt;\u0026gt;.（以及between A and B 用法）\nTuple comparison 1 2 3 select name, course_id from instructor, teaches where (instructor.ID, dept_name) = (teaches.ID, \u0026#39;Biology\u0026#39;); Tuple Variables 涉及到对instructor关系中属性salary的不同值的比较\n1 2 3 select distinct T.name from instructor as T, instructor as S where T.salary \u0026gt; S.salary and S.dept_name = ‘Comp. Sci.’ 执行顺序 FROM - 从表中获取数据\nWHERE - 对原始行数据进行筛选\nGROUP BY - 对筛选后的数据进行分组\nHAVING - 对分组后的聚合结果进行筛选\nSELECT - 选择要显示的列\n在 WHERE 子句中不能直接使用 COUNT 等聚合函数，因为执行顺序的问题。\n1 2 3 4 5 -- ✅ 正确：使用HAVING对分组结果进行筛选 SELECT department, COUNT(*) as emp_count FROM employees GROUP BY department HAVING COUNT(*) \u0026gt; 5; -- 这里COUNT()在每组内计算 CTE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 WITH department_stats AS ( SELECT department, AVG(salary) as avg_salary, COUNT(*) as employee_count FROM employees GROUP BY department ), high_avg_departments AS ( -- 这个CTE引用了前一个CTE SELECT department, avg_salary FROM department_stats WHERE avg_salary \u0026gt; 6000 ) -- 主查询 SELECT e.name, e.salary, h.avg_salary as department_avg FROM employees e JOIN high_avg_departments h ON e.department = h.department WHERE e.salary \u0026gt; h.avg_salary; GROUP BY Attributes in select clause outside of aggregate functions must appear in group by list（必须要有聚合运算） 错误示例：\n1 2 3 4 /* erroneous query */ select dept_name, ID, avg (salary) -- ID 不在聚合属性中 from instructor group by dept_name 正确用法：（可以有多个聚合运算）\nproduct category sales_amount A Electronics 100 B Electronics 150 A Electronics 200 C Clothing 80 B Electronics 120 1 2 3 4 5 6 SELECT category, COUNT(*) as transaction_count, SUM(sales_amount) as total_sales FROM sales GROUP BY category; category transaction_count total_sales Electronics 4 570 Clothing 1 80 常用聚合函数\n1 2 3 4 5 6 7 8 9 SELECT department, COUNT(*) as employee_count, -- 计数 AVG(salary) as avg_salary, -- 平均值 SUM(salary) as total_salary, -- 求和 MAX(salary) as max_salary, -- 最大值 MIN(salary) as min_salary -- 最小值 FROM employees GROUP BY department; ORDER BY 1 2 SELECT * FROM employees ORDER BY salary DESC; SELECT * FROM employees ORDER BY department ASC, salary DESC; ","date":"2025-09-30T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter3-intro-to-sql/","title":"Chapter3 Intro-to-SQL"},{"content":"关系数据库结构 table、relation、attributes\nkey A superkey (超键) is a set of one or more attributes that, taken collectively, can be used to identify uniquely a tuple in the relation.\nK is a candidate key (候选键) if K is minimal super key. e.g.{ID} is a candidate key for instructor, assuming no two instructors can possibly have the same identifiers. A relation may have several candidate keys\nPrimary key (主键) is a candidate key chosen by the database designer as principal means to identify tuples within a relation\nDef. Primary attributes (主属性!) taking the key as a attribute set, the attributes in the candidate keys, i.e. the element of the primary key is called the primary attributes non-primary attributes (非主属性)\nSuper key \u0026gt;= candidate key \u0026gt;= primary key\nrelational algebra (关系代数) Six basic operators (选择) select: $\\sigma$ (投影) project: (笛卡尔积) Cartesian product: x (集合并) union: (集合差) set difference: – (重命名) rename: 复合关系运算 暂时值（Assignment） ","date":"2025-09-10T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter2-%E5%85%B3%E7%B3%BB%E6%95%B0%E6%8D%AE%E5%BA%93%E5%9F%BA%E7%A1%80/","title":"Chapter2 关系数据库基础"},{"content":"名词 Database (DB) The term DBS and DBMS are used interchangeably in the textbook Database application system DB + DBMS + Application programs + Users/Administers DBS = DB + DBMS OS文件系统缺点 Data redundancy and inconsistency Difficulty in accessing data Data isolation/独立性（信号量） 数据库系统目的 Integrity/完整性 problems【语义约束】 Atomicity/原子性 of updates Concurrent access/并发访问 by multiple users Security problems 数据模型、数据建模、数据抽象 data models a collection of conceptual tools for describing: data, data relationships/联系 data semantics/语义 consistency/一致性 constraints specifications for data organization and access data modeling organize application data in the database, according to data model, by data abstraction data abstraction database modeling mechanism hide the complexity of data structures to represent data in the database from users through view-logical-physical levels of data abstraction Levels of Abstraction Physical level describes how a record (e.g., instructor) is stored and accessed in database files Logical level Implementation/DB-oriented describes data stored in database, and the relationships among the data. View level application programs hide details of data types views can also hide information (such as an employee’s salary) for security purposes. described as Entity-relationship (E-R) diagrams DDL DML Data Definition Language DML procedural/过程性 DML \u0026ndash; require a user to specify what data are needed and how to get those data [e.g. relational algebra]\ndeclarative/声明性 DML \u0026ndash; require a user to specify what data are needed without specifying how to get those data [e.g. SQL]\n数据库设计阶段 从保持data independence角度出发，根据data models所定义的数据规范形式，在view、logical 、 physical三个层次，通过data abstraction，经过概念设计、逻辑设计、物理设计三个步骤，构造 面向具体应用领域的DBS的 E-R diagrams, external schema/logical schema , internal schema的集合, 得到conceptual DB 、logical DB 、physical DB设计结果\n","date":"2025-09-01T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter1-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/","title":"Chapter1 基本概念"},{"content":"\\o/ \\o/ \\o/\n","date":"2023-01-01T00:00:00+08:00","permalink":"https://invalidval.github.io/p/blog%E4%BA%8C%E5%91%A8%E7%9B%AE%E6%AD%A3%E5%BC%8F%E4%B8%8A%E7%BA%BF/","title":"blog二周目正式上线"},{"content":"思想 递归\n分治的条件 规模缩小到一定程度可以容易解决 具有最优子结构性质 子问题的解可以合并为该问题的解（与动态规划的区别）（不能：贪心、DP） 不包含公共子问题（各个子问题相互独立，否则使用DP） 快速排序：原地排序、$nlogn$ 2.3 二分搜索 2.4 大整数乘法 2.5 Strassen矩阵乘法 2.7 合并排序 2.8 快速排序 2.9 选择问题 长度为$n$线性有序集合，找出第$k$小 分治，$pivot$ 线性时间选择问题，问题规模 $0\u0026lt;\\epsilon\u0026lt;1$\n步骤 划分成$\\frac{n}{5}$个组 各组内任意排序 每组中，$pivot_{i}$ = 中位数 一共$\\frac{n}{5}$个$pivot$，再找出中位数 只有75个元素以上才能缩小$\\frac{1}{4}$ 补充 划分因子选择3、7：7可以，3不行\n2.10 最近点对问题 直线 暴力$O(n^{2})$ 一次排序、一维扫描，$O(nlogn)$\n二维 蛮力；分治（平衡子问题） 如何分治？能在线性时间内完成？\n","date":"2023-01-01T00:00:00+08:00","permalink":"https://invalidval.github.io/p/chapter-2-%E5%88%86%E6%B2%BB/","title":"Chapter 2 分治"}]