資料結構開發(23):二叉樹中結點的查詢、插入、刪除與清除操作
阿新 • • 發佈:2018-12-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