void clear()node
- 将树中全部的节点清除(释放堆中的节点)
free(node)编程
- 清除 node 为根节点的树
- 释放树中的每个节点
文件:GTree.hide
#ifndef GTREE_H #define GTREE_H #include "Tree.h" #include "GTreeNode.h" #include "Exception.h" namespace DTLib { template <typename T> class GTree : public Tree<T> { public: bool insert(TreeNode<T> *node) override { bool ret = true; if (node != nullptr) { if (this->m_root == nullptr) { node->parent = nullptr; this->m_root = node; } else { GTreeNode<T> *np = find(node->parent); if (np != nullptr) { GTreeNode<T> *n = dynamic_cast<GTreeNode<T>*>(node); if (np->child.find(n) < 0) { np->child.insert(n); } } else { THROW_EXCEPTION(InvalidOpertionExcetion, "Invalid partent tree node ..."); } } } else { THROW_EXCEPTION(InvalidParameterExcetion, "Parameter node cannot be NULL ..."); } return ret; } bool insert(const T &value, TreeNode<T> *parent) override { bool ret = true; GTreeNode<T> *node = new GTreeNode<T>(); if (node != nullptr) { node->value = value; node->parent = parent; insert(node); } else { THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to create node ..."); } return ret; } SharedPointer<Tree<T>> remove(const T &value) override { return nullptr; } SharedPointer<Tree<T>> remove(TreeNode<T> *node) override { return nullptr; } GTreeNode<T>* find(const T &value) const override { return find(root(), value); } GTreeNode<T>* find(TreeNode<T> *node) const override { return find(root(), dynamic_cast<GTreeNode<T>*>(node)); } GTreeNode<T>* root() const override { return dynamic_cast<GTreeNode<T>*>(this->m_root); } int degree() const override { return 0; } int count() const override { return 0; } int height() const override { return 0; } void clear() override { free(root()); this->m_root = nullptr; } ~GTree() { clear(); } protected: GTreeNode<T> *find(GTreeNode<T>* node, const T &value) const { GTreeNode<T> *ret = nullptr; if (node != nullptr) { if (node->value == value) { return node; } else { for (node->child.move(0); !node->child.end() && (ret == nullptr); node->child.next()) { ret = find(node->child.current(), value); } } } return ret; } GTreeNode<T> *find(GTreeNode<T>* node, GTreeNode<T> *obj) const { GTreeNode<T> *ret = nullptr; if (node == obj) { return node; } else { if (node != nullptr) { for (node->child.move(0); !node->child.end() && (ret == nullptr); node->child.next()) { ret = find(node->child.current(), obj); } } } return ret; } void free(GTreeNode<T> *node) { if (node != nullptr) { for (node->child.move(0); !node->child.end(); node->child.next()) { free(node->child.current()); } delete node; } } }; } #endif // GTREE_H
树中的节点可能来源于不一样的存储空间,如何判断堆空间中的节点并释放?
void func() { GTree<char> t; GTreeNode<char> root; root.value = 'A'; root.parent = nullptr; t.insert(&root); // 栈空间节点 t.insert('B', t.find('A')); // 堆空间节点 t.clear(); // 注意:非堆空间中节点不该被释放!! }
- 单凭内存地址很难准确判断具体的存储区域
- 只有堆空间的内存须要主动释放 (delete)
- 清除操做时只须要对堆中的节点进行释放
- 在 GTreeNode 中增长保护成员变量 m_flag
- 将 GTreeNode 中的 operator new 重载为保护成员(禁止类外部 new 节点)
- 提供工厂方法
GTreeNode<T> *NewNode()
- 在工厂方法中 new 新节点并将 m_flag 设置为 true
GtreeNode<int> *hn = GTreeNode<int>::NewNode(); GTreeNode<int> sn; if (hn->flag()) // true { delete hn; } hn = &sn; if (hn->flag()) // false { delete hn; }
文件:GTreeNode.hthis
#ifndef GTREENODE_H #define GTREENODE_H #include "TreeNode.h" #include "LinkList.h" namespace DTLib { template <typename T> class GTreeNode : public TreeNode<T> { public: LinkList<GTreeNode<T>*> child; bool flag() { return m_flag; } static GTreeNode<T>* NewNode() { GTreeNode<T> *ret = new GTreeNode<T>(); if (ret != nullptr) { ret->m_flag = true; } return ret; } protected: bool m_flag = false; void *operator new (unsigned int size) noexcept(true) { return Object::operator new(size); } }; } #endif // GTREENODE_H
文件:GTree.hspa
#ifndef GTREE_H #define GTREE_H #include "Tree.h" #include "GTreeNode.h" #include "Exception.h" namespace DTLib { template <typename T> class GTree : public Tree<T> { public: bool insert(TreeNode<T> *node) override { bool ret = true; if (node != nullptr) { if (this->m_root == nullptr) { node->parent = nullptr; this->m_root = node; } else { GTreeNode<T> *np = find(node->parent); if (np != nullptr) { GTreeNode<T> *n = dynamic_cast<GTreeNode<T>*>(node); if (np->child.find(n) < 0) { np->child.insert(n); } } else { THROW_EXCEPTION(InvalidOpertionExcetion, "Invalid partent tree node ..."); } } } else { THROW_EXCEPTION(InvalidParameterExcetion, "Parameter node cannot be NULL ..."); } return ret; } bool insert(const T &value, TreeNode<T> *parent) override { bool ret = true; GTreeNode<T> *node = GTreeNode<T>::NewNode(); if (node != nullptr) { node->value = value; node->parent = parent; insert(node); } else { THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to create node ..."); } return ret; } SharedPointer<Tree<T>> remove(const T &value) override { return nullptr; } SharedPointer<Tree<T>> remove(TreeNode<T> *node) override { return nullptr; } GTreeNode<T>* find(const T &value) const override { return find(root(), value); } GTreeNode<T>* find(TreeNode<T> *node) const override { return find(root(), dynamic_cast<GTreeNode<T>*>(node)); } GTreeNode<T>* root() const override { return dynamic_cast<GTreeNode<T>*>(this->m_root); } int degree() const override { return 0; } int count() const override { return 0; } int height() const override { return 0; } void clear() override { free(root()); this->m_root = nullptr; } ~GTree() { clear(); } protected: GTreeNode<T> *find(GTreeNode<T>* node, const T &value) const { GTreeNode<T> *ret = nullptr; if (node != nullptr) { if (node->value == value) { return node; } else { for (node->child.move(0); !node->child.end() && (ret == nullptr); node->child.next()) { ret = find(node->child.current(), value); } } } return ret; } GTreeNode<T> *find(GTreeNode<T>* node, GTreeNode<T> *obj) const { GTreeNode<T> *ret = nullptr; if (node == obj) { return node; } else { if (node != nullptr) { for (node->child.move(0); !node->child.end() && (ret == nullptr); node->child.next()) { ret = find(node->child.current(), obj); } } } return ret; } void free(GTreeNode<T> *node) { if (node != nullptr) { for (node->child.move(0); !node->child.end(); node->child.next()) { free(node->child.current()); } if (node->flag()) { delete node; } } } }; } #endif // GTREE_H
- 清除操做用于销毁树中的每一个节点
- 销毁节点时须要决定是否释放对应的内存空间
- 工厂模式可用于 "定制" 堆空间中的节点
- 只有销毁定制节点的时候须要进行释放
思考: 如何实现 GTree (通用树结构) 的节点删除操做?
SharedPointer<Tree<T>> remove(const T &value) override { GTreeNode<T> *ret = NULL; // ... return ret; } SharedPointer<Tree<T>> remove(TreeNode<T> *node) override { GTreeNode<T> *ret = NULL; // ... return ret; }
以上内容整理于狄泰软件学院系列课程,请你们保护原创!3d