数据结构和算法

DSA 主页 DSA 概述 DSA 环境设置 DSA 算法基础 DSA 渐近分析

数据结构

DSA 数据结构基础 DSA 数据结构和类型 DSA 数组数据结构

链接列表

DSA 链接列表数据结构 DSA 双向链接列表数据结构 DSA 循环链表数据结构

堆栈 &队列

DSA 堆栈数据结构 DSA 表达式解析 DSA 队列数据结构

搜索算法

DSA 搜索算法 DSA 线性搜索算法 DSA 二分搜索算法 DSA 插值搜索 DSA 跳跃搜索算法 DSA 指数搜索 DSA 斐波那契搜索 DSA 子列表搜索 DSA 哈希表

排序算法

DSA 排序算法 DSA 冒泡排序算法 DSA 插入排序算法 DSA 选择排序算法 DSA 归并排序算法 DSA 希尔排序算法 DSA 堆排序 DSA 桶排序算法 DSA 计数排序算法 DSA 基数排序算法 DSA 快速排序算法

图形数据结构

DSA 图形数据结构 DSA 深度优先遍历 DSA 广度优先遍历 DSA 生成树

树数据结构

DSA 树数据结构 DSA 树遍历 DSA 二叉搜索树 DSA AVL 树 DSA 红黑树 DSA B树 DSA B+ 树 DSA 伸展树 DSA 尝试 DSA 堆数据结构

递归

DSA 递归算法 DSA 使用递归的汉诺塔 DSA 使用递归的斐波那契数列

分而治之

DSA 分而治之 DSA 最大最小问题 DSA 施特拉森矩阵乘法 DSA Karatsuba 算法

贪婪算法

DSA 贪婪算法 DSA 旅行商问题(贪婪方法) DSA Prim 最小生成树 DSA Kruskal 最小生成树 DSA Dijkstra 最短路径算法 DSA 地图着色算法 DSA 分数背包问题 DSA 作业排序截止日期 DSA 最佳合并模式算法

动态规划

DSA 动态规划 DSA 矩阵链乘法 DSA Floyd Warshall 算法 DSA 0-1 背包问题 DSA 最长公共子序列算法 DSA 旅行商问题(动态方法)

近似算法

DSA 近似算法 DSA 顶点覆盖算法 DSA 集合覆盖问题 DSA 旅行商问题(近似方法)

随机算法

DSA 随机算法 DSA 随机快速排序算法 DSA Karger 最小割算法 DSA Fisher-Yates 洗牌算法

DSA 有用资源

DSA 问答 DSA 快速指南


数据结构 - 算法基础


算法是一个循序渐进的过程,它定义了一组按特定顺序执行以获得所需输出的指令。算法通常独立于底层语言创建,即一个算法可以用多种编程语言实现。

从数据结构的角度来看,以下是一些重要的算法类别 −

  • 搜索 − 在数据结构中搜索项目的算法。

  • 排序 −按特定顺序对项目进行排序的算法。

  • 插入 − 在数据结构中插入项目的算法。

  • 更新 − 在数据结构中更新现有项目的算法。

  • 删除 − 从数据结构中删除现有项目的算法。

算法的特征

并非所有过程都可以称为算法。算法应具有以下特征 −

  • 无歧义 − 算法应该清晰明确。其每个步骤(或阶段)及其输入/输出都应该清晰,并且必须只有一个含义。

  • 输入 − 算法应该有0个或多个明确定义的输入。

  • 输出 − 算法应该有1个或多个明确定义的输出,并且应该与期望的输出匹配。

  • 有限性 − 算法必须在有限数量的步骤后终止。

  • 可行性 − 应该在现有资源下可行。

  • 独立性 −算法应该有逐步说明,并且独立于任何编程代码。

如何编写算法?

编写算法没有明确的标准。相反,它取决于具体问题和资源。算法从不是为了支持特定的编程代码而编写的。

