tongqingliu

保持学习的态度

C++二叉搜索树

//BST.h
#pragma once
template <typename T> class BST;
template <typename T> class BSTNode {
public:
    friend class BST<T>;
    BSTNode() {
        lChild = rChild = parent = nullptr;
        data = nullptr;
    }
    BSTNode(T value) {
        lChild = rChild = parent = nullptr;
        data = value;
    }
private:
    BSTNode<T>* lChild, * rChild, * parent;
    T data;
};

template<typename T> class BST {
public:
    BST() { }

    //插入操作
    void insert(BSTNode<T>* node);

    //二叉查找树的中序遍历,就相当于排序了
    void inSort(BSTNode<T>* node);

    //按节点删除
    void deleteNode(BSTNode<T>* node);

    //按数值删除
    void deleteNode(const T& t);

    BSTNode<T>* search(T key);
    BSTNode<T>* root = nullptr;

private:
    int count;
};

template<typename T>
void BST<T>::insert(BSTNode<T>* node)
{
    BSTNode<T>* curr, * temp = nullptr;
    curr = root;
    while (nullptr != curr) //遍历二叉树,找到应该插入的父节点
    {
        temp = curr;
        if (node->data > curr->data)
        {
            curr = curr->rChild;
        }
        else {
            curr = curr->lChild;
        }
    }
    node->parent = temp;//temp 代码当前最后遍历的node,设置node->parent为该节点
    if (temp == nullptr)
    {
        root = node;
        count++;
    }
    else {
        if (node->data < temp->data)
        {
            temp->lChild = node;
            count++;
        }
        else {
            temp->rChild = node;
            count++;
        }
    }
}

template<typename T>
void BST<T>::inSort(BSTNode<T>* node)
{
    if (node != nullptr)
    {
        inSort(node->lChild);
        std::cout << node->data << ",";
        inSort(node->rChild);
    }
}

template<typename T>
inline void BST<T>::deleteNode(BSTNode<T>* node)
{
    BSTNode<T>* p = node->parent;//获取node的父节点,这里很重要
    if (node->lChild == nullptr && node->rChild == nullptr) //叶子节点直接删除
    {
        if (node == node->parent->lChild)
        {
            node->parent->lChild = nullptr;
        }
        else {
            node->parent->rChild = nullptr;
        }
        delete node;
        count--;
    }
    else if (node->rChild != nullptr && node->lChild == nullptr) {//存在右孩子
        if (p == nullptr)//说明节点为根节点
        {
            root = node->rChild;
            count--;
        }
        else {
            node->rChild->parent = p;
            if (p->lChild == node) //判断是父节点的左孩子还是右孩子
            {
                p->lChild = node->rChild;
            }
            else {
                p->rChild = node->rChild;
            }
            delete node;
            count--;
        }
    }
    else if (node->lChild != nullptr && node->rChild == nullptr)//存在左孩子
    {
        if (p == nullptr)
        {
            root = root->lChild;
            count--;
        }
        else {
            node->lChild->parent = p;
            if (p->lChild == node)
            {
                p->lChild = node->lChild;
            }
            else {
                p->rChild = node->lChild;
            }
            delete node;
            count--;
        }
    }
    else {
        BSTNode<T>* left, * curp = nullptr;
        left = node->rChild; //本方案是找右侧最小值,替换node节点,其他节点保持不动即可
        while (left != nullptr)
        {
            curp = left;
            left = left->lChild;
        }

        if (curp->rChild != nullptr)
        {
            if (curp->lChild == curp)
            {
                curp->parent->lChild = curp->rChild;
            }
            else {
                curp->parent->rChild = curp->rChild;
            }
        }
        else {
            if (curp->parent->lChild == curp)
            {
                curp->parent->lChild = nullptr;
            }
            else {
                curp->parent->rChild = nullptr;
            }
            //curp->parent->lChild = nullptr;
        }
        //替curp 替换 node
        curp->parent = p;
        curp->lChild = node->lChild;
        curp->rChild = node->rChild;

        if (p->lChild == node)//判断node 是p 的左孩子还是右孩
        {
            p->lChild = curp;
        }
        else {
            p->rChild = curp;
        }
        delete node;
        count--;
    }
}

template<typename T>
inline void BST<T>::deleteNode(const T& k)
{
    BSTNode<T>* node = search(k);
    if (node != nullptr)
    {
        deleteNode(node);
    }
}


template<typename T>
inline BSTNode<T>* BST<T>::search(T k)
{
    BSTNode<T>* node = root;
    while (node != nullptr)
    {
        if (k < node->data)
        {
            node = node->lChild;
        }
        else if (k > node->data)
        {
            node = node->rChild;
        }
        else {
            break;
        }
    }
    return node;
}

//BSTree.h
//BST.cpp
#include "BST.h"
//main.cpp
//https://www.cnblogs.com/clc2008/p/10193550.html
//#include "pch.h"
#include <iostream>
#include "BST.h"
using namespace std;

int main()
{
    // 树结构示意
    //     30
    //    /  \
    //  15   25
    // /  \
    //9    18
    //   /   \
    //  16   25
    //      /  \
    //    20    26  
    BST<int> sbt;
    sbt.insert(new BSTNode<int>(30));
    sbt.insert(new BSTNode<int>(15));
    sbt.insert(new BSTNode<int>(9));
    sbt.insert(new BSTNode<int>(18));
    sbt.insert(new BSTNode<int>(16));
    sbt.insert(new BSTNode<int>(25));
    sbt.insert(new BSTNode<int>(20));
    sbt.insert(new BSTNode<int>(26));
    sbt.insert(new BSTNode<int>(35));

    cout << "搜索树排序后:";
    sbt.inSort(sbt.root);

    sbt.deleteNode(18);

    cout << endl << "删除18 后排序:";

    sbt.inSort(sbt.root);
}

posted on 2020-09-01 18:29  tongqingliu  阅读(85)  评论(0编辑  收藏  举报

导航