测试面试回顾(1)

硬件测试面试回顾(1)

  • pn结
  • MOS和CMOS
  • 消耗功耗——MOS器件开关时
  • 半导体工艺
  • 半导体器件
  • SPSS常用的10种统计分析
  • 如何用SPSS进行数据分析?
  • Jmeter介绍及测试用例编写
  • Jmeter
  • Selenium
  • 测试用例
  • 测试用例设计方法
  • 通用测试用例八要素
  • 自动化运维
  • 全局变量与静态全局变量、静态局部变量
  • C语言中【变量】的存储类型共有4种类型
  • 全局变量与局部变量
  • 堆和栈
  • 排序算法总结
  • 数据结构
  • 链表和数组
  • 访问越界

pn结

PN结,也称为晶体二极管(Diode),是一种重要的半导体器件,常用于电子电路中。PN结是由P型半导体和N型半导体材料组成的二极管结构。以下是有关PN结的主要特点和工作原理:

  • 结构和特点:
    P型半导体(P-region):P型半导体中的电子浓度较低,因此它带有多余的正电荷,通常表示为"H+“。P型半导体具有较高的空穴浓度,空穴是正电荷的载流子。
    N型半导体(N-region):N型半导体中的电子浓度较高,因此它带有多余的负电荷,通常表示为"e-”。N型半导体具有较高的自由电子浓度,自由电子是负电荷的载流子。
    PN结(P-N Junction):当P型半导体与N型半导体紧密接触时,它们的电荷会扩散到彼此的区域中,形成一个称为PN结的界面。在PN结中,自由电子从N区流向P区,而空穴则从P区流向N区。这导致了在PN结周围产生电势差。
  • 工作原理:
    正向偏置(Forward Bias):当在PN结上施加正向电压时,即将P区连接到正电极,将N区连接到负电极,电场势能帮助自由电子和空穴穿越PN结,电流得以流动。在正向偏置下,PN结呈现低电阻状态,电流可以流过。
    反向偏置(Reverse Bias):当在PN结上施加反向电压时,即将P区连接到负电极,将N区连接到正电极,电场势能阻止自由电子和空穴穿越PN结,几乎没有电流流动。在反向偏置下,PN结呈现高电阻状态。
  • 应用:
    PN结二极管具有多种应用,其中包括但不限于以下领域:
    1.整流器:PN结二极管可用于将交流电转换为直流电,这在电源和电子设备中非常常见。
    2.放大器:在一些高频放大器中,PN结二极管用作小信号放大器的元件。
    3.开关:PN结二极管可用作开关,特别是在数字逻辑电路和数字电子学中。
    4.发光二极管(LED):LED是一种特殊类型的PN结二极管,它可以发光,用于显示和照明应用。
    5.太阳能电池:太阳能电池也是一种PN结二极管,可以将光能转换为电能。
    总的来说,PN结是一种关键的半导体器件,具有多种应用,从电源转换到光电子学。它的工作原理基于电荷扩散和电场效应,使其在电子和电路工程中发挥着重要作用。

MOS和CMOS

  • MOS(Metal-Oxide-Semiconductor)和CMOS(Complementary Metal-Oxide-Semiconductor)是半导体技术中常见的两种关键技术,用于制造集成电路(IC)和电子设备。以下是它们的主要特点和区别:
  • 1.MOS(金属-氧化-半导体):
    结构:MOS技术基于金属-氧化-半导体结构。它包括一个半导体材料(通常是硅),上面覆盖着氧化物层(通常是二氧化硅),然后再覆盖一层金属。
    工作原理:MOS器件的工作原理涉及通过施加电场控制半导体材料中的载流子流动。通过改变栅极电压,可以控制通道中的电流。MOS器件通常包括MOSFET(MOS场效应晶体管),它是数字电路和模拟电路中的关键元件。
    功耗:MOS器件在开关时会消耗功耗,因此在大规模集成电路中使用时可能会导致静态功耗问题。
  • 2.CMOS(互补金属-氧化-半导体):
    结构:CMOS技术是一种特殊的MOS技术,它包括互补的两种MOS器件:N型MOS(NMOS)和P型MOS(PMOS)。这两种器件共同工作,使得在CMOS电路中几乎不消耗静态功耗。
    工作原理:CMOS电路中的NMOS和PMOS器件在不同的电压状态下工作,其中一个处于导通状态,另一个处于截止状态。这种互补工作原理导致CMOS电路几乎不消耗静态功耗,因此在大规模集成电路中得到广泛应用。
    功耗:CMOS电路的静态功耗非常低,因此适用于需要长时间持续运行的电子设备,如移动设备和电池供电的设备。
    总的来说,MOS是一种基本的半导体技术,用于制造MOSFET等器件,而CMOS是一种特殊的MOS技术,通过使用互补的MOS器件,几乎消除了静态功耗,使其成为集成电路设计中的首选技术。CMOS技术在数字电路、微处理器、存储器和其他集成电路中得到广泛应用,因为它具有低功耗、高性能和可靠性的优势。

消耗功耗——MOS器件开关时

MOS(金属-氧化-半导体)器件在开关时会消耗功耗,这主要是由于两个原因:
1.通道电流:当MOSFET(MOS场效应晶体管)或其他MOS器件处于导通状态时,电流可以通过通道流动,从而执行特定的电路功能,例如放大、开关或驱动其他元件。流动的电流在通道中会产生电阻,根据欧姆定律,电流通过电阻会产生功耗,功耗可以通过以下公式计算:
功耗(P) = 电流(I) × 电流(I) × 电阻(R)。因此,通道中的电流流动会导致功耗。
2.开关时间:MOS器件从关断到导通以及从导通到关断都需要一定的时间。在这个切换过程中,MOS器件的电流和电压都会变化。这种切换过程中的电流变化和电荷移动也会导致功耗。
尽管MOS器件在开关过程中会产生功耗,但在实际应用中,通常会采取措施来降低功耗。例如,使用CMOS(互补金属-氧化-半导体)技术,其中包括互补的N型MOS和P型MOS器件,以几乎消除静态功耗。此外,现代电子设备和电路设计通常会优化开关速度以减少开关时间,从而降低切换功耗。
总之,MOS器件在开关时会消耗功耗,这是由于电流流动和开关过程中的电荷移动引起的。然而,在实际应用中,可以采取各种措施来降低功耗,并根据特定应用的需求进行优化。

半导体工艺

  • 半导体工艺是半导体器件制造的过程,包括多个步骤,用于创建集成电路(IC)和其他半导体器件。这些步骤需要高度的精确性和洁净度,以确保最终的半导体器件具有高性能和可靠性。以下是典型的半导体工艺步骤:
    1.晶片设计:首先,工程师会设计要制造的半导体器件的电路图和物理布局。这一设计考虑了器件的功能、性能和电气特性。
    2.晶圆制备:半导体晶片通常是在硅晶圆上制造的。晶圆是圆形薄片,通常直径为6英寸、8英寸或12英寸。晶圆必须经过清洗、抛光和其他准备步骤,以确保表面平整和干净。
    3.光刻:这是将设计的电路图传输到晶圆表面的过程。光刻机使用掩模(mask)来定义要创造的电路图,然后使用紫外光或激光刻蚀技术将图案转移到光刻胶上。光刻胶在后续步骤中用于刻蚀或沉积材料。
    4.刻蚀:在光刻之后,使用化学刻蚀或物理刻蚀技术来从晶圆上去除不需要的材料。这一步骤用于创建电路的精细结构和互连。
    5.沉积:在某些区域,需要增加额外的材料。这可以通过化学气相沉积(CVD)或物理气相沉积(PVD)等技术来实现。
    6.离子注入:离子注入是一种将离子引入晶圆中以改变其电学特性的过程。这用于形成N型区域和P型区域,以创建晶体管等元件。
    7.退火:在制造过程的不同阶段,需要在高温下退火晶圆,以去除应力、提高晶体质量和修复某些处理步骤中引入的缺陷。
    8.金属化:在晶圆上添加金属层,以连接不同的电路元件和形成互连。金属层通常包括铝、铜或其他导电材料。
    9.测试和包装:晶片制造后,它们需要进行测试,以确保它们符合规格。通过在晶片上添加封装来保护它们,并连接到电路板上,以实现完整的电子设备。
    10.封装和封装测试:最后,芯片被安装在封装中,这是一个外壳,保护芯片并提供连接到其他设备的方式。然后,芯片需要进行封装测试,以确保它们正常工作。
    这些步骤只是半导体制造工艺的一部分,具体的步骤和技术取决于要制造的半导体器件类型和设计。半导体工艺需要高度的工程技术和设备,以确保制造出高质量的半导体器件。

