删除的方式
基于数据元素的删除
- SharedPointer<Tree<T>> remove(const T &value)
基于结点的删除
- SharedPointer<Tree<T>> remove(TreeNode<T> *node)
删除操作成员函数的设计要点
- 将被删结点所代表的子树进行删除
- 删除函数返回一颗堆空间中的树
- 具体返回值为指向树的智能指针对象
树中结点的删除
实用的设计原则
当需要从函数中返回堆中的对象时,使用智能指针(SharedPointer) 作为函数的返回值
删除操作功能的定义
void remove(GTreeNode<T> node, GTree<T> &ret)
- 将 node 作为根结点的子树从原来的树中删除
- ret 作为子树返回 (ret 指向堆空间中的树对象)
删除函数的实现
编程实验:树结点的删除操作
文件:GTree.h
#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
{
GTree<T> *ret = nullptr;
GTreeNode<T> *node = find(value);
if (node != nullptr)
{
remove(node, ret);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "can not find the node ...");
}
return ret;
}
SharedPointer<Tree<T>> remove(TreeNode<T> *node) override
{
GTree<T> *ret = nullptr;
node = find(node);
if (node != nullptr)
{
remove(dynamic_cast<GTreeNode<T>*>(node), ret);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter node is invalid ...");
}
return ret;
}
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;
}
}
}
void remove(GTreeNode<T> *node, GTree<T> *&ret)
{
ret = new GTree<T>();
if (ret != nullptr)
{
if (node == root())
{
this->m_root = nullptr;
}
else
{
GTreeNode<T> *parent = dynamic_cast<GTreeNode<T>*>(node->parent);
parent->child.remove(parent->child.find(node));
node->parent = nullptr;
}
ret->m_root = node;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to create tree ...");
}
}
};
}
#endif // GTREE_H
文件:main.cpp
#include <iostream>
#include "GTree.h"
using namespace std;
using namespace DTLib;
int main()
{
GTree<char> t;
GTreeNode<char> *node = nullptr;
GTreeNode<char> root;
root.value = 'A';
root.parent = nullptr;
t.insert(&root);
node = t.find('A');
t.insert('B', node);
t.insert('C', node);
t.insert('D', node);
node = t.find('B');
t.insert('E', node);
t.insert('F', node);
node = t.find('E');
t.insert('K', node);
t.insert('L', node);
node = t.find('C');
t.insert('G', node);
node = t.find('D');
t.insert('H', node);
t.insert('I', node);
t.insert('J', node);
node = t.find('H');
t.insert('M', node);
SharedPointer<Tree<char>> p = t.remove(t.find('D'));
const char *s = "KLFGMIJ";
for (int i=0; i<7; ++i)
{
TreeNode<char> *node = t.find(s[i]);
while (node != nullptr)
{
cout << node->value << " ";
node = node->parent;
}
cout << endl;
}
cout << "----------------" << endl;
for (int i=0; i<7; ++i)
{
TreeNode<char> *node = p->find(s[i]);
while (node != nullptr)
{
cout << node->value << " ";
node = node->parent;
}
cout << endl;
}
return 0;
}
输出:
K E B A
L E B A
F B A
G C A
----------------
M H D
I D
J D
小结
- 删错操作将目标结点所代标的子树移除
- 删除操作必须完善处理父结点和子结点的关系
- 删除操作的返回值为指向树的智能指针对象
- 函数中返回堆中的对象时,使用智能指针作为返回值
To be continued
思考:如何实现 GTree (通用树结构) 的属性操作函数
int degree() const;
int count() const;
int height() const;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。