Kylin/DataStructure/GeneralTree.h
2023-12-27 10:29:16 +08:00

213 lines
6.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef GENERALTREE_H
#define GENERALTREE_H
#include "LinkedList.h"
#include "LinkedQueue.h"
#include "Tree.h"
namespace Kylin {
template <typename T>
class GeneralTreeNode : public TreeNode<T> {
public:
GeneralTreeNode(const T &value, TreeNode<T> *parent = nullptr) : TreeNode<T>(value, parent) {}
LinkedList<GeneralTreeNode<T> *> children;
};
template <typename T>
class GeneralTree : public Tree<T> {
public:
class Iterator {
public:
Iterator(GeneralTreeNode<T> *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<T> *m_pos = nullptr;
LinkedQueue<GeneralTreeNode<T> *> m_queue;
};
GeneralTree() = default;
GeneralTree(GeneralTree &&other) {
this->m_root = other.m_root;
other.m_root = nullptr;
}
~GeneralTree() { clear(); }
bool insert(TreeNode<T> *node) {
bool ret = false;
auto n = dynamic_cast<GeneralTreeNode<T> *>(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<GeneralTreeNode<T> *>(node->parent);
parent->children.append(n);
ret = true;
}
return ret;
}
/**
* @brief 插入成功返回TreeNode的地址否则nullptr
*/
GeneralTreeNode<T> *insert(const T &value, TreeNode<T> *parent) {
auto ret = new GeneralTreeNode<T>(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<T> remove(const T &value) {
auto node = find(value);
return node == nullptr ? GeneralTree<T>() : remove(node);
}
GeneralTree<T> remove(const GeneralTreeNode<T> *node) {
if (node == nullptr) return GeneralTree<T>();
GeneralTree<T> tree;
auto n = const_cast<GeneralTreeNode<T> *>(node);
if (n == this->m_root) {
this->m_root = nullptr;
tree.m_root = n;
return tree;
}
auto parent = dynamic_cast<GeneralTreeNode<T> *>(n->parent);
auto &children = parent->children;
auto pos = children.indexOf(n);
if (pos == LinkedList<T>::npos) return GeneralTree<T>();
children.removeAt(pos);
tree.m_root = n;
return tree;
}
GeneralTreeNode<T> *find(const T &value) const {
return find(dynamic_cast<GeneralTreeNode<T> *>(this->m_root), value);
}
bool find(TreeNode<T> *node) const override {
return find(dynamic_cast<GeneralTreeNode<T> *>(this->m_root),
dynamic_cast<GeneralTreeNode<T> *>(node));
}
GeneralTreeNode<T> *root() const { return dynamic_cast<GeneralTreeNode<T> *>(this->m_root); }
int count() const { return count(dynamic_cast<GeneralTreeNode<T> *>(this->m_root)); }
int degree() const { return degree(dynamic_cast<GeneralTreeNode<T> *>(this->m_root)); }
int height() const { return height(dynamic_cast<GeneralTreeNode<T> *>(this->m_root)); }
void clear() {
destroy(dynamic_cast<GeneralTreeNode<T> *>(this->m_root));
this->m_root = nullptr;
}
Iterator begin() { return Iterator(dynamic_cast<GeneralTreeNode<T> *>(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<T> *find(const GeneralTreeNode<T> *node, const T &value) const {
if (node == nullptr) return nullptr;
if (node->value == value) return const_cast<GeneralTreeNode<T> *>(node);
GeneralTreeNode<T> *ret = nullptr;
auto &children = const_cast<LinkedList<GeneralTreeNode<T> *> &>(node->children);
for (auto &child : children) {
ret = find(child, value);
if (ret != nullptr) break;
}
return ret;
}
/**
* @brief find 在node子树中查找obj
*/
GeneralTreeNode<T> *find(const GeneralTreeNode<T> *node, const GeneralTreeNode<T> *obj) const {
if (node == nullptr) return nullptr;
if (node == obj) return const_cast<GeneralTreeNode<T> *>(node);
GeneralTreeNode<T> *result = nullptr;
auto &children = const_cast<LinkedList<GeneralTreeNode<T> *> &>(node->children);
for (auto &child : children) {
result = find(child, obj);
if (result != nullptr) break;
}
return result;
}
void destroy(GeneralTreeNode<T> *node) {
if (node == nullptr) return;
auto &children = node->children;
for (auto &child : children) {
destroy(child);
}
delete node;
}
int count(const GeneralTreeNode<T> *node) const {
if (node == nullptr) return 0;
int ret = 1;
auto &children = const_cast<LinkedList<GeneralTreeNode<T> *> &>(node->children);
for (auto &child : children) {
ret += count(child);
}
return ret;
}
int height(const GeneralTreeNode<T> *node) const {
if (node == nullptr) return 0;
int ret = 0;
auto &children = const_cast<LinkedList<GeneralTreeNode<T> *> &>(node->children);
for (auto &child : children) {
int h = height(child);
if (ret < h) ret = h;
}
return ret + 1;
}
int degree(const GeneralTreeNode<T> *node) const {
if (node == nullptr) return 0;
int ret = node->children.length();
auto &children = const_cast<LinkedList<GeneralTreeNode<T> *> &>(node->children);
for (auto &child : children) {
int d = degree(child);
if (d > ret) ret = d;
}
return ret;
}
};
} // namespace Kylin
#endif // GENERALTREE_H