跳转至

Computer Science Distilled

[!Important]

本文部分离散数学已涉及内容不再赘述

学习借助 gemini

Chapter 3 : Strategy

策略 (Strategy) 核心思想 优点 缺点/适用场景
迭代 & 递归 控制流程的基本方式 基础,直接 它们本身是工具,服务于其他策略
暴力破解 尝试所有可能 简单,保证找到最优解 效率极低,仅适用于小规模问题
回溯 智能搜索,走不通就退回 比暴力破解高效,系统性强 解决约束满足问题,如谜题
启发式 找“足够好”的快速解 速度极快 不保证最优,是种权衡
分治 分解、解决、合并 效率高,逻辑清晰 适用于子问题相互独立的情况
动态规划 记录结果,避免重复计算 极大提升效率,化指数为多项式 适用于子问题重叠的情况
分支界定 评估边界,剪掉无效分支 智能优化搜索,高效 适用于最优化问题(求最大/最小值)

Chapter 4 : Data

4.1 抽象数据类型 (Abstract Data Types, ADTs)

使用 ADT 的好处:

  • 代码更简洁: 你的算法代码只跟 ADT 互动,不用关心底层细节。
  • 灵活性高
  • 可复用性强: 一套写好的数据处理模块(比如一个处理“列表”的模块)可以在任何需要“列表”的地方使用。

4.2 常见抽象 (Common Abstractions)

  • 栈 (Stack):
    • 原则: 后进先出 (LIFO - Last-In, First-Out)。
    • 操作: push (入栈), pop (出栈)。
  • 队列 (Queue):
    • 原则: 先进先出 (FIFO - First-In, First-Out)。
    • 操作: enqueue (入队), dequeue (出队)。
  • 优先队列 (Priority Queue):
    • 原则: 不论谁先进来,优先级最高的先出去。
    • 例子: 操作系统的任务调度(重要的系统进程比普通应用优先级高)。
  • 列表 (List)
  • 映射 (Map) / 字典 (Dictionary):
    • 一句话解释: 像一本真正的字典,通过一个“键”(Key,比如一个单词)可以快速查到对应的“值”(Value,比如单词的释义)。
    • 例子: 电话簿(姓名 -> 电话号码)、存储用户配置(配置项名称 -> 配置值)。
  • 集合 (Set):
    • 例子: 一个班级里的所有学生名单(每个学生都是唯一的)。

4.3 数据结构 (Data Structures)

选择哪种数据结构直接决定了程序的性能。

  • 数组 (Array):

    • 物理结构: 内存中一块**连续**的空间,像一排连号的储物柜。
    • 优点: 访问速度极快。因为地址是连续的,可以通过索引直接计算出任何一个元素的位置(O(1) 复杂度),实现“指哪打哪”。
    • 缺点: 大小固定,不灵活。在中间插入或删除元素非常慢,因为需要移动后面的所有元素(O(n) 复杂度)。
  • 链表 (Linked List):

    • 物理结构: 内存中**分散**的节点,像一个寻宝游戏,每个节点里存着数据和指向下一个节点的“线索”(指针)。
    • 优点: 大小灵活,可以动态增长。在中间插入或删除元素非常快(O(1) 复杂度),只需要改变相邻节点的“线索”即可。
    • 缺点: 访问速度慢。想找第 n 个元素,必须从第一个开始,顺着线索一个一个往下找(O(n) 复杂度)。(书中还提到了**双向链表**,增加了“回头看”的线索,更灵活但占用更多空间)。
  • 树 (Tree):

    • 物理结构: 像一个家族树或文件系统,是分层级的结构。
    • 重点是二叉搜索树 (Binary Search Tree, BST): 一种特殊的树,左边的子节点比父节点小,右边的比父节点大。
    • 优点: 在**平衡**的情况下,查找、插入、删除都很快(O(log n) 复杂度)。
    • 缺点: 容易变得**不平衡**,退化成链表,性能急剧下降到 O(n)。解决方案是使用**自平衡树**(如红黑树)。
  • 哈希表 (Hash Table):

    • 物理结构: 本质上是一个数组,但它通过一个神奇的**哈希函数 (hash function)**,能把任意的“键”转换成一个数组索引。
    • 优点: 查找、插入、删除的平均速度都快到不可思议(O(1) 复杂度)。是实现 Map 和 Set 的首选。
    • 缺点: 可能会发生**哈希冲突**(两个不同的键被算到了同一个索引上),需要额外处理。比较消耗内存,且元素是无序的。

