#ifndef GENERALTREE_H #define GENERALTREE_H #include "LinkedList.h" #include "LinkedQueue.h" #include "Tree.h" namespace Kylin { template class GeneralTreeNode : public TreeNode { public: GeneralTreeNode(const T &value, TreeNode *parent = nullptr) : TreeNode(value, parent) {} LinkedList *> children; }; template class GeneralTree : public Tree { public: class Iterator { public: Iterator(GeneralTreeNode *pos) : m_pos(pos) {} bool operator!=(const Iterator &other) { return (m_pos != other.m_pos); } T &operator*() { return m_pos->value; } Iterator &operator++() { auto &children = m_pos->children; for (auto &child : children) { m_queue.enqueue(child); } m_pos = m_queue.empty() ? nullptr : m_queue.dequeue(); return *this; } private: GeneralTreeNode *m_pos = nullptr; LinkedQueue *> m_queue; }; GeneralTree() = default; GeneralTree(GeneralTree &&other) { this->m_root = other.m_root; other.m_root = nullptr; } ~GeneralTree() { clear(); } bool insert(TreeNode *node) { bool ret = false; auto n = dynamic_cast *>(node); if (n == nullptr) THROW_EXCEPTION(InvalidParameterException, "the node must is GeneralTreeNode."); if (this->m_root == nullptr) { this->m_root = node; node->parent = nullptr; ret = true; } else { if (!find(n->parent)) return false; auto parent = dynamic_cast *>(node->parent); parent->children.append(n); ret = true; } return ret; } /** * @brief 插入成功返回TreeNode的地址,否则nullptr */ GeneralTreeNode *insert(const T &value, TreeNode *parent) { auto ret = new GeneralTreeNode(value, parent); if (ret == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to insert an element."); bool status = insert(ret); if (!status) { delete ret; ret = nullptr; } return ret; } GeneralTree remove(const T &value) { auto node = find(value); return node == nullptr ? GeneralTree() : remove(node); } GeneralTree remove(const GeneralTreeNode *node) { if (node == nullptr) return GeneralTree(); GeneralTree tree; auto n = const_cast *>(node); if (n == this->m_root) { this->m_root = nullptr; tree.m_root = n; return tree; } auto parent = dynamic_cast *>(n->parent); auto &children = parent->children; auto pos = children.indexOf(n); if (pos == LinkedList::npos) return GeneralTree(); children.removeAt(pos); tree.m_root = n; return tree; } GeneralTreeNode *find(const T &value) const { return find(dynamic_cast *>(this->m_root), value); } bool find(TreeNode *node) const override { return find(dynamic_cast *>(this->m_root), dynamic_cast *>(node)); } GeneralTreeNode *root() const { return dynamic_cast *>(this->m_root); } int count() const { return count(dynamic_cast *>(this->m_root)); } int degree() const { return degree(dynamic_cast *>(this->m_root)); } int height() const { return height(dynamic_cast *>(this->m_root)); } void clear() { destroy(dynamic_cast *>(this->m_root)); this->m_root = nullptr; } Iterator begin() { return Iterator(dynamic_cast *>(this->m_root)); } Iterator end() { return Iterator(nullptr); } GeneralTree &operator=(GeneralTree &&other) { if (&other != this) { auto root(this->m_root); this->m_root = other.m_root; other.m_root = root; } return *this; } protected: /** * @brief 以Node为根节点的GeneralTree,查找的值为value的GeneralTreeNode */ GeneralTreeNode *find(const GeneralTreeNode *node, const T &value) const { if (node == nullptr) return nullptr; if (node->value == value) return const_cast *>(node); GeneralTreeNode *ret = nullptr; auto &children = const_cast *> &>(node->children); for (auto &child : children) { ret = find(child, value); if (ret != nullptr) break; } return ret; } /** * @brief find 在node子树中查找obj */ GeneralTreeNode *find(const GeneralTreeNode *node, const GeneralTreeNode *obj) const { if (node == nullptr) return nullptr; if (node == obj) return const_cast *>(node); GeneralTreeNode *result = nullptr; auto &children = const_cast *> &>(node->children); for (auto &child : children) { result = find(child, obj); if (result != nullptr) break; } return result; } void destroy(GeneralTreeNode *node) { if (node == nullptr) return; auto &children = node->children; for (auto &child : children) { destroy(child); } delete node; } int count(const GeneralTreeNode *node) const { if (node == nullptr) return 0; int ret = 1; auto &children = const_cast *> &>(node->children); for (auto &child : children) { ret += count(child); } return ret; } int height(const GeneralTreeNode *node) const { if (node == nullptr) return 0; int ret = 0; auto &children = const_cast *> &>(node->children); for (auto &child : children) { int h = height(child); if (ret < h) ret = h; } return ret + 1; } int degree(const GeneralTreeNode *node) const { if (node == nullptr) return 0; int ret = node->children.length(); auto &children = const_cast *> &>(node->children); for (auto &child : children) { int d = degree(child); if (d > ret) ret = d; } return ret; } }; } // namespace Kylin #endif // GENERALTREE_H