正态分布钟形曲线

正态分布:从赌桌到宇宙的完美曲线

引言:钟声隐隐 如果你走进一个 crowded 的教室,测量每个人的身高;或者在同一条件下反复测量一个物理量;又或者在工厂里统计成千上万件产品的尺寸——你会发现,这些数据总是呈现出一种奇特的规律:大部分数值聚集在中间,越往两端越少。 画出分布图,你会看到一条优雅的曲线——中间隆起如钟,两侧缓缓下降,渐近于零却永不触及。这就是正态分布(Normal Distribution),也叫高斯分布(Gaussian Distribution)或钟形曲线(Bell Curve)。 它是概率论中最重要、最自然的分布。从气体分子的运动到股票价格的波动,从人类的身高到测量的误差,正态分布无处不在。 但你是否想过:为什么大自然偏爱这种分布?这条曲线是如何被人类发现的?它背后隐藏着怎样的数学之美? 让我们穿越回17、18世纪,去看看这条曲线是如何在历史的迷雾中逐渐浮现的。 第一章:前史——测量与误差的困惑 伽利略的洞见 早在1632年,伽利略在他的《关于两大世界体系的对话》中就观察到了一个有趣的现象:当你反复测量某个物理量时,误差总是呈现出一种规律——小的误差比大的误差更常见,正误差和负误差出现的频率大致相等。 这是人类对"误差分布"最早的直觉认知之一。伽利略并没有给出数学公式,但他敏锐地察觉到:观测误差并非杂乱无章,而是遵循某种规律。 早期天文学家的困扰 17、18世纪的天文学家面临着一个实际问题:同一颗行星或恒星,不同观测者得到的数据总有微小差异。如何从这些"有误差"的观测值中推断出真实值? 当时流行的方法是取平均值,但没有人能从理论上解释为什么这样做是合理的。一个困扰着那个时代科学家的问题是:是否存在一种"最优"的估计方法? 这些朴素的问题和观察,为正态分布的发现埋下了种子。 第二章:意外发现——棣莫弗与二项分布的极限 正态分布的第一次正式登场,来自一个看似毫不相关的问题:赌博。 亚伯拉罕·棣莫弗 亚伯拉罕·棣莫弗(Abraham de Moivre, 1667-1754)是一位法国-英国数学家。他年轻时因宗教迫害流亡英国,在伦敦靠当家庭教师和赌博顾问维生。 1733年,棣莫弗在研究一个具体问题时做出了一个重大发现:当伯努利试验的次数 $n$ 很大时,二项分布可以用一条光滑的曲线来近似。 这个发现最初只是他一本小册子中的一段内容,后来被收录进1738年出版的《机遇原理》(The Doctrine of Chances)第二版中。 从二项分布到正态曲线 考虑抛硬币的问题:抛 $n$ 次硬币,出现 $k$ 次正面的概率由二项分布给出: $$P(X = k) = \binom{n}{k}p^k(1-p)^{n-k}$$ 当 $n$ 很大时,直接计算这个公式非常困难——阶乘会变得极其巨大。棣莫弗想知道:能否找到一个近似公式? 通过巧妙的数学技巧(斯特林公式的早期版本),棣莫弗发现:当 $n \to \infty$ 时,标准化的二项分布收敛到: $$f(x) = \frac{1}{\sqrt{2\pi}}e^{-x^2/2}$$ 这就是标准正态分布的概率密度函数! 图1:棣莫弗-拉普拉斯极限定理。当二项分布的试验次数 $n$ 增大时,标准化后的分布逐渐逼近标准正态分布(红色曲线)。 历史的遗憾 有趣的是,棣莫弗并不知道自己发现了一个"普适"的分布。他只是把它当作计算二项分布的一个实用技巧。他的工作也没有引起当时学术界的广泛关注。 直到多年后,这条曲线才被拉普拉斯和高斯重新发掘,并赋予其更深刻的意义。 flowchart LR A["1632伽利略观测误差规律"] --> B["1733棣莫弗二项分布极限"] B --> C["1809高斯误差理论"] C --> D["1810拉普拉斯中心极限定理"] D --> E["1860麦克斯韦对称性推导"] style A fill:#FF9500,color:#fff,stroke-width:2px style B fill:#FF9500,color:#fff,stroke-width:2px style C fill:#007AFF,color:#fff,stroke-width:3px style D fill:#34C759,color:#fff,stroke-width:2px style E fill:#34C759,color:#fff,stroke-width:2px 第三章:高斯的革命——误差理论与最小二乘法 正态分布真正成为概率论的核心,要归功于卡尔·弗里德里希·高斯(Carl Friedrich Gauss, 1777-1855)。 ...

