12.2 顺序文件

  • 顺序文件
    记录在文件中的排列顺序 是由 记录进入存储介质的次序 决定的。
    换言之,文件 物理结构中记录的排列顺序 和 文件 逻辑结构中记录的排列顺序 一致。

  • 顺序文件的组织形式
    连续文件次序相继的两个物理记录存储介质 上的存储位置是相邻
    串联文件:物理记录之间的次序由指针相链表示

  • 操作特点
    1、顺序文件是根据 记录或序号的相对位置 来进行存取的文件组织方式
    2、便于进行 顺序存取,不便于进行 直接存取。若要取 第 i 个记录,必须先读出 前 i-1 个记录 ,对于 等长连续记录文件 可以进行 折半查找(因为文件序号是有序的)。
    3、插入新的记录时只能加在 文件末尾
    4、删除记录不是真正的删除,只是对该条记录做一个特殊标记。
    5、更新文件中的某个记录,则必须将 整个文件 进行复制,生成 新的文件

  • 文件的批处理方式
    通常将顺序文件做成有序文件,称为 主文件,同时将所有的 操作 作成一个 事务文件(经过排序也成为了 有序文件)。
    然后将 这两个文件 合为一个 新的主文件 ,有点类似于 归并排序
    但时要特别注意:
    1、对于 事务文件 中的每个 操作 首先要判别其 合法性
    2、事务文件 可能存在多个操作是对主文件中 同一个记录 进行的

  • 磁带
    磁带是一种 顺序存取设备,因此存储在磁带上的文件只能是 顺序文件
    磁带文件 适合于文件的数据量大,记录变化少,制作批量修改的情况。
    在对磁带文件做修改时,一般需用 另一条复制带原带上不变的记录 复制一遍,同时在复制过程中插入新的记录和用更改后的新记录代替原记录写入。
    为了修改方便起见,要求待复制的顺序文件按 关键字 或者 逻辑记录号 有序。

  • 磁带的批处理过程
    主文件 为待修改的原始文件,存放在一条磁带上。
    事务文件 是所有的修改请求集中构成的一个文件,存放在另一条磁带上。
    尚需要 第三台磁带 作为 新的主文件的存储介质
    主文件按关键字升序(或降序)有序事务文件 必须和 主文件相同的有序关系
    首先对 事务文件 进行排序,然后将 主文件事务文件 归并成一个 新的主文件 ,示意图如下:
    在这里插入图片描述
    归并过程如下:
    顺序读出 主文件事务文件 的记录,比较它们的 关键字 并分别进行处理:
    对于关键字不匹配的主文件中的记录,直接将其写入 新主文件 中(更改和删去记录时,要求其关键字相匹配)。
    删去不用写入。
    更改则要将更改后的新记录写入新的主文件中。
    插入不要求关键字相匹配,可直接将事物文件上要插入的记录写到新主文件的适当位置。

  • 批处理实例:银行账目文件
    主文件 保存着 各储户的存款余额
    每个储户 作为一个 记录关键字储户账号
    记录 按关键字从小到大顺序排列。
    一天的 存入和支出 集中在一个 事务文件 中,事务文件中的记录也是按账号排序。
    如下图:
    在这里插入图片描述

  • 批处理算法

void Merge(FILE *f, FILE *g, FILE *h)
{
	// 按关键字递增有序的费控顺序文件 f 和 g 归并得到新文件 h,三个文件均已打开,
	// f 和 g 为只读文件,文件中各附加一个最大关键字记录,且 g 文件中对该记录的
	// 操作为插入。h 为只写文件。
	fread(&fr, sizeof(RcdType), 1, f );
	fread(&gr, sizeof(RcdType), 1, g );
	while(!feof(f) || !feof(g))
	{
		switch
		{
			case fr.key < gr.key: //复制旧的主文件中的记录
				fwrite(&fr, sizeof(RcdType), 1, h);
				if(!feof(f))
				{
					fread(&fr, sizeof(RcdType), 1, f );
				}
				break;
			case gr.code == 'D' && fr.key == gr.key: // 删除“旧”猪文件中记录,即不复制
				if(!feof(f))
				{
					fread(&fr, sizeof(RcdType), 1, f );
				}
				if(!feof(g))
				{
					fread(&gr, sizeof(RcdType), 1, g );
				}
				break;
			case gr.code == 'I' && fr.key > gr.key: // 插入,函数P把gr加工为h的结构
				fwrite(P(gr), sizeof(RcdType), 1, h);
				if(!feof(g))
				{
					fread(&gr, sizeof(RcdType), 1, g );
				}
				break;
			case gr.code == 'U' && fr.key == gr.key: // 更改“旧”主文件中记录
				fwrite(Q(fr, gr), sizeof(RcdType), 1, h); // 函数 Q 将 fr 和 gr 归并成一个 h 结构的记录
				if(!feof(f))
				{
					fread(&fr, sizeof(RcdType), 1, f );
				}
				if(!feof(g))
				{
					fread(&gr, sizeof(RcdType), 1, g );
				}
				break;
			default
				ERROR();
		}
	}
}
  • 批处理算法时间性能分析
    主文件 中包含 n 个记录,事务文件 中包含 m 个记录。
    一般情况下,事务文件较小,可以进行内部排序,则时间复杂度为 O(mlom)
    内部归并的时间复杂度为 O(n+m)
    总的内部处理的时间复杂度为 O(mlogm+n)
    假设缓冲区大小为 s 个记录,且所有的输入输出都是通过缓冲区进行的
    整个批处理过程 中,读写外存的总次数2 * [ m / s ] + 2 * [ (m+n) / s ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值