操作系统文件系统

1 基本概念

1.1 文件系统和文件

1.1.1 简述

文件系统: 一种用于持久性存储的系统抽象

  • 在存储器上: 组织, 控制, 导航, 访问和检索数据
  • 大多数计算机系统包含文件系统
  • 个人电脑, 服务器, 笔记本电脑
  • ipod, Tivo/机顶盒, 手机/掌上电脑
  • google可能是由一个文件系统构成的

文件: 文件系统中一个单元的相关数据在操作系统中的抽象

1.1.2 文件系统的功能

  • 分配文件磁盘空间
  • 管理文件块(哪一块属于那一个文件)
  • 管理空闲空间(哪一块是空闲的)
  • 分配算法(策略)
  • 管理文件集合
  • 定位文件及其内容
  • 命名: 通过名字找到文件的接口
  • 最常见: 分层文件系统
  • 文件系统类型(组织文件的不同方式) 
  • 提供的便利及特征
  • 保护: 分层来保护数据安全
  • 可靠性/持久性: 保持文件的持久即便发生崩溃, 媒体错误, 攻击等 

1.1.3 文件

文件属性:

名称, 类型, 位置, 大小, 保护, 创建者, 创建时间, 最近修改时间...

文件头:

  • 在存储元数据中保存了每个文件的信息
  • 保存文件的属性
  • 跟踪哪一块存储块属于逻辑上文件结构的哪个偏移 

1.2 文件描述符

1.2.1 对于文件操作的一些背景

文件使用方式:

使用程序必须在使用前先"打开"文件

f = open(name, flag);...
close(f);

内核跟踪每个进程打开的文件:

  • 操作系统为每个进程维护一个打开文件表
  • 一个打开文件描述符是这个表中的索引

操作系统需要一些元数据来管理打开文件:

  • 文件指针: 指向最近的一次读写位置, 每个打开了这个文件的进程都这个指针
  • 文件打开计数: 记录文件打开的次数 --- 当最后一个进程关闭了文件时, 允许将其从打开文件表中移除
  • 文件磁盘位置: 缓存数据访问信息
  • 访问权限: 每个进程访问模式信息

用户视图:

持久的数据结构

系统访问接口:

  • 字节的集合(UNIX)
  • 系统不会关心你想存储在磁盘上的任何的数据结构

操作系统内部视角:

  • 块的集合(块是逻辑转换单元, 而扇区是物理转换单元)
  • 块大小 <==> 扇区大小: 在UNIX中, 块的大小是4KB

举例:

当一个用户的需求为, 访问2 - 12字节空间会发生以下事情:

  • 文件系统获取字节所在的块
  • 返回块的对应部分

如果是要写2 - 12字节的话:

  • 获取块
  • 修改块内对应部分
  • 写回块

在文件系统中的所有操作都是在整个块空间上进行的: 即使每次只访问一个字节, 也会缓存目标数据所属的整个块, 也就是4096字节.

用户的文件访问方式(在系统层面需要知道用户的访问模式):

  • 顺序访问: 按字节依次读取(几乎所有的访问都是这种方式)
  • 随机访问: 从中间读写
  • 不常用, 但是仍然重要. 例如, 虚拟内存支持文件: 内存也存储在文件中
  • 更加快速 - 不希望获取文件中间的内容的时候也必须先获取块内所有字节
  • 基于内容访问: 通过特征
  • 许多系统不提供此种访问方式. 相反, 数据库是建立在索引内容的磁盘访问上(需要高效的随机访问) 

1.2.2 文件

文件内部结构:

  • 无结构
  • 单词, 比特的队列
  • 简单记录结构
  • 固定长度
  • 可变长度 
  • 复杂结构
  • 格式化的文档(如, MS Word, PDF)
  • 可执行的文件 

这些结构, 对于相应的应用程序可以理解, 但是站在操作系统的角度上, 只会知道这个文件的字节流, 不会知道这个文件具体的内容.

访问权限:

