用存放中文字符串的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为返回结果.