当前位置: 首页 > article >正文

2.4-数据结构:二叉搜索树

2.4-数据结构-二叉搜索树

本文利用C++实现了数据结构中二叉搜索树的常见接口。

#pragma once
#include <iostream>
using namespace std;

template<class K>
struct BSTreeNode {
    BSTreeNode<K>* _left = nullptr;
    BSTreeNode<K>* _right = nullptr;
    K _key;
    BSTreeNode(K key) : _key(key) {}
};

template<class K>
class BSTree {
    typedef BSTreeNode<K> Node;
public:
    // 构造函数
    BSTree() : _root(nullptr) {}

    // 拷贝构造函数
    BSTree(const BSTree<K>& t) {
        _root = Copy(t._root); // 深拷贝。
    }

    // 赋值运算符重载
    BSTree<K>& operator=(BSTree<K> t) {
        swap(_root, t._root);
        return *this;
    }

    // 析构函数
    ~BSTree() {
        Destroy(_root);
        _root = nullptr;
    }

    bool Insert(const K& key) {
        if (_root == nullptr) {
            _root = new Node(key);
            return true;
        }
        Node* parent = nullptr;
        Node* cur = _root;
        while (cur) {
            if (cur->_key < key) {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key) {
                parent = cur;
                cur = cur->_left;
            }
            else {
                return false;
            }
        }

        cur = new Node(key);
        if (parent->_key < key) {
            parent->_right = cur;
        }
        else if (parent->_key > key) {
            parent->_left = cur;
        }

        return true;
    }

    // 打印树。
    void InOrder() {
        _InOrder(_root);
    }
    void _InOrder(Node* root) {
        if (root == nullptr) return;
        _InOrder(root->_left);
        cout << root->_key << " ";
        _InOrder(root->_right);
    }

    bool Find(const K& key) {
        Node* cur = _root;
        while (cur) {
            if (cur->_key < key) {
                cur = cur->_right;
            }
            else if (cur->_key > key) {
                cur = cur->_left;
            }
            else {
                return true;
            }
        }

        return false;
    }

    bool erase(const K& key) {
        Node* parent = nullptr;
        Node* cur = _root;

        while (cur) {
            if (cur->_key < key) {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key) {
                parent = cur;
                cur = cur->_left;
            }
            else {
                // 删除
                // 1.叶子节点 / 托孤
                // 左侧为空。
                if (cur->_left == nullptr) {
                    if (cur == _root) {
                        _root = cur->_right;
                    }
                    else {
                        if (parent->_left == cur) {
                            parent->_left = cur->_right;
                        }
                        else {
                            parent->_right = cur->_right;
                        }
                    }
                    delete cur;
                }/*右侧为空*/
                else if (cur->_right == nullptr) {
                    if (cur == _root) {
                        _root = cur->_left;
                    }
                    else {
                        if (parent->_left == cur) {
                            parent->_left = cur->_left;
                        }
                        else {
                            parent->_right = cur->_left;
                        }
                    }
                    delete cur;
                } /*2.找左子树最大节点 / 右子树最小节点*/
                else {
                    Node* pminRight = cur;
                    Node* minRight = cur->_right;
                    while (minRight->_left) {
                        pminRight = minRight;
                        minRight = minRight->_left;
                    }
                    cur->_key = minRight->_key;
                    if (pminRight->_left == minRight)
                        pminRight->_left = minRight->_right;
                    else
                        pminRight->_right = minRight->_right;

                    delete minRight;
                }
                return true;
            }
        }

        return false;
    }
    
private:
    Node* Copy(Node* root) {
        if (root == nullptr) {
            return nullptr;
        }
        Node* newRoot = new Node(root->_key);
        newRoot->_left = Copy(root->_left);
        newRoot->_right = Copy(root->_right);
        return newRoot;
    }

    void Destroy(Node*& root) {
        if (root == nullptr) {
            return;
        }
        Destroy(root->_left);
        Destroy(root->_right);
        delete root;
        root = nullptr;
    }

    Node* _root = nullptr;
};

附上一段测试样例

#include "BSTree.h"

int main() {
    int a[] = { 8, 3, 1, 10, 6, 4, 7, 14 ,13 };
    BSTree<int> t;
    for (auto e: a){
        t.Insert(e);
    }

    t.InOrder(); // 1 3 4 6 7 8 10 13 14 
    cout << endl;

    t.erase(7); // 删叶子节点。1 3 4 6 8 10 13 14 
    t.InOrder();
    cout << endl;
    t.erase(3); // 只有左孩子的节点。1 4 6 8 10 13 14 
    t.InOrder();
    cout << endl;
    t.erase(6); // 删有两个孩子的节点。1 4 8 10 13 14 
    t.InOrder();
    cout << endl;
    t.erase(8); // 删叶子节点。1 4 10 13 14 
    t.InOrder();
    cout << endl;

    return 0;
}

值得一提的是,对于一些接口,利用迭代可以使代码有所简化。

  1. 插入
bool _InsertR(Node*& root, const K& x) {
        if (root == nullptr) {
            // 插入
            root = new Node(x);
            return true;
        } 
        
        else if (root->_key > x) {
            _InsertR(root->_left, x);
        }
        else if (root->_key < x) {
            _InsertR(root->_right, x);
        }
        else { return false; }
    }
bool InsertR(const K& x) {
        return _InsertR(_root, x);
    }
  1. 删除
bool _EraseR(Node*& root, const K& x) {
        if (root == nullptr) {
            return false;
        }

        if (root->_key < x) {
            return _EraseR(root->_right, x);
        }
        else if (root->_key > x) {
            return _EraseR(root->_left, x);
        }
        else {
            Node* del = root;
            if (root->_left == nullptr) {
                root = root->_right;
            }
            else if (root->_right == nullptr) {
                root = root->_left;
            }
            else {
                Node* maxLeft = root->_left;
                while (maxLeft->_right) {
                    maxLeft = maxLeft->_right;
                }
                root->_key = maxLeft->_key;
                return _EraseR(root->_left, maxLeft->_key);
            }
            delete del;
            return true;
        }
    }

bool EraseR(const K& x) {
        return _EraseR(_root, x);
    }

http://www.kler.cn/a/536873.html

相关文章:

  • DeepSeek和ChatGPT的对比
  • Redis数据库篇 -- Pipeline
  • Java 8 Lambda表达式详解:从入门到实践
  • 多用户同时RDP登入Win10
  • SpringBoot的工作原理
  • 【AI大模型】Ubuntu18.04安装deepseek-r1模型+服务器部署+内网访问
  • 性能优化中的配置优化
  • 深入学习反射
  • 基于asr的所见即可说方案
  • oracle基础语法
  • Ubuntu系统 Zabbix 7.2LTS一键部署脚本
  • spring的事件驱动有时候比消息队列好用
  • 【Docker】 Manifest与Buildx:多架构镜像管理的解析与实践
  • 自己做了个微信小游戏:推一个箱子
  • 基于钉钉API的连接器实现:企业数据集成与自动化管理
  • 大模型产品Deepseek(五)、本地安装部署(Docker方式)
  • 【C语言】数 组与指针:深度剖析与等价表达
  • 力扣240 搜索二维矩阵 ll
  • golang命令大全13--相关资源与学习路径【完】
  • <论文>DeepSeek-R1:通过强化学习激励大语言模型的推理能力
  • python-leetcode-除法求值
  • UML学习
  • 【dotnet】安全编码规范
  • 【清晰教程】通过Docker为本地DeepSeek-r1部署WebUI界面
  • 2025年2月2日(多任务 线程)
  • vue3 的 onScopeDispose 是什么作用