获取树形结构中,父节点下所有子/孙节点(递归方式)
- 1 树形结构(TreeItem类)
- 2 测试代码(main函数)
- 3 运行效果
1 树形结构(TreeItem类)
这里通用型树形结构为TreeItem类,头文件,如下:
#ifndef TREEITEM_H
#define TREEITEM_H
#include <QList>
class TreeItem
{
public:
explicit TreeItem(QString name, TreeItem *parent = nullptr);
~TreeItem();
void appendChild(TreeItem *item);
void clearChildren();
TreeItem *child(int row) { return _children.value(row); }
QList<TreeItem*> children() { return _children; }
static QList<TreeItem*> grandchildren(TreeItem* parent);
QList<TreeItem*> grandchildren();
TreeItem *parent() { return _parent; }
int childCount() const { return _children.count(); }
int row() const { return _row; }
void setRow(int row){ _row = row; }
QString name() { return _name; }
void setName(QString name) { _name = name; }
private:
TreeItem *_parent; ///<父节点
QList<TreeItem*> _children; ///<子节点列表
int _row; ///<记录本item位于父节点下第几个节点
QString _name;
};
#endif // TREEITEM_H
源文件,如下:
#include "TreeItem.h"
TreeItem::TreeItem(QString name, TreeItem *parent)
: _parent(parent),
_row(0),
_name(name)
{
}
TreeItem::~TreeItem()
{
clearChildren();
}
/**
* @brief TreeItem::appendChild
* 在此节点下增加子节点
* @param child 节点
*/
void TreeItem::appendChild(TreeItem *item)
{
item->setRow(_children.size()); // item存自己是第几个,可以优化效率
_children.append(item);
}
/**
* @brief TreeItem::clearChildren
* 清空所有子节点
*/
void TreeItem::clearChildren()
{
qDeleteAll(_children);
_children.clear();
}
/**
* @brief TreeItem::grandchildren
* 获取指定父节点parent下的所有子节点(递归包括孙子、重孙子节点)
* @param parent 父节点
* @return 子节点列表
*/
QList<TreeItem*> TreeItem::grandchildren(TreeItem* parent)
{
if (parent->childCount() == 0)
{
return QList<TreeItem*>();
}
QList<TreeItem*> listItems;
listItems << parent->children();
foreach (auto child, parent->children())
{
listItems << child->grandchildren(child);
}
return listItems;
}
/**
* @brief TreeItem::grandchildren
* 获取当前节点下的所有子节点(递归包括孙子、重孙子节点)
* @return 子节点列表
*/
QList<TreeItem*> TreeItem::grandchildren()
{
return grandchildren(this);
}
这个类的函数比较简单,就是利用TreeItem类型,彼此依次添加,就可以形成树形结构。
这里需要关注的关键函数为:
QList<TreeItem*> TreeItem::grandchildren(TreeItem* parent)
{
if (parent->childCount() == 0)
{
return QList<TreeItem*>();
}
QList<TreeItem*> listItems;
listItems << parent->children();
foreach (auto child, parent->children())
{
listItems << child->grandchildren(child);
}
return listItems;
}
QList<TreeItem*> TreeItem::grandchildren()
{
return grandchildren(this);
}
利用了递归方式,对形参parent节点下的所有节点进行遍历,并将该parent节点下所有子/孙节点,全部添加到一个List中,并返回给调用者。
2 测试代码(main函数)
测试代码,如下所示:
#include <QCoreApplication>
#include <QDebug>
#include "TreeItem.h"
void print(QList<TreeItem*> items)
{
for (int i = 0; i < items.size(); i++)
{
QString name = items.at(i)->name();
qDebug() << "Item" << i << ":" << name;
}
qDebug() << "Print Over, Total Item Count :" << items.size();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/*
* China
* / | \
* SiChuan BeiJing GuangDong
* / \ / | \
* ChengDu YiBin GuangZhou ShenZhen FoShan
*/
// 四川
TreeItem* sichuan = new TreeItem("SiChuan");
TreeItem* chengdu = new TreeItem("ChengDu");
TreeItem* yibin = new TreeItem("YiBin");
sichuan->appendChild(chengdu);
sichuan->appendChild(yibin);
// 北京
TreeItem* beijing = new TreeItem("BeiJing");
// 广东
TreeItem* guangdong = new TreeItem("GuangDong");
TreeItem* guangzhou = new TreeItem("GuangZhou");
TreeItem* shenzhen = new TreeItem("ShenZhen");
TreeItem* foshan = new TreeItem("FoShan");
guangdong->appendChild(guangzhou);
guangdong->appendChild(shenzhen);
guangdong->appendChild(foshan);
// China
TreeItem* china = new TreeItem("China");
china->appendChild(sichuan);
china->appendChild(beijing);
china->appendChild(guangdong);
// 查看China下所有节点
QList<TreeItem*> items = china->grandchildren();
print(items);
// 查看SiChuan下所有节点
items = sichuan->grandchildren();
print(items);
// 查看GuangDong下所有节点
items = TreeItem::grandchildren(guangdong);
print(items);
delete china; // 仅需删除根节点对象
return a.exec();
}
该测试代码,首先生成一个,如下图所示的树形结构:
3 运行效果
最后,分别打印输出China、SiChuan、GuangDong节点下的所有子/孙节点名称。
需要注意:
最后释放内存时,仅需删除根节点对象(china)即可,在析构函数中,会自动依次删除所有子/孙节点内存。
具体工程代码,详见:https://gitee.com/bailiyang/cdemo/tree/master/Qt/67TreeDataTest/TreeDataTest