众所周知,所有编程语言都共享一些基本的代码结构,例如循环(do、for、while)、流程控制(if-else)等。这些通用结构可用于编写算法。

我们以逐步的方式编写算法,但情况并非总是如此。算法编写是一个过程,是在明确问题域之后执行的。也就是说,我们应该了解我们正在设计解决方案的问题领域。

示例

让我们尝试通过一个例子来学习算法编写。

问题 − 设计一个算法,将两个数字相加并显示结果。

步骤 1 − 开始
步骤 2 − 声明三个整数 a、b 和 c
步骤 3 − 定义 a 和 b 的值
步骤 4 − 将 a 和 b 的值相加
步骤 5 −将步骤 4的输出存储到c
步骤 6 − 打印 c
步骤 7 − 停止

算法告诉程序员如何编写程序。或者,算法可以写成 −

步骤 1 − 开始添加
步骤 2 − 获取 a 和 b 的值
步骤 3 − c ← a + b
步骤 4 − 显示 c
步骤 5 − 停止

在算法设计和分析中,通常使用第二种方法来描述算法。它使分析师能够轻松地分析算法,忽略所有不必要的定义。他可以观察正在使用的操作以及流程的流程。

编写步骤编号是可选的。

我们设计一种算法来获得给定问题的解决方案。一个问题可以通过多种方式解决。

algorithm_analysis

因此,对于给定问题可以推导出许多求解算法。下一步是分析这些提出的求解算法,并实现最合适的解决方案。

算法分析

算法的效率可以在两个不同的阶段进行分析:实施前和实施后。它们如下: −

  • 先验分析 − 这是对算法的理论分析。算法的效率是通过假设所有其他因素(例如处理器速度)保持不变且对实现没有影响来衡量的。

  • 后验分析 − 这是对算法的实证分析。所选算法使用编程语言实现。然后在目标计算机上执行。在此分析中,会收集实际统计数据,例如运行时间和所需空间。

我们将学习先验算法分析。算法分析涉及各种操作的执行或运行时间。操作的运行时间可以定义为每次操作执行的计算机指令数。

算法复杂度

假设X是一种算法,n是输入数据的大小,则算法X所使用的时间和空间是决定其效率的两个主要因素。

  • 时间因素 − 时间是通过计算排序算法中关键操作(例如比较)的数量来衡量的。

  • 空间因素 −空间是通过计算算法所需的最大内存空间来衡量的。

算法的复杂度 f(n) 给出了算法所需的运行时间和/或存储空间,其中 n 是输入数据的大小。

空间复杂度

算法的空间复杂度表示算法在其生命周期内所需的内存空间量。算法所需的空间等于以下两个部分的总和 −

  • 固定部分是指存储某些数据和变量所需的空间,这些数据和变量与问题的大小无关。例如,使用的简单变量和常量、程序大小等。

  • 变量部分是指变量所需的空间,其大小取决于问题的大小。例如,动态内存分配、递归堆栈空间等。

任何算法 P 的空间复杂度 S(P) 都是 S(P) = C + SP(I),其中 C 是算法的固定部分,S(I) 是算法的可变部分,取决于实例特征 I。以下是一个简单的示例,试图解释 − 的概念。

算法:SUM(A, B)
步骤 1 − 开始
步骤 2 − C ← A + B + 10
步骤 3 − 停止

这里我们有三个变量 A、B 和 C 以及一个常量。因此 S(P) = 1 + 3. 现在,空间取决于给定变量和常量类型的数据类型,并且会相应地成倍增加。

时间复杂度

算法的时间复杂度表示算法运行完成所需的时间。时间需求可以定义为数值函数 T(n),其中 T(n) 可以用步数来衡量,前提是每一步都消耗常数时间。

例如,两个 n 位整数的加法需要 n 步。因此,总计算时间为 T(n) = c ∗ n,其中 c 是两位加法所需的时间。这里,我们观察到 T(n) 随着输入大小的增加而线性增长。