January 21, 2026 · 3 min · 520 words · s-ai-unix
信息熵与通信理论

香农信息熵:不确定性的数学刻度

引言:一条电报引发的思考 信息是什么? 1844年5月24日,萨缪尔·摩斯(Samuel Morse)从华盛顿向巴尔的摩发出了人类历史上第一条电报: “What hath God wrought!” 这四个单词穿越了64公里的铜线,开启了电信时代。但在庆祝之余,一个问题逐渐浮现:这条消息究竟包含了多少"信息"? 这个问题看似简单,实则深奥。“信息"是一个抽象的概念,如何用数学来量化它?一封情书和一份天气预报,哪一份包含更多"信息”?一条加密后的消息和原始消息,信息量是否相同? 这些问题的答案,隐藏在一位贝尔实验室工程师的伟大发现中。 香农的登场 1948年,克劳德·香农(Claude Shannon)发表了题为《通信的数学理论》的论文。这篇32页的论文,被誉为"数字时代的创世大宪章"。 在论文中,香农给出了"信息"的精确定义,并引入了一个核心概念——信息熵。这个名字借用了热力学中的"熵",暗示了两者之间深刻的联系。 本文将带你踏上一段历史与数学交织的旅程,从电报时代的实际问题出发,逐步揭示信息熵的诞生、内涵及其深远影响。 第一章:信息时代的黎明——通信效率的困惑 1.1 摩斯电码中的智慧 在香农之前,通信工程师们已经面临着一个实际问题:如何用最少的符号传输最多的信息? 摩斯电码给出了一个直观的答案。观察摩斯电码的设计: E: . (最常用) T: - (第二常用) A: .- Q: --.- (很少使用) Z: --.. 摩斯天才地意识到:常用的字母应该用较短的编码,不常用的字母可以用较长的编码。这个设计原则在今天看来理所当然,但在当时是革命性的。 但这引发了更深层的思考:如何精确衡量一个字母的"常用程度"?如何计算整个编码系统的效率?这些问题需要数学语言的精确描述。 1.2 电报的经济学问题 19世纪的电报按字收费,一条消息的成本与其长度直接相关。因此,压缩信息不仅是技术问题,更是经济问题。 工程师们开始思考: 如果我们能知道每个字母出现的概率,能否设计出最优的编码? 通信线路的"容量"有没有理论极限? 噪声(干扰)对信息传输的影响有多大? 这些问题的答案,要等到20世纪才逐渐浮现。 flowchart LR subgraph A["19世纪通信挑战"] A1["摩斯电码1837"] A2["电报经济学按长度收费"] end subgraph B["20世纪理论突破"] B1["奈奎斯特1924"] B2["哈特利1928"] B3["香农1948"] end subgraph C["现代信息时代"] C1["数字通信"] C2["数据压缩"] C3["机器学习"] end A1 --> B1 A2 --> B2 B1 --> B3 B2 --> B3 B3 --> C1 B3 --> C2 B3 --> C3 style A1 fill:#34C759,color:#ffffff,stroke-width:2px style A2 fill:#34C759,color:#ffffff,stroke-width:2px style B1 fill:#007AFF,color:#ffffff,stroke-width:2px style B2 fill:#007AFF,color:#ffffff,stroke-width:2px style B3 fill:#007AFF,color:#ffffff,stroke-width:3px style C1 fill:#34C759,color:#ffffff,stroke-width:2px style C2 fill:#34C759,color:#ffffff,stroke-width:2px style C3 fill:#34C759,color:#ffffff,stroke-width:2px 第二章:先驱的脚步——奈奎斯特与哈特利 2.1 奈奎斯特的发现 1924年,贝尔实验室的哈里·奈奎斯特(Harry Nyquist)在研究电报传输时,做出了一个重要发现。 ...

January 21, 2026 · 5 min · 891 words · s-ai-unix
感知机发展历程

感知机的完整发展历程:从线性分类到深度学习的基石

引言:人工智能的原点 在人工智能的发展历程中,感知机(Perceptron)是一个具有里程碑意义的概念。它不仅是最早的机器学习算法之一,也是现代深度学习和神经网络的基础。 感知机的故事开始于 20 世纪中叶,当时计算机科学刚刚萌芽,科学家们开始探索如何让机器具备"学习"的能力。 第一章:感知机的诞生背景 1.1 早期人工智能研究的梦想 20 世纪 40 年代末到 50 年代初,随着计算机的诞生,科学家们开始思考:机器能否像人一样思考和学习? 图灵测试:1950 年,艾伦·图灵提出了著名的图灵测试,为人工智能的发展奠定了理论基础。 神经网络的早期构想:1943 年,麦卡洛克和皮茨提出了第一个人工神经网络模型,称为麦卡洛克-皮茨神经元。 1.2 罗森布拉特的突破 1957 年,美国心理学家弗兰克·罗森布拉特(Frank Rosenblatt)在康奈尔航空实验室提出了感知机模型。他将感知机描述为"能够通过经验自动学习的机器"。 罗森布拉特的工作受到了神经科学的启发,他试图模拟人类大脑中神经元的工作方式。 第二章:感知机的核心原理 2.1 感知机的基本结构 感知机是一个简单的线性分类器,它的结构非常简单: graph TD A[输入] --> B[权重] C[偏置] --> D[求和] B --> D D --> E[激活函数] E --> F[输出] style A color:#ffffff,fill:#007AFF,stroke:#007AFF,stroke-width:3px style B color:#ffffff,fill:#34C759,stroke:#34C759,stroke-width:2px style C color:#ffffff,fill:#34C759,stroke:#34C759,stroke-width:2px style D color:#ffffff,fill:#007AFF,stroke:#007AFF,stroke-width:3px style E color:#ffffff,fill:#007AFF,stroke:#007AFF,stroke-width:3px style F color:#ffffff,fill:#007AFF,stroke:#007AFF,stroke-width:3px 2.2 感知机的工作原理 感知机的工作原理可以用以下公式表示: ...

January 21, 2026 · 4 min · 749 words · s-ai-unix
狄拉克方程的数学之美

狄拉克方程:相对论量子力学的诞生

引言:1928年的物理学困境 1928年的秋天,剑桥大学。一位26岁的年轻物理学家保罗·狄拉克(Paul Dirac)正面临着物理学界最根本的问题之一:如何将量子力学与狭义相对论统一起来? 当时的物理学界似乎被分裂成两个不相容的世界。一边是薛定谔方程,它在描述原子中的电子行为时取得了巨大成功,但只在低速情况下有效;另一边是爱因斯坦的狭义相对论,它精确地描述了高速运动物体的行为。问题是——这两个理论在数学结构上似乎根本无法协调。 让我们从这个困境出发,一步步理解狄拉克是如何通过数学的纯粹美感,找到了连接这两个世界的桥梁。 第一章:薛定谔方程的困境 1.1 非相对论量子力学的成功 1926年,奥地利物理学家埃尔温·薛定谔提出了著名的波动方程: $$ i\hbar\frac{\partial}{\partial t}\psi(\mathbf{r},t) = \hat{H}\psi(\mathbf{r},t) $$ 对于自由粒子(没有外力作用),哈密顿量是: $$ \hat{H} = \frac{\hat{\mathbf{p}}^2}{2m} = -\frac{\hbar^2}{2m}\nabla^2 $$ 这个方程在描述氢原子等低速系统时非常成功。它精确地预言了氢原子的能级,解释了原子光谱的规律。但是,如果你仔细观察这个方程的数学结构,会发现一个根本性的不对称性: 时间导数是一阶的: $\frac{\partial}{\partial t}$ 空间导数是二阶的: $\nabla^2 = \frac{\partial^2}{\partial x^2} + \frac{\partial^2}{\partial y^2} + \frac{\partial^2}{\partial z^2}$ 这种不对称性意味着这个方程在洛伦兹变换下不会保持不变——换句话说,它不符合狭义相对论。 graph LR A[薛定谔方程非相对论量子力学] --> B[时间导数: 一阶空间导数: 二阶] B --> C[洛伦兹协变性破缺不符合狭义相对论] style A fill:#FF9500,stroke:#FF9500,stroke-width:2px,color:#ffffff style B fill:#AF52DE,stroke:#AF52DE,stroke-width:2px,color:#ffffff style C fill:#FF3B30,stroke:#FF3B30,stroke-width:3px,color:#ffffff 1.2 相对论的能量-动量关系 在狭义相对论中,自由粒子的能量和动量满足一个简单而优雅的关系: ...

