最近和BYD 的一个Brew MP 平台的工程师有点业务往来,当我们要支持一个SPRINT的功能的时候,发生了分期。功能很简单,就是一个目录下有不到30个文件,但是这些文件中,有几个文件要删除,但是不确定要删除的文件名称,只知道需要保留的文件列表,这个列表不到20个文件名称。
1.这个工作要BYD的工程师去做,他电话告诉我他的思路,就是将保留文件copy 到另外的一个地方,然后将这个目录下文件都删掉,再将文件copy 回来。然后给我的解释是这样做程序的效率会好一点。听完这个话,我还真的很纳闷,为什么要效率好一点呢?也许别人以为我不懂开发吧。也只能这样理解了,20个文件copy 要多长时间,我没有在Brew MP 平台测试过。没有资格评论。但是 晚上回来我一直琢磨这个问题不对,所以就在PC上做了测试,发现了,这个还真不是那么回事情。
2.对待这个问题,我首先的想法,就是自己去枚举目录下的文件,然后看在列表中没有,如果不在,那么就删除,如果在就保留,因为我们删除文件的个数比较少,所以保留文的只要保证我们查找文件的算法小于将一个文件copy 两次的时间,那么我们就肯定能是优胜的算法,怎么呢,首先我想到了二分查找法。
void * bsearch_s ( const void *key, const void *base, size_t num, size_t width, int ( *compare)(void *, const void *) ) { char *lo = (char *)base; char *hi = (char *)base + (num - 1) * width; char *mid; size_t half; int result; while (lo <= hi) { if ((half = num / 2) != 0) { mid = lo + (num & 1 ? half : (half - 1)) * width; if (!(result = compare((void*)key, (void*)(*(char**)mid)))) return(mid); else if (result < 0) { hi = mid - width; num = num & 1 ? half : half-1; } else { lo = mid + width; num = half; } } else if (num) return (compare((void*)key, (void*)(*(char **)lo)) ? NULL : lo); else break; } return NULL; }
const char * g_FileNames[] = { "constit.ini", "constit_23.ini", "hello.ini", "gett.txt" };那么这样看起来枚举文件不用在20 个文件名列表中进行遍历了吧,当然这里给出PC 的源码
const char * g_FileNames[] = { "constit.ini", "constit_23.ini", "hello.ini", "gett.txt" }; int comparefunction(void * a1, void* a2) { return strcmp((const char*)a1, (const char*)a2); } typedef int ( *_COMPARE_)(void *, const void *); void * bsearch_s ( const void *key, const void *base, size_t num, size_t width, int ( *compare)(void *, const void *) ) { char *lo = (char *)base; char *hi = (char *)base + (num - 1) * width; char *mid; size_t half; int result; while (lo <= hi) { if ((half = num / 2) != 0) { mid = lo + (num & 1 ? half : (half - 1)) * width; if (!(result = compare((void*)key, (void*)(*(char**)mid)))) return(mid); else if (result < 0) { hi = mid - width; num = num & 1 ? half : half-1; } else { lo = mid + width; num = half; } } else if (num) return (compare((void*)key, (void*)(*(char **)lo)) ? NULL : lo); else break; } return NULL; } int _tmain(int argc, _TCHAR* argv[]) { char *pKey = "constwwit.ini"; void *pFind = bsearch_s( pKey, g_FileNames, sizeof(g_FileNames) /sizeof(g_FileNames[0]), sizeof(g_FileNames[0]), (_COMPARE_)comparefunction ); return 0; }