二叉樹(三)二叉查找樹

来源:https://www.cnblogs.com/teternity/archive/2020/02/01/BinarySearchTree.html
-Advertisement-
Play Games

二叉查找樹(二叉搜索樹、二叉排序樹)的創建、增、刪、查、改。 main.cpp: #include <iostream> #include "BinarySearchTree.h" using namespace std; int main() { BinarySearchTree<int> bst ...


二叉查找樹(二叉搜索樹、二叉排序樹)的創建、增、刪、查、改。

 

main.cpp:

#include <iostream>
#include "BinarySearchTree.h"
using namespace std;

int main()
{
    BinarySearchTree<int> bst{ 5,1,3,5,6,6,8,2,4,8,9,0,3,1,7 };
    auto il = { 1,2,3,4,5,6 };

    bst.insert(il.begin(), il.end());
    cout << "datas: ";
    bst.show();
    cout << endl;
    cout << "size: " << bst.size() << endl;
    cout << "level: " << bst.level() << endl << endl;
    cout << "after erase 6: " << endl;
    cout << "erased: " << bst.erase(6) << " node(s)" << endl;
    cout << "datas: ";
    bst.show();
    cout << endl;
    cout << "size: " << bst.size() << endl;
    cout << "level: " << bst.level() << endl;

    return 0;
}

 

BinarySearchTree.h:

#pragma once
#ifndef __BINARYSEARCHTREE_H__
#define __BINARYSEARCHTREE_H__


#include <queue>
#include <initializer_list>
template<typename _Ty>
class BinarySearchTree
{
private:
    struct Node
    {
        _Ty key;
        Node* left = nullptr;
        Node* right = nullptr;
        Node* parent = nullptr;
        Node(const _Ty& _key) :key(_key) {}
    };

public:
    BinarySearchTree() = default;
    template<typename _Iter>
    BinarySearchTree(_Iter, _Iter);
    BinarySearchTree(const std::initializer_list<_Ty>&);
    BinarySearchTree(const BinarySearchTree<_Ty>&);
    BinarySearchTree(BinarySearchTree<_Ty>&&) noexcept;

    ~BinarySearchTree() { clear(root); }
    void clear() { clear(root); }
    bool empty() const { return size_n == 0; }
    size_t size() const { return size_n; }
    void show() const { show(root); }
    size_t level() const;

    void swap(BinarySearchTree<_Ty>&);
    void insert(const _Ty&);
    template<typename _Iter>
    void insert(_Iter, _Iter);
    size_t erase(const _Ty&);
    void erase(Node*);

    Node* find(const _Ty& _key) const { return find(root, _key); }
    Node* iterative_find(const _Ty& _key) const { return iterative_find(root, _key); }
    Node* maximum() const { return maximum(root); }
    Node* minimum() const { return minimum(root); }
    Node* predecessor() const { return predecessor(root); }
    Node* successor() const { return successor(root); }

private:
    void copy(Node*);
    void clear(Node*&);
    void show(Node*) const;
    Node* find(Node*, const _Ty&) const;
    Node* iterative_find(Node*, const _Ty&) const;
    Node* maximum(Node*) const;
    Node* minimum(Node*) const;
    Node* predecessor(Node*) const;
    Node* successor(Node*) const;

private:
    size_t size_n = 0;
    Node* root = nullptr;
};

template<typename _Ty>
template<typename _Iter>
BinarySearchTree<_Ty>::BinarySearchTree(_Iter _it1, _Iter _it2)
{
    while (_it1 != _it2)
    {
        insert(*_it1);
        ++_it1;
    }
}

template<typename _Ty>
BinarySearchTree<_Ty>::BinarySearchTree(const std::initializer_list<_Ty>& _il)
{
    for (const auto& key : _il) insert(key);
}

template<typename _Ty>
BinarySearchTree<_Ty>::BinarySearchTree(const BinarySearchTree<_Ty>& _right)
{
    copy(_right.getRoot());
}

template<typename _Ty>
BinarySearchTree<_Ty>::BinarySearchTree(BinarySearchTree<_Ty>&& _right) noexcept
{
    root = _right.root;
    size_n = _right.size_n;
    _right.root = nullptr;
    _right.size_n = 0;
}