January 20, 2026 · 7 min · 1485 words · s-ai-unix
神经网络连接

基于神经网络的深度学习算法:从感知机到Transformer的完整指南

引言:从生物启发到智能革命 1943年,Warren McCulloch和Walter Pitts提出了第一个神经元数学模型。他们用一个简单的数学公式模拟了生物神经元的工作方式:接收输入、加权求和、激活输出。这个看似简单的想法,却孕育了后来改变世界的人工智能技术。 1958年,Frank Rosenblatt发明了感知机(Perceptron),这是第一个可以学习的神经网络。但1969年,Minsky和Papert在《Perceptrons》一书中证明了单层感知机无法解决异或(XOR)问题,这个致命缺陷导致了神经网络研究的第一次寒冬。 1986年,David Rumelhart、Geoffrey Hinton和Ronald Williams重新发现了反向传播算法,解决了多层网络的训练问题。神经网络迎来了短暂的春天。 但在90年代到2000年代初,支持向量机(SVM)等传统机器学习算法统治了学术界。神经网络因为数据量不足、计算能力有限、缺乏有效的训练技巧,再次陷入沉寂。 2012年,ImageNet竞赛上,Hinton的学生Alex Krizhevsky使用深度卷积神经网络AlexNet,以压倒性优势击败了传统方法,分类错误率从26%降低到15.3%。这一年,深度学习时代正式开启。 从此,深度学习以惊人的速度发展:2014年的VGG、GoogLeNet,2015年的ResNet解决深度退化问题,2017年的Transformer彻底改变自然语言处理,2022年的ChatGPT让全世界见识到大模型的力量。 本文将从数学原理出发,系统讲解深度学习的核心算法:从基础神经网络到卷积神经网络(CNN),从循环神经网络(RNN)到Transformer,最后探讨未来发展趋势。 第一章:神经网络的数学基础 1.1 单神经元:感知机的数学模型 1.1.1 前向传播 感知机是最基础的神经网络单元,模拟生物神经元的工作原理。给定输入向量 $x \in \mathbb{R}^d$,权重向量 $w \in \mathbb{R}^d$,偏置 $b \in \mathbb{R}$: $$z = w^Tx + b = \sum_{i=1}^d w_i x_i + b$$ 激活函数 $\sigma(z)$ 决定神经元的输出: $$a = \sigma(z)$$ 1.1.2 常用激活函数 Sigmoid函数: $$\sigma(z) = \frac{1}{1 + e^{-z}}$$ 导数: $$\sigma’(z) = \sigma(z)(1 - \sigma(z))$$ 性质: 输出范围:$(0, 1)$ S型曲线,可微 缺点:梯度消失($| \sigma’(z) | \leq 0.25$),输出不以零为中心 Tanh函数: $$\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}$$ ...

January 14, 2026 · 11 min · 2188 words · s-ai-unix
抽象几何图形

传统机器学习与统计学习算法:从理论到实践的完整指南

引言:从统计学到机器学习 1956年,达特茅斯会议上正式提出了"人工智能"这个词。但在那之前的一百年里,统计学家们已经在用数学工具从数据中提取规律。高斯在1809年就用最小二乘法解决了天文学中的观测数据拟合问题,这可以看作是最早的机器学习算法。 机器学习和统计学习,本质上是一回事:从数据中学习规律,并用这些规律做出预测。只是出发点略有不同——统计学家关注估计的可靠性和显著性检验,而计算机科学家更关心算法的计算效率和泛化能力。 当我们说"传统机器学习"时,指的是深度学习时代之前的那些经典算法。这些算法虽然不像神经网络那样"万能",但在数据量有限、需要可解释性的场景下,依然发挥着不可替代的作用。 第一章:统计学习的理论基础 1.1 学习问题的数学框架 假设我们有一个数据集 $D = {(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)}$,其中 $x_i \in \mathcal{X}$ 是输入(特征),$y_i \in \mathcal{Y}$ 是输出(标签)。我们的目标是找到一个函数 $f: \mathcal{X} \to \mathcal{Y}$,使得对于新的输入 $x$,$f(x)$ 能准确预测对应的 $y$。 但在统计学习的框架下,我们还需要引入概率论的概念。假设数据是按照某个未知的联合分布 $P(X,Y)$ 生成的,我们的目标是学习一个决策函数 $f$,使得期望风险最小化: $$R(f) = \mathbb{E}_{(X,Y) \sim P}[L(Y, f(X))]$$ 其中 $L$ 是损失函数。对于回归问题,常用平方损失;对于分类问题,常用0-1损失或交叉熵损失。 问题在于:我们不知道 $P(X,Y)$,无法直接计算 $R(f)$。我们只能用经验风险(Empirical Risk)来近似: $$\hat{R}(f) = \frac{1}{n}\sum_{i=1}^n L(y_i, f(x_i))$$ 这就是经验风险最小化(ERM)的基本思想。但直接最小化经验风险会导致过拟合(overfitting)。 1.2 偏差-方差权衡 这是统计学习中最重要的概念之一。模型的预测误差可以分解为三个部分: $$\mathbb{E}[(y - \hat{f}(x))^2] = \text{Bias}[\hat{f}(x)]^2 + \text{Var}[\hat{f}(x)] + \sigma^2$$ 其中: $\text{Bias}[\hat{f}(x)] = \mathbb{E}[\hat{f}(x)] - f^{\ast}(x)$:模型预测的期望与真实值的差距 $\text{Var}[\hat{f}(x)] = \mathbb{E}[(\hat{f}(x) - \mathbb{E}[\hat{f}(x)])^2]$:模型预测的方差 $\sigma^2$:不可约误差(数据本身的噪声) 偏差反映了模型的"假设强度"。如果模型过于简单(比如用线性模型拟合高度非线性的数据),会产生高偏差,导致欠拟合。 ...

January 14, 2026 · 11 min · 2161 words · s-ai-unix
ISO 26262 指南

ISO 26262-10 指南:标准实施的实践指南

引言 ISO 26262 标准提供了完整的汽车功能安全要求,但在实际应用中,如何正确理解和应用这些要求是一个挑战。ISO 26262-10 指南部分正是为了解决这个问题而设计的,它提供了详细的解释、示例和最佳实践。 想象一个真实场景:某汽车电子公司的工程师在实施 ASIL D 项目时,对于如何确定硬件架构指标(SPFM、LFM)存在困惑。不同的工程师有不同的理解,导致项目进展缓慢。 这个案例告诉我们:**需要详细的指南和示例来帮助正确理解和应用 ISO 26262 标准。**这正是 ISO 26262-10 指南部分的核心使命。 指南的结构和内容 指南的目的 ISO 26262-10 的主要目的是: 解释标准要求:详细解释 ISO 26262 各部分的要求 提供示例:提供实际应用的示例 分享最佳实践:分享行业最佳实践 解决常见问题:解决常见的问题和困惑 指南的内容 ISO 26262-10 包含以下内容: 概念阶段的指南 危害分析(HARA)的示例 ASIL 确定的示例 功能安全概念的示例 系统级开发的指南 系统架构设计的示例 技术 安全概念的示例 系统集成和测试的示例 硬件级开发的指南 硬件架构设计的示例 FMEDA 分析的示例 硬件架构指标计算的示例 软件级开发的指南 软件架构设计的示例 软件单元测试的示例 软件集成和测试的示例 生产和运行的指南 生产一致性的示例 服务和维护的示例 支持过程的指南 配置管理的示例 文档管理的示例 工具置信度评估的示例 ASIL 导向分析的指南 FMEA 的示例 FTA 的示例 STPA 的示例 概念阶段的指南 危害分析(HARA)的示例 示例 1:制动系统的 HARA 系统功能:电子液压制动系统(EHB) ...

January 4, 2026 · 8 min · 1596 words · s-ai-unix
ISO 26262 功能安全整体框架

ISO 26262 整体综述:汽车功能安全的完整体系

