STL中_Rb_tree的探索

来源:https://www.cnblogs.com/sandychn/archive/2020/02/20/12334194.html
-Advertisement-
Play Games

我們知道STL中我們常用的 與`multiset map multimap _Rb_tree _Rb_tree`的各個參數的確定。 特別註意在如下代碼的 類用於從 中選出用於排序的key值,這個仿函數必須返回 而不能是 ,否則 會拋出 。由於源碼中邏輯比較複雜,但是可以觀察到內部涉及這方面的地方經常 ...


我們知道STL中我們常用的setmultisetmapmultimap都是基於紅黑樹。本文介紹了它們的在STL中的底層數據結構_Rb_tree的直接用法與部分函數。難點主要是_Rb_tree的各個參數的確定。

特別註意在如下代碼的Selector類用於從Node中選出用於排序的key值,這個仿函數必須返回const int&而不能是int,否則less<int>::operator(const int&, const int&)會拋出segmentation fault。由於源碼中邏輯比較複雜,但是可以觀察到內部涉及這方面的地方經常使用到指針。所以可以推測是因為引用了已經釋放的局部變數所以才拋出的segmentation fault。一開始寫成int,看了很多源碼才發現是這個原因,一定要註意。

接下來是樣例代碼,裡面都有註釋了。

#include <iostream>
#include <iomanip>

// 原則上不要直接引用這個頭文件,這裡只是為了測試
#include <bits/stl_tree.h>

using namespace std;

struct Node {
    int first, second;
    Node(int _first, int _second) : first(_first), second(_second){};

    friend ostream& operator<<(ostream& outs, const Node& node) {
        outs << '{' << node.first << ',' << node.second << '}';
        return outs;
    }
};

template <class T>
struct Selector {
    // MUST return const int&, not int.
    // if return int, segmentation fault will occur.
    // I have spent much time because of this.
    const int& operator()(const T& obj) const {
        return obj.first;
    }
};

int main() {
    // _Rb_tree: red-black tree in STL.
    using tree_type = _Rb_tree<int, Node, Selector<Node>, less<int>>;
    using iterator_type = tree_type::iterator;
    using result_pair_type = pair<tree_type::iterator, bool>;
    tree_type tree;

    // 插入元素Node(1, 2)
    result_pair_type res = tree._M_insert_unique(Node(1, 2));
    cout << "insert address = " << res.first._M_node << endl;
    cout << "insert result = " << boolalpha << res.second << endl; // true

    iterator_type it = tree.begin();
    cout << "begin address = " << it._M_node << endl;

    it = tree.find(1);
    cout << "address = " << it._M_node << ", value = " << *it << endl;

    // 再插入元素Node(1, 2)但是因為調用的是insert_unique
    // 它不會添加重覆值,所以插入會被拒絕
    res = tree._M_insert_unique(Node(1, 2));
    cout << "insert result = " << boolalpha << res.second << endl; // false

    // 再插入元素Node(1, 2)但這次調用insert_equal
    // multiset和multimap就是利用這個函數來插入重覆值
    // 也就是這個函數允許重覆值,所以插入成功
    tree._M_insert_equal(Node(1, 3));
    cout << "size = " << tree.size() << endl; // 大小就變為2

    pair<iterator_type, iterator_type> result = tree.equal_range(1);
    for (iterator_type ite = result.first; ite != result.second; ++ite) {
        cout << "address = " << ite._M_node << ", value = " << *ite << endl;
    }
    
    return 0;
}

程式的輸出為(記憶體地址不定):

insert address = 0xf91be0
insert result = true
begin address = 0xf91be0
address = 0xf91be0, value = {1,2}
insert result = false
size = 2
address = 0xf91be0, value = {1,2}
address = 0xf91c10, value = {1,3}

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

-Advertisement-
Play Games
更多相關文章
  • 二進位和八進位數值表示法 ES6提供了二進位和八進位數值的新寫法,分別首碼 0b(或0B)、 0o(或0O)然後跟上二進位、八進位值即可。 二進位(Binary)表示法新寫法:首碼 0b 或 0B。 let binary = 0b010101; // 21 let binary2 = 0B01011 ...
  • 點擊添加群聊 今天在整理百度雲盤裡的資源,這幾年累計了不少軟體和教程。 在這特殊的時期里,先給大家分享一波。圖片里的文件夾就是目錄, 加入群聊免費領取 好資源就是要大家一起共用, 你們也不用到處在網上找資源, 或者幫別人轉發到朋友圈才能得到。 只要是我有的,而你也剛好需要,那我願意和你分享。 除了軟 ...
  • 變數提升 聲明的變數會提升到函數或全局作用域頂部 簡單例子 函數提升 函數寫法:函數表達式、函數聲明、Function構造函數(這種不推薦).其中函數表達式不會 函數提升 , 函數聲明 會函數提升。 我們都知道程式在執行時是從上往下執行的,而這裡 在定義之前就調用了為什麼不報錯? 實例一 值為多少? ...
  • 1、首先是設計稿 2、然後使用PxCook進行尺寸標註 3、字體信息去PS里看 4、首頁框架代碼編寫 index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <lin ...
  • var eleLink = document.createElement('a'); eleLink.href = "/wordpress/?p=9227"; console.log(eleLink.href); ...
  • 提到new,肯定會和類和實例聯繫起來,如: function Func() { let x = 100; this.num = x + } let f = new Func(); 上面的代碼,我們首先創建了一個函數,如果是用面向對象的說法就是創建了一個Function類的實例,如果直接執行這個函數, ...
  • FOUC(Flash Of Unstyled Content)即瀏覽器樣式閃爍或者叫做無樣式記憶體閃爍(用戶定義樣式表載入之前瀏覽器使用預設樣式顯示文檔,用戶樣式載入渲染之後再從新顯示文檔,造成頁面閃爍。) 解決方法:用link載入css文件,放在head標簽裡面。 ...
  • Vue中的$Bus使用 將Bus單獨抽離成一個文件 Bus.js 創建兩個兄弟組建 C2.vue C1.vue index.vue 註意:這種引入方式,經過webpack打包後可能會出現Bus局部作用域的情況,即引用的是兩個不同的Bus,導致不能正常通信 將Bus註入到Vue的prototype上 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...