文章中部分内容和思路来自《数据结构、算法与应用 c++语言描述》


二叉搜索树定义

搜索树

是一颗二叉树,可能为空;一颗非空的二叉搜索树应满足以下条件:

1) 每个元素有一个关键字,并且任意两个元素关键字不同;因此,所有元素的关键字唯一

2) 在根节点的左子树中,元素的关键字(若有)都小于根节点的关键字

3) 在根节点的右子树中,元素的关键字(若有)都大于根节点的关键字

4) 根节点的左右子树也都是二叉搜索树

图14-1中除a)图外都是二叉搜索树

[ps:条件1可以去掉,然后用小于等于替代2中小于,大于等于替代3中大于,可以构成有重复值的二叉搜索树]


二叉搜索树插入

示意:

搜索树

代码:

template<class T>
void BinarySearchTree<T>::insert(const T &value, BSTNODE<T> *&node)
{
    if (NULL == node)
    {
        node = new BSTNODE<T>;
        node->element = value;
        node->leftchild = NULL;
        node->rightchild = NULL;
    }
    else if (node->element > value)
    {
        insert(value, node->leftchild);
    }
    else if (node->element < value)
    {
        insert(value, node->rightchild);
    }
    else
    {
        // 无重复值节点
    }
}

 

二叉搜索树删除

原理及示意:

分三种情况,1)删除的节点是叶子节点 2)删除的节点只有一个孩子节点 3)删除的节点有两个孩子节点

搜索树

第一种情况比较简单,这里不作解释[删除节点释放内存即可]

第二种情况也比较简单,以图b为例,若删除节点5,则使其父节点指向其子节点,删除节点释放内存即可

第三种情况复杂一些,以图a为例,若删除节点40,则取节点左子树中最大节点35或右子树最小节点60,替换该节点值,并删除35/60节点释放内存即可

代码:

template<class T>
void BinarySearchTree<T>::remove(const T &value, BSTNODE<T> *&node)
{
    // 空节点直接返回
    if (NULL == node)
        return;

    if (value < node->element)
        remove(value, node->leftchild);
    else if (value > node->element)
        remove(value, node->rightchild);
    else
    {
        // 重点:
        // 若节点有两个孩子,则先将左树的最大节点/右树的最小节点替换当前节点,然后删除左树最大节点/右树最小节点
        // 若节点只有一个孩子,则用孩子节点替换当前节点,并使当前节点指向孩子节点的孩子节点,删除孩子节点
        if (node->leftchild != NULL && node->rightchild != NULL) // 待删除的节点有两个孩子
        {
            node->element = findMax(node->leftchild)->element;
            remove(node->element, node->leftchild);
        }
        else
        {
            // 先将当前节点指向
            BSTNODE<T> *tmpNode = node;
            node = (node->leftchild != NULL) ? node->leftchild : node->rightchild;
            delete tmpNode;
            tmpNode = NULL;
        }
    }
}


索引二叉搜索树

搜索树

源于普通二叉搜索树,只是在每个节点上添加一个leftSize域。域的值是该节点左子树元素个数


二叉搜索树操作完整例子代码

---------

strdef.h

---------

#ifndef STRDEF_H
#define STRDEF_H

template <class T>
struct BSTNode
{
    T element; // 值域
    BSTNode* leftchild; // 左孩子
    BSTNode* rightchild; // 右孩子
};

template <class T>
using BSTNODE = BSTNode<T>;

#endif // STRDEF_H

 

------------------

BinarySearchTree.h

------------------

#ifndef BINARYSEARCHTREE_H
#define BINARYSEARCHTREE_H

#include "strdef.h"

template <class T>
class BinarySearchTree
{
public:
    BinarySearchTree();
    ~BinarySearchTree();

public:
    bool contains(const T& value); // 搜索
    void insert(const T& value); // 插入
    void remove(const T& value); // 删除
    void printNodes(); // 打印全部节点,前序
    BSTNODE<T> *findMax(BSTNODE<T> *node); // 查找最大

private:
    bool contains(const T &value, BSTNODE<T> *node);
    void insert(const T& value, BSTNODE<T> *&node);
    void remove(const T& value, BSTNODE<T> *&node);
    void releaseNode(BSTNODE<T> *node);
    void printNodes(BSTNODE<T> *node);

private:
    BSTNODE<T> *_root;
};

#endif // BINARYSEARCHTREE_H

 

--------------------

BinarySearchTree.cpp

--------------------

#include "BinarySearchTree.h"

#include <QDebug>

template<class T>
BinarySearchTree<T>::BinarySearchTree()
{
    _root = NULL;
}

template<class T>
BinarySearchTree<T>::~BinarySearchTree()
{
    releaseNode(_root);
}

template<class T>
bool BinarySearchTree<T>::contains(const T &value)
{
    return contains(value, _root);
}

template<class T>
void BinarySearchTree<T>::insert(const T &value)
{
    insert(value, _root);
}

template<class T>
void BinarySearchTree<T>::remove(const T &value)
{
    remove(value, _root);
}

template<class T>
void BinarySearchTree<T>::printNodes()
{
    printNodes(_root);
}

template<class T>
BSTNODE<T> *BinarySearchTree<T>::findMax(BSTNODE<T> *node)
{
    if (NULL == node->rightchild)
        return node;
    else
        return findMax(node->rightchild);
}

template<class T>
bool BinarySearchTree<T>::contains(const T &value, BSTNODE<T> *node)
{
    if (node)
    {
        if (node->element == value)
        {
            return true;
        }
        else if (value < node->element)
        {
            return contains(value, node->leftchild);
        }
        else
        {
            return contains(value, node->rightchild);
        }
    }

    return false;
}

template<class T>
void BinarySearchTree<T>::insert(const T &value, BSTNODE<T> *&node)
{
    if (NULL == node)
    {
        node = new BSTNODE<T>;
        node->element = value;
        node->leftchild = NULL;
        node->rightchild = NULL;
    }
    else if (node->element > value)
    {
        insert(value, node->leftchild);
    }
    else if (node->element < value)
    {
        insert(value, node->rightchild);
    }
    else
    {
        // 无重复值节点
    }
}

template<class T>
void BinarySearchTree<T>::remove(const T &value, BSTNODE<T> *&node)
{
    // 空节点直接返回
    if (NULL == node)
        return;

    if (value < node->element)
        remove(value, node->leftchild);
    else if (value > node->element)
        remove(value, node->rightchild);
    else
    {
        // 重点:
        // 若节点有两个孩子,则先将左树的最大节点/右树的最小节点替换当前节点,然后删除左树最大节点/右树最小节点
        // 若节点只有一个孩子,则用孩子节点替换当前节点,并使当前节点指向孩子节点的孩子节点,删除孩子节点
        if (node->leftchild != NULL && node->rightchild != NULL) // 待删除的节点有两个孩子
        {
            node->element = findMax(node->leftchild)->element;
            remove(node->element, node->leftchild);
        }
        else
        {
            // 先将当前节点指向
            BSTNODE<T> *tmpNode = node;
            node = (node->leftchild != NULL) ? node->leftchild : node->rightchild;
            delete tmpNode;
            tmpNode = NULL;
        }
    }
}

template<class T>
void BinarySearchTree<T>::releaseNode(BSTNODE<T> *node)
{
    if (node)
    {
        releaseNode(node->leftchild);
        releaseNode(node->rightchild);
        delete node;
    }
    node = NULL;
}

template<class T>
void BinarySearchTree<T>::printNodes(BSTNODE<T> *node)
{
    if (node)
    {
        qDebug() << node->element;
        printNodes(node->leftchild);
        printNodes(node->rightchild);
    }
}

 

--------

main.cpp

--------

#include <QCoreApplication>

#include "BinarySearchTree.cpp"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    BinarySearchTree<int> bst;


    // 测试数据
    bst.insert(30);
    bst.insert(5);
    bst.insert(40);
    bst.insert(2);
    bst.insert(35);
    bst.insert(80);
    bst.insert(32);
    bst.insert(60);
    bst.insert(85);
    bst.insert(31);
    bst.insert(33);


    // 测试插入
    bst.printNodes();


    // 测试搜索
    qDebug() << bst.contains(20);
    qDebug() << bst.contains(32);


//    // 测试删除叶子节点
//    qDebug() << "测试删除叶子节点";
//    bst.remove(2);
//    bst.printNodes();


//    // 测试删除单孩子节点
//    qDebug() << "测试删除单孩子节点";
//    bst.remove(5);
//    bst.printNodes();
 

    // 测试删除双孩子节点
    qDebug() << "测试删除双孩子节点";
    bst.remove(40);
    bst.printNodes();

    return a.exec();
}


相关文章:

  • 2022-12-23
  • 2021-12-30
  • 2021-10-31
  • 2021-05-24
  • 2021-05-06
猜你喜欢
  • 2021-09-04
  • 2021-11-04
  • 2021-05-20
  • 2021-12-21
  • 2021-10-05
  • 2021-08-17
  • 2022-12-23
相关资源
相似解决方案