数据结构和算法 - 前置扫盲

news2024/12/23 10:42:46

数据结构和算法

一、前置扫盲

1、数据结构分类

1.1 逻辑结构:线性与非线性

tip:逻辑结构揭示了数据元素之间的逻辑关系

  • 线性数据结构:元素间存在明确的顺序关系。

    1. 数据按照一定顺序排列,其中元素之间存在一个对应关系,使得它们按照线性顺序排列。
    2. 每个元素都有且仅有一个前驱元素和一个后继元素,除了第一个和最后一个元素外。
    3. 代表:数组、链表、栈、队列、哈希表。
  • 非线性数据结构:元素不是按照序列排列的

    • 元素之间存在多对多的关系,其组织方式不受固定顺序的限制。
    • 非线性数据结构中的元素不是按照序列排列的。
    • 代表:树、堆、图、哈希表。

图例

在这里插入图片描述

1.2 物理结构:顺序与链式

tip:所有数据结构都是基于数组、链表或二者的组合实现的

  • 连续空间存储(顺序)
    1. 特点:数据元素存储在物理空间上是连续的,通过元素的物理地址和相对位置来访问数据。
    2. 优缺点:
      • 优点: 随机访问速度快,存储效率高。
      • 缺点: 插入和删除操作可能涉及大量数据的移动,且需要预先分配连续的内存空间。
    3. 代表:基于数组可实现:栈、队列、哈希表、树、堆、图、矩阵、张量(维度 ≥3 的数组)等。
  • 分散空间存储(链式)
    1. 特点:数据元素存储在物理空间上是分散的,通过指针来连接各个元素。
    2. 优缺点:
      • 优点: 插入和删除操作相对容易,不需要连续的内存空间。
      • 缺点: 不支持快速的随机访问,需要遍历才能找到特定位置的元素。
    3. 代表:基于链表可实现:栈、队列、哈希表、树、堆、图等。

图例

在这里插入图片描述

2、算法效率评估

tip:算法的效率主要评估的是时间和空间,名词称为-时间复杂度和空间复杂度,但是不是统计具体的算法运行时间和使用空间,而是统计算法运行时间和使用空间随着数据量变大时的增长趋势,使用大O计数法表示

2.1 时间复杂度

例子:下列一段代码,分别使用两种方式统计时间复杂度。

void algorithm(int n) {
    int a = 2;  
    a = a + 1;  
    a = a * 2;  
    for (int i = 0; i < n; i++) {  
        System.out.println(0);     
    }
}
2.1.1 统计具体时间
  1. 确定运行平台,包括硬件配置、编程语言、系统环境等,这些因素都会影响代码的运行效率。
  2. 评估各种计算操作所需的运行时间,假如加法操作 + 需要 1 ns ,乘法操作 * 需要 10 ns ,打印操作 print() 需要 5 ns 等。
  3. 统计代码中所有的计算操作,并将所有操作的执行时间求和,从而得到运行时间。
// 在某运行平台下
void algorithm(int n) {
    int a = 2;  // 1 ns
    a = a + 1;  // 1 ns
    a = a * 2;  // 10 ns
    // 循环 n 次
    for (int i = 0; i < n; i++) {  // 1 ns ,每轮都要执行 i++
        System.out.println(0);     // 5 ns
    }
}

根据以上方法,可以得到算法的运行时间为 (6n+12) ns

统计算法的运行时间既不合理也不现实

  1. 预估时间和运行平台绑定,因为算法需要在各种不同的平台上运行。
  2. 很难获知每种操作的运行时间,这给预估过程带来了极大的难度。
2.1.2 统计增长趋势

“时间增长趋势(是算法运行时间随着数据量变大时的增长趋势)”这个概念比较抽象,我们通过一个例子来加以理解。假设输入数据大小为 n ,给定三个算法 ABC

// 算法 A 的时间复杂度:常数阶
void algorithm_A(int n) {
    System.out.println(0);
}
// 算法 B 的时间复杂度:线性阶
void algorithm_B(int n) {
    for (int i = 0; i < n; i++) {
        System.out.println(0);
    }
}
// 算法 C 的时间复杂度:常数阶
void algorithm_C(int n) {
    for (int i = 0; i < 1000000; i++) {
        System.out.println(0);
    }
}

在这里插入图片描述

  • 算法 A 只有 1 个打印操作,算法运行时间不随着 n增大而增长。我们称此算法的时间复杂度为“常数阶”。
  • 算法 B 中的打印操作需要循环 n 次,算法运行时间随着 n 增大呈线性增长。此算法的时间复杂度被称为“线性阶”。
  • 算法 C 中的打印操作需要循环 1000000 次,虽然运行时间很长,但它与输入数据大小n 无关。因此 C 的时间复杂度和 A 相同,仍为“常数阶