template<typename _Ty>
size_t BinarySearchTree<_Ty>::level() const
{
    if (root == nullptr) 0;
    size_t n = 0;
    std::queue<Node*> nodePointers;
    nodePointers.push(root);
    while (!nodePointers.empty())
    {
        Node* levelBegin = nodePointers.front();
        Node* levelEnd = nodePointers.back();
        Node* cur = levelBegin;
        while (true)
        {
            if (cur->left != nullptr) nodePointers.push(cur->left);
            if (cur->right != nullptr) nodePointers.push(cur->right);
            if (cur == levelEnd)
                break;
            nodePointers.pop();
            cur = nodePointers.front();
        }
        nodePointers.pop();
        ++n;
    }
    return n;
}

template<typename _Ty>
void BinarySearchTree<_Ty>::copy(Node* _node)
{
    if (_node == nullptr) return;
    insert(_node->key);
    copy(_node->left);
    copy(_node->right);
}

template<typename _Ty>
void BinarySearchTree<_Ty>::clear(Node*& _node)
{
    if (_node == nullptr) return;
    clear(_node->left);
    clear(_node->right);
    delete _node;
    _node = nullptr;
    --size_n;
}

template<typename _Ty>
void BinarySearchTree<_Ty>::show(Node* _node) const
{
    if (_node == nullptr) return;
    show(_node->left);
    std::cout << _node->key << " ";
    show(_node->right);
}

template<typename _Ty>
void BinarySearchTree<_Ty>::swap(BinarySearchTree<_Ty>& _right)
{
    std::swap(root, _right->root);
    std::swap(size_n, _right->size_n);
}

template<typename _Ty>
void BinarySearchTree<_Ty>::insert(const _Ty& _key)
{
    ++size_n;
    if (root == nullptr)
    {
        root = new Node(_key);
        return;
    }
    Node* temp = root;
    while (true)
    {
        if (_key < temp->key && temp->left != nullptr)
            temp = temp->left;
        else if (_key < temp->key && temp->left == nullptr)
            break;
        else if (_key >= temp->key && temp->right != nullptr)
            temp = temp->right;
        else
            break;
    }
    Node* newNode = new Node(_key);
    newNode->parent = temp;
    if (_key < temp->key) temp->left = newNode;
    else temp->right = newNode;
}

template<typename _Ty>
template<typename _Iter>
void BinarySearchTree<_Ty>::insert(_Iter _it1, _Iter _it2)
{
    while (_it1 != _it2)
    {
        insert(*_it1);
        ++_it1;
    }
}

template<typename _Ty>
size_t BinarySearchTree<_Ty>::erase(const _Ty& _key)
{
    size_t n = 0;
    Node* del = find(_key);
    while (del != nullptr)
    {
        ++n;
        erase(del);
        del = find(_key);
    }
    return n;
}

template<typename _Ty>
void BinarySearchTree<_Ty>::erase(Node* _node)
{
    if (_node == nullptr) return;
    if (_node == root)
    {
        if (_node->right != nullptr)
        {
            Node* min = minimum(_node->right);
            min->left = _node->left;
            root = _node->right;
        }
        else
            root = _node->left;
        root->parent = nullptr;
        delete _node;
        return;
    }
    Node* par = _node->parent;
    if (_node->left == nullptr && _node->right == nullptr)
    {
        if (par->left == _node)
            par->left = nullptr;
        else
            par->right = nullptr;
    }
    else
    {
        if (_node->right != nullptr)
        {
            if (_node->left != nullptr)
            {
                Node* min = minimum(_node->right);
                min->left = _node->left;
            }
            _node->right->parent = par;
            if (par->left == _node)
                par->left = _node->right;
            else
                par->right = _node->right;
        }
        else
        {
            if (_node->left != nullptr)
                _node->left->parent = par;
            if (par->left == _node)
                par->left = _node->left;
            else
                par->right = _node->left;
        }
    }
    delete _node;
    --size_n;
}

template<typename _Ty>
typename BinarySearchTree<_Ty>::Node* BinarySearchTree<_Ty>::find(Node* _node, const _Ty& _key) const
{
    if (_node == nullptr || _node->key == _key)
        return _node;
    if (_key < _node->key)
        return find(_node->left, _key);
    else
        return find(_node->right, _key);
}