多用户系统中的文件共享是很必要的, 所以需要有访问控制:

  • 谁能够获得哪些文件的哪些访问权限
  • 访问模式: 读, 写, 执行, 删除, 列举等

文件访问控制列表(ACL)可以实现以上需求

  • <文件实体, 权限>

Unix模式

  • <用户 | 组 | 所有人, 读 | 写 | 可执行>
  • 用户ID识别用户, 表明每个用户所允许的权限及保护模式
  • 组ID允许用户组成组, 并制定了组访问权限

多用户同时访问时:

  • 指定多用户/客户如何同时访问共享文件
  • 和过程同步算法相似
  • 因磁盘I/O和网络延迟而设计简单
  • Unix文件系统(UFS)语义
  • 对打开文件的写入内容立即对其他打开同一文件的其他用户可见
  • 共享文件指针允许多用户同时读取和写入文件 
  • 会话语义
  • 写入内容只有当文件关闭时可见 
  • 一些操作系统和文件系统提供该功能 

1.3 目录

文件以目录的方式组织起来, 目录是一类特殊的文件, 每个目录都包含了一张表<name, pointer to file header>.

目录和文件是成树形结构(早期的文件系统是扁平的, 只有一层目录)

层次命名空间

目录的典型操作:

  • 搜索文件
  • 创建文件
  • 删除文件
  • 枚举目录
  • 重命名文件
  • 在文件系统中遍历一个路径

操作系统应该只允许内核模式修改目录:

  • 确保映射的完整性
  • 应用程序能够读目录(如ls)

 

文件名列表:

  • 用文件名的线性列表实现, 包含了指向数据块的指针
  • 编程简单
  • 执行耗时
  • Hash表 - hash数据结构的线性表
  • 减少目录搜索时间
  • 碰撞 - 两个文件名的hash值相同
  • 固定大小 

路径遍历:

  • 名字解析: 逻辑名字转换成物理资源(如文件)的过程
  •  在文件系统中: 到实际文件的文件名(路径)
  • 遍历文件目录直到找到目标文件

 

  • 举例: 解析"/bin/ls"
  • 读取root的文件头(在磁盘固定位置)
  • 读取root的数据块: 搜索"bin"项
  • 读取bin的大小
  • 读取bin的数据块: 搜索"ls"项
  • 读取ls的文件头 
  • 当前工作目录(可以提高效率, 因为已经对当前目录作了缓存)
  • 每个进程都会指向一个文件目录用于解析文件名
  • 允许用户指定相对路径来代替绝对路径 

文件系统的挂载:

  • 一个文件系统需要先挂载才能被访问
  • 一个未被挂载的文件系统被挂载在挂载点上 

1.4 文件别名

有可能会两个或多个文件名关联同一个文件:

  • 硬链接: 多个文件项指向一个文件, 这个多个文件的文件内容都是同一文件
  • 软链接: 以"快捷方式"指向其他文件, 这个文件的文件内容是另一个文件的文件路径
  • 通过存储真实文件的逻辑名称来实现

如果删除一个有别名的文件会如何:

  • 如果用的软链接方式, 这个别名将成为一个"悬空指针"
  • 如果用的硬链接方式, 只是引用计数减少了1

Backpointers方案:

  • 每个文件有一个包含多个backpointers的列表, 所以删除所有的backpointers
  • Backpointers使用菊花链管理

添加一个间接层: 目录项数据结构

  • 链接 - 已存在文件的另外一个名字(指针)
  • 链接处理 - 跟随指针来定位文件

这个别名机制会存在潜在的问题 -- 循环, 也就是有可能树状结构变成环状, 需要保证没有环:

  • 只允许到文件的链接, 不允许在子目录的链接
  • 每增加一个新的链接都要用循环检测算法确定是否合理

更多实践:

  • 限制路径可遍历文件目录的数量