半导体器件

  • 半导体器件是利用半导体材料的电子特性来实现各种电子功能的器件。半导体器件在现代电子技术中占据重要地位,它们包括多种不同类型的器件,用于各种应用,以下是一些常见的半导体器件:
    1.二极管(Diode):
    二极管是最简单的半导体器件之一,由P型半导体和N型半导体组成。它具有电流只能单向流动的特性,广泛用于整流器、放大器、开关等应用中。
    2.晶体管(Transistor):
    晶体管是一种用于放大和开关电流的器件,它有多种类型,包括双极型晶体管(BJT)和场效应晶体管(FET)。晶体管是现代电子电路的基础元件,用于构建放大器、逻辑门、微处理器等。
    3.场效应晶体管(FET):
    FET包括MOSFET(金属-氧化-半导体场效应晶体管)和JFET(结型场效应晶体管),用于电路放大和开关。
    4.光电二极管(Photodiode):
    光电二极管是一种可以将光信号转换为电流或电压的半导体器件,常用于光电传感器、光通信和光测量中。
    5.光发射二极管(LED):
    LED是一种可以将电能转换为光能的半导体器件,用于指示灯、显示器、照明等。
    6.太阳能电池(Solar Cell):
    太阳能电池是一种半导体器件,可以将太阳光转换为电能,广泛用于太阳能发电系统。
    7.整流器(Rectifier):
    整流器是用于将交流电转换为直流电的半导体器件,常见的类型包括二极管整流器和可控整流器。
    8.集成电路(Integrated Circuit,IC):
    集成电路是在单个半导体晶片上集成了数百万甚至数十亿个晶体管和其他电子元件的器件。它们用于各种电子设备和应用,包括微处理器、存储器、传感器和通信设备。
    9.功率半导体器件:
    功率半导体器件包括功率晶体管、功率MOSFET和功率IGBT等,用于高电压和高电流应用,如电源管理、电机驱动和电力电子。
    10.传感器:
    半导体传感器是一种可以感测温度、压力、光、湿度等物理量的器件,广泛应用于自动化、医疗、环境监测等领域。
    这些半导体器件在现代科技和电子领域中起着关键作用,它们的不同类型和特性使它们适用于各种不同的应用。半导体技术的不断发展和创新推动了电子设备和通信技术的进步。

SPSS常用的10种统计分析

  • 地理数据的统计处理、双变量相关分析、主成分分析、因子分析、多元线性回归、聚类分析、时间序列分析、地统计分析、趋势面分析、马尔可夫分析
    SPSS(统计包装软件,Statistical Package for the Social Sciences)是一款广泛用于数据分析和统计建模的软件工具。
    SPSS(统计包装软件,Statistical Package for the Social Sciences)是一款广泛用于数据分析和统计建模的软件工具。下面我将以一个简单的示例介绍如何使用SPSS进行数据分析。
    示例:学生考试成绩分析
    假设你是一位教育研究员,有一份包含学生考试成绩的数据集,你想使用SPSS来分析这些数据,了解学生的表现情况。
    步骤 1:导入数据
    首先,打开SPSS软件并创建一个新的数据分析项目。然后,导入包含学生考试成绩的数据文件,通常数据文件的格式可以是Excel、CSV或SPSS自己的格式。
    步骤 2:数据清理
    在导入数据后,你可能需要进行数据清理,包括检查和处理缺失值、异常值和重复值。你可以使用SPSS的数据编辑功能来进行这些操作。
    步骤 3:描述性统计
    接下来,你可以使用SPSS生成一些描述性统计信息,例如平均分、标准差、最小值、最大值等,以了解数据的基本特征。你可以通过依次选择"分析" > “描述统计” > “统计"来执行此操作。
    步骤 4:绘制图表
    SPSS还可以用来绘制各种图表,如直方图、散点图、箱线图等,以可视化数据的分布和关系。你可以通过选择"图表” > “图表编辑器"来创建和自定义图表。
    步骤 5:假设检验
    如果你想进一步了解数据之间的关系,可以执行假设检验。例如,你可以使用t检验来比较两组学生的平均分是否存在显著差异。在SPSS中,你可以选择"分析” > “比较均值” > “独立样本t检验"来执行此操作。
    步骤 6:回归分析
    如果你想了解影响学生成绩的因素,可以执行回归分析。SPSS提供了多种回归分析方法,如线性回归、多元回归等。你可以选择"分析” > "回归"来执行此操作。
    步骤 7:结果解释和报告
    最后,在完成分析后,你可以查看分析结果,解释统计模型的输出,并撰写报告以分享你的发现。SPSS通常会生成详细的输出,包括假设检验的结果、回归系数和显著性水平等。

如何用SPSS进行数据分析?

  • 链接: link

Jmeter介绍及测试用例编写

  • 链接: Jmeter详解
  • Jmeter简介
    Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言
  • 我们为什么使用Jmeter?
    开源免费,基于Java编写,可集成到其他系统可拓展各个功能插件
    支持接口测试,压力测试等多种功能,支持录制回放,入门简单
    相较于自己编写框架活其他开源工具,有较为完善的UI界面,便于接口调试
    多平台支持,可在Linux,Windows,Mac上运行
  • 链接: 利用JMeter编写测试用例
  • 1、双击打开JMeter.bat;2、新建测试计划(新建—>测试计划);3、新建一个线程组(选中“测试计划”,右键选择:添加—>线程(用户)—>线程组);4、修改线程组名称为:用户,并保存(保存路径可自己选择);5.新建一个HTTP请求(选中“用户”,右键选择:添加—>取样器—>HTTP请求);6.修改HTTP请求的名称为:百度主页;7.设置HTTP请求;8.新建两个监听器(选中“用户”,右键选择:添加—>监听器—>察看结果树、用表格察看结果);9.运行测试(运行时可以点击stop 和shutdown图标来终止运行);10.察看测试结果(重点关注状态和时间的值);
  • 链接: jmeter常用测试用例(图文超简单)&接口压测指标说明
  • 测试面试回顾(1)_第1张图片
  • 接口压测看哪些指标?
    1、吞吐量
    一次性能测试过程中网络上传输的数据量的总和.吞吐量/传输时间,就是吞吐率
    2、TPS(transaction per second)
    每秒钟系统能够处理的请求数量.它是衡量系统处理能力的重要指标.
    Tps即每秒处理事务数,包括了
    1)用户请求服务器
    2)服务器自己的内部处理
    3)服务器返回给用户
    这三个过程,每秒能够完成N个这三个过程,TPS也就是N;
  • 测试面试回顾(1)_第2张图片
  • 链接: Jmeter测试Tomcat

Jmeter

  • 在JMeter中,通常是以多线程或多进程的方式模拟用户行为来产生负载,所以,Thread Group可以理解为负载发生器。脚本中模拟用户的行为,叫用户运行器,通常用户运行器附加在线程或进程上。资源生成器,指用于生成测试过程中服务器,负载机的资源数据。报表生成器,根据测试的数据生成报表。
  • 链接: link

Selenium

  • Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera,Edge等。这个工具的主要功能包括:测试与浏览器的兼容性——测试应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成.Net、Java、Perl等不同语言的测试脚本。

测试用例

  • 测试用例(主指功能测试用例模板)的内容通常包括测试目标(目的),需求标示(一般同需求文档中的需求编号对应),预置条件(如需要的网络配置、环境配置等),输入数据(如测试用到的账号等数据),测试步骤,预期结果,通过标准(什么情况下该用例执行成功)等。
  • 测试面试回顾(1)_第3张图片
  • 测试面试回顾(1)_第4张图片
  • 测试面试回顾(1)_第5张图片
  • 测试面试回顾(1)_第6张图片
  • 缺陷类型
    功能错误
    界面(Ui)错误 ,兼容性 (前端)
    数据,易用性,改进建议,架构
    1、如何区分是前端bug还是后端bug
    1)、如果是界面和兼容性问题——前端问题
    2)、如果是功能错误,需要 抓包 查看请求和响应!
  • 链接: link

