菜鸡学C语言之寻根溯源
题目链接:https://buaacoding.cn/problem/2058/index
题目分析:本题按照常规做法,不考虑时间复杂度算是道比较简单的题。由于种种原因,在航C上机前我没有来得及做这道题,所以他们上机时候我也在思考这道题,老师对这道题给出十分经典而且优秀的算法,而且现场码完代码,令人肃然起敬~
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。易错点:n=0的情况,即要查找的人没有父亲,父子关系中没有他,说明他就是最高辈。
解法一:
表面上看去,是个二维数组的题,将所有父子姓名都保存下来,每次都循环遍历查找即可。
题目给出的数据范围并不大,而且只需要查找一次,我们可以把这个关系表存下来,然后首先查找当前这个人的父亲,将这个过程“递归”下去,直到查找不到当前这个人的父亲,我们就找到了辈分最大的人
不过这种做法还是存在一定的弊端:
1. 字符串存在重复存储,空间效率较低;
2. 查询父亲的过程需要用到strcpy和strcmp函数,时间效率较低。
3. 如果需要用到大量的查询操作,效率问题更为明显。
#include <stdio.h> #include <string.h> char father[1600][30]; char son[1600][30]; int main() { int n; char name[30]; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%s%s", father[i], son[i]); scanf("%s", name); // 记录待查找的名字 int flag = 1; // 用来标记是否查到当前人的父亲 int cnt = 0; // 记录查找次数 while(flag) { flag = 0; for(int i = 1; i <= n; i++) { if(!strcmp(son[i], name)) { strcpy(name, father[i]); // 下次查找此次查找人的父亲 cnt++; flag = 1; break; } } } printf("%s %d", name, cnt); return 0; }
附:这是十分容易写出来的一种方法,适用在考试这种时间紧张的情形中。
解法二:
改进措施:降维处理+使用指针数组
思路:
1. 人名和关系分别用两个一维数组存,人名是指针数组,关系是int数组;
2. 每次输入两个名字时,动态插入到指针数组中,并用malloc开辟空间,这样可以节省大量内存;
3. 关系存在int数组中,人名数组不处理关系问题,简化操作;
4. 查询的时候使用int数组,查询效率要比检查字符串高很多很多
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1500 #define M 21 char* mans[2 * N] = {0}; // 将所有出现人的名字用一个数组来保存 int num_of_mans = 0; int relations[2 * N] = {0}; // 记录父子关系 // relations[i] = j 表明i的父亲是j, 其中i、j为在mans数组中的索引 // 当j = -1时, 表示此人没有父亲 char* addMan(const char* name) { char* newman = 0; if(!name) return newman; newman = (char*)malloc(strlen(name)+1); strcpy(newman, name); mans[num_of_mans++] = newman; return newman; } void initRelations() { int i; for(i = 0; i < 2 * N; i++) { relations[i] = -1; } } int findMan(char name[]) { int i; for(i = 0; i < num_of_mans; i++) { if(strcmp(name, mans[i]) == 0) { return i; } } return -1; } int insertMan(char name[]) { // 如果待插入的人已存在,则返回其在mans数组中的索引值; // 否则增加一个新元素并返回其索引值 int id; id = findMan(name); if(id >= 0) { return id; } addMan(name); return num_of_mans - 1; } void addFatherSon(int father, int son) { relations[son] = father; } int findRoot(int id, int *count) { int root; *count = 0; while(id >= 0) { root = id; id = relations[id]; if(id >= 0) (*count)++; } return root; } int main() { int i; char father[M], son[M], target[M]; int fid, sid, tid, rid, count = 0; int num; initRelations(); // 初始化所有人没有父亲 scanf("%d", &num); for(i = 0; i < num; i++) { scanf("%s%s", father, son); fid = insertMan(father); sid = insertMan(son); addFatherSon(fid, sid); // 建立父子关系 } scanf("%s", target); tid = findMan(target); // 找到当前待查找人的索引 if(tid == -1) { // 没有存入此人信息,即没有父亲 printf("%s %d", target, count); } else { rid = findRoot(tid, &count); printf("%s %d", mans[rid], count); } return 0; }
写在后面:以上代码均非本人所写,希望能和大家共同学习成长!

更多精彩