引言 在汽车电子化、智能化迅猛发展的今天,一辆现代汽车可能包含上百个电子控制单元(ECU),数千行软件代码,以及复杂的传感器和执行器网络。当这些系统失效时,后果可能是灾难性的。这就是为什么 ISO 26262——道路车辆功能安全标准——成为汽车行业的圣经。 ISO 26262 不是一本简单的操作手册,而是一个完整的体系,包含 12 个相互关联的标准文件。这 12 个文件就像乐高积木,每个都有其特定的功能和位置,只有将它们正确地组合在一起,才能构建出功能安全的汽车电子系统。 在本系列文章中,我们已经深入解读了 ISO 26262 的每一个部分。在本文中,我们将从整体视角审视这个标准,理解它们如何协同工作,形成一个完整的汽车功能安全体系。 ISO 26262 的诞生与演进 为什么需要功能安全标准? 在 ISO 26262 诞生之前,汽车行业使用的是 IEC 61508——通用的功能安全标准。然而,汽车电子有其特殊性: 安全性要求高:汽车故障可能导致人员伤亡 成本敏感:汽车是大宗消费品,必须控制成本 供应链复杂:涉及 OEM、Tier 1、Tier 2、半导体供应商等多方 使用环境苛刻:温度、湿度、振动、电磁干扰等 因此,ISO 于 2011 年发布了专门针对道路车辆的 ISO 26262 标准,并于 2018 年进行了全面更新(第二版)。 标准的总体目标 ISO 26262 的核心目标可以用一句话概括: 确保电子电气系统在发生故障时,不会导致不合理的安全风险 这个目标分解为三个关键要素: 预防性开发:通过系统化的开发过程,预防系统性故障 故障控制:通过安全机制,检测和控制随机硬件故障 全生命周期管理:从概念到报废的全程安全管理 与 IEC 61508 的关系 ISO 26262 是 IEC 61508 在汽车领域的应用和裁剪,两者关系如下: 特性 IEC 61508 ISO 26262 应用领域 所有行业 道路车辆 SIL 等级 SIL 1-4 ASIL A-D (汽车) / MSIL (摩托车) 特化程度 通用 汽车特定 复杂度 高 中等(更易理解) ISO 26262 的 12 个部分:全景图 ISO 26262 分为 12 个部分,每个部分都有其特定的职责和范围: ...

January 1, 2026 · 8 min · 1498 words · s-ai-unix
数据结构与算法

数据结构实现系列:线性表、链表与栈的完整实现

数据结构是计算机科学的基础,掌握各种数据结构的实现原理对于编写高效程序至关重要。本文将详细介绍线性表、链表、栈等基础数据结构的实现方法。 一、线性表的顺序存储实现 线性表是最基本的数据结构之一,其顺序存储方式使用连续的内存空间来存储数据元素。 1.1 使用指针实现 #include "stdio.h" #include "stdlib.h" #include "math.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 20 typedef int Status; typedef int ElemType; /* 定义顺序表结构 */ typedef struct { ElemType data[MAXSIZE]; int length; } SqList; /* 初始化顺序表 */ Status InitList(SqList *L) { L->length = 0; return OK; } /* 判断顺序表是否为空 */ Status ListEmpty(SqList L) { if(L.length == 0) return TRUE; else return FALSE; } /* 清空顺序表 */ Status ClearList(SqList *L) { L->length = 0; return OK; } /* 获取顺序表长度 */ int ListLength(SqList L) { return L.length; } /* 获取第i个元素 */ Status GetElem(SqList L, int i, ElemType *e) { if(L.length == 0 || i < 1 || i > L.length) return ERROR; *e = L.data[i-1]; return OK; } /* 查找元素e的位置 */ int LocateElem(SqList L, ElemType e) { int i; if (L.length == 0) return 0; for(i = 0; i < L.length; i++) { if (L.data[i] == e) break; } if(i >= L.length) return 0; return i + 1; } /* 在第i个位置插入元素e */ Status ListInsert(SqList *L, int i, ElemType e) { int k; if (L->length == MAXSIZE) return ERROR; if (i < 1 || i > L->length + 1) return ERROR; if (i <= L->length) { for(k = L->length - 1; k >= i - 1; k--) L->data[k+1] = L->data[k]; } L->data[i-1] = e; L->length++; return OK; } /* 删除第i个元素 */ Status ListDelete(SqList *L, int i, ElemType *e) { int k; if (L->length == 0) return ERROR; if (i < 1 || i > L->length) return ERROR; *e = L->data[i-1]; if (i < L->length) { for(k = i; k < L->length; k++) L->data[k-1] = L->data[k]; } L->length--; return OK; } /* 遍历顺序表 */ Status ListTraverse(SqList L) { int i; for(i = 0; i < L.length; i++) printf("%d ", L.data[i]); printf("\n"); return OK; } 1.2 使用C++引用实现 #include <stdio.h> #include <stdlib.h> #define MaxSize 50 typedef char ElemType; typedef struct { ElemType data[MaxSize]; int length; } SqList; /* 创建顺序表 */ void CreateList(SqList *&L, ElemType a[], int n) { int i; L = (SqList *)malloc(sizeof(SqList)); for (i = 0; i < n; i++) L->data[i] = a[i]; L->length = n; } /* 初始化顺序表 */ void InitList(SqList *&L) { L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } /* 销毁顺序表 */ void DestroyList(SqList *&L) { free(L); } /* 判断是否为空 */ int ListEmpty(SqList *L) { return(L->length == 0); } /* 获取长度 */ int ListLength(SqList *L) { return(L->length); } /* 显示顺序表 */ void DispList(SqList *L) { int i; if (ListEmpty(L)) return; for (i = 0; i < L->length; i++) printf("%c ", L->data[i]); printf("\n"); } /* 获取第i个元素 */ int GetElem(SqList *L, int i, ElemType &e) { if (i < 1 || i > L->length) return 0; e = L->data[i-1]; return 1; } /* 查找元素 */ int LocateElem(SqList *L, ElemType e) { int i = 0; while (i < L->length && L->data[i] != e) i++; if (i >= L->length) return 0; else return i + 1; } /* 插入元素 */ int ListInsert(SqList *&L, int i, ElemType e) { int j; if (i < 1 || i > L->length + 1) return 0; i--; for (j = L->length; j > i; j--) L->data[j] = L->data[j-1]; L->data[i] = e; L->length++; return 1; } /* 删除元素 */ int ListDelete(SqList *&L, int i, ElemType &e) { int j; if (i < 1 || i > L->length) return 0; i--; e = L->data[i]; for (j = i; j < L->length - 1; j++) L->data[j] = L->data[j+1]; L->length--; return 1; } 关键区别: ...