Chapter 5 : Algorithms

在前人的基础上选择最好的算法。本章主要介绍了四大类问题的经典算法。

5.1 排序 (Sorting)

  • 简单的算法 (O(n²)):

    • 选择排序 (Selection Sort): 每次都从剩下的里面找最小的放前面。
    • 插入排序 (Insertion Sort): 像打牌时整理手牌一样,每次把一张新牌插入到已排好序的部分。
    • 关键点: 这些算法简单直观,但在数据量大时会变得非常慢。不过,插入排序对于“基本有序”的数据,速度飞快,接近 O(n),这是它的一大优势。
  • 高效的算法 (O(n log n)):

    • 归并排序 (Merge Sort): (第三章讲过)典型的“分治”策略,稳定可靠。
    • 快速排序 (Quicksort): 另一种“分治”策略。
      • 工作方式: 随机挑一个元素作为“基准”(pivot)。把比它小的放左边,比它大的放右边。然后对左右两堆重复这个过程。
      • 关键点: 名字里就带个“快”字,在实践中通常是性能最好的排序算法之一。

5.2 搜索 (Searching)

  • 顺序搜索 (Sequential Search):

    • 方法: 一个一个地找。
    • 复杂度: O(n)。这是最笨的方法。
  • 二分搜索 (Binary Search):

    • 前提: 数据必须是有序的!
    • 方法: 每次都看中间的元素。如果目标比它大,就扔掉前半部分;如果比它小,就扔掉后半部分。每次都把搜索范围缩小一半。
    • 复杂度: O(log n)。非常高效。
  • 哈希表搜索 (Hash Table Search):

    • 前提: 数据存储在哈希表中。
    • 方法: 通过哈希函数直接计算出位置。
    • 复杂度: O(1)。理论上最快,近乎瞬时。

