📄 treeinfo.cpp
字号:
if(pPrev->pPrev == NULL)
{
pNode->pParent->pChild = pNode;
}
else
{
pPrev->pPrev->pNext = pNode;
}
pPrev->pNext = pNext;
pPrev->pPrev = pNode;
}
return TRUE;
}
// 拷贝当前节点(当前节点如有子节点,则包括子节点)。
// 返回:被拷贝的节点地址(重新分配的),成功 非NULL;失败 NULL
// 注意:各节点是重新NEW出来的,使用时应不应忘记Remove
PTREENODE CTreeInfo::CopyNode( PCTREENODE pcNode )
{
_ASSERTE( pcNode != NULL );
PTREENODE pNew = MallocNode();
if(pNew == NULL)
return NULL;
memcpy(pNew, pcNode, sizeof(TREE_NODE));
pNew->pParent = NULL;
pNew->pChild = NULL;
pNew->pPrev = NULL;
pNew->pNext = NULL;
PTREENODE pRet = NULL;
PTREENODE pPrev = NULL;
for(PCTREENODE pCur = pcNode->pChild; pCur != NULL; pCur = pCur->pNext)
{
pRet = CopyNode(pCur);
if(pRet != NULL)
{
// the first child
if(pCur->pPrev == NULL)
{
pNew->pChild = pRet;
pRet->pParent = pNew;
pPrev = pRet;
}
else
{
// Not the first child
_ASSERTE( pPrev != NULL );
pRet->pParent = pNew;
pRet->pPrev = pPrev;
pPrev->pNext = pRet;
pPrev = pRet;
}
}
else
{
break;
}
}
return pNew;
}
// 将给定的节点孤立出来
// 注意:需要将兄弟节点连接起来
void CTreeInfo::IsolateNode( PTREENODE pNode )
{
PTREENODE pCur = pNode;
PTREENODE pParent = pCur->pParent;
PTREENODE pPrev = pCur->pPrev;
PTREENODE pNext = pCur->pNext;
if(pPrev != NULL)
{
pPrev->pNext = pNext;
}
else
{
if(pParent != NULL)
{
pParent->pChild = pNext;
}
}
if(pNext != NULL)
{
pNext->pPrev = pPrev;
}
pNode->pParent = NULL;
}
// 获取给定节点的子节点的层数(有几层子节点),不包含本身。
// 0说明无子节点,1说明有1层子节点,2说明有两层子节点...
UINT CTreeInfo::GetLevelCount( PCTREENODE pcNode ) const
{
_ASSERTE( pcNode != NULL );
if( pcNode->pChild == NULL )
return 0;
UINT uMaxLevel = 0;
for ( PCTREENODE pCur = pcNode->pChild; pCur != NULL; pCur = pCur->pNext )
{
UINT uLevel = GetLevelCount( pCur );
if ( uLevel > uMaxLevel )
{
uMaxLevel = uLevel;
}
}
return uMaxLevel + 1;
}
// 获取相对于当前菜单某一层(某一代)所有菜单的数量
// pcNode:当前给定节点, nLevel: 要访问的层数,子节点的层数为1,孙子节点的层数为2...
// 返回:给定层的菜单的数量
UINT CTreeInfo::GetCountInLevel( PCTREENODE pcNode, int nLevel ) const
{
_ASSERTE( pcNode != NULL && nLevel >= 0 );
if(pcNode->pChild == NULL || nLevel == 0)
{
return 0;
}
UINT uLevelCount = 0;
for ( PCTREENODE pCur = pcNode->pChild; pCur != NULL; pCur = pCur->pNext )
{
if(1 == nLevel)
{
uLevelCount++;
}
else
{
uLevelCount += GetCountInLevel(pCur, nLevel - 1);
}
}
return uLevelCount;
}
// 获取当前节点,给定层数,给定索引的节点。说明:这些节点的索引顺序
// 按照在节点树中的顺序由上到下排列。
// pcNode:给定的节点, nLevel:层数, nIndex:给定层上节点的索引
// 返回:NULL 给定信息无对应的节点, 非NULL 获取的节点
PTREENODE CTreeInfo::GetNodeInLevel( PCTREENODE pcNode, int nLevel, int nIndex ) const
{
_ASSERTE(pcNode != NULL);
_ASSERTE( nLevel >= 0 && nIndex >= 0 );
return GetLevelInternalUse(pcNode, nLevel, nIndex);
}
PTREENODE CTreeInfo::GetLevelInternalUse(PCTREENODE pcNode, int nLevel, int &nIndex) const
{
_ASSERTE(pcNode != NULL);
if(pcNode->pChild == NULL || nLevel == 0)
return NULL;
PTREENODE pRet = NULL;
for ( PTREENODE pCur = pcNode->pChild; pCur != NULL; pCur = pCur->pNext)
{
if(1 == nLevel)
{
if(0 == nIndex)
return pCur;
else
nIndex--;
}
else
{
pRet = GetLevelInternalUse(pCur, nLevel - 1, nIndex);
if(pRet != NULL)
break;
}
}
return pRet;
}
// 获取当前给定节点的所有子孙节点的数量(包括本身)
UINT CTreeInfo::GetAllPosteritiesCount( PCTREENODE pcNode ) const
{
_ASSERTE( pcNode != NULL );
if( pcNode->pChild == NULL )
return 1;
UINT uMaxCount = 1;
for( PCTREENODE pCur = pcNode->pChild; pCur != NULL; pCur = pCur->pNext )
{
uMaxCount += GetAllPosteritiesCount( pCur );
}
return uMaxCount;
}
// 给定的节点(lpcNode)是否是lpcParent的子孙节点(包括本身)
BOOL CTreeInfo::IsPosterity(PCTREENODE pcParent, PCTREENODE pcNode) const
{
_ASSERTE(pcParent != NULL);
_ASSERTE(pcNode != NULL);
if( pcParent == pcNode )
return TRUE;
PCTREENODE pChild = pcParent->pChild;
for(; pChild != NULL; pChild = pChild->pNext)
{
if( IsPosterity(pChild, pcNode) )
return TRUE;
}
return FALSE;
}
void CTreeInfo::RemoveNodeInternalUse( PTREENODE pNode )
{
if( NULL == pNode )
return;
PTREENODE pChild = pNode->pChild;
while ( NULL != pChild )
{
PTREENODE pNext = pChild->pNext;
RemoveNode( pChild );
pChild = pNext;
}
delete pNode;
}
// 删除当前节点(当前节点如有子节点,则包括子节点)
// 注意:需要对上下的指向节点进行处理
void CTreeInfo::RemoveNode( PTREENODE lpNode )
{
if(lpNode != NULL)
{
IsolateNode(lpNode);
RemoveNodeInternalUse(lpNode);
}
}
// 此函数直接调用RemoveNode(PTREENODE lpNode),将根节点作为参数传入即可。
void CTreeInfo::RemoveAll()
{
if(m_pRoot != NULL)
{
RemoveNode(m_pRoot);
m_pRoot = NULL;
}
}
void CTreeInfo::ZeroNode( PTREENODE pNode )
{
if(pNode != NULL)
{
pNode->pChild = NULL;
pNode->pNext = NULL;
pNode->pParent = NULL;
pNode->pPrev = NULL;
}
}
//////////////////////////////////////////////////////////////////////
// virtual fun 需要在派生类中重新实现
//////////////////////////////////////////////////////////////////////
// 从内存中分配一个新节点,此函数应在派生类中重新实现,以便获取实际节点。
PTREENODE CTreeInfo::MallocNode( void )
{
return new TREE_NODE;
}
void CTreeInfo::FreeNode( PTREENODE pNode )
{
delete pNode;
}
//////////////////////////////////////////////////////////////////////
// 文件操作(不再提供)
//////////////////////////////////////////////////////////////////////
// 将指定节点及其子孙节点保存到文件,此函数会调用GetNodeSize来获取节点的
// 大小。
//BOOL CTreeInfo::SaveToFile( PCTREENODE pcNode, FILE * pFILE )
//{
// 此函数应在派生类中实现
// _ASSERTE( 0 );
// return FALSE;
//}
// 从文件中读取所有节点信息,并返回链表中第一个节点的指针,
// 注意此函数会调用MallocNode来分配新节点。
//PTREENODE CTreeInfo::ReadFromFile( FILE * pFILE )
//{
// 此函数应在派生类中实现
// _ASSERTE( 0 );
// return NULL;
//}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -