读书人

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

发布时间: 2012-03-29 12:53:12 作者: rapoo

一个查找数字的程序!
用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);} 

读书人网 >C++ Builder

热点推荐