5.3 图 (Graphs)

  • 图的遍历 (Graph Traversal)

    • 深度优先搜索 (DFS - Depth-First Search): **使用**栈 (Stack) 来实现。
    • 广度优先搜索 (BFS - Breadth-First Search): 它使用**队列 (Queue)** 来实现。
    • 关键点: DFS 占用内存少,实现简单。BFS 能找到起点到终点的**最短路径(指经过的边最少)**。
  • 最短路径寻找 (Path Finding):

    • 迪科斯彻算法 (Dijkstra's Algorithm)
      • 注意: Dijkstra 算法不能处理带有**负权重**边的图。
  • 图着色 (Graph Coloring):

    • 问题: 给图的每个节点“涂色”,要求任意两个相连的节点颜色不能相同。
    • 例子: 为手机基站分配频率,相邻基站频率不能相同以避免干扰。
    • 关键点: 这是一个著名的 NP-完全问题,意味着目前没有已知的“高效”算法。

5.4 运筹学 (Operations Research)

运筹学用于解决资源分配和决策优化问题。

  • 线性规划 (Linear Programming):
    • 问题类型: 当你的**目标**(如利润最大化)和**约束**(如预算、原材料限制)都能表示成**线性**方程时,就属于线性规划问题。
    • 例子: 家具厂如何安排生产两种柜子,在满足成本和空间限制的前提下,让存储容量最大化。
    • 解决方法:单纯形法 (Simplex Method)
    • 关键点: 你**不需要自己实现单纯形法**。你需要做的是**识别出这是一个线性规划问题**,然后把你的目标和约束方程输入到一个现成的“单纯形求解器”里,它会直接告诉你答案。

这里类似数学建模的线性规划算法吧,可以根据目标函数和约束条件求出极值

Chapter 6 : Databases

核心主题:持久化数据的结构化管理与抽象

6.1 关系型模型 (Relational Model)

6.1.1 核心构成要素 (Core Components):

  • 关系 (Relation) / 表 (Table): 数据的基本组织单位,是一个二维结构,由元组(行)和属性(列)构成。
  • 元组 (Tuple) / 行 (Row): 代表一个实体(Entity)的实例。
  • 属性 (Attribute) / 列 (Column/Field): 描述实体的一个特征,具有严格的数据类型(如 INTEGER, VARCHAR, TIMESTAMP)。
  • 模式 (Schema): 对关系的结构化定义,包括其属性、数据类型以及完整性约束。关系型数据库是**强模式 (Strong Schema)** 或 Schema-on-Write 的,数据在写入前必须符合预定义的模式。

6.1.2 完整性与关系 (Integrity & Relationships): * 主键 (Primary Key): 在关系中唯一标识一个元组的一个或一组属性。其值必须是唯一的(Entity Integrity)且非空。 * 外键 (Foreign Key): 一个关系中的属性(或属性组),其值是另一个关系的主键。外键是建立两个关系之间**参照完整性 (Referential Integrity)** 的机制。 * 规范化 (Normalization): * 目标: 最小化数据冗余,避免数据异常(插入异常、更新异常、删除异常)。 * 过程: 通过一系列范式(Normal Forms, 如 1NF, 2NF, 3NF, BCNF)对数据库模式进行分解和优化的过程。 * 权衡: 高度规范化可以最大程度减少冗余,但可能导致查询时需要进行更多的连接操作,影响性能。在实践中,有时会为了性能而进行**反规范化 (Denormalization)**。

6.1.3 查询与操作 (Querying & Operations):

  • SQL (Structured Query Language): 声明式的、事实上的行业标准查询语言。
    • DML (Data Manipulation Language): SELECT, INSERT, UPDATE, DELETE
    • DDL (Data Definition Language): CREATE, ALTER, DROP
    • JOIN 操作: 关系模型的核心操作,用于根据关系(外键)组合来自多个表的数据。常见的 JOIN 类型包括 INNER JOIN, LEFT/RIGHT JOIN, FULL OUTER JOIN。JOIN 是关系型数据库功能强大的体现,但也是主要的性能瓶颈来源,其计算复杂度可能与连接表的笛卡尔积相关。
  • 索引 (Index):
    • 目的: 提高 SELECT 查询的性能,尤其是带有 WHERE 子句的查询,以及 ORDER BY 操作。
    • 底层实现: 通常是 B-Tree 或其变体(如 B+ Tree),这种数据结构特别适合块存储设备(如硬盘)的 I/O 特性。
    • 代价: 索引会占用额外的存储空间,并**降低写操作(INSERT, UPDATE, DELETE)的性能**,因为每次写操作都需要更新相关的索引。因此,索引策略是数据库性能优化的关键,需要在读性能和写性能之间进行权衡。
  • 事务 (Transactions) 与 ACID:
    • 事务: 一组必须作为一个整体、原子性地执行的数据库操作单元。
    • ACID 属性: 关系型数据库对事务处理的核心保证。
      • 原子性 (Atomicity): 事务要么全部成功,要么全部失败回滚。
      • 一致性 (Consistency): 事务使数据库从一个一致的状态转移到另一个一致的状态。
      • 隔离性 (Isolation): 并发执行的事务之间互不干扰,如同串行执行一样。通过锁机制和多版本并发控制(MVCC)实现。
      • 持久性 (Durability): 一旦事务提交,其结果就是永久性的,即使系统崩溃也不会丢失。

[!Note]

这里SQL语法参见


6.2 非关系型模型 (Non-Relational / NoSQL)

NoSQL 是一系列数据库模型的总称,旨在解决关系型模型在某些场景下的局限性,特别是在**大规模 (Scale)、**高性能 (Performance) 和**高可用性 (Availability)** 方面的挑战。

6.2.1 核心设计哲学: * 模式灵活性 (Schema Flexibility): 通常是弱模式或无模式 (Schema-on-Read),允许数据结构动态变化。 * 水平扩展 (Horizontal Scaling / Scale-out): 设计上易于通过增加更多普通服务器来扩展系统能力,而非依赖昂贵的单一高性能服务器(纵向扩展)。 * 性能导向: 通常通过反规范化(数据冗余)来避免昂贵的 JOIN 操作,优化特定应用的读写性能。

6.2.2 主流 NoSQL 模型: * 文档存储 (Document Store) - e.g., MongoDB, Couchbase: * 数据单元: 文档(通常是 JSON/BSON/XML 格式)。 * 特点: 半结构化,适合存储复杂的、有层次结构的对象。数据聚合在一起,一次查询即可获取完整实体。 * 键值存储 (Key-Value Store) - e.g., Redis, Riak, Memcached: * 数据单元: (Key, Value) 对。 * 特点: 模型最简单,本质上是持久化的哈希表。读写性能极高,通常 O(1)。 * 核心用途: 高速缓存、会话管理、实时计数器等。 * 图数据库 (Graph Database) - e.g., Neo4j, JanusGraph: * 数据单元: 节点 (Nodes/Vertices) 和 边 (Edges/Relationships)。节点和边都可以有属性。 * 特点: 专门用于存储和查询实体间的复杂、多对多关系。在进行深度关系遍历(如“朋友的朋友”)时,性能远超关系型数据库。 * 列式存储 (Column-Family Store) - e.g., Apache Cassandra, HBase: * 特点: 数据按列族而非行进行存储。适合大规模数据集的聚合查询和分析(OLAP 场景)。


6.3 分布式系统 (Distributed Systems Concepts)

无论是 SQL 还是 NoSQL,当数据规模和并发量超过单机承载能力时,都必须走向分布式。

  • 复制 (Replication):
    • 目的: 提高可用性 (Availability) 和读取吞吐量。
    • 模式: 主从复制 (Master-Slave)、多主复制 (Multi-Master)。
  • 分片 (Sharding / Partitioning):
    • 目的: 解决单机存储容量和写入性能瓶颈。
    • 策略: 根据分片键(Shard Key)将数据水平切分到不同的节点上。
  • CAP 定理 (CAP Theorem):
    • 一个分布式系统在以下三个特性中,最多只能同时满足两个:
      • 一致性 (Consistency): 所有节点在同一时间看到相同的数据。
      • 可用性 (Availability): 每个请求都能收到一个(非错误)响应。
      • 分区容错性 (Partition Tolerance): 系统在网络分区(节点间通信中断)的情况下仍能继续运行。
    • 实践: 由于网络分区是不可避免的,现代分布式系统必须支持分区容错性。因此,设计者必须在**一致性 (CP)** 和**可用性 (AP)** 之间做出选择。传统关系型数据库倾向于 CP,而许多 NoSQL 系统倾向于 AP。
  • 一致性模型:
    • 强一致性 (Strong Consistency): ACID 模型所追求的。
    • 最终一致性 (Eventual Consistency): BASE 模型(Basically Available, Soft state, Eventually consistent)的核心。系统保证在没有新的更新操作时,所有副本的数据最终会达到一致状态。这是许多高可用 NoSQL 系统的设计基础。

6.4 数据交换格式 (Data Serialization Formats)

用于数据库备份、迁移和系统间通信。

  • SQL Dumps: 关系型数据库的标准,生成包含 DDL 和 DML 语句的 .sql 文件。
  • JSON (JavaScript Object Notation): 轻量级、易于人类阅读和机器解析。已成为 Web API 和 NoSQL 文档存储的事实标准。
  • XML (eXtensible Markup Language): 结构化、可扩展,但较为冗长。在企业级 SOA 和配置文件中仍有应用。
  • CSV (Comma-Separated Values): 简单,通用,适合表格数据的基本交换。

Chapter 7 : Computers

[!important]

本章部分内容数字逻辑设计课程与超算课程已有涉及,不再赘述

7.1 计算机架构 (Architecture)

一台计算机最核心的两个部分是:

  • 内存 (RAM - Random Access Memory):

    • 作用: 用来存放**所有**当前正在运行的程序的**指令**和**数据**。
    • 结构: 它被分成很多个小格子,每个格子叫一个**内存单元 (cell),通常能存一个**字节 (byte) 的数据。每个格子都有一个独一无二的**地址**,就像门牌号。
    • 工作方式: 通过**地址总线 (address bus)** 告诉内存“我要访问哪个门牌号”,然后通过**数据总线 (data bus)** 把数据存进去或取出来。
  • 中央处理器 (CPU - Central Processing Unit):

    • 作用: 这是计算机的“大脑”,负责**执行指令**和**进行计算**。
    • 内部结构: CPU 内部有极少量、但速度飞快的存储单元,叫做**寄存器 (registers)。CPU 所有的计算(加法、比较等)都**只能在寄存器上进行
    • 指令集 (Instruction Set): 每个 CPU 都有一套它能理解的“指令清单”,比如“从内存地址 X 读取数据到寄存器 R1”、“把寄存器 R1 和 R2 的值相加”、“如果寄存器 R3 的值是0,就跳转到指令 Y 去执行”。
    • 工作循环 (Fetch-Execute Cycle): CPU 永远在重复做一件事:
      1. 取指 (Fetch): 根据一个叫**程序计数器 (Program Counter, PC)** 的特殊寄存器里存的地址,去内存里取出下一条指令。
      2. 译码 (Decode): 理解这条指令是要干什么。
      3. 执行 (Execute): 干活。可能是计算,也可能是搬运数据。
      4. 写回 (Write-back): 把结果存回寄存器或内存。
      5. 然后 PC 指向下一条指令,无限循环。

核心关系: CPU 无法直接处理庞大的内存数据。它需要不断地把指令和数据从内存这个“大仓库”搬到寄存器这个“工作台”上进行处理,处理完再放回去。这个“搬运”过程的效率,直接决定了计算机的性能。

7.2 编译器 (Compilers)

我们写的代码(如 Python, Java, C++)叫做**高级语言**,CPU 完全看不懂。CPU 只认识由 0 和 1 组成的**机器码 (machine code)**。

**编译器**就是一个神奇的翻译程序,它的工作就是把你写的高级语言代码,**一次性地**翻译成 CPU 能懂的机器码。

  • 为什么需要编译器?

    • 直接写机器码是反人类的,极其繁琐且容易出错。
    • 高级语言让我们能用更接近人类思维的方式来表达复杂的逻辑。
  • 编译过程发生了什么?

    • x = y + z; 这句简单的高级代码,可能会被编译器翻译成好几条机器指令:
      1. 从内存加载 y 的值到寄存器 R1。
      2. 从内存加载 z 的值到寄存器 R2。
      3. 把 R1 和 R2 的值相加,结果存入 R3。
      4. 把 R3 的值存回内存中 x 的位置。
  • 编译器优化 (Compiler Optimizations): 现代编译器非常智能。它们在翻译的同时,还会想方设法地优化代码,让生成的机器码更高效。比如,它会自动帮你消除不必要的计算,或者重新安排指令顺序来提高执行效率。这也是为什么我们常说“不要进行过早的手动微观优化”,因为编译器可能比你做得更好。

  • 解释器 (Interpreter): 像 Python, JavaScript 这类语言,通常使用**解释器**。解释器是**一边翻译一边执行**的,而不是一次性翻译完。这让开发调试更方便快捷,但运行速度通常比编译型语言慢。

这就是分流面试的题目吧)

