查找二叉樹模板類的完全實現
查找二叉樹的特點是:左子樹的所有節點小於根節點,右子樹的所有節點大於根節點。
類似的數據結構最難的操作是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中使用指針的引用,至於爲什麼大家可以結合代碼自己體會一下。