查找二叉樹(二)

查找二叉樹模板類的完全實現

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章