题面如图:
本题有四个步骤:建树、找出文件,排序,输出文件路径。
1·建树
树的类型如下:
由于空间不限,所以直接把所有子节点的指针保存在父节点中。
同时,由于后面需要用到层级排序,所以同时也要存储层级。
typedef struct node_type{
char name[220];
char parent_name[220];
int type;
char date[20];
int level;
struct node_type *child[200];
int cnt;
}node;
建树和打印机有点像:
node *find(node *p,char *s){
if(strcmp(p->name,s)==0) return p;
for(int i=0;i<p->cnt;i++){
if (p->child[i]!=NULL&&find(p->child[i],s)!=NULL) return find(p->child[i],s);
}
return NULL;
}
node *make_tree(){
FILE *src = fopen("files.txt","r");
//读入根
char id[220],par[220],time[20];
int ty;
fscanf(src,"%s%s%d%s",id,par,&ty,time);
node *root=(node*)malloc(sizeof(node));
root->cnt=0;
for(int i=0;i<200;i++) root->child[i]=NULL;
root->type=ty;
strcpy(root->name,id);strcpy(root->parent_name,par);strcpy(root->date,time);
int n;
scanf("%d",&n);
for(int i=0;i<n-1;i++){
fscanf(src,"%s%s%d%s",id,par,&ty,time);
node *p=(node*)malloc(sizeof(node));
p->cnt=0;
for(int j=0;j<200;j++) p->child[j]=NULL;
p->type=ty;
strcpy(p->name,id);strcpy(p->parent_name,par);strcpy(p->date,time);
node *q=find(root,p->parent_name);
q->child[(q->cnt)++]=p;
}
return root;
}
2·寻找文件
遍历即可,遍历完以后也能保证上面的文件在前
node *rst[110];
int rcnt=0;
void find_aim(node *p,char *s){
if(p->type==0&&strcmp(p->name,s)==0) rst[rcnt++]=p;
for(int i=0;i<p->cnt;i++){
if(p->child[i]!=NULL) find_aim(p->child[i],s);
}
}
3·排序
排序是本题的重点了:
本题要用三级排序:日期->层级->先后
日期是最简单的,strcmp就可以实现。
而对于层级,就需要先使用一个函数计算出层级然后存储到结构体里再比较:
void get_level(node *p,int lvp){
p->level=lvp;
for(int i=0;i<p->cnt;i++){
get_level(p->child[i],lvp+1);
}
}
而对于先后顺序,实际上我们遍历就是按先后顺序排列好的,所以没必要刻意去排序,只需要在之前的排序过程中选择一个稳定的排序算法就好了:这也就要求这题不能够用方便快捷的qsort了,由于DSP考试没有苛刻的时间复杂度要求,这里就选用比较简单的冒泡排序:
int cmp(node *p,node *q){
if(strcmp(p->date,q->date)!=0) return -strcmp(p->date,q->date);
if(p->level!=q->level) return p->level-q->level;
return 0;
}
void swap(node **a,node **b){
node *tmp = *a;
*a=*b;
*b=tmp;
}
void bubble_sort(node *a[],int n)
{
int flag = 1;
for (int i = n - 1; i > 0 && flag == 1; i--)
{
flag = 0;
for (int j = 0; j < i; j++)
{
if (cmp(a[j],a[j+1])>0)
{
swap(&a[j],&a[j + 1]);
flag = 1;
}
}
}
}
(这段排序代码顺便帮我复习了一下指针数组和指针的指针
4·输出路径
输出路径递归即可,不递归使用上一条博客(打印机)的方法也可
void show_path(node *t,node *p){
if(t->level==0) printf("%s:",t->name);
else{
printf("\\%s",t->name);
}
for(int i=0;i<t->cnt;i++){
if(is_anc(t->child[i],p)) show_path(t->child[i],p);
}
}
void print_rst(node *tree){
for(int i=0;i<rcnt;i++){
show_path(tree,rst[i]);
puts("");
}
}
最后还是附上完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node_type{
char name[220];
char parent_name[220];
int type;
char date[20];
int level;
struct node_type *child[200];
int cnt;
}node;
node *find(node *p,char *s){
if(strcmp(p->name,s)==0) return p;
for(int i=0;i<p->cnt;i++){
if (p->child[i]!=NULL&&find(p->child[i],s)!=NULL) return find(p->child[i],s);
}
return NULL;
}
node *make_tree(){
FILE *src = fopen("files.txt","r");
//读入根
char id[220],par[220],time[20];
int ty;
fscanf(src,"%s%s%d%s",id,par,&ty,time);
node *root=(node*)malloc(sizeof(node));
root->cnt=0;
for(int i=0;i<200;i++) root->child[i]=NULL;
root->type=ty;
strcpy(root->name,id);strcpy(root->parent_name,par);strcpy(root->date,time);
int n;
scanf("%d",&n);
for(int i=0;i<n-1;i++){
fscanf(src,"%s%s%d%s",id,par,&ty,time);
node *p=(node*)malloc(sizeof(node));
p->cnt=0;
for(int j=0;j<200;j++) p->child[j]=NULL;
p->type=ty;
strcpy(p->name,id);strcpy(p->parent_name,par);strcpy(p->date,time);
node *q=find(root,p->parent_name);
q->child[(q->cnt)++]=p;
}
return root;
}
void pre_traverse(node *p){
printf("%d:%s\n",p->level,p->name);
for(int i=0;i<p->cnt;i++){
if(p->child[i]!=NULL) pre_traverse(p->child[i]);
}
}
node *rst[110];
int rcnt=0;
void find_aim(node *p,char *s){
if(p->type==0&&strcmp(p->name,s)==0) rst[rcnt++]=p;
for(int i=0;i<p->cnt;i++){
if(p->child[i]!=NULL) find_aim(p->child[i],s);
}
}
void get_level(node *p,int lvp){
p->level=lvp;
for(int i=0;i<p->cnt;i++){
get_level(p->child[i],lvp+1);
}
}
int cmp(node *p,node *q){
if(strcmp(p->date,q->date)!=0) return -strcmp(p->date,q->date);
if(p->level!=q->level) return p->level-q->level;
return 0;
}
void swap(node **a,node **b){
node *tmp = *a;
*a=*b;
*b=tmp;
}
void bubble_sort(node *a[],int n)
{
int flag = 1;
for (int i = n - 1; i > 0 && flag == 1; i--)
{
flag = 0;
for (int j = 0; j < i; j++)
{
if (cmp(a[j],a[j+1])>0)
{
swap(&a[j],&a[j + 1]);
flag = 1;
}
}
}
}
int is_anc(node *p,node *q){
if(p==q) return 1;
for(int i=0;i<p->cnt;i++){
if(is_anc(p->child[i],q)) return 1;
}
return 0;
}
void show_path(node *t,node *p){
if(t->level==0) printf("%s:",t->name);
else{
printf("\\%s",t->name);
}
for(int i=0;i<t->cnt;i++){
if(is_anc(t->child[i],p)) show_path(t->child[i],p);
}
}
void print_rst(node *tree){
for(int i=0;i<rcnt;i++){
show_path(tree,rst[i]);
puts("");
}
}
int main(){
node *tree = make_tree();
get_level(tree,0);
//pre_traverse(tree);
char aim[220];
scanf("%s",aim);
find_aim(tree,aim);
//for(int i=0;i<rcnt;i++) printf("%s->%s\n",rst[i]->parent_name,rst[i]->name);
puts("");
bubble_sort(rst,rcnt);
//for(int i=0;i<rcnt;i++) printf("%s->%s %s %d\n",rst[i]->parent_name,rst[i]->name,rst[i]->date,rst[i]->level);
print_rst(tree);
}