相较于直接统计算法的运行时间,时间复杂度的特点

  • 时间复杂度能够有效评估算法效率。例如,算法 B 的运行时间呈线性增长,在 n>1 时比算法 A 更慢,在n>1000000时比算法 C 更慢。事实上,只要输入数据大小 n 足够大,复杂度为“常数阶”的算法一定优于“线性阶”的算法,这正是时间增长趋势的含义。
  • 时间复杂度的推算方法更简便。显然,运行平台和计算操作类型都与算法运行时间的增长趋势无关。因此在时间复杂度分析中,我们可以简单地将所有计算操作的执行时间视为相同的“单位时间”,从而将“计算操作运行时间统计”简化为“计算操作数量统计”,这样一来估算难度就大大降低了。
  • 时间复杂度也存在一定的局限性。例如,尽管算法 AC 的时间复杂度相同,但实际运行时间差别很大。同样,尽管算法 B 的时间复杂度比 C 高,但在输入数据大小 n 较小时,算法 B 明显优于算法 C 。在这些情况下,我们很难仅凭时间复杂度判断算法效率的高低。当然,尽管存在上述问题,复杂度分析仍然是评判算法效率最有效且常用的方法。

具体计算方式:使用函数T(n)演变为O(n)表示。

void algorithm(int n) {//每次调用函数执行的次数
    int a = 1;  // +1
    a = a + 1;  // +1
    a = a * 2;  // +1
    // 循环 n 次
    for (int i = 0; i < n; i++) { // +1(每轮都执行 i ++)
        System.out.println(0);    // +1
    }
}

设算法的操作数量是一个关于输入数据大小 n 的函数,记为T(n),则以上函数的操作数量为
T ( n ) = 3 + 2 n T(n)=3+2n T(n)=3+2n
T(n)是一次函数,说明其运行时间的增长趋势是线性的,因此它的时间复杂度是线性阶,我们将线性阶的时间复杂度记为O(n),这个数学符号称为「大O记号big-O notationJ,表示函数T(n)的「渐近上界asymptotic upper bound」。

  • 代码的时间复杂度:线性阶时间复杂度
  • 函数表示:T(n)=3+2n
  • 线性阶表示:O(3+2n)
    • 输入的n不受控制,可以为任意数,而时间复杂度是很难计算准确的,所以统计的为最差情况的时间复杂度。
    • 假如输入n的数趋近于∞(无穷),那么常数3可以忽略,同理系数2也可以忽略,无穷和2倍无穷不还是无穷吗
    • 所以最终时间复杂度表示为:O(n)

总结:

计数简化技巧:

  1. 忽略T(n) 中的常数项。因为它们都与 n 无关,所以对时间复杂度不产生影响。
  2. 省略所有系数。例如,循环 2n 次、5n+1 次等,都可以简化记为 n 次,因为 n前面的系数对时间复杂度没有影响。
  3. 循环嵌套时使用乘法。总操作数量等于外层循环和内层循环操作数量之积,每一层循环依然可以分别套用第 1. 点和第 2. 点的技巧。
  4. 最差情况判断:当输入数最差情况为n,趋近于无穷大时,最高阶的项将发挥主导作用,其他项的影响都可以忽略。
void algorithm(int n) {
    int a = 1;  // +1
    a = a + n;  // +1
    // +5n
    for (int i = 0; i < 5 * n + 1; i++) {
        System.out.println(0);
    }
    // +2n
    for (int i = 0; i < 2 * n; i++) {
        //加n+1
        for (int j = 0; j < n + 1; j++) {
            System.out.println(0);
        }
    }
}

函数表示: T ( n ) = 2 + 5 n + 2 n ( n + 1 ) = 2 n 2 + 7 n + 3 函数表示:T(n)=2+5n+2n(n+1)=2n^2+7n+3 函数表示:T(n)=2+5n+2n(n+1)=2n2+7n+3

大 O 计数法表示: O ( n 2 ) − − − 当 n − > ∞ , n 2 为主导,除去常数、系数、非主导项,使用 大O计数法表示:O(n^2)---当n->∞,n^2为主导,除去常数、系数、非主导项,使用 O计数法表示:O(n2)n>,n2为主导,除去常数、系数、非主导项,使用


拓展:常见大O类型和图例

时间复杂度: O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) < O ( 2 n ) < O ( n ! ) 时间复杂度:O(1) < O(logn)<O(n)<O(nlogn)<O(n^2)<O(2^n)<O(n!) 时间复杂度:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(2n)<O(n!)

