2019数据结构期末考试·3·文件查找

题面如图:

本题有四个步骤:建树、找出文件,排序,输出文件路径。

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);
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值