首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

一个查找数字的程序!该怎么解决

2012-03-29 
一个查找数字的程序!用BCB做一个像打开一个文本文件的程序,然后实现查找文本里面的数据的功能,这些数据都

一个查找数字的程序!
用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 在內存中查找。直到找完全部匹配項。

[解决办法]

C/C++ code
// 以下未经编译测试,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 ,

C/C++ code
#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);} 

热点排行