时间复杂度:常数阶 < 对数阶 < 线性阶 < 线性对数阶 < 平方阶 < 指数阶 < 阶层阶 时间复杂度:常数 阶<对数阶<线性阶<线性对数阶<平方阶<指数阶<阶层阶 时间复杂度:常数阶<对数阶<线性阶<线性对数阶<平方阶<指数阶<阶层阶

在这里插入图片描述

  • 线性阶的操作数量相对于输入数据大小 n以线性级别增长。线性阶通常出现在单层循环中

  • 平方阶的操作数量相对于输入数据大小 n 以平方级别增长。平方阶通常出现在嵌套循环中

  • 生物学的“细胞分裂”是指数阶增长的典型例子:初始状态为 1 个细胞,分裂一轮后变为 2 个,分裂两轮后变为 4 个,以此类推,分裂 n 轮后有 2^n 个细胞,指数阶常出现于递归函数中。

  • 对数阶反映了“每轮缩减到一半”的情况。设输入数据大小为 n ,由于每轮缩减到一半,因此循环次数是 log2⁡n ,即 2^n 的反函数。

    • 在这里插入图片描述
  • 线性对数阶常出现于嵌套循环中

  • 阶乘阶对应数学上的“全排列”问题。给定 n 个互不重复的元素,求其所有可能的排列方案,方案数量为n!,常用于回溯。

2.2 空间复杂度

tip:现在很发达了,内存没以前贵,直接跳过此处

「空间复杂度 space complexity」用于衡量算法占用内存空间随着数据量变大时的增长趋势。这个概念与时间复杂度非常类似,只需将“运行时间”替换为“占用内存空间”。

算法在运行过程中使用的内存空间主要包括以下几种。

  • 输入空间:用于存储算法的输入数据。
  • 暂存空间:用于存储算法在运行过程中的变量、对象、函数上下文等数据。
  • 输出空间:用于存储算法的输出数据。

一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。

暂存空间可以进一步划分为三个部分。

  • 暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。
  • 栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数返回后,栈帧空间会被释放。
  • 指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1308037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二百零四回 模拟对话窗口的页面

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 经验分享5. 内容总结 我们在上一章回中介绍了"修改组件风格的另外一种方法"相关的内容&#xff0c;本章回中将介绍" 如何做一个模拟对话框窗口的页面".闲话休提&#xff0c;让我…

PCL点云处理之判断某一点在三角形的内部、外部、还是边上(二百二十二)

PCL点云处理之判断某一点在三角形的内部、外部、还是边上(二百二十二) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 点与三角形的位置共有三种: 1 内部 2 外部 3 点刚好在边上 (这个判断还是很有必要的,应用广泛,下面代码复制粘贴即可使用,纯C++实现) 二、算…

模块一——双指针:18.四数之和

文章目录 题目描述算法原理排序双指针 代码实现排序双指针复杂度分析时间复杂度&#xff1a;O(N^3^)空间复杂度&#xff1a;O(log⁡N)或者O(N) 题目描述 题目链接&#xff1a;18.四数之和 算法原理 排序双指针 依次固定⼀个数a &#xff1b;在这个数a 的后⾯区间上&#x…

点云几何 之 计算二维平面某一点到直线的距离(2)

点云几何 之 计算二维平面某一点到直线的距离&#xff08;2&#xff09; 一、算法介绍.二、算法实现1.代码2.结果 总结 一、算法介绍. 计算某一点到直线的距离&#xff0c;这里的直线会用2个点来表示&#xff0c;如果你只有直线上一点和直线的方向向量&#xff0c;应该也可以转…

yo!这里是Linux信号相关介绍

目录​​​​​​​ 前言 基本介绍 概念 信号列表 信号处理 产生(发送)信号 通过按键产生 系统函数产生 软件条件产生 硬件异常产生 阻塞信号 信号状态 sigset_t 状态相关函数 1.sigprocmask 2.sigpending 捕捉信号 内核态与用户态 捕捉过程 sigaction 后…

1.4 Postman的安装

hello大家好&#xff0c;本小节我们来安装一下Postman&#xff0c;好为我们后续的测试工作做准备。 首先&#xff0c;打开Postman的官网Postman API Platform 然后根据同学们自己电脑的操作系统来下载对应的Postman安装包。我这里拿windows来举例。我们点击windows的图标 会跳…

深入解析Freemarker模板引擎及其在Spring Boot中的高级整合

目录 引言1. Freemarker1.1.什么是Freemarker1.2 Freemarker模板组成部分1.3.优点 2. Spring Boot整合Freemarker2.1 配置2.2 数据类型 3. 案例总结 引言 Freemarker作为一款强大的模板引擎&#xff0c;与Spring Boot的整合能够极大地提升Web应用的开发效率和灵活性。本篇博客…

2023 巅峰之作 | AIGC、AGI、GhatGPT、人工智能大语言模型的崛起与挑战

文章目录 01 《ChatGPT 驱动软件开发》内容简介 02 《ChatGPT原理与实战》内容简介 03 《神经网络与深度学习》04 《AIGC重塑教育》内容简介 05 《通用人工智能》目  录 2023年是人工智能大语言模型大爆发的一年&#xff0c;一些概念和英文缩写也在这一年里集中出现&#xff…

你都那么老了,还在每天写博客吗?

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 白色便民网&#xff1a;我想多开一个公司会不会被税局查? 事件背景&#xff1a; 松松已创业9年&#xff0c;自媒体14年&#xff0c;经历过从0开公司、项目失败、赚钱等各种高光时刻。所以对于小微企业经营还是…

aardio网页组件:webPageOperation

webPageOperation是webview的初步封装&#xff0c;用来网页填表、操作网页。可操作web.form、web.view、web.view2等浏览器组件。 使用方法 首先把webPageOperation.aardio&#xff08;源码在后面&#xff09;放到~\lib\godking目录下&#xff0c;然后新建窗口项目&#xff…

[c]零钱兑换

题目比较简单&#xff0c;看答案就能看懂什么意思 #include<stdio.h> int main() {int count 0;int n;scanf("%d", &n);for (int i 0; i < n; i){for (int k 0; k <n/2; k){for (int j 0; j < n/5 ; j){if (i 2 * k 5 * j n){count;}}}}p…

R2O语义分割: Refine and Represent: Region-to-Object Representation Learning

paper: arxiv.org/pdf/2208.11821v2.pdf repo link: KKallidromitis/r2o: PyTorch implementation of Refine and Represent: Region-to-Object Representation Learning. (github.com) 摘要&#xff1a; 在本文中提出了区域到对象表示学习&#xff08;Region-to-Object Rep…

windows10下jdk安装

文章目录 windows10下jdk安装说明what安装包下载执行安装包验证是否安装成功 windows10下jdk安装 说明 操作系统&#xff1a;windows10 版本&#xff1a;1.8 what JDK(Java Development Kit) 是 Java 语言的软件开发工具包 安装包下载 https://www.oracle.com/java/techn…

4.11 构建onnx结构模型-Clip

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 Clip 结点进行分析 方式 方法一…

下一站 Gen AI 城市巡展指南来了!“码”上出发,Let‘s 构!

亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术&#xff0c;观点&#xff0c;和项目&#xff0c;并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏…

【Java用法】Hutool树结构工具-TreeUtil快速构建树形结构的两种方式 + 数据排序

Hutool树结构工具-TreeUtil快速构建树形结构的两种方式 数据排序 一、业务场景二、Hutool官网树结构工具2.1 介绍2.2 使用2.2.1 定义结构2.2.2 构建Tree2.2.3 自定义字段名 2.3 说明 三、具体的使用场景3.1 实现的效果3.2 业务代码3.3 实现自定义字段的排序 四、踩过的坑4.1 坑…

Android studio如何安装ai辅助工具

引言 在没有翻墙的情况下&#xff0c;即单纯在公司打工&#xff0c;经测试&#xff0c;大部分ai工具都是使用不了的&#xff08;比如各种gpt,codeium,copilot&#xff09;&#xff0c;根本登录不了账号&#xff0c;但有一个国内的codegeex是可以使用的&#xff0c;在这里不对各…

DS冲刺整理做题定理(二)线性表、栈、队列的套路

继续归纳套路&#xff0c;做题练习非常重要&#xff0c;王道的基本上足够了&#xff0c;学有余力可以做一下数据结构1800~ DS冲刺整理做题定理&#xff08;一&#xff09;二叉树专题https://blog.csdn.net/jsl123x/article/details/134949736?spm1001.2014.3001.5501 目录 一…

Spring Boot--Freemarker渲染技术+实际案例

目录 Freemarker 1.1.什么是Freemarker 1.2.Freemarker模板组成部分 1.3.优点 FreeMarker常见的方法&#xff1a; 2.2.2.数值 2.2.3.布尔值 2.2.4.日期 2.3.常见指令 2.3.1.处理不存在的值 assign 2.3.4.list 2.3.5.include SpringBoot整合Freemarker Freemarker…

回归预测 | MATLAB实现CHOA-BiLSTM黑猩猩优化算法优化双向长短期记忆网络回归预测 (多指标,多图)

回归预测 | MATLAB实现CHOA-BiLSTM黑猩猩优化算法优化双向长短期记忆网络回归预测 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现CHOA-BiLSTM黑猩猩优化算法优化双向长短期记忆网络回归预测 &#xff08;多指标&#xff0c;多图&#xff09;效果…