测试用例设计方法

  • 等价类,边界值,判定表,场景设计法,因为这四个是实际运用的多的测试用例设计方法。基于需求的设计,RBT( Requirements-Based Testing)是基于需求的测试方法,会使测试更加有效,因为 它使测试专注于质量问题产生的根源,即需求。
  • 链接: link

通用测试用例八要素

1、用例编号;
  2、测试项目;
  3、测试标题;
  4、重要级别;
  5、预置条件;
  6、测试输入;
  7、操作步骤;
  8、预期输出

  • 链接: link

自动化运维

  • 自动化运维-初级
    自动化发布:利用自动工具,shell 。比如: ansible + shell + jenkins + gitlab 解决一些自动化发布问题:
    git push 到gitlab >> 触发jenkins webhooks API >> 执行ansible
    jenkins 所需插件——在插件里面搜索pipeline
    自动化部署: 利用 shell、ansible,编写playbook 做一些 标准化东西,例如:服务器初始化、服务初始化(nginx、mysql等等)
    日志管理:可以用 rsyslog 管理日志,日志量多了,再打个包,或者弄个NFS存储,保留多少天。
    监控自动化: 可以利用zabbix ,监控一些标准化的指标,根据服务器及业务的实际性能。
  • 测试面试回顾(1)_第7张图片
  • 测试面试回顾(1)_第8张图片
  • 测试面试回顾(1)_第9张图片
  • 首先要弄个 CMDB,你可以叫基础信息管理、服务器信息管理等等或者资源信息。
    通常情况,我们会收集服务器信息,作为基础信息,后面写一些跟这个相关都需要使用这些基础信息,如:发布系统、监控管理、配置中心等等。
    这里面我们选择写这个系统的语言,大部分都是会使用Python+Django+bootstrap
    这里面还涉及到一个服务树的概念,后面再说
  • 发布系统,主要解决,代码自动发布。这里面有几个选择吧
    自己从头到尾写,包括设计、开发等等
    调用其他比较成熟的devops 工具,例如: 可以调用jenkins API、 或者gitlab runner 的API等
  • 配置中心,主要解决,管理软件服务中的配置文件和代码中的配置文件。
    当然这里面有些成熟的配置中心可以做参考,但是不一定适用你们,如:disconf、Apollo等
    或者自己撸个程序。
    域名管理系统
    内网域名 管理,这里主要是指: IDC 机房内部、或者云上内部,例如:我们之前适用bind做内网解析的使用,天天维护配置文件,很烦。那我们就可以自己搞个系统。把配置文件这些数据都写到数据库中进行管理就会方便很多。
    外网域名管理,其实这个就是调用第三方接口,进行域名更改,例如: 万网API、Dnspod等等
  • 链接: link

全局变量与静态全局变量、静态局部变量

  • A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块之间的耦合度。
    B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块之间的耦合度。
    C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题,因为他们都放在静态数据存储区,全局可见;
    D.如果我们需要一个可重入的函数,那么我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的函数)。
    E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。

  • 附加说明:
    变量的存储类型

auto int a = 10;自动变量 系统默认都是自动变量默认不会初始化;会产生随机数
static int a=20; 默认会被初始化;并仅仅初始化一次;生命周期整个程序
extern int a; 外部变量(全局变量) 默认会被初始化;并仅仅初始化一次 生命周期整个程序
register int a; 存放在cpu寄存器当中;不能用static 修饰;并且只能是局部变量、要求性能高的时候用
如:
register int y = 10; //错误
int get(){
register int x = 10; //正确
}
函数的局部变量
{
作用域只在函数体内;//压到栈 ,使用完后会被弹出释放;
}

文件main.c
#include 
/*
auto 自动变量
register 寄存器变量
extern 外部变量
static 静态变量
*/
int a = 100; //全局变量 其他文件可以用extern调用
//register int x = 10; //错误
extern void get();
static int name2 = 490; //全局静态变量 其他文件无法使用
int main()
{


get(); //分配1次 栈的空间有可能不是同一个
get(); //分配1次 栈的空间有可能不是同一个
get(); //分配1次 栈的空间有可能不是同一个


return 0;
}

文件1:
#include 
int abc = 2; //默认auto类型 //

static int name = 8890;
//extern static int name2; //错误;不允许定义2个存储类型
void get(){
extern int a;//引用全局变量
int aa = a;
a++;
auto int b = 20;
b++;
static int c = 20;//静态局部变量
c++;
register int r =30;
r++;
name++;
abc++;
printf("a=%d b=%d c=%d r=%d name=%d abc=%d\n",aa,b,c,r,name,abc);
}

//局部变量在栈上
/* 用户空间
(栈【局部变量】、堆、数据段【全局变量(静态全局,静态局部,动态变量)】、代码段)
*/
//全局变量在数据段存储
/* 数据段包括两部分(静态存储区、动态存储区)
静态存储区
【
全局变量(非静态,静态的全局;静态局部变量)
静态变量(全局和局部2种静态)
data初始化区
bss未出化区

全部变量: auto int a; static int a; 函数内部的局部静态变量static int b;
静态变量就分全局和局部2种;

】
*/

C语言中【变量】的存储类型共有4种类型

  • 在C语言中,对变量的存储类型说明有以下四种:
    auto 自动变量 (动态存储)
    register 寄存器变量(动态存储)
    extern 外部变量(静态存储)
    static 静态变量(静态存储)
    所谓存储类型是指变量占用内存空间的方式,也称为存储方式。
    这4种类型 不允许重复定义 如: extern static int a=200;是错误的;只能指定一中存储类型;如;static int a =200;或者是 extern int a;
    变量的存储方式可分为“静态存储”和“动态存储”两种。
    静态存储变量:在定义时候存储单元里一直保持不变;直到程序结束。
    动态存储变量:在程序执行时候;使用他的时候才分配内存单元,使用完毕后立即释放,再使用在分配。
    从以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。

  • 一个变量属于哪一种存储方式,并不能仅从其变量作用域(文件,函数体,代码块,函数声明)来判断,还应有明确的存储类型说明;
    如:static int a=20;
    变量说明的完整形式应为:【存储类型说明符】【 数据类型说明符】【 变量名,变量名…】;

  • 链接: c语言局部变量存在什么区_C语言的存储空间

全局变量与局部变量

  • 链接: 【C语言】变量、变量的存储区域和存储类型

堆和栈

  • 链接: C++中堆(heap)和栈(stack)的区别(面试中被问到的题目)
  • 首先说明,在C++中,内存分为5个区:堆、占、自由存储区、全局/静态存储区、常量存储区。
    栈:是由编译器在需要时自动分配,不需要时自动清除的变量存储区。通常存放局部变量、函数参数等。
    堆:是由new分配的内存块,由程序员释放(编译器不管),一般一个new与一个delete对应,一个new[]与一个delete[]对应。如果程序员没有释放掉, 资源将由操作系统在程序结束后自动回收。
    自由存储区:是由malloc等分配的内存块,和堆十分相似,用free来释放。
    全局/静态存储区:全局变量和静态变量被分配到同一块内存中(在C语言中,全局变量又分为初始化的和未初始化的,C++中没有这一区分)。
    常量存储区:这是一块特殊存储区,里边存放常量,不允许修改。
  • 测试面试回顾(1)_第10张图片
  • 测试面试回顾(1)_第11张图片

