上节实现了二叉树中的结点查找、插入,这节实现二叉树中的结点删除,清除,属性操作
目录
1、二叉树中的结点删除
删除的方式 (与通用树结构一致)
-基于数据元素值的删除
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
#ifndef BTREE_H
#define BTREE_H
#include "Tree.h"
#include "BTreeNode.h"
#include "Exception.h"
#include "LinkQueue.h"
#include "DynamicArray.h"
namespace DTLib
{
template < typename T >
class BTree : public Tree<T>
{
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);
m_queue.clear();
}
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);
m_queue.clear();
}
return ret;
}
// ...
};
}
#endif // BTREE_H
main.cpp
#include <iostream>
#include "BTree.h"
using namespace std;
using namespace DTLib;
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;
}
2、二叉树中的结点清除
清除操作的定义
-void clear()
● 将二叉树中的所有结点清除(释放堆中的结点)
二叉树中结点的清除
递归的操作(先清除左子树再右子树再根结点)
清除操作功能的定义
-free( node )
● 清除 node 为根结点的二叉树
● 释放二叉树中的每一个结点
编程实验
清除二叉树中的结点
#ifndef BTREE_H
#define BTREE_H
#include "Tree.h"
#include "BTreeNode.h"
#include "Exception.h"
#include "LinkQueue.h"
#include "DynamicArray.h"
namespace DTLib
{
template < typename T >
class BTree : public Tree<T>
{
protected:
// ...
virtual void free(BTreeNode<T>* node)
{
if(node != NULL)
{
free(node->left);
free(node->right);
if( node->flag() )
{
delete node; // 堆空间的结点才delete
}
}
}
public:
// ...
void clear()
{
free(root());
this->m_root = NULL;
}
~BTree()
{
clear();
}
};
}
#endif // BTREE_H
小结
删除操作将目标结点所代表的子树移除
删除操作必须完善处理父结点和子结点的关系
清除操作用于销毁树中的每个结点
销毁结点时判断是否释放对应的内存空间(工厂模式)
3、二叉树中属性操作函数的实现
count() = 10; height() = 4; degree() = 2;
1、二叉树中结点的数目
定义功能: count( node )
功能: 在node为根结点的二叉树中统计结点数目
左子树结点数 + 右子树结点数 + 1
2、二叉树的高度
定义功能: height( node )
功能: 获取node为根结点的二叉树的高度
取左子树高度与右子树高度最大值 + 1
3、二叉树的度数
定义功能: degree( node )
功能: 获取 node 为根结点的二叉树的度数
!!node->left + !!node->right:当前根结点的度 (两次取反相当于强制bool)
4、编程实验
#ifndef BTREE_H
#define BTREE_H
#include "Tree.h"
#include "BTreeNode.h"
#include "Exception.h"
#include "LinkQueue.h"
#include "DynamicArray.h"
namespace DTLib
{
template < typename T >
class BTree : public Tree<T>
{
protected:
// ...
int count(BTreeNode<T>* node) const
{
// int ret = 0;
// if(node != NULL)
// {
// ret = count(node->left) + count(node->right) + 1;
// }
// return ret;
return (node != NULL) ? (count(node->left) + count(node->right) + 1) : 0;
}
int height(BTreeNode<T>* node) const
{
int ret = 0;
if(node != NULL)
{
int lh = height(node->left);
int rh = height(node->right);
ret = (lh > rh ? lh: rh) + 1;
}
return ret;
}
int degree(BTreeNode<T>* node) const
{
int ret = 0;
if(node != NULL)
{
/*
写法1:不高效的写法(二叉树结点的度最大为2)
int dl = degree(node->left);
int dr = degree(node->right);
ret = (!!node->left + !!node->right); // 根结点度 0, 1, 2
if(ret < dl)
{
ret = dl;
}
if(ret < dr)
{
ret = dr;
}
*/
/*
写法2:代码冗余
ret = (!!node->left + !!node->right); // 可以先得到结点的度
if(ret < 2)
{
int dl = degree(node->left);
if(ret < dl)
{
ret = dl;
}
}
if(ret < 2)
{
int dr = degree(node->right);
if(ret < dr)
{
ret = dr;
}
}
*/
// 写法2的升级
BTreeNode<T>* child[] = {node->left, node->right};
ret = (!!node->left + !!node->right);
for(int i=0; (i<2) && (ret<2); i++)
{
int d = degree(child[i]);
if(ret < d)
{
ret = d;
}
}
}
return ret;
}
public:
// ...
int degree() const
{
return degree(root());
}
int count() const
{
return count(root());
}
int height() const
{
return height(root());
}
// ...
};
}
#endif // BTREE_H
main.cpp
#include <iostream>
#include "BTree.h"
using namespace std;
using namespace DTLib;
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);
cout << bt.count() << endl;
cout << bt.height() << endl;
cout << bt.degree() << endl;
return 0;
}