查找二叉树模板类的完全实现
查找二叉树的特点是:左子树的所有节点小于根节点,右子树的所有节点大于根节点。
类似的数据结构最难的操作是remove操作,这也是本文中最经典的操作(自我感觉),在代码后面详细说一下remove操作
binaryTree.h
#ifndef BINARYSEARCHTREE_H
#define BINARYSEARCHTREE_H
template<typename Comparable>
class BinarySearchTree
{
public:
BinarySearchTree();
BinarySearchTree(const BinarySearchTree& rhs);
~BinarySearchTree();
const Comparable& findMin() const;
const Comparable& findMax() const;
bool contains(const Comparable& x) const;
bool isEmpty() const;
void printTree() const;
void makeEmpty();
void insert(const Comparable& x);
void remove(const Comparable& x);
const BinarySearchTree& operator=(const BinarySearchTree& rhs);
private:
struct BinaryNode
{
Comparable element;
BinaryNode* left;
BinaryNode* right;
BinaryNode(const Comparable& theElement, BinaryNode* lt, BinaryNode* rt) :
element(theElement), left(lt), right(rt){}
};
BinaryNode* root;
private:
void insert(const Comparable &x, BinaryNode*& t) const;
void remove(const Comparable &x, BinaryNode*& t) const;
BinaryNode* findMin(BinaryNode* t) const;
BinaryNode* findMax(BinaryNode* t) const;
bool contains(const Comparable &x, BinaryNode* t) const;
void makeEmpty(BinaryNode*& t);
void printTree(BinaryNode* t) const;
BinaryNode* clone(BinaryNode *t) const;
};
#endif // BINARYSEARCHTREE_H
binaryTree.cpp
#include "binarySearchTree.h"
#include <iostream>
template<typename Comparable>
BinarySearchTree<Comparable>::BinarySearchTree()
{
root = nullptr;
}
template<typename Comparable>
BinarySearchTree<Comparable>::BinarySearchTree(const BinarySearchTree &rhs)
{
this->root = clone(rhs.root);
}
template<typename Comparable>
BinarySearchTree<Comparable>::~BinarySearchTree()
{
makeEmpty();
}
template<typename Comparable>
const Comparable &BinarySearchTree<Comparable>::findMin() const
{
return findMin(root);
}
template<typename Comparable>
const Comparable &BinarySearchTree<Comparable>::findMax() const
{
return findMax(root);
}
template<typename Comparable>
bool BinarySearchTree<Comparable>::contains(const Comparable &x) const
{
return contains(x, root);
}
template<typename Comparable>
bool BinarySearchTree<Comparable>::isEmpty() const
{
if(root == nullptr)
return true;
else
return false;
}
template<typename Comparable>
void BinarySearchTree<Comparable>::printTree() const
{
printTree(root);
}
template<typename Comparable>
void BinarySearchTree<Comparable>::makeEmpty()
{
makeEmpty();
}
template<typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable &x)
{
insert(x, root);
}
template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable &x)
{
remove(x, root);
}
template<typename Comparable>
const BinarySearchTree<Comparable> &BinarySearchTree<Comparable>::operator=(const BinarySearchTree &rhs)
{
if(this != &rhs)
{
makeEmpty();
root = clone(rhs.root);
}
return *this;
}
///
/// down private:
///
template<typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable &x, BinarySearchTree<Comparable>::BinaryNode *&t) const
{
if(t == nullptr)
t = new BinaryNode(x, nullptr, nullptr);
else if(x < t->element)
insert(x, t->left);
else if(t->element < x)
insert(x, t->right);
else
;
}
template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable &x, BinarySearchTree<Comparable>::BinaryNode *&t) const
{
if(t == nullptr)
return;
if(x < t->element)
remove(x, t->left);
else if(t->element < x)
remove(x, t->right);
else if(t->left != nullptr && t->right != nullptr)
{
t->element = findMin(t->right)->element;
remove(t->element, t->right);
}
else
{
BinaryNode *oldNode = t;
t = (t->left != nullptr)?t->left:t->right;
delete oldNode;
}
}
template<typename Comparable>
typename BinarySearchTree<Comparable>::BinaryNode *BinarySearchTree<Comparable>::findMin(BinarySearchTree<Comparable>::BinaryNode *t) const
{
if(t == nullptr)
return nullptr;
if(t->left == nullptr)
return t;
return findMin(t->left);
}
template<typename Comparable>
typename BinarySearchTree<Comparable>::BinaryNode *BinarySearchTree<Comparable>::findMax(BinarySearchTree<Comparable>::BinaryNode *t) const
{
if(t != nullptr)
while(t->right != nullptr)
t = t->right;
return t;
}
template<typename Comparable>
bool BinarySearchTree<Comparable>::contains(const Comparable &x, BinarySearchTree<Comparable>::BinaryNode *t) const
{
if(t == nullptr)
return false;
else if(x < t->element)
return contains(x, t->left);
else if(t->element < x)
return contains(x, t->right);
else
return true;
}
template<typename Comparable>
void BinarySearchTree<Comparable>::makeEmpty(BinarySearchTree<Comparable>::BinaryNode *&t)
{
if(t != nullptr)
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = nullptr;
}
template<typename Comparable>
void BinarySearchTree<Comparable>::printTree(BinarySearchTree<Comparable>::BinaryNode *t) const
{
if(t != nullptr)
{
std::cout << t->element << " ";
printTree(t->left);
printTree(t->right);
}
}
template<typename Comparable>
typename BinarySearchTree<Comparable>::BinaryNode *BinarySearchTree<Comparable>::clone(BinarySearchTree<Comparable>::BinaryNode *t) const
{
if(t == nullptr)
return nullptr;
return new BinaryNode(t->element, clone(t->left), clone(t->right));
}
查找二叉树的remove操作需要在删除节点后,其余的树还符合查找二叉树的特征。这也就造成了remove的难点,不能简单的delete。
remove分为三种情况
要删除的节点是叶子节点:
这种情况是最简单的,直接delete Node
要删除的节点有一个子节点:
直接用子节点代替要删除的节点
删除Node
要删除的节点有两个子节点:
查找要删除节点右子树中的最小节点
有这个最小节点代替要删除的节点
delete Node
之所以觉的remove经典是因为在remove中使用指针的引用,至于为什么大家可以结合代码自己体会一下。