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
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...