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

用存放中文字符串的vector作为map的key,竟然有重复的。该怎么处理

2012-02-24 
用存放中文字符串的vector作为map的key,竟然有重复的。我的作为key的数据结构是:classCHerbKey{public:CHer

用存放中文字符串的vector作为map的key,竟然有重复的。
我的作为key的数据结构是:    
class     CHerbKey    
{    
public:    
        CHerbKey(void){     m_csHerbs.clear();   }    
        CHerbKey(void){   m_csHerbs.clear();   }    

        void     AddHerb(CString     csHerb)    
        {    
m_csHerbs.push_back(csHerb);    
        }    
        int     GetHerbsCount()     const    
        {    
return     m_csHerbs.size();    
        }    
        vector <CString>     GetHerbs()     const    
        {    
return     m_csHerbs;    
        }    
        CString     GetItem(int     index)     const    
        {    
return     m_csHerbs[index];    
        }    
        bool     HaveHerb(CString     csHerb)     const    
      {    
bool     bRet;    
int     i     =     0;    
int     iCount     =     GetHerbsCount();    
for(i     =     0;i <iCount;i++)    
{    
        if(csHerb.CompareNoCase(GetItem(i))     ==     0)    
return     true;    
}    
      return     false;    
        }    
        bool     operator     <     (const     CHerbKey&     oneHerbKey)     const    
        {                            
int     iRet     =     compare(oneHerbKey);                            
return     iRet <0;    
        }    
private:    
        int     compare(const     CHerbKey&     oneHerbKey)     const    
        {    
int     iRet     =     0;    
int     iRetCompare     =     iRet;    
int     iCount1     =     GetHerbsCount();    
int     iCount2     =     oneHerbKey.GetHerbsCount();    
                  if(iCount1     <     iCount2)    
        return     -1;    
else     if(iCount1     >     iCount2)    
        return     1;    


else     /*iCount1     ==     iCount2*/    
{    
        int     iIndex1     =     0;    
        int     iIndex2     =     0;    
        for(iIndex1     =     0;iIndex1 <iCount2;iIndex1++)    
        {    
CString     csHerb2     =     oneHerbKey.GetItem(iIndex1);    
if(!HaveHerb(csHerb2))    
{    
        for(iIndex2     =     0;iIndex2 <iCount1;iIndex2++)    
        {    
CString     csHerb1     =     GetItem(iIndex2);    
if(!oneHerbKey.HaveHerb(csHerb1))    
{    
        return     csHerb1.CompareNoCase(csHerb2);    
}    
          }    
}    

        }    
        return     0;    
                  }    
        }    
 
private:    
        vector <CString>     m_csHerbs;    
};    
 
我冲过读取Excel表得到的map中竟然有这样的结果:    
map <( "人参 ", "生姜 "),     1>    
map <( "生姜 ", "人参 "),     1>    
 
map <( "人参 ", "生姜 ", "甘草 "),     1>    
map <( "生姜 ", "人参 ", "甘草 "),     1>    
map <( "甘草 ", "人参 ", "生姜 "),     1>    

但不是所有的key都这样。比如
无论调用一次map[( "人参 ", "甘草 ")]++和一次map[( "甘草 ", "人参 ")]++  
就只有个
map <( "人参 ", "甘草 "),     2>    

我跟踪调试了几次,发现,我填充一次map[( "人参 ", "生姜 ")]++后,当调用   map[( "生姜 ", "人参 ")]   ++的时候,竟然没有进入到 <重载函数中。
不知道是哪里出了问题,请高手指教。或许是我的重载 <函数有问题?  


[解决办法]
看了LZ的测试结果,有些明白了。简单的说,compare没有遵守Strict Weakly Comparable 约定,有可能出现 A < B, B < C, C < A , 或者 A < B , B < A '(这里A和A '等价,但形式不同) 的情况。所以,在某些案例中,从RB树上搜索时,两个相等的Key没能走在一个分支上,从而判定为两个值;后者树的上层节点因为新Key加入发生了变化,导致再输入的A找不到原来的A节点了。而我的测试对象太少(只有两个不同的Key),恰好没能重现LZ遇到的情况。

统一成一定顺序时,compare就能够遵守Strict Weakly Comparable 约定了。最好统一顺序的工作由compare自己完成,毕竟这是它应尽的责任。(其实统一顺序后,就没必要找对方没有的Herb了,因为如果A的i项 < B的i项,哪怕A中将来会有B的i项,已经可以推论出B中必由一项> A的i项,且不在A中。所以,按照次序一个一个比较就可以了)。
[解决办法]
谢谢楼主反过来耐心解释.记性差,学过的东西很快就忘了. 经楼主提醒,想起来了,中文叫 "严格弱序要求 "

问题出在前后比较标准不统一,而且后面部分隐藏了bug
前面部分按字符项目数一锤定音,隐藏规则,字符项没有重复项.
后面部分部分实际上按排序后的字典顺序,而且只考虑了只一个项不相同的情况,两个项不同时可能会出两种结果.
( "A ", "B ", "D ", "E ") < ( "A ", "B ", "G ", "C ") 外层循环找到第一个不同D,内层循环找到第一个不同的G, D < G为返回结果.
( "A ", "B ", "D ", "E ")> ( "A ", "B ", "C ", "G ") 外层循环找到第一个不同D,内层循环找到第一个不同的C, D> C为返回结果.




热点排行