7.3 内存层次 (Memory Hierarchy)

CPU 的计算速度和内存的访问速度之间存在巨大的鸿沟,这就是**“处理器-内存性能差距” (Processor-Memory Gap)**。CPU 一秒钟能做几十亿次计算,但去内存取一次数据可能要等上几百个计算周期,大部分时间都在“发呆”。

为了解决这个问题,于是有了**内存层次结构**:

  • 顶层:寄存器 (Registers)
    • 位置: 在 CPU 内部。
    • 速度: 最快,接近光速(1个时钟周期)。
    • 容量: 极小 (KB 级别)。
    • 作用: CPU 的工作台。
  • 第二层:缓存 (Cache - L1, L2, L3)
    • 位置: 集成在 CPU 芯片上或紧挨着 CPU。
    • 速度: 非常快(几十到几百个时钟周期)。
    • 容量: 较小 (MB 级别)。
    • 工作方式: 缓存是一个“小抄”,它会自动把 CPU 最近常用以及其周边的数据,从大而慢的内存中复制一份进来。当 CPU 需要数据时,它会**先看缓存里有没有**,如果有(称为**缓存命中, cache hit**),就直接拿走,速度飞快!如果缓存里没有(称为**缓存未命中, cache miss**),才去慢悠悠的内存里取。
  • 第三层:主内存 (Main Memory / RAM)
    • 位置: 主板上的内存条。
    • 速度: 较慢(几百到上千个时钟周期)。
    • 容量: 较大 (GB 级别)。
    • 作用: 存放所有正在运行的程序和数据。
  • 底层:二级存储 (Secondary Storage - 硬盘/SSD)
    • 位置: 独立的硬盘设备。
    • 速度: 极慢(百万个时钟周期以上)。
    • 容量: 巨大 (TB 级别)。
    • 作用: 永久存储数据和程序。当内存不够用时,操作系统会把内存中不常用的部分临时存到硬盘上(这个过程叫**交换, swapping**),但这会导致性能急剧下降,即**“系统颠簸” (Thrashing)**。

