工程中实际使用的,采用cpp模板实现。
TreeWalker仿函数是非递归方式遍历树,效率比递归方式快很多。
/** @brief 遍历用仿函数,允许查询替代属性*/
template <typename T>
class ForEach
{
public:
void operator()(T *set, T *node,
const XStringList &att_names, const XStringList &att_values)const
{
if (set == NULL || node == NULL)
{
return;
}
if (node->IsEqual(att_names, att_values))
{
set->AddChild(node);
}
}
};
/** @brief 遍历用仿函数,模糊比较*/
template <typename T>
class ForEachFuzzy
{
public:
void operator()(T *set, T *node,
const XStringList &att_names, const XStringList &att_values)const
{
if (set == NULL || node == NULL)
{
return;
}
if (node->IsEqualFuzzy(att_names, att_values))
{
set->AddChild(node);
}
}
};
/** @brief 遍历用仿函数,只比较已有属性,不查询替代属性*/
template <typename T>
class ForEachBase
{
public:
void operator()(T *set, T *node,
const XStringList &att_names, const XStringList &att_values)const
{
if (set == NULL || node == NULL)
{
return;
}
if (node->IsEqualBase(att_names, att_values))
{
set->AddChild(node);
}
}
};
/** @brief 非递归遍历树结构*/
template<typename T, typename ForEachT = ForEach<T> >
class TreeWalker
{
public:
int32 operator()(T *set, T *root,
const XStringList &att_names, const XStringList &att_values)const
{
if (set == NULL)
{
//return kEEC_POINTER_IS_NULL;
return kEEC_ERROR;
}
if (root == NULL)
{
//return kEEC_POINTER_IS_NULL;
return kEEC_ERROR;
}
if (set == root)
{
//return kEEC_POINTER_IS_SAME;
return kEEC_ERROR;
}
//
T *cur = root;//此根节点也可能是实际tree中的中间节点
ForEachT()(set, cur, att_names, att_values);//root node
if (root->CountChild() == 0)
{
return kEEC_OK;//子节点为空时不用遍历
}
do{
if (cur->ChildAtPos(0))
{
cur = cur->ChildAtPos(0);
ForEachT()(set, cur, att_names, att_values);
}
else if (cur->GetNext())
{
//子节点为空时如果遍历,此处会访问根节点的兄弟结点
cur = cur->GetNext();
ForEachT()(set, cur, att_names, att_values);
}
else
{
while (!cur->GetNext() && cur != root && cur->GetFather())
{
cur = cur->GetFather();
}
if (cur != root)
{
cur = cur->GetNext();
ForEachT()(set, cur, att_names, att_values);
}
}
} while (cur && cur != root);
return kEEC_OK;
}
};
使用示例:
TreeWalker<XObject>()(set, root, att_names, att_values);
TreeWalker<XObject, ForEachBase<XObject>>()(set, root, att_names, att_values);
return TreeWalker<XObject, ForEachFuzzy<XObject> >()(set, root, att_names, att_values);