Linux--进程(1)
目录
前言
1.冯诺依曼体系结构
2. 操作系统(Operator System)--第一个被加载的软件
3.进程
3.1基本概念
3.2Linux中的PCB
3.3通过系统调用创建子进程-fork初识
fork:创建一个子进程
为什么要创建子进程?
fork的原理:
进一步了解fork的返回值
demo代码(一次创建多个子进程)
前言
在学习进程之前,我们要明白先了解两个东西:
1.体系结构----硬件上
2.操作系统----软件上
1.冯诺依曼体系结构
我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
截至目前,我们所认识的计算机,都是有一个个的硬件组件组成
- 输入单元:包括键盘, 鼠标,扫描仪, 写板等
- 中央处理器(CPU):含有运算器和控制器等
- 输出单元:显示器,打印机,磁盘,显卡,网卡,声卡等
关于冯诺依曼,必须强调几点:
- 这里的存储器指的是内存(掉电易失)
- 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)
- 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
- 一句话,所有设备都只能直接和内存打交道。
再谈一个问题,为什么在体系结构中要有内存?
冯诺依曼体系结构中要有内存,主要是因为内存可以适配CPU与外设之间速度不匹配的问题,从而提高整机效率。
在冯诺依曼体系结构中,CPU的速度最快,而输入输出设备是最慢的。这会导致从输入设备传入数据到CPU处理,再从CPU传出已处理的数据到输出设备,这些过程之间的速度不匹配问题,降低了整机效率。为了解决这个问题,冯诺依曼体系引入了内存的概念。
内存具有数据存储的能力,可以提前把数据准备好,CPU只需要从内存中拿数据进行处理。此外,根据局部性原理,当CPU需要获取某一行数据时,内存可以将该行数据之后的数据一同加载进来,而CPU处理数据和内存加载数据是可以同时进行的,这样下次CPU就可以直接从内存当中获取数据。
因此,内存作为计算机数据的核心,可以大大提高数据处理的效率和速度。引入内存就把,效率问题,转化为了软件问题。场景:
程序在运行的时候必须把程序先加载到内存中,为什么?
程序最终都是文件,文件都存储在硬盘上,硬盘属于外设;程序运行所产生的指令和数据,最终是要让cpu执行的;存储在硬盘中的程序(外设)最终会交给内存,是因为在数据层面,cpu只和内存交互,程序需要加载到内存中,再由内存交给cpu处理,这是冯诺依曼体系结构这么规定的。
对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上,请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。 从你打开窗口,开始给他发消息,到他的到消息之后的数据流动过程。如果是在qq上发送文件呢?
聊天的时候,键盘输入的信息储存在内存中,并将其打包成特定的网络协议格式。CPU对这些数据进行处理,确保它们可以正确地通过网络发送。这些数据包通过网络发送到朋友的计算机上。朋友的计算机上的QQ程序处理这些接收到的消息,将其解包并显示在屏幕上。如果是发送文件,这个文件首先被从硬盘读取到内存中。再以同样的方式发送到朋友那,朋友接收后,QQ程序处理这些数据包,去掉头信息,并将它们重新组装成原始的文件。这个文件随后被存储在朋友的计算机的硬盘上,朋友可以在其计算机上访问和查看这个文件。
这个过程内存也是起着核心作用。
2. 操作系统(Operator System)--第一个被加载的软件
任何计算机系统都包含一个基本的程序集合,称为操作系统。笼统的理解操作系统包括:
- 内核(进程管理,内存管理,文件管理,驱动管理)
- 其他程序(例如函数库, shell程序等等)
设计OS的目的:
- 与硬件交互,管理所有的软硬件资源
- 为用户程序(应用程序)提供一个良好的执行环境
定位:在整个计算机软硬件架构中,操作系统的定位是: 一款纯正的“搞管理”的软件
在这里我们引入一张图:计算机的层状结构
在这里我们先谈硬件部分:
首先,底层硬件是计算机系统的最底层部分,包括处理器、内存、硬盘、显卡等物理设备。这些硬件是计算机系统的基础,提供了运行程序和存储数据的能力。
其次,驱动程序是介于底层硬件和操作系统之间的软件。由于不同的硬件厂商生产的硬件设备可能采用不同的技术和协议,因此操作系统无法直接识别和管理这些硬件。驱动程序的作用就是为操作系统提供与硬件设备进行通信和控制的能力。驱动程序包含有关硬件设备的信息,可以让操作系统识别和管理硬件,并与其进行交互。
最后,操作系统是运行在计算机硬件之上的系统软件,它是计算机系统的核心。操作系统负责管理和控制计算机的硬件和软件资源,提供用户界面,支持多任务处理和文件系统等功能。操作系统通过与驱动程序进行交互,实现对底层硬件的管理和控制。底层硬件提供了计算机系统的物质基础,驱动程序为操作系统提供了与硬件进行交互和控制的能力,而操作系统则负责管理和控制整个计算机系统的资源和运行(先描述,在组织)。
为什么要有操作系统?
1. 管理硬件资源:操作系统负责管理计算机的各种硬件资源,如内存、处理器、硬盘、网络等,确保它们能够有效地被应用程序使用。
2. 提供用户接口:操作系统提供了用户与计算机之间的接口,使用户能够方便地与计算机进行交互,运行程序和管理文件。
3. 调度任务:操作系统负责对计算机上运行的各个任务进行调度和管理,确保它们能够按照一定的规则和优先级进行执行。
4. 提供安全性:操作系统通过访问控制和权限管理等机制来保护计算机系统的安全,防止未授权的访问和恶意软件的入侵。
总的来说,操作系统是计算机系统中不可或缺的部分,它为应用程序的运行和用户的操作提供了基础支持和保障,对下管理号软硬件系统(手段),对上提供一个良好的运行环境(目的)。系统调用和库函数概念
- 在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
- 系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
3.进程
承上启下
那在还没有学习进程之前,就问大家,操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来,再把、进程组织起来!
3.1基本概念
首先在操作系统中是不是只能运行一个程序呢?当然不是。
事实:
1.我们可以启动多个程序---我们一定要将多个.exe加载到内存
2.操作系统要不要管理多个加载到内存的程序呢?要的
3.操作系统如何管理加载到内存的程序 呢?先描述,再组织!
操作系统管理加载到内存的程序通常遵循以下步骤:
- 加载程序:当用户启动一个程序时,操作系统首先会将程序的可执行文件从磁盘加载到内存中。这个过程涉及将程序的代码段、数据段和堆栈段等部分加载到内存的不同区域。
- 设置程序的执行环境:操作系统会为每个加载到内存的程序设置一个独立的执行环境,包括分配内存空间、建立程序的数据结构、初始化寄存器等。
- 创建进程控制块(PCB):操作系统会为每个加载到内存的程序创建一个进程控制块(PCB)是操作系统中用于管理进程的数据结构,它包含了进程的各种信息和状态,PCB对象会根据自己所包含的信息在内存中找到自己对应的程序,记录和管理程序的运行状态、资源占用情况、优先级等信息,在内存中的PCB对象会形成数据结构方便操作系统的管理(增删查改)。
- 分配资源:操作系统会根据程序的需求分配各种资源,如内存空间、CPU时间片、文件句柄等,以确保程序能够正常运行。
- 运行程序:一旦程序被加载到内存并设置好执行环境,操作系统会按照调度算法将程序放入就绪队列,等待CPU执行。当程序获得CPU时间片时,操作系统会将控制权交给程序,程序开始执行。
为什么加载到内存加载到内存,变成进程之后,我们要给每一个进行形成一个PCB对象呢?因为操作系统要进行管理
通以上的操作其实就将对进程的管理,转化成为了对PCB对象的管理,变成了操作系统对PCB对象所形成的数据结构的增删查改。
在这里我们就可以对进程下定义了:
进程= 内核PCB对象(内核数据结构)+可执行程序
3.2Linux中的PCB
PCB:是操作系统学科的叫法。在Linux中,PCB就是task struct。
我们来见一见Linux中的task struct。这是Linux内核的源代码,里面确实存在这个结构体
task struct中有哪些属性?
命令ps axj可以查看当前的进程
我们生成了一个mytest的可执行程序,并运行它,这时候就变成了进程,程序运行结束进程也就结束了(进程是有“生命”的)。
下面是它所对应的进程,我们发现在mytest进程下面还有一个grep的进程,这是为什么?
这是因为几乎所有的指令,都是程序,运行起来也要变成进程,grep当然也不例外。
- 标示符: 描述本进程的唯一标示符,用来区别其他进程。
在上图中,PID一栏就是标识符,下面在程序中可以通过getpid函数查看PID
除了PID外还有PPID(父进程),在Linux中每个人进程都有一个父进程,而父进程可能有多个子进程。每一次启动进程PID几乎都会变化,因为我的进程是一个新的进程!而父进程不会变,子进程有父进程创建
我们可以查询16986这个进程,发现它就是bash(命令行解释器)。
除了ps ajx查看进程的方式,我们还可以通过proc文件去查看正在运行的程序的信息
cwd表示当前的进程的工作目录:我们在学习C语言的时候,会学习创建文件,如果你没有指定完整的路径,那么这些操作就会在这个工作目录下进行。
exe记录的是进程可执行文件的位置
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器(pc指针): 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/ O状态信息: 包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
3.3通过系统调用创建子进程-fork初识
fork:创建一个子进程
我们先来看一段代码:
我们发现after打印了两次,一旦fork后会创建子进程,这时就会有两个执行分支了,两分支都要执行printf。我们还发现最后一个after,他的父进程就是上一个after,而上面两个的父进程是24662(bash)。fork之后,后续的代码父和子都会执行
再看一段代码:
我们发现,fork是有返回值的;在父进程中fork会返回子进程的ID,因为父进程需要记住创建的子进程。在子进程中,会返回0/-1,返回0就代表fork函数执行成功,返回0来标识子进程,返回-1就代表fork函数出错了
为什么要创建子进程?
当然是要子进程帮父进程去办事,让父子做不同的事情。
看下面的代码:使用if语句进行分流,让父子做不同的事情。
通过返回值的不同来区分父子进程,进而让父子进程去做不同的事情。
fork的原理:
1.每一个进程=内核数据结构+可执行代码和数据
2.创建一个进程的时候,系统中会多一个进程;因此会给子进程创建一个task_struct,但是子进程没有代码和数据进行执行,这时子进程会默认指向父进程的代码和数据。
3.但这样是不行的,这时我们虽然是共享了代码,但要使得这个操作有意义,我们得执行不同的操作,因此fork函数就通过返回值的不同,让父与子去执行代码块不同的部分。当然这代码依旧是来自父亲,fork之后,儿子就帮父亲分担了一部分工作。
4.子进程为什么能去调度代码,是因为子进程会继承父进程中task_struct的大多数属性,以父进程为模板创建子进程。
进一步了解fork的返回值
1.给父进程返回父进程的pid,给子进程返回0,为什么?
父:子 = 1:n,父亲可以有很多儿子,而儿子只有一个父亲,因此子进程需要返回自己的ID给父亲,方便父亲唯一性的确认和控制这个子进程,而父亲是唯一的,不需要进行标识。
2.fork 函数为什么会返回两次?
调用fork只能是父进程去调用fork。如果一个函数,已经运行到了最后开始执行return的时候,这个函数的核心逻辑做完了吗?当然做完了。fork是函数,fork执行完了也需要return。而fork也是有自己的执行代码的,在return之前子进程就已经被创建了,创建好了之后,父子进程代码共享,return也是代码,那么子进程当然也可以执行return,因此fork会返回两次,一次是父进程返回的,另一次当然是子进程返回的。
3.这里还有一个最让人不能理解的地方,同一个变量id,怎么可能既等于0,又大于0 呢?
一个进程崩溃了,会不会影响其它进程?当然是不会的。
进程之间是具有独立性的,互不影响。
这个返回值也被存储在一个名为id的变量中,但这个变量是子进程的局部变量,与父进程中的id变量是完全独立的。
这两个返回值是通过操作系统内核的调度机制实现的,它确保了父进程和子进程在逻辑上是并发的,但实际上它们在物理上可能是交替执行的。由于这两个进程有独立的地址空间,因此它们各自的局部变量(即使变量名相同)也是相互独立的。
这就是为什么你会看到id变量似乎“同时”存入了两个值,但实际上这两个值分别属于两个不同的进程上下文。每个进程都有自己的变量副本,这些变量在进程内部是唯一的,并且互不干扰。
demo代码(一次创建多个子进程)
代码:
#include <stdlib.h>const int num = 10; void worker() {int cnt = 12;while (cnt){printf("child %d is running,cnt:%d\n", getpid(), cnt);cnt--;sleep(1);} } int main() {for (int i = 0; i < num; i++){pid_t id = fork();if (id < 0) break;if (id == 0){//子进程worker();exit(0);//让子进程退出 }printf("father create child process success,child pid:%d\n", id);}//只有父亲进程会执行到这里sleep(15);return 0; }
在主函数 main 中,通过循环创建了10个子进程,每个子进程通过调用 worker 函数来输出信息,然后退出。父进程在创建子进程后会打印子进程的PID,并在所有子进程创建完成后通过 sleep(15) 来延迟一段时间。需要注意的是,父进程在创建子进程时应该检查 fork() 的返回值以处理可能的错误情况。
我们发现最后子进程都退出了,有<defunct>的标识,留下来的只有父进程
相关文章:

Linux--进程(1)
目录 前言 1.冯诺依曼体系结构 2. 操作系统(Operator System)--第一个被加载的软件 3.进程 3.1基本概念 3.2Linux中的PCB 3.3通过系统调用创建子进程-fork初识 fork:创建一个子进程 为什么要创建子进程? fork的原理: 进一步了解fo…...

Qt登录页面
#include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget) {ui->setupUi(this);//接收动图QMovie *mv new QMovie(":/pictrue/luori.gif");ui->loglab->setMovie(…...

软件工程-第8章 软件测试
8.1 软件测试目标域软件测试过程模型 8.2 软件测试技术 8.3 静态分析技术-程序正确性证明 8.4 软件测试步骤 8.5 本章小结...

专业135+总分400+重庆邮电大学801信号与系统考研经验重邮电子信息与通信工程,真题,大纲,参考书。
今年分数出来还是比较满意,专业801信号与系统135,总分400,没想到自己也可以考出400以上的分数,一年的努力付出都是值得的,总结一下自己的复习心得,希望对大家复习有所帮助。专业课:(…...

主干网络篇 | YOLOv8改进之在主干网络中引入密集连接卷积网络DenseNet
前言:Hello大家好,我是小哥谈。DenseNet(密集连接卷积网络)是一种深度学习神经网络架构,它在2017年由Gao Huang等人提出。DenseNet的核心思想是通过密集连接(dense connection)来促进信息的流动和共享。在传统的卷积神经网络中,每个层的输入只来自于前一层的输出。而在…...
lavarel的php程序是顺序执行,用pdo mysql连接池好像没有什么用啊。没有办法挂起等待啊,为什么要用连接池,应用场景是什么
Laravel 的 PHP 程序确实是基于请求-响应模式,每个请求都是顺序执行的。这意味着一旦一个请求开始处理,它会按照代码的顺序执行,直到完成并返回响应。因此,从表面上看,使用 PDO 或 MySQL 连接池在 Laravel 中可能看起来…...
spring maven项目 实时接口请求次数及时间发送到grafana监控_亲测成功
spring maven项目 实时接口请求次数及时间发送到grafana监控_亲测成功 说明: spring项目使用aop方式拿到请求接口uri,算出从请求到响应的耗时, 然后使用statsd包发送udp数据给grafana去展示. 完全不影响代码性能和稳定性,因为使用udp协议发送,就算grafana那边挂了,也不影响项…...

银行数字人民币系统应用架构设计
2019年10月,01区块链联合数字资产研究院发布了《人民币3.0:中国央行数字货币运行框架与技术解析》,从数字货币界定和人民币发展历程出发,区分了央行数字货币与比特币、移动支付等的区别,全面介绍了央行数字货币的发展历…...

流畅的 Python 第二版(GPT 重译)(三)
第五章:数据类构建器 数据类就像孩子一样。它们作为一个起点是可以的,但要作为一个成熟的对象参与,它们需要承担一些责任。 马丁福勒和肯特贝克 Python 提供了几种构建简单类的方法,这些类只是一组字段,几乎没有额外功…...

06-验证浮点数输入
鉴于shell脚本的限制和本事,浮点数(或“实数”)的验证过程乍一看似乎让人望而生畏,不过考虑到浮点数只不过是由小数点分隔的两个整数,再配合能够在脚本中引用其他脚本的能力(validint)ÿ…...

shell实现查询进程号并批量kill(脚本)
问题或需求描述 在shell中,如果你想通过命令行查询出一系列匹配某个关键词的进程,并使用xargs命令批量结束这些进程,可以按照以下步骤操作: # 查询并提取进程号 pgrep -f "关键词" | xargs kill# 或者,如果…...
【软考】蠕虫病毒
目录 一、概念1.1 说明 二、示例2.1 震网2.2 熊猫烧香2.2 红色代码2.3 爱虫病毒 一、概念 1.1 说明 1.一段可以借助程序自行传播的程序或代码 二、示例 2.1 震网 1.Stuxnet 2.利用系统漏洞破坏工业基础设施,攻击工业控制系统 2.2 熊猫烧香 1.是一种经过多次变种…...

大模型知识点汇总——分布式训练
PS:本篇只在宏观上介绍相关概念和技术,不做数学推导和过于细节介绍,旨在快速有一个宏观认知,不拘泥在细节上,导致很混乱。 涉及技术名词 分布式框架等涉及的技术名词很多,很容易让人眼花缭乱,…...
java之网络编程
网络编程之TCP/IP协议 网络编程分为两个不同的层次:一是基于Socket的低层次网络编程,二是基于URL的高层次网络编程 高低层次就是通信协议的高低层次,Socket采用TCP、UDP等协议,这些协议属于低层次的通信协议;URL采用H…...

【Linux】Centos7安装redis
目录 下载安装包安装1.解压2.环境安装3.查看redis的安装路径4.将之前redis的配置文件,复制到安装路径下(新建一个文件夹并复制)5.redis 设置默认后台启动,修改配置文件6.启动redis服务默认启动通过配置文件启动查看进程 7.开放637…...

蓝桥杯(2):python基础算法【上】
时间复杂度、枚举、模拟、递归、进制转换、前缀和、差分、离散化 1 时间复杂度 重要是看循环,一共运行了几次 1.1 简单代码看循环 #时间复杂度1 n int(input()) for i in range(1,n1):for j in range(0,i):pass ###时间复杂度:123....nn(1n)/2 所以…...
一个js正则,轻松去除字符串里的\n\t空格
推荐一款AI网站,免费使用GPT3.5,戳此入👇:AI写作 在Node.js中,如果你想要从字符串中全局去除换行符(\n)、制表符(\t)和空格,你可以使用正则表达式与String.prototype.replace()方法结合使用。下面是一个简…...

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(四)—— 过拟合和欠拟合
政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: Tensorflow与Keras实战演绎 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 通过增加容量或提前停止来提高性能。 在深度学习中&…...

RuoYi-Vue若依框架-代码生成器的使用
代码生成器 导入表 在系统工具内找到代码生成,点击导入,会显示数据库内未被导入的数据库表单,选择自己需要生成代码的表,友情提醒,第一次使用最好先导入一张表进行试水~ 预览 操作成功后可以点击预览查看效果&…...

AI PPT生成工具 V1.0.0
AI PPT是一款高效快速的PPT生成工具,能够一键生成符合相关主题的PPT文件,大大提高工作效率。生成的PPT内容专业、细致、实用。 软件特点 免费无广告,简单易用,快速高效,提高工作效率 一键生成相关主题的标题、大纲、…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
用js实现常见排序算法
以下是几种常见排序算法的 JS实现,包括选择排序、冒泡排序、插入排序、快速排序和归并排序,以及每种算法的特点和复杂度分析 1. 选择排序(Selection Sort) 核心思想:每次从未排序部分选择最小元素,与未排…...