1.5 文件系统种类

  • 磁盘文件系统
  • 文件存储在数据存储设备上, 如磁盘
  • 例如: FAT, NTFS, ext2/3, ISO9660, 等
  • 数据库文件系统
  • 文件根据其特征是可被寻址(辨识)的
  • 例如: WinFS
  • 日志文件系统
  • 记录文件系统的修改/事件
  • 例如: Journaling file system
  • 网络/分布式文件系统

例如: NFS, SMB, AFS, GFS

分布式文件系统:

分布式文件系统一大特点就是文件可以通过网络被共享:

  • 文件位于远程服务器
  • 客户端远程挂载服务器文件系统
  • 标准系统文件访问被转换成远程访问
  • 标准文件共享协议: NFS for Unix, CIFS for Windows

分布式文件系统的问题:

  • 客户端和客户端上的用户辨别起来很复杂
  • 例如, NFS是不安全的
  • 一致性问题
  • 特殊/虚拟文件系统

2 虚拟文件系统

文件系统是分层结构的:

  • 上层: 虚拟(逻辑)文件系统
  • 底层: 特定文件系统模块

设计虚拟文件系统的目的:

  • 对所有不同文件系统的抽象

虚拟文件系统功能:

  • 提供相同的文件和文件系统接口
  • 管理所有文件和文件系统关联的数据结构
  • 高效查询例程, 遍历文件系统
  • 与特定文件系统模块的交互

抛开差异性, 一个基本的文件系统应该包含的数据结构有:

  • 卷控制块(Unix: "superblock")
  • 每个文件系统一个
  • 文件系统详细信息
  • 块, 块大小, 空余块, 计数/指针等
  • 文件控制块(Unix: "vnode" or "inode")
  • 每个文件一个
  • 文件详细信息
  • 许可, 拥有者, 大小, 数据库位置等
  • 目录节点(Linux: "dentry")
  • 每个目录项一个(目录和文件)
  • 将目录项数据结构及树型布局编码或树型数据结构
  • 指向文件控制块, 父节点, 项目列表等

3 数据块缓存

数据缓存有以下几种情况:

  • 数据块按需读入内存
  • 提供read()操作
  • 预读: 预选读取后面的数据块
  • 数据块使用后被缓存
  • 假设数据将会再次被使用
  • 写操作可能被缓存和延迟写入
  • 两种数据块缓存方式
  • 普通缓冲区缓存
  • 页缓存: 统一缓存数据块和内存页

操作系统希望将硬盘的缓存同内存的页式管理结合在一起, 实现一个基于分页的缓存机制, 使得硬盘的数据可以更好的被上层应用所使用:

  • 分页要求
  • 当需要一个页时才将其载入内存
  • 支持存储
  • 一个页(在虚拟地址空间中)可以映射到一个本地文件中(在二级存储中)

文件数据块的页缓存:

  • 在虚拟内存中文件数据块被映射成页
  • 文件的读/写操作被转换成对内存的访问
  • 可能导致缺页和/或设置成脏页
  • 问题: 页置换 - 从进程或文件页缓存中? 

4 打开文件的数据结构

打开文件就是把硬盘里面相应文件的文件控制块的内容读到内存中来, 然后把相关信息放入打开文件列表中, 其中专门设置了一个index, 把index作为fd返回给应用程序. 接下来应用程序都是基于这个fd对文件进行操作, 所以有以下.

打开文件描述:

  • 每个被打开的文件一个
  • 文件状态信息
  • 目录项, 当前文件指针, 文件操作设置等

打开文件表:

  • 一个进程一个
  • 一个系统级的
  • 每个卷控制块也会保存一个列表
  • 所以如果有文件被打开将不能被卸载

因为文件是存在硬盘中, 所有对该文件有操作权限的进程都可以进行该文件的相应操作, 所以可能会出现多进程同时访问一个文件的情况. 所以会存在用锁来进行同步互斥操作:

  • 一些操作系统和文件系统提供该功能
  • 调节对文件的访问
  • 强制和劝告
  • 强制: 根据锁保持情况和需求拒绝访问
  • 劝告: 进程可以查找锁的状态来决定怎么做