template<typename _Ty>
typename BinarySearchTree<_Ty>::Node* BinarySearchTree<_Ty>::iterative_find(Node* _node, const _Ty& _key) const
{
    while (_node != nullptr && _node->key != _key)
    {
        if (_key < _node->key)
            _node = _node->left;
        else
            _node = _node->right;
    }
    return _node;
}

template<typename _Ty>
typename BinarySearchTree<_Ty>::Node* BinarySearchTree<_Ty>::maximum(Node* _node) const
{

    if (_node == nullptr) return _node;
    while (_node->right != nullptr)
        _node = _node->right;
    return _node;
}

template<typename _Ty>
typename BinarySearchTree<_Ty>::Node* BinarySearchTree<_Ty>::minimum(Node* _node) const
{
    if (_node == nullptr) return _node;
    while (_node->left != nullptr)
        _node = _node->left;
    return _node;
}

template<typename _Ty>
typename BinarySearchTree<_Ty>::Node* BinarySearchTree<_Ty>::predecessor(Node* _node) const
{
    if (_node->left != nullptr)
        return maximum(_node->left);
    Node* par = _node->parent;
    while ((par != nullptr) && (_node == par->left))
    {
        _node = par;
        par = par->parent;
    }
    return par;
}

template<typename _Ty>
typename BinarySearchTree<_Ty>::Node* BinarySearchTree<_Ty>::successor(Node* _node) const
{
    if (_node->right != nullptr)
        return minimum(_node->left);
    Node* par = _node->parent;
    while ((par != nullptr) && (_node == par->right))
    {
        _node = par;
        par = par->parent;
    }
    return par;
}


#endif // !__BINARYSEARCHTREE_H__

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 常見行佈局: 導航使用position:fixed固定住 導航會脫離文檔流,不占據空間 導致下麵的元素上移,因此需要將下麵的元素的padding-top設置成導航的高度 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <t ...
  • Umi 通常會搭配 Dva 使用,用於管理頁面狀態和邏輯 一、註冊 model 首先需要在 .umirc.js 中啟用 dva 插件 export default { plugins: [ ['umi-plugin-react', { dva: { immer: true, }, }], ], } ...
  • jQuery事件發展歷程 事件發展歷程:從簡單事件,到bind,到委托事件,到on事件綁定 //簡單事件,給自己註冊的事件 $("div").click(function () { alert("哈哈"); }); //bind方式 $("p").bind({ click: function () ...
  • 最近做個小項目,給網頁加個浮窗,考驗了基礎的css,js技術,還是蠻有意思的,代碼如下(部分代碼來源於引用,見底部) <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=d ...
  • 前端的性能優化 資源的壓縮與合併 + 優化要點:減少http數量請求和資源大小請求 + 運用壓縮與合併 + 實現方式有線上網站和壓縮工具(需要node) web前端本質上是一種GUI軟體,本可以直接借鑒其他GUI系統架構設計方法,但web前端有點特別 瀏覽器的一個請求從發送到返回都經歷了什麼? 在這 ...
  • 一、前言 斷斷續續的也有在閑餘時間接觸領域驅動設計的相關知識,因為目前在工作中更多的還只是一名 crud boy,因此目前也只是對其中的某些知識點有知曉,實際使用的比較少,僅此而已。因此,趁著這個春節假期,整理了一下自己的 github 帳號,同時結合自己定的學習計劃以及自己的期望發展方向,決定從一 ...
  • Java基礎系列1:深入理解Java數據類型 當初學習電腦的時候,教科書中對程式的定義是:程式=數據結構+演算法,Java基礎系列第一篇就聊聊Java中的數據類型。 本篇聊Java數據類型主要包括四個內容: Java基本類型 Java封裝類型 自動裝箱和拆箱 封裝類型緩存機制 Java基本類型 Ja ...
  • 最近在比賽一個項目 , 是給Dubbo寫一個負載均衡介面 , 其實dubbo已經實現了下麵四種, 所以他做的不是這個單面負載均衡, 需要做雙向負載均衡 , 負載均衡的權重取決於服務端,所以有些時候我們不知道如何計算權重, 權重受到很多因素影響 ,所以就需要動態考慮了. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...