August 19, 2014 · 9 min · 1792 words · s-ai-unix
Perl代码编辑器

Perl基础与核心概念详解

Perl是一种功能强大的文本处理语言,以其灵活性和表达能力著称。本文将详细介绍Perl的核心概念和基础知识。 变量作用域:my、our和local Perl提供了三种变量声明方式,它们各有不同的作用域规则。 my - 词法作用域变量 my声明的是词法变量,其作用域限于当前的代码块。 my $var = 1; { my $var = 2; print "$var\n"; # 输出: 2 } print "$var\n"; # 输出: 1 our - 包全局变量 our声明的是包全局变量,即使在不同的代码块中也保持相同的值。 our $var = 1; { our $var = 2; print "$var\n"; # 输出: 2 } print "$var\n"; # 输出: 2 混合使用示例 当my和our混合使用时,my变量会优先: our $var = 1; { my $var = 2; print "$var\n"; # 输出: 2(my优先) } print "$var\n"; # 输出: 1(our的值) 列表操作符 Perl提供了丰富的列表操作符,这些是Perl编程的核心工具。 grep - 列表过滤 grep操作符用于过滤列表,返回满足条件的元素。 # 获取1-1000中的所有奇数 my @odd_numbers = grep { $_ % 2 } 1..1000; # 匹配包含"fred"的行(不区分大小写) my @matching_lines = grep { /\bfred\b/i } <$fh>; # 在标量上下文中获取匹配数量 my $line_count = grep /\bfred\b/i, <$fh>; grep的工作原理: 将列表中的每个元素依次放入$_变量 在标量上下文中评估测试条件 如果结果为真,将该元素加入输出列表 map - 列表转换 map操作符用于转换列表中的每个元素。 # 格式化货币数据 my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95); my @formatted_data = map { big_money($_) } @data; # 直接打印格式化结果 print "The money numbers are:\n", map { sprintf("%25s\n", $_) } @formatted_data; # 输出2的幂次 print "Some powers of two are:\n", map "\t" . ( 2 ** $_ ) . "\n", 0..15; 其他列表操作符 # 排序 my @castaways = sort qw(Gilligan Skipper Ginger Professor Mary-Ann); # 反序 my @reversed = reverse qw(Gilligan Skipper Ginger Professor Mary-Ann); 循环控制 标签循环 Perl允许为循环添加标签,从而在内层循环中控制外层循环。 ...

June 6, 2014 · 3 min · 503 words · s-ai-unix