5 文件分配

大多数文件都很小, 所以需要对小文见提供强力的支持, 所以块的空间不能太大. 然而部分文件非常大, 所以也必须支持大文件(64 - bit偏移), 大文件访问需要相当高效.

5.1 为文件分配数据块

分配方式:

  • 连续分配
  • 链式分配
  • 索引分配

评价分配方式指标:

  • 高效: 如存储利用(外部碎片)
  • 表现: 如访问速度

5.2 分配数据块方式

5.2.1 连续分配

文件头(文件控制块)指定起始块和长度.

分配策略(与连续内存分配类似):

  • 最先匹配
  • 最佳匹配
  • ...

优势:

  • 文件读取表现好
  • 高效的顺序和随机访问

劣势:

  • 碎片
  • 文件增长问题

5.2.2 链式分配

文件以数据块链表方式存储, 文件头包含了到第一块和最后一块的指针

优势:

  • 创建, 增大, 缩小很容易
  • 没有碎片

劣势:

  • 不可能进行真正的随机访问
  • 可靠性(破坏了一个链)

5.2.3 索引分配

为每个文件创建一个名为索引数据块的非数据数据块, 到文件数据块的指针列表, 文件头包含了索引数据块.

优势:

  • 创建, 增大, 缩小很容易
  • 没有碎片
  • 支持直接访问

劣势:

  • 当文件很小时, 存储索引的开销
  • 如何处理大文件?

针对大文件的索引块分配:

  • 链式索引块
  • 多级索引块

大文件文件头包含13个指针:

  • 10个指针指向数据块
  • 第11个指针指向间接数据块
  • 第12个指针指向二重间接数据块
  • 第13个指针指向三重间接数据块

这样做的影响:

  • 提高了文件大小限制阈值
  • 动态分配数据块, 文件扩展很容易
  • 小文件开销小
  • 只为大文件分配间接数据块, 大文件在访问间接数据块是需要大量的查询

6 空闲空间列表

空闲空间列表用来跟踪在存储中的所有未分配的数据块, 空闲空间列表存储在哪里? 空闲空间列表的最佳数据结构是什么样的?

6.1 空闲空间列表的形式

位图:

可以用位图代表空闲数据块列表(例如1111000010010101011101), 如果位图的第i位为0, 表明数据块i是空闲的, 反之则已分配.

位图的方式使用简单但是可能会是一个big vector:

  • 160GB disk -> 40M blocks -> 5MB worth of bits
  • 然而, 如果空闲空间在磁盘中均匀分布, 那么在找到"0"之前需要扫描n / rn表示磁盘上数据块的总数, r表示空闲块的数目

用这种方式, 需要保证一致性, 也就是说, 要使用位图形式的空闲空间列表的话, 需要先把其读入内存, 但是如果位图发生变化, 需要保证内存中和硬盘中位图的一致性, 即需要保护:

  • 指向空闲列表的指针
  • 位图
  • 必须保存在磁盘上
  • 在内存和磁盘拷贝可能有所不同
  • 不允许block[i]在内存中的状态为bit[i] = 1而在磁盘中bit[i] = 0
  • 解决
  • 在磁盘上设置bit[i] = 1
  • 分配block[i]
  • 在内存中设置bit[i] = 1

6.2 其他方式

  • 链式列表
  • 分组列表
  • ... 

7 多磁盘管理 - RAID

分区: 硬件磁盘的一种适合操作系统指定格式的划分

卷: 一个拥有一个文件系统实例的可访问的存储空间

  • 通常常驻在磁盘的单个分区上

单磁盘, 读写速度较慢, 使用多个并行磁盘来增加:

  • 吞吐量(通过并行)
  • 可靠性和可用性(通过冗余)

RAID - 冗余磁盘阵列

  • 各种磁盘管理技术
  • RAID levels: 不同RAID分类(如RAID - 0, RAID - 1, RAID - 5)

