数据结构开发(23):二叉树中结点的查找、插入、删除与清除操作
0.目录
1.二叉树中结点的查找操作
2.二叉树中结点的插入操作
3.二叉树中结点的删除操作
4.二叉树中结点的清除操作
5.小结
1.二叉树中结点的查找操作
查找的方式:
- 基于数据元素值的查找
BTreeNode<T>* find(const T& value) const
- 基于结点的查找
BTreeNode<T>* find(TreeNode<T>* node) const
树中数据元素和结点的查找:
基于数据元素值的查找:
- 定义功能:find(node, value)
- 在 node 为根结点的二叉树中查找 value 所在的结点
在BTree.h中实现基于数据元素值的查找:
protected:
virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
{
BTreeNode<T>* ret = NULL;
if( node != NULL )
{
if( node->value == value )
{
return node;
}
else
{
if( ret == NULL )
{
ret = find(node->left, value);
}
if( ret == NULL )
{
ret = find(node->right, value);
}
}
}
return ret;
}
public:
BTreeNode<T>* find(const T& value) const
{
return find(root(), value);
}
基于结点的查找:
- 定义功能:find(node, obj)
- 在 node 为根结点的二叉树中查找是否存在 obj 结点
在BTree.h中实现基于结点的查找:
protected:
virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
{
BTreeNode<T>* ret = NULL;
if( node == obj )
{
return node;
}
else
{
if( node != NULL )
{
if( ret == NULL )
{
ret = find(node->left, obj);
}
if( ret == NULL )
{
ret = find(node->right, obj);
}
}
}
return ret;
}
public:
BTreeNode<T>* find(TreeNode<T>* node) const
{
return find(root(), dynamic_cast<BTreeNode<T>*>(node));
}
2.二叉树中结点的插入操作
需要考虑的问题:
- 是否能够在二叉树的任意结点处插入子结点?
- 是否需要指定新数据元素 ( 新结点 ) 的插入位置?
二叉树结点的位置枚举类型:
插入的方式
- 插入新结点
bool insert(TreeNode<T>* node)
bool insert(TreeNode<T>* node, BTNodePos pos)
- 插入数据元素
bool insert(const T& value, TreeNode<T>* parent)
bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
新结点的插入:
指定位置的结点插入:
插入新结点:
插入数据元素:
在BTreeNode.h中实现BTNodePos枚举类型:
#ifndef BTREENODE_H
#define BTREENODE_H
#include "TreeNode.h"
namespace StLib
{
enum BTNodePos
{
ANY,
LEFT,
RIGHT
};
template <typename T>
class BTreeNode : public TreeNode<T>
{
public:
BTreeNode<T>* left;
BTreeNode<T>* right;
BTreeNode()
{
left = NULL;
right = NULL;
}
static BTreeNode<T>* NewNode()
{
BTreeNode<T>* ret = new BTreeNode<T>();
if( ret != NULL )
{
ret->m_flag = true;
}
return ret;
}
};
}
#endif // BTREENODE_H
在BTree.h中实现结点的插入操作:
protected:
virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
{
bool ret = true;
if( pos == ANY )
{
if( np->left == NULL )
{
np->left = n;
}
else if( np->right == NULL )
{
np->right = n;
}
else
{
ret = false;
}
}
else if( pos == LEFT )
{
if( np->left == NULL )
{
np->left = n;
}
else
{
ret = false;
}
}
else if( pos == RIGHT )
{
if( np->right == NULL )
{
np->right = n;
}
else
{
ret = false;
}
}
else
{
ret = false;
}
return ret;
}
public:
bool insert(TreeNode<T>* node)
{
return insert(node, ANY);
}
virtual bool insert(TreeNode<T>* node, BTNodePos pos)
{
bool ret = true;
if( node != NULL )
{
if( this->m_root == NULL )
{
node->parent = NULL;
this->m_root = node;
}
else
{
BTreeNode<T>* np = find(node->parent);
if( np != NULL )
{
ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node ...");
}
}
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
}
return ret;
}
bool insert(const T& value, TreeNode<T>* parent)
{
return insert(value, parent, ANY);
}
virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
{
bool ret = true;
BTreeNode<T>* node = BTreeNode<T>::NewNode();
if( node == NULL )
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
}
else
{
node->value = value;
node->parent = parent;
ret = insert(node, pos);
if( !ret )
{
delete node;
}
}
return ret;
}
mian.cpp测试这棵树:
#include <iostream>
#include "BTree.h"
using namespace std;
using namespace StLib;
int main()
{
BTree<int> bt;
BTreeNode<int>* n = NULL;
bt.insert(1, NULL);
n = bt.find(1);
bt.insert(2, n);
bt.insert(3, n);
n = bt.find(2);
bt.insert(4, n);
bt.insert(5, n);
n = bt.find(4);
bt.insert(8, n);
bt.insert(9, n);
n = bt.find(5);
bt.insert(10, n);
n = bt.find(3);
bt.insert(6, n);
bt.insert(7, n);
n = bt.find(6);
bt.insert(11, n, LEFT);
int a[] = {8, 9, 10, 11, 7};
for(int i=0; i<5; i++)
{
TreeNode<int>* node = bt.find(a[i]);
while( node )
{
cout << node->value << " ";
node = node->parent;
}
cout << endl;
}
return 0;
}
运行结果为:
8 4 2 1
9 4 2 1
10 5 2 1
11 6 3 1
7 3 1
3.二叉树中结点的删除操作
删除的方式:
- 基于数据元素值的删除
SharedPointer< Tree<T> > remove(const T& value)
- 基于结点的删除
SharedPointer< Tree<T> > remove(TreeNode<T>* node)
二叉树中的结点删除:
删除操作功能的定义:
void remove(BTreeNode<T>* node, BTree<T>*& ret)
- 将 node 为根结点的子树从原来的二叉树中删除
- ret 作为子树返回 ( ret 指向堆空间中的二叉树对象 )
删除功能函数的实现:
在BTree.h中实现结点的删除操作:
protected:
virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
{
ret = new BTree<T>();
if( ret == NULL )
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
}
else
{
if( root() == node )
{
this->m_root = NULL;
}
else
{
BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
if( parent->left == node )
{
parent->left = NULL;
}
else if( parent->right == node )
{
parent->right = NULL;
}
node->parent = NULL;
}
ret->m_root = node;
}
}
public:
SharedPointer< Tree<T> > remove(const T& value)
{
BTree<T>* ret = NULL;
BTreeNode<T>* node = find(value);
if( node == NULL )
{
THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
}
else
{
remove(node, ret);
}
return ret;
}
SharedPointer< Tree<T> > remove(TreeNode<T>* node)
{
BTree<T>* ret = NULL;
node = find(node);
if( node == NULL )
{
THROW_EXCEPTION(InvalidParameterException, "Parameter node is invalid ...");
}
else
{
remove(dynamic_cast<BTreeNode<T>*>(node), ret);
}
return ret;
}
mian.cpp测试:
#include <iostream>
#include "BTree.h"
using namespace std;
using namespace StLib;
int main()
{
BTree<int> bt;
BTreeNode<int>* n = NULL;
bt.insert(1, NULL);
n = bt.find(1);
bt.insert(2, n);
bt.insert(3, n);
n = bt.find(2);
bt.insert(4, n);
bt.insert(5, n);
n = bt.find(4);
bt.insert(8, n);
bt.insert(9, n);
n = bt.find(5);
bt.insert(10, n);
n = bt.find(3);
bt.insert(6, n);
bt.insert(7, n);
n = bt.find(6);
bt.insert(11, n, LEFT);
int a[] = {8, 9, 10, 11, 7};
SharedPointer< Tree<int> > sp = bt.remove(3);
for(int i=0; i<5; i++)
{
TreeNode<int>* node = sp->find(a[i]);
while( node )
{
cout << node->value << " ";
node = node->parent;
}
cout << endl;
}
return 0;
}
运行结果为:
11 6 3
7 3
4.二叉树中结点的清除操作
清除操作的定义:
- void clear()
- 将二叉树中的所有结点清除 ( 释放堆中的结点 )
二叉树中结点的清除:
清除操作功能的定义:
- free(node)
- 清除 node 为根结点的二叉树
- 释放二叉树中的每一个结点
在BTree.h中实现结点的清除操作:
protected:
virtual void free(BTreeNode<T>* node)
{
if( node != NULL )
{
free(node->left);
free(node->right);
if( node->flag() )
{
delete node;
}
}
}
public:
void clear()
{
free(root());
this->m_root = NULL;
}
5.小结
- 二叉树的插入操作需要指明插入的位置
- 插入操作必须正确处理指向父结点的指针
- 插入数据元素时需要从堆空间中创建结点
- 当数据元素插入失败时需要释放结点空间
- 删除操作将目标结点所代表的子树移除
- 删除操作必须完善处理父结点和子结点的关系
- 清除操作用于销毁树中的每个结点
- 销毁结点时判断是否释放对应的内存空间 ( 工厂模式 )
最终的BTree.h代码:
BTree.h
#ifndef BTREE_H
#define BTREE_H
#include "Tree.h"
#include "BTreeNode.h"
#include "Exception.h"
#include "LinkQueue.h"
namespace StLib
{
template <typename T>
class BTree : public Tree<T>
{
protected:
virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
{
BTreeNode<T>* ret = NULL;
if( node != NULL )
{
if( node->value == value )
{
return node;
}
else
{
if( ret == NULL )
{
ret = find(node->left, value);
}
if( ret == NULL )
{
ret = find(node->right, value);
}
}
}
return ret;
}
virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
{
BTreeNode<T>* ret = NULL;
if( node == obj )
{
return node;
}
else
{
if( node != NULL )
{
if( ret == NULL )
{
ret = find(node->left, obj);
}
if( ret == NULL )
{
ret = find(node->right, obj);
}
}
}
return ret;
}
virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
{
bool ret = true;
if( pos == ANY )
{
if( np->left == NULL )
{
np->left = n;
}
else if( np->right == NULL )
{
np->right = n;
}
else
{
ret = false;
}
}
else if( pos == LEFT )
{
if( np->left == NULL )
{
np->left = n;
}
else
{
ret = false;
}
}
else if( pos == RIGHT )
{
if( np->right == NULL )
{
np->right = n;
}
else
{
ret = false;
}
}
else
{
ret = false;
}
return ret;
}
virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
{
ret = new BTree<T>();
if( ret == NULL )
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
}
else
{
if( root() == node )
{
this->m_root = NULL;
}
else
{
BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
if( parent->left == node )
{
parent->left = NULL;
}
else if( parent->right == node )
{
parent->right = NULL;
}
node->parent = NULL;
}
ret->m_root = node;
}
}
virtual void free(BTreeNode<T>* node)
{
if( node != NULL )
{
free(node->left);
free(node->right);
if( node->flag() )
{
delete node;
}
}
}
public:
bool insert(TreeNode<T>* node)
{
return insert(node, ANY);
}
virtual bool insert(TreeNode<T>* node, BTNodePos pos)
{
bool ret = true;
if( node != NULL )
{
if( this->m_root == NULL )
{
node->parent = NULL;
this->m_root = node;
}
else
{
BTreeNode<T>* np = find(node->parent);
if( np != NULL )
{
ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node ...");
}
}
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
}
return ret;
}
bool insert(const T& value, TreeNode<T>* parent)
{
return insert(value, parent, ANY);
}
virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
{
bool ret = true;
BTreeNode<T>* node = BTreeNode<T>::NewNode();
if( node == NULL )
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
}
else
{
node->value = value;
node->parent = parent;
ret = insert(node, pos);
if( !ret )
{
delete node;
}
}
return ret;
}
SharedPointer< Tree<T> > remove(const T& value)
{
BTree<T>* ret = NULL;
BTreeNode<T>* node = find(value);
if( node == NULL )
{
THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
}
else
{
remove(node, ret);
}
return ret;
}
SharedPointer< Tree<T> > remove(TreeNode<T>* node)
{
BTree<T>* ret = NULL;
node = find(node);
if( node == NULL )
{
THROW_EXCEPTION(InvalidParameterException, "Parameter node is invalid ...");
}
else
{
remove(dynamic_cast<BTreeNode<T>*>(node), ret);
}
return ret;
}
BTreeNode<T>* find(const T& value) const
{
return find(root(), value);
}
BTreeNode<T>* find(TreeNode<T>* node) const
{
return find(root(), dynamic_cast<BTreeNode<T>*>(node));
}
BTreeNode<T>* root() const
{
return dynamic_cast<BTreeNode<T>*>(this->m_root);
}
int degree() const
{
return NULL;
}
int count() const
{
return NULL;
}
int height() const
{
return NULL;
}
void clear()
{
free(root());
this->m_root = NULL;
}
~BTree()
{
clear();
}
};
}
#endif // BTREE_H