这个和超算讲的差不多哎

Chapter 8 : Programming

核心主题:编程语言的本质、构成与思想范式


**8.1 语言学 (Linguistics) **

任何编程语言都是用于表达计算思想的符号系统,其基本构成要素如下:

  • 值 (Values):

    • 定义: 程序中用来表示和操作信息的实体。是编程语言的“一等公民”(First-Class Citizens),意味着它们可以被创建、作为参数传递、作为函数返回值等。
    • 分类:
      • 原生值 (Primitive Values):integer, float, boolean, string
      • 复合值 (Compound Values): 由其他值构成的结构,如 struct, object, array
  • 表达式 (Expressions):

    • 定义: 任何可以被求值(reduce)并**产生一个值**的代码片段。
    • 构成:
      • 字面量 (Literals): 值的直接表示,如 42, "hello", true
      • 函数调用 (Function Calls):calculate_sum(a, b)
      • 操作符 (Operators): 连接其他表达式构成更复杂的表达式,如 2 * (a + b)
    • 关键特性: 表达式必须有返回值。
  • 语句 (Statements):

    • 定义: 指示计算机**执行一个动作**或改变程序状态的指令。
    • 分类:
      • 简单语句: 如赋值 x = 5,函数调用 print("done")
      • 复合语句/控制流语句:if-else 条件判断、for/while 循环。
      • 定义语句 (Definitions): 创建新的实体(如变量、函数)并为其绑定名称。