实现:

  • 在操作系统内核: 存储/卷管理
  • RAID硬件控制器(I/O)

RAID优势:

  • 数据块分成多个子块, 存储在独立的磁盘中(和内存交叉类似)
  • 通过更大的有效块大小来提供更大的磁盘带宽
  • 可靠性成倍增长
  • 读取性能线性增加(向两个磁盘写入, 从任何一个读取)

8 磁盘调度

磁盘调度是在OS层面通过重新组织I/O请求顺序来有效减少磁盘访问开销. 

磁盘访问的开销是很大的, 和内存访问的速度差了好几个量级:

  • 读取或写入时, 磁头必须被定位在期望的磁道, 并从所期望的扇区开始.
  • 寻道时间: 定位到期望的磁道所花费的时间
  • 旋转延迟: 从扇区的开始处到到达目的处所花费的时间
  • 平均旋转延迟时间 = 磁盘旋转一周时间的一半T_{r} = \frac{1}{2r}

 计算磁盘的I/O传输时间有以下几个参数:

  • T_{a} = 访问时间
  • T_{s} = 寻道时间
  • T_{r} = 旋转延迟
  • T = 传输时间
  • b  = 传输的比特数
  • N = 磁道上的比特数
  • r  = 磁盘转数

有:

T_{a} = T_{s} + \frac{1}{2r} + \frac{b}{rN}

T_{r} = \frac{1}{2r}

T_{t} = \frac{b}{rN}

其中, 寻道时间是性能上区别的原因, 对单个磁盘, 会有一个I/O请求数目, 如果请求是随机的, 那么表现会很差.

具体的调度策略有:

  • FIFO, 先进先出
  • 按顺序处理请求
  • 公平对待所有进程
  • 在有很多进程的情况下, 接近随机调度的性能
  • 最短服务优先
  • 选择从磁臂当前位置需要移动最少的I/O请求
  • 总是选择最短寻道时间
  • 容易使得进程饥饿
  • SCAN方法
  • 磁臂在一个方向上移动, 满足所有未完成的请求, 知道磁臂到达该方向上最后的磁道
  • 调换方向
  • 有时被成为elevator algorithm

优化1(C-SCAN):

  • 限制了仅在一个方向上扫描
  • 当最后一个磁道也被访问过了后, 磁臂返回到磁盘的另外一端再次进行扫描

优化2(C-LOOK):

  • C-SCAN的改进版本
  • 磁臂先到达该方向上最后一个请求处, 然后立即反转
  •  N-Step-SCAN
  • 在SSTF,  SCAN及CSCAN几种调度算法中, 都可能出现磁臂停留在某处不动的情况, 例如进程反复请求对某一磁道的I/O操作. 我们把这一现象成为"磁臂粘着".
  • N-Step-SCAN算法是将磁盘请求队列分成若干个长度为N的子队列, 磁盘调度将按照FCFS算法依次处理这些子队列. 而每处理一个队列时又是按SCAN算法, 对一个队列处理完后, 再处理其他队列
  • 当正在处理某子队列时, 如果又出现新的磁盘I/O请求, 便将新请求进程放入其他队列, 这样就可避免出现粘着现象

FSCAN:

  • FSCAN算法实质上是N步SCAN算法的简化, 即FSCAN只将磁盘请求队列分成两个子队列. 
  • 一个是由当前所有请求磁盘I/O的进程形成的队列. 由磁盘调度按SCAN算法进行处理. 在处理某队列期间, 将新出现的所有请求磁盘I/O的进程, 放入另一个等待处理的队列. 这样, 所有的新请求都将被推迟到下一次扫描时处理.

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

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

相关文章

c++代码整洁之道pdf_别再问如何用python提取PDF内容了

作者&#xff1a;陈熹 来源&#xff1a;早起Python大家好&#xff0c;在之前的办公自动化系列文章中我们已经详细介绍了如何使用python批量处理PDF文件&#xff0c;包括合并、拆分、水印、加密等操作。今天我们再次回到PDF&#xff0c;详细讲解如何使用python从PDF提取指定的信…

