一个查找数字的程序!
用BCB做一个像打开一个文本文件的程序,然后实现查找文本里面的数据的功能,这些数据都是由三位数组成,比如:148,589,501等等。和
一般查找不同的是,这里把148 184 481 418 841 814这6个数看做是同一个数,就是只要三个数字相同,位置不同也算做同一个数。这个程序该怎么设计
??
[解决办法]
不是很明白你的意思……
接分
帮顶
Up
[解决办法]
楼上的回复很面熟. 很象最近活跃在C++Builder版块的一位同学. 貌似已混成一颗星了.
[解决办法]
你的意思是不是查148能查出148,481,418,184,814,841来啊?把你要查找的数处理一下就可以,只是多查几遍的问题。
[解决办法]
[解决办法]
思考中!!
[解决办法]
我也觉得用正则表达式比较方便。
不过BCB里不会操作。
[解决办法]
http://topic.csdn.net/t/20030830/13/2205447.html
LZ可以参考一下这个
[解决办法]
1、寫一個比較函數: 只要三个数字相同,位置不同也算做同一个数
bool sameword(char *a , char *b)
{
return
(*(a+0) == *b || *(a+0) == *(b+1) || *(a+0) == *(b+2) ) &&
(*(a+1) == *b || *(a+1) == *(b+1) || *(a+1) == *(b+2) ) &&
(*(a+2) == *b || *(a+2) == *(b+1) || *(a+2) == *(b+2) ) &&
(*(b+0) == *a || *(b+0) == *(a+1) || *(b+0) == *(a+2) ) &&
(*(b+1) == *a || *(b+1) == *(a+1) || *(b+1) == *(a+2) ) &&
(*(b+2) == *a || *(b+2) == *(a+1) || *(b+2) == *(a+2) ) ;
}
2、寫一個讀函數,順序讀入下一單詞。返回NULL 為結束,無下一單詞。
inline char *GetNextWord(char *pos/*當前位置*/,char *end/*結束點*/)
{
pos+= 4 ; //最簡單方式 3 字節字符 + 1字節分隔符。這要依據文件格式來寫。
return (pos < end ) ? pos : NULL ;
}
3、寫一個查找函數,從當前位置向後找,返回第一個找到的位置。找不到返回 NULL
char * findword(char *findwhat,char *pos,char *end)
{
while(pos && !sameword(findwhat,pos))
pos = GetNextWord(pos,end);
return pos ;
}
4、整個流程:
1)、將文件全部讀入內存中去。
2)、使用 findword 在內存中查找。直到找完全部匹配項。
[解决办法]
// 以下未经编译测试,text是按照换行的数字文本// 例如:// 123// 456// num是要找的数// 返回是第几行,0是没找到// 汗,上面的少了n个字母tint FindNumPos(const TStringList *text, int num){ int pos = 0; int count = text->Count; String numStr = num; for (int i=0; i<count; i++) { // text->Strings[i][1]这个不是2维数组,第二个是String的[]运算符 if ((numStr.Pos(text->Strings[i][1]) > 0) && (numStr.Pos(text->Strings[i][2]) > 0) && (numStr.Pos(text->Strings[i][3]) > 0)) { pos = i + 1; break; } } return pos;}
[解决办法]
即然这样要求的话,可以把这些先分一下,三个一组,用ComAryStr进行比较,如果相同,则删除其中一组,再进行下一个比较,这样最后剩下的,都是元素值最少有一个值是不同的
/*
功能:判断sVal1和sVal2是否等集(即元素相同,位置不同)
返回:true:相同,false:不同
*/
bool __fastcall ComAryStr(AnsiString sVal1, AnsiString sVal2)
{
bool bResult = false;
if ((sVal1.Pos(sVal2.SubString(1,1)) > 0)
&& (sVal1.Pos(sVal2.SubString(2,1)) > 0)
&& (sVal1.Pos(sVal2.SubString(3,1)) > 0))
{
bResult = true;
}
return bResult;
}
[解决办法]
给一个高效的算法(不害羞的说,是最高效率的算法思路)
如果无法理解,后面再给补代码,呵呵
思路(以空间换时间):
(1)建立一个辅助索引,hash索引
(2)对于读取到的元素,如(148 184 481 418 841 814),统一按数字升序进行hash计算
即例子中,全部以 148 进行计算,提供一个简单hash公式:
key = key * 31 + value;
(3)查找的时候,计算hash key,同样采用(2)的处理方法,按照升序进行
(4)遍历hash冲突链 即可以得到查找结果
该算法的时间复杂度是 O(1)
空间复杂度,看hash设计,一般为 N * 8 ~ N * 16 (BYTE), 代价不高
[解决办法]
測試一下 BCB 中的 hash_map ,
#include <map>#include <hash_map>#include <vector>struct TMyWord{ char a[3]; inline void Sort() //升序 a[0] < a[1] < a[2] { // 即用 148 代表 841 418 184 ... if(a[0] > a[1] ) std::swap(a[0],a[1]) ; if(a[0] > a[2] ) std::swap(a[0],a[2]) ; if(a[1] > a[2] ) std::swap(a[1],a[2]) ; }};//單詞相同比較,因為雙方已序,所以簡單對比。inline bool operator == (TMyWord const & a, TMyWord const&b){ return a.a[0] == b.a[0] && a.a[1] == b.a[1] && a.a[2] == b.a[2] ;}//單詞升序排序比較inline bool operator < (TMyWord const & a, TMyWord const&b){ return a.a[0] < b.a[0] ? true : a.a[0] > b.a[0] ? false : a.a[1] < b.a[1] ? true : a.a[1] > b.a[1] ? false : a.a[2] < b.a[2] ;}struct hash_TMyWord //如果使用 hash_map{ enum { bucket_size = 1, min_buckets = 8}; //定義桶數及桶大小 //hash函數 這個比較考人 ... 好浪費空間啊 size_t operator()(const TMyWord& Word) const {return (Word.a[0]*100+Word.a[1]*10+Word.a[2]);} //比較函數 bool operator()(const TMyWord & a, const TMyWord & b)const {return operator <(a,b);}};//索引。用std::map 做的索引,其查找復雜度保證為 O(logN) 紅黑樹,每節點約16字節//typedef std::map <TMyWord , std::vector<char *> > TMyWordsIndex ;//使用 hash_map .查找復雜度為 O(1) 空間浪費很多, 兩種方法難說誰快的呵。typedef std::hash_map <TMyWord , std::vector<char *> , hash_TMyWord > TMyWordsIndex ;inline char *GetNextWord(char *pos/*當前位置*/,char *end/*結束點*/){ pos+= 4 ; //最簡單方式 3 字節字符 + 1字節分隔符。這要依據文件格式來寫。 return (pos < end ) ? pos : NULL ;}//將內存中數據整理入 map 中void ReadWordsFromBuff(char *buff,char *buffend,TMyWordsIndex &MyWordsIndex){ for(char *p = buff ; p != NULL ; p = GetNextWord(p,buffend)) { TMyWord A ; A.a[0] = p[0] ; A.a[1] = p[1] ; A.a[2] = p[2] ; A.Sort(); TMyWordsIndex::iterator pos = MyWordsIndex.find(A); if(pos == MyWordsIndex.end()) { std::vector<char *> B(1); B[0] = p ; MyWordsIndex[A] = B ; } else pos->second.push_back(p); }}//查找:用std::vector<char *> 返回出現的全部開始點std::vector<char *> * FindMyWords(TMyWordsIndex &MyWordsIndex, const char *what){ TMyWord A ; A.a[0] = what[0] ; A.a[1] = what[1] ; A.a[2] = what[2] ; A.Sort(); TMyWordsIndex::iterator p = MyWordsIndex.find(A); if(p != MyWordsIndex.end()) return &(p->second); return NULL ;}//---------------------------------------//測試用例:void __fastcall TForm1::Button1Click(TObject *Sender){#define SourceTEXT "148 841 582 165 184 957 475 574 558 998 444 444 343 555 433" const char *findwhat = "481"; char *buff = SourceTEXT ; const int buffsize = sizeof(SourceTEXT) - 1 ; TMyWordsIndex WordsIndex ; ReadWordsFromBuff(buff,buff+buffsize,WordsIndex); std::vector<char *> *R = FindMyWords(WordsIndex,findwhat); AnsiString str ; if(R != NULL) { str += "found " + IntToStr(R->size()) + " :\n"; for(std::vector<char *>::iterator p = R->begin() ; p != R->end() ; ++p) { str += *p ; str += "\n" ; } } else str += " not found " ; ShowMessage(str);}