**8.2 变量 (Variables) **

  • 定义: 变量是**名称 (Name)** 与**值 (Value)** 所在内存地址的**绑定 (Binding)**。它是程序状态管理的核心机制。

  • 变量类型系统 (Variable Typing):

    • 静态类型 (Static Typing):
      • 特点: 变量类型在**编译时**就已确定且不可更改(如 int count;)。
      • 优点: 编译器可进行早期类型检查,安全性高;利于编译器进行性能优化。
      • 缺点: 编码灵活性较低,较为繁琐。
      • 代表语言: C++, Java, C#, Go。
    • 动态类型 (Dynamic Typing):
      • 特点: 变量类型在**运行时**确定,可随时改变(如 x = 10; x = "hello";)。
      • 优点: 编码快速、灵活,适合快速原型开发。
      • 缺点: 类型错误需在运行时才能发现,依赖充分的测试;存在一定的性能开销。
      • 代表语言: Python, JavaScript, Ruby。
  • 作用域 (Scope) 与命名空间 (Namespace):

    • 作用域: 一个名称绑定(如变量名)在程序中有效的上下文区域。通常分为**全局作用域 (Global Scope)** 和**局部作用域 (Local Scope)**(如函数内部)。
    • 目的: 避免在大型程序中出现**名称冲突 (Name Collision)**。
    • 命名空间: 程序中所有可用的名称的集合。应保持命名空间的**洁净 (clean),避免不必要的全局变量和导入,防止**命名空间污染 (Namespace Pollution)

