213 lines
6.8 KiB
C
213 lines
6.8 KiB
C
|
#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
|