最近和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 環境中就可以使用了。 看起來這個還不是最優化的算法的結果,如果明天晚上有時間,將最佳的算法在寫出來。。