**8.3 编程范式 (Programming Paradigms) **

编程范式是程序设计的方法论和风格。

8.3.1 命令式编程 (Imperative Programming)
  • 核心思想: 关注“如何做”(How)。通过一系列明确的指令(命令)来逐步修改程序的状态,最终达到目标。
  • 特点: 代码是状态变化的指令序列,与冯·诺依曼计算机架构的底层工作方式(指令序列、内存读写)直接对应。
  • 子范式:
    • 过程式编程 (Procedural): 将代码组织成可复用的**过程 (Procedures)** 或**函数 (Functions)**。这是结构化编程的基础。
    • 面向对象编程 (Object-Oriented, OOP): 将**数据 (Data)** 和操作数据的**方法 (Methods)** 封装在**对象 (Objects)** 中。通过封装、继承、多态来管理复杂性。
8.3.2 声明式编程 (Declarative Programming)
  • 核心思想: 关注“做什么”(What)。只描述期望达成的目标或结果,而将具体的实现步骤交给语言的执行引擎。
  • 特点: 代码可读性高,更接近问题本身的逻辑描述,而非执行步骤。
  • 代表: SQL (SELECT...),HTML (<p>...)。
  • 重要子范式:函数式编程 (Functional Programming, FP)
    • 核心: 将计算视为数学函数的求值,避免状态改变和可变数据。
    • 关键概念:
      • 纯函数 (Pure Functions): 无副作用(不修改外部状态),对于相同的输入总是有相同的输出。
      • 不可变性 (Immutability): 数据一旦创建就不能被修改,任何修改都将产生新的数据副本。
      • 高阶函数 (Higher-Order Functions): 函数可以作为参数或返回值。
        • map: 对集合中每个元素应用一个函数,返回新集合。
        • filter: 根据一个判断函数筛选集合中的元素,返回新集合。
        • reduce: 将集合中的所有元素聚合为一个单一的值。
      • 闭包 (Closure): 函数可以“捕获”并记住其创建时所在的环境(变量)。这使得函数可以携带状态,是实现柯里化(Currying)、延迟求值(Lazy Evaluation)等高级技术的基础。
      • 模式匹配 (Pattern Matching): 允许函数根据输入的结构或值来定义不同的行为,是 if/elseswitch 的更强大、更声明式的替代方案。
8.3.3 逻辑编程 (Logic Programming)
  • 核心思想: 描述“事实与规则”(Facts and Rules)。程序由一系列逻辑断言构成。
  • 执行方式: 程序员定义一个逻辑模型,然后向系统**查询 (Query)。系统使用内置的**逻辑推理引擎(如回溯算法)在解空间中搜索满足查询条件的答案。
  • 代表语言: Prolog。
  • 应用领域: 人工智能、专家系统、自然语言处理、定理证明等。

这部分其实没大看懂……