-
顺序文件
记录在文件中的排列顺序
是由记录进入存储介质的次序
决定的。
换言之,文件物理结构中记录的排列顺序
和 文件逻辑结构中记录的排列顺序
一致。 -
顺序文件的组织形式
连续文件:次序相继的两个物理记录
在存储介质
上的存储位置是相邻的
串联文件:物理记录之间的次序由指针相链表示 -
操作特点
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 ]