排序算法总结

  • 测试面试回顾(1)_第12张图片
  • 如:桶排序打印的时候就是不稳定的,不一定按先后顺序来
  • 插入、冒泡、选择都是两层for循环,快速平均nlogn,最坏n^2,桶排序一个for循环
  • 归并排序,划分n个轴点之后合并,合并每一次n/2,左右合并*2
    测试面试回顾(1)_第13张图片
    测试面试回顾(1)_第14张图片
  • 调用随机函数取轴点元素,加快快速排序n^2
  • 冒泡、插入、选择排序不需要额外辅助空间,空间复杂度为O(1);桶排序需要开辟出n个元素的空间,归并排序也是O(n),因为创建了临时的辅助数组。快速排序最好的情况,元素比较均匀,每一次轴点元素左右都是相等的,空间复杂度为logn,最坏情况下元素是已经排好序的,空间复杂度O(n)。
  • 冒泡排序:大的网上浮,浮到最后,小的从右向左浮到最前。
  • 选择排序:每次选个最大的放到最后;每次选个最小的放到最前。
  • 插入排序:从左往右遍历,从后往前比较。2,1,3,5,7——1,2,3,5,6,7
  • 希尔排序:增量的分组排序,n/2,(n/2)/2…先部分有序再全局有序
  • 归并排序:从上到下递归到一个个元素,再从一个元素二路归并到有序。
  • 快速排序:每次找到一个上升位置——基准值,左边比基准值小,右边比基准值大。
  • 堆排序:基于堆基数的,大型堆做升序,小型堆做降序。是一个完全二叉树。构建堆、堆调整。
  • 计数排序:不需比较,放入某种空间(使元素值和下标有某种关联),空间的值就是频次。
  • 桶排序:通过某种规则将数据放入桶中,桶间有序,只需要做桶内比较。
  • 基数排序:桶排序的一种,个十百位,逐位排序。一个数,比较的基本的点不一样。
    测试面试回顾(1)_第15张图片
  • 排序算法是一种将一组数据按照特定顺序重新排列的算法。在计算机科学和数据处理中,排序是一个常见的操作,有许多不同的排序算法可供选择,每种算法都有其独特的性能和用途。以下是一些常见的排序算法:
    1.冒泡排序(Bubble Sort):
    冒泡排序是一种简单的比较排序算法,它重复地比较相邻的两个元素,如果它们的顺序不正确,就交换它们,直到整个数组排序完成。
    时间复杂度:O(n^2),其中n是要排序的元素数量。
    2.选择排序(Selection Sort):
    选择排序在每一轮中选择未排序部分中的最小元素,并将其放置在已排序部分的末尾。
    时间复杂度:O(n^2)。
    3.插入排序(Insertion Sort):
    插入排序将数组分为已排序和未排序两部分,然后逐个将未排序的元素插入已排序部分的适当位置。
    时间复杂度:O(n^2),但对于小型数据集或已部分排序的数据集效率较高。
    4.快速排序(Quick Sort):
    快速排序使用分治策略,将数组分成两个子数组,然后对子数组递归地进行排序。它通常使用分区算法(如Lomuto分区或Hoare分区)来确定元素的位置。
    时间复杂度:平均情况下为O(nlog(n)),最坏情况下为O(n^2),但通常比冒泡、选择和插入排序更快。
    5.归并排序(Merge Sort):
    归并排序也使用分治策略,将数组分成两个子数组,然后合并排序后的子数组,以获得最终排序结果。
    时间复杂度:始终为O(n
    log(n)),具有稳定的性能。
    6.堆排序(Heap Sort):
    堆排序使用堆数据结构来排序元素。它首先构建一个最大堆(或最小堆),然后依次移除堆顶元素并将其放入已排序部分。
    时间复杂度:O(nlog(n))。
    7.计数排序(Counting Sort):
    计数排序适用于已知数据范围的整数排序。它创建一个计数数组来计算每个元素出现的次数,然后将元素放回原始数组中。
    时间复杂度:O(n+k),其中k是数据范围的大小。
    8.基数排序(Radix Sort):
    基数排序适用于对数字进行排序。它从最低位到最高位依次对数字进行排序,通常使用稳定的排序算法(如计数排序或桶排序)作为辅助。
    时间复杂度:O(n
    k),其中k是数字的最大位数。
    不同的排序算法在不同情况下表现出不同的性能,因此选择合适的排序算法取决于数据的特性和排序需求。某些算法对于小型数据集或基本有序的数据集可能更适合,而其他算法则适用于大型数据集。排序算法的选择也受到编程语言和库的支持和限制的影响。

数据结构

  • 链接: link

  • 是只能在某一端插入和删除的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。

队列
一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列是按照“先进先出”或“后进后出”的原则组织数据的。队列中没有元素时,称为空队列。

链表
是一种物理存储单元上非连续、非顺序的存储结构,它既可以表示线性结构,也可以用于表示非线性结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
测试面试回顾(1)_第16张图片

链表和数组

  • 对于想要快速访问数据,不经常有插入和删除元素的时候,选择数组;对于需要经常的插入和删除元素,而对访问元素时的效率没有很高要求的话,选择链表。
  • 链表和数组是两种常见的数据结构,用于组织和存储数据。它们在内部实现和使用方面有很多不同之处,因此适用于不同的应用场景。以下是链表和数组的主要区别:
    1.数组(Array):
    内存分配:
    数组是一种连续内存分配的数据结构,元素在内存中紧密排列。
    数组的大小通常在创建时确定,且不能轻易更改。
    访问速度:
    数组支持随机访问,因为元素的位置在内存中是固定的,可以直接通过索引访问元素。
    时间复杂度为O(1)。
    插入和删除:
    在数组中插入或删除元素可能需要将其他元素移动,这会导致较高的时间复杂度。
    在数组中插入或删除元素的平均时间复杂度为O(n),其中n是数组的大小。
    大小调整:
    数组的大小通常是固定的,如果需要更多的空间,通常需要创建一个新的更大的数组,并将元素复制到新数组中。
    空间复杂度:
    数组通常具有较低的空间复杂度,因为它们不需要额外的指针来连接元素。
    2.链表(Linked List):
    内存分配:
    链表使用分散的内存分配,每个节点包含数据和指向下一个节点的指针(单链表)或同时包含指向下一个节点和上一个节点的指针(双链表)。
    访问速度:
    链表不支持随机访问,必须从头节点开始,按顺序遍历链表来访问元素。
    时间复杂度取决于要访问的元素的位置,最坏情况下为O(n)。
    插入和删除:
    链表在插入和删除元素时效率较高,因为只需要调整节点的指针,不需要移动其他节点。
    插入和删除的平均时间复杂度为O(1),但需要知道要插入或删除的节点位置。
    大小调整:
    链表的大小可以动态增长或缩小,不需要提前知道大小。
    空间复杂度:
    链表通常具有较高的空间复杂度,因为每个节点都需要额外的指针来连接其他节点。
    根据具体的需求和应用场景,选择使用数组还是链表是重要的决策。如果需要随机访问元素,并且元素数量不会频繁变化,数组可能更合适。如果需要频繁插入和删除元素,或者元素数量会动态变化,链表可能更合适。在某些情况下,也可以使用其他数据结构(如栈、队列、树等)来更好地满足需求。
    测试面试回顾(1)_第17张图片
    链接: 数组和链表的区别
    各自的优缺点:
  • 数组的优点
    随机访问性强
    查找速度快
    数组的缺点
    插入和删除效率低
    可能浪费内存
    内存空间要求高,必须有足够的连续内存空间。
    数组大小固定,不能动态拓展
  • 链表的优点
    插入删除速度快
    内存利用率高,不会浪费内存
    大小没有固定,拓展很灵活。
    链表的缺点
    不能随机查找,必须从第一个开始遍历,查找效率低

访问越界

  • python中列表越界的话,可以把数据存放到数据库或本地文件中,然后分段读取访问。
  • 在Python和C中,当你尝试访问列表中不存在的元素时,都会导致列表越界错误。但是两者处理方式有所不同。
    Python和C在处理列表或数组越界时有不同的行为,Python会引发异常以保护程序免受错误的影响,而C则会允许越界访问,但可能导致不确定的结果。因此,在编写C代码时,要特别小心处理数组索引以避免越界错误。
  • C防止越界:
    1.使用循环控制索引:在使用数组索引访问元素之前,使用循环或条件语句确保索引位于有效范围内。
    2.使用数组长度变量:通常,在C中使用数组时,你可以定义一个变量来存储数组的长度,然后确保索引不超出这个长度。这有助于提高代码的可读性和可维护性。
    3.使用标准库函数:C标准库提供了一些用于处理字符串和数组的函数,这些函数通常会进行边界检查以防止越界。例如,strcpy和strncpy函数用于字符串复制,memcpy函数用于内存复制,它们都会检查边界。
    4.使用动态内存分配:如果你不确定数组大小,可以使用动态内存分配函数(如malloc和calloc)来创建动态数组,然后根据需要动态调整数组大小,以避免越界问题。

你可能感兴趣的:(面试八股文,单片机,嵌入式硬件)