最近项目中碰到这么一个问题。 |
有些人会想到一般的比较方法,这个要花费几分钟时间。想到hash表,如果你对hash不是很了解,请看数据结构hash用在什么场合,这里我就不总结了,实际上这个是非常重要的。
书上是这么说的:理想的情况是希望不经过任何比较,一次存取便能得到所查询记录,就必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中唯一的存储位置相对应。
直接帖代码:
class CBranch
{
public:
CBranch()
{
m_tags.RemoveAll();
m_nLayer = 0;
m_pBranches = NULL;
}
~CBranch()
{
while( !m_tags.IsEmpty() )
delete m_tags.RemoveTail();
if (!m_pBranches)
{
delete []m_pBranches;
}
}
void AddTag( CExTag* pTag ) {m_tags.AddTail(pTag);}
int m_nLayer;
ExTagList m_tags;
CBranch* m_pBranches;
};
void COPCServerView::OnOperatecheck()
{
// TODO: Add your command handler code here
CMainFrame *pFrame = (CMainFrame*)GetParentFrame();
COPCServerDoc *pDoc = (COPCServerDoc *) pFrame->GetActiveDocument();
CBranch brhTagList[256];
UCHAR uchTemp= 0;
BOOL bRet = FALSE;
CExTag *pTagFind = new CExTag;
pTagFind->m_strName = "AMMM";
CreateHash(&brhTagList[0], 0);
POSITION posC = pDoc->m_Root.m_Channels.GetHeadPosition();
while(posC)
{
CChannel* pChannel = pDoc->m_Root.m_Channels.GetNext(posC);
POSITION posD = pChannel->m_Devices.GetHeadPosition();
while(posD)
{
CDevice* pDevice = pChannel->m_Devices.GetNext(posD);
POSITION posG = pDevice->m_Groups.GetHeadPosition();
while(posG)
{
CGroup* pGroup = pDevice->m_Groups.GetNext(posG);
POSITION posT = pGroup->m_Tags.GetHeadPosition();
while(posT)
{
CExTag* pTag = pGroup->m_Tags.GetNext(posT);
if (!pTag || pTag->m_strName.GetLength() < 0)
{
continue;
}
else if (pTag->m_strName.GetLength() == 1)
{
uchTemp = pTag->m_strName.GetAt(0);
brhTagList[uchTemp].AddTag(pTag);
}
else if(pTag->m_strName.GetLength() == 2)
{
UCHAR uchTempFirst= 0;
UCHAR uchTempSecond = 0;
uchTempSecond = pTag->m_strName.GetAt(0);
uchTempFirst = pTag->m_strName.GetAt(1);
brhTagList[uchTempFirst].m_pBranches[uchTempSecond].AddTag(pTag);
}
else if(pTag->m_strName.GetLength() >= 3)
{
UCHAR uchTempFirst= 0;
UCHAR uchTempSecond = 0;
UCHAR uchTempThird = 0;
int nIndex = pTag->m_strName.GetLength();
uchTempFirst = pTag->m_strName.GetAt(nIndex-1);
uchTempSecond = pTag->m_strName.GetAt(nIndex-2);
uchTempThird = pTag->m_strName.GetAt(nIndex-3);
brhTagList[uchTempFirst].m_pBranches[uchTempSecond].m_pBranches[uchTempThird].AddTag(pTag);
}
}
}
}
}
BOOL bNotExist = CheckTagName(&brhTagList[0], pTagFind, FALSE );
if (!bNotExist)
{
MessageBox("点名存在");
}
BOOL COPCServerView::CreateHash(CBranch *pBranches, int nLayer)
{
CBranch *pBrh = NULL;
pBrh = pBranches;
if (nLayer < 2)
{
for (int i = 0; i < 256; i++)
{
(pBrh+i)->m_pBranches = new CBranch[256];
if (!(pBrh+i)->m_pBranches)
{
return FALSE;
}
CreateHash(&(pBrh+i)->m_pBranches[0], nLayer+1);
}
}
return TRUE;
}
关键字为取点名后面三位,比如PN1234,则取234,其中'2’对应ASCII值为0x50,一个unsigned char最大表示0-255,所以建hash表大小为256。利用冲突法中的链表地址法,建立三次hash表,每个链表中点分别对应256中情况。
其中里面的逻辑问题说明CChannel(通道),CDevice(设备),CGroup(组),CExTag(标签),一个通道下面有多个设备,一个设备下有多个组,一个组有多个标签。
总结:hash表的问题关键在关键字的确定,hash表的创建(创建后给它赋值具体的内容),处理冲突。
最后代码是老同志写的,我只是理解了一下!