查看文章影响因子的插件_Scholarscope--在新版PubMed中实现基于影响因子的文献筛选...

小编之前介绍过如何在Pubmed上直接显示杂志影响因子的方法&#xff0c;这个方法主要是依托Scholarscope插件&#xff0c;其实除了显示影响因子&#xff0c;这个插件还可以帮助大家根据影响因子筛选文献哦&#xff0c;操作也很简单&#xff0c;只要生成自定义过滤器即可&#xf…

leetcode32 --- longestValidParentheses

1 题目 给你一个只包含 ( 和 ) 的字符串&#xff0c;找出最长有效&#xff08;格式正确且连续&#xff09;括号子串的长度。 2 解法 2.1 动态规划方法 维护一个字符串长度的数组cur_max_len, 第i个元素代表以当前(或者)结束的最长有效括号的长度. 这样就会利用动态规划递推…

armitage识别不了漏洞_Shiro RememberMe 漏洞检测的探索之路

前言Shiro 是 Apache 旗下的一个用于权限管理的开源框架&#xff0c;提供开箱即用的身份验证、授权、密码套件和会话管理等功能。该框架在 2016 年报出了一个著名的漏洞——Shiro-550&#xff0c;即 RememberMe 反序列化漏洞。4年过去了&#xff0c;该漏洞不但没有沉没在漏洞的…

css响应式布局_用 CSS Grid 布局制作一个响应式柱状图

最新一段时间比较喜欢玩弄图表&#xff0c;出于好奇&#xff0c;我想找出比较好的用 CSS 制作图表的方案。开始学习网上开源图表库&#xff0c;它对我学习新的和不熟悉的前端技术很有帮助&#xff0c;比如这个&#xff1a;CSS Grid。今天和大家分享我学到的新知识&#xff1a;如…

vs code 插件_[VSCode插件开发] 由浅入深,带你了解如何打造百万级产品

去年&#xff0c;笔者有幸在微软技术暨生态大会上做了个演讲&#xff0c;主题是“从零开始开发一款属于你的 Visual Studio Code 插件”。演讲内容主要覆盖了VS Code插件开发的四个方面&#xff1a;设计、实现、推广和维护。作为一个开发者&#xff0c;我们往往会把大多数的时间…

leetcode45 --- jump

1 题目 给定一个非负整数数组&#xff0c;你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 假设你总是可以到达数组的最后一个位置。 2 解法 2.1 从终点遍历的方法(时间复杂度)…

python怎么查看网页编码格式_怎么用python爬取网页文字?

用Python进行爬取网页文字的代码&#xff1a;#!/usr/bin/python# -*- coding: UTF-8 -*-import requestsimport re# 下载一个网页url htt用python进行爬取网页文字的代码&#xff1a;#!/usr/bin/python# -*- coding: UTF-8 -*-import requestsimport re# 下载一个网页url htt…

leetcode41 --- firstMissingPositive

1 题目 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 2 解法 最笨的方法是从1开始试, 看1在数组里面是否出现过, 2, 3, ....不过时间复杂度是. 2.1 hash 可以考虑…

计算机网络中的数据链路层

概述 结点: 主机, 路由器 链路: 网络中两个结点之间的物理通道, 链路的传输介质主要有双绞线, 光纤和微波, 分为有线链路和无线链路. 数据链路: 网络中两个结点之间的逻辑通道, 把实现控制数据传输协议的硬件和软件加到链路上就构成数据链路. 帧: 链路层的协议数据单元…

jnativecpp.dll一定要放到系统目录下吗_电脑硬盘有必要分区吗,分几个区最好?...

购买电脑后&#xff0c;必不可少的一个步骤就是对电脑硬盘进行分区了&#xff0c;其实硬盘分区也是有讲究的&#xff0c;并不是随意分的&#xff0c;下面租物租就给大家介绍下电脑分区的知识。硬盘分区可以提高数据的安全&#xff0c;防止数据丢失&#xff0c;但是防止数据丢失…

数据结构中的树

1. 树 即是以层次化方式组织和存放数据的特定数据结构 边: 节点与节点之间的连线 根节点: 叶子节点: 度: 节点的度数即为其分叉数, 即其子节点个数. 整棵树的度数是所有节点中度数的最大值 节点深度: 根节点到该节点的唯一路径长(即边的数量) 树高: 所有节点中深度的最大…

排序算法 --- 堆排序

根据大顶堆的描述, 父节点的值始终大于子节点(如果有的话)的值, 再加上堆是完全二叉树, 可以用数组表示, 那么就可以用来进行排序. 具体做法就是, 对于随机排列的数组: 1. 首先将其构建成一个大顶堆, 根据堆的性质, 此时堆顶就是最大值. 2. 把堆顶元素与数组最后一个元素进行…

数据结构中的树 --- 红黑树

红黑树是一种几近平衡的二叉搜索树, 但不是AVL树. 1 红黑树的一些特殊性质 1. 每个节点皆为红色或者黑色。 2. 根节点是黑色。 3. 每个叶子节点&#xff08;NIL&#xff09;是黑色(注意, 每个叶子节点必须都为空节点, 也就是指针为nullptr, 无key值)。 4. 每个红色结点的两…

c++数据结构中 顺序队列的队首队尾_数据结构与算法—队列详解

前言栈和队列是一对好兄弟&#xff0c;前面我们介绍过数据结构与算法—栈详解&#xff0c;那么栈的机制相对简单&#xff0c;后入先出&#xff0c;就像进入一个狭小的山洞&#xff0c;山洞只有一个出口&#xff0c;只能后进先出(在外面的先出去)。而队列就好比是一个隧道&#…

phpstudy apache无法启动_phpstudy和wamp哪个好

刚刚接触php的同学会想知道phpstudy和wamp的区别有哪些&#xff1f;phpstudy和wamp哪个好&#xff1f;下面我们来总结一下。一&#xff1a;phpstudy好还是wamp好php的运行环境配置对于新手都是一件比较困难的事情&#xff0c;但是对于高手配置是一件繁琐的事情&#xff0c;个人…

哈夫曼树(最优二叉树)

1 用途 现在假如有一个需求, 把一个很长的字符串用二进制编码的形式存储, 要尽可能的占用较小空间, 那么应该怎么存储呢. 肯定是要确定每个字母的编码方法, 比如 001是A, 010是B等. 那么要怎么确定每个字符编成什么二进制码从而使得总长度最短? 一个根本思想是, 出现频率高的…

visual studio无法更新_VS Code Python 扩展 5 月更新

(给Python编程开发加星标&#xff0c;提升编程技能.)12 号&#xff0c;微软在官方博客发布了 VS Code 编辑器中 Python 扩展的 5 月更新&#xff0c;其中只有一个较为重要的特性&#xff1a;新增了浏览选择 Python 解释器的能力。增加这个功能&#xff0c;主要是为了让选择或变…

至强cpu型号列表_装机必看——CPU型号参数详解

装机必看——CPU型号参数详解——装机个人练习生-海在初步解了电脑构成后&#xff0c;我们DIY装机首先要看的就是如何选CPU&#xff0c;今天就带大家详细学习CPU的各类数据。说到CPU&#xff0c;我们先来介绍下生产CPU的两大公司——Intel和AMD。这两家公司相爱相杀接近50年了&…

多路平衡查找树 --- B(B-)树

1 简介 可以用阶数来描述B树, 一棵M阶B树代表着该B树最多有M个孩子节点. 如果M为2, 那么该B树就是一棵二叉搜索树. 一棵M阶B树具有以下性质: 1. 每个节点最多有M - 1个关键字. 跟普通的树不同, B树的关键字有多个. 2. 根节点最少可以只有一个关键字. 3. 非根节点至少有k个关…