关键词:文件系统,静态链式存储,二分查找
看不懂别人的代码,可以来看这个,逻辑相当简单暴力, 只是需要基础扎实, 强烈建议手搓实现以下;
相信大家第一时间能观察到:
1)如果不考虑重复与排序,仅有一条路径,正确打印十分容易,无非就是换行后多两个空格;
2)如果我们已经有一个树,用于表示文件结构,只需先序遍历,在开头额外打印2倍深度h的空格即可,h从0开始;
根据题目,我们需要有意识的练习:
1)在机考竞赛等环境下,树的构建,首选静态数组,而非动态申请空间;
2)所有题目中,一旦给出“单调”的信息,那么必须要利用,或是二分,或是提前退出等;
如果对于树的运用,和for循环一样熟练,那这题的标签确实称得上“简单”,否则还是有难度的;
为了构建这棵树,我们需要回忆:408操作系统中的目录文件;
每个目录文件需要存储:1)自身的名称;2)该目录下所有文件的地址;
因此,逻辑并不复杂,只是实操过程中需要注意一下细节:
1)输入最多10行,每行最多50个字符,至少一半是 '\\' ,因此最多250个文件,即251个索引节点(0号为根节点root);
2)同时,某个文件夹内,最多包含10个不同名的文件,每个文件最多占满50个字符;
3)我们只用1个数 FILES 记录有效文件个数即可,小于FILES就代表已分配,大于FILES的节点无意义,文件夹内的 files 同理;
4)我们只需要用一个工作目录pwd,顺着所给路径,遍历这棵树,并在遍历的途中,顺手添加节点即可;
5)添加时,我们默认,当前状态下,目录内的文件名已然有序,我们直接插入即可,插入后仍然有序;
其他技巧性问题:
1)考虑状态间的最小变化,找到“递推关系”,是分治、动态规划等更高阶题目的核心,应当培养这种思维方式;
2)二分查找只是逻辑上的优化,对本题而言,10以内的维度,意义不大,但熟练后,也就是顺手的事;
3)用'\0'替换特定字符,是手搓split很好用的方式,熟练后,也是顺手的事;
//简洁的索引文件系统, 可简单复用, 显式的静态链式结构,
//总文件数量<=250(10*25), 单层总文件数<=10, 文件名长度<=50
//空间只递增分配, 用FILES控制视野, 只增不减, 只覆盖
//用pwd指向当前索引节点的地址
#include <stdio.h>
#include <string.h>
typedef struct TreeNode{
char name[51];
int files;
struct TreeNode* idx[10];
}Tn, *Ptn;
void InitNode(char* name, Ptn node){
node->files=0;
strcpy(node->name, name);
}
Tn dir[251];
int FILES=1;
Ptn pwd;
char path[51];
void Find(char* name){
//在pwd下, 尝试找到name, 并更新pwd, 不存在则创建一个name
//idx列表内, 始终按字典序递增, 因此可以二分查找, 最后调整索引的指向即可
int l=0, r=pwd->files, m, cmp;
while(l<r){
m = (l+r)>>1;
cmp = strcmp(name, pwd->idx[m]->name);
if(cmp==0) {//找到则直接返回
pwd = pwd->idx[m]; return;
}
if(cmp<0) r=m;
else l=m+1;
}//退出时l=r, l左侧永远更小, 因此l是当前插入位置
for(int i=pwd->files; i>l; --i) pwd->idx[i] = pwd->idx[i-1];
//没出现过, 则分配, 并有效文件+1, 随后进入并初始化节点
pwd->idx[l] = &dir[FILES++];//分配一个索引节点
pwd->files ++;
pwd = pwd->idx[l];
InitNode(name, pwd);
}
void printNode(Ptn node, int h){
for(int i=0; i<h; ++i) printf(" ");
printf("%s\n", node->name);
for(int i=0; i<node->files; ++i)
printNode(node->idx[i], h+1);
}
int main() {
int n, i;
while (scanf("%d\n", &n) != EOF && n) {
//初始化根节点
InitNode("root", &dir[0]); FILES = 1;
int l, r;
for(i=0; i<n; ++i){
//每次都从根节点出发, 边遍历边构建树
pwd = &dir[0];
scanf("%s\n", path);
for(r=0, l=0; path[r]; ++r){
if(path[r]=='\\'){
path[r] = '\0';
Find(path+l);
l = r+1;
}
}
//空名不添加
if(strlen(path+l)>0) Find(path+l);
}
//打印
for(int i=0; i<dir[0].files; ++i)
printNode(dir[0].idx[i], 0);
printf("\n");
}
return 0;
}

京公网安备 11010502036488号