最近和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;
}
只要将compare 函数中的strcmp 替换为STRCMP就成Brew 环境中就可以使用了。 看起来这个还不是最优化的算法的结果,如果明天晚上有时间,将最佳的算法在写出来。。