最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++封裝紅黑樹實現(xiàn)mymap和myset完整代碼

 更新時間:2026年04月19日 09:51:54   作者:鳳年徐  
紅黑樹作為一種自平衡的二叉搜索樹,是C++標準庫中map和set容器的底層實現(xiàn),下面這篇文章主要介紹了C++封裝紅黑樹實現(xiàn)mymap和myset的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

一、源碼及框架分析

在 SGI-STL 30 版本中,mapset 的實現(xiàn)巧妙地復用了同一棵紅黑樹(rb_tree)。其核心代碼主要位于 stl_tree.hstl_map.hstl_set.h 中。

1.1 框架核心代碼

以下是 setmap 的簡化定義:

// stl_set.h
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:
    typedef Key key_type;
    typedef Key value_type;
private:
    typedef rb_tree<key_type, value_type,
                    identity<value_type>, key_compare, Alloc> rep_type;
    rep_type t; // 底層紅黑樹
};
// stl_map.h
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:
    typedef Key key_type;
    typedef T mapped_type;
    typedef pair<const Key, T> value_type;
private:
    typedef rb_tree<key_type, value_type,
                    select1st<value_type>, key_compare, Alloc> rep_type;
    rep_type t; // 底層紅黑樹
};

1.2 紅黑樹的泛型設計

rb_tree 通過模板參數(shù)實現(xiàn)泛型,使其既能用于 set(存儲 Key),也能用于 map(存儲 pair<const Key, T>)。其結(jié)點定義如下:

template <class Value>
struct __rb_tree_node : public __rb_tree_node_base {
    typedef __rb_tree_node<Value>* link_type;
    Value value_field; // 存儲的實際數(shù)據(jù)
};

rb_tree 的模板參數(shù):

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc = alloc>
class rb_tree {
    // ...
};
  • Key:鍵的類型,用于 find、erase 等接口的參數(shù)類型。
  • Value:結(jié)點中存儲的數(shù)據(jù)類型,在 set 中為 Key,在 map 中為 pair<const Key, T>
  • KeyOfValue:仿函數(shù),用于從 Value 中提取 Key,因為紅黑樹在比較時只比較鍵。

1.3 為何需要兩個模板參數(shù)Key和Value?

set 的兩個模板參數(shù)相同,map 則不同。這是因為:

  • Value 決定了結(jié)點存儲的內(nèi)容。
  • Key 決定了 find、erase 等函數(shù)接受的參數(shù)類型。

mapValuepair<const Key, T>,但查找時只需傳入 Key 類型的值,因此兩個模板參數(shù)缺一不可。

注:源碼中命名風格略有混亂,set 使用 Keymap 使用 KeyT,rb_tree 又使用 KeyValue,但設計思路清晰。

二、模擬實現(xiàn) map 和 set

接下來,我們將基于自己實現(xiàn)的紅黑樹,封裝出 mapset

2.1 實現(xiàn)紅黑樹框架,支持插入

我們首先實現(xiàn)一個紅黑樹 RBTree,它通過 KeyOfT 仿函數(shù)提取鍵值進行比較。

RBTree.h

enum Colour { RED, BLACK };
template<class T>
struct RBTreeNode {
    T _data;
    RBTreeNode<T>* _left;
    RBTreeNode<T>* _right;
    RBTreeNode<T>* _parent;
    Colour _col;
    RBTreeNode(const T& data)
        : _data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED) {}
};
template<class K, class T, class KeyOfT>
class RBTree {
    typedef RBTreeNode<T> Node;
public:
    bool Insert(const T& data) {
        if (_root == nullptr) {
            _root = new Node(data);
            _root->_col = BLACK;
            return true;
        }
        KeyOfT kot;
        Node* parent = nullptr;
        Node* cur = _root;
        while (cur) {
            if (kot(cur->_data) < kot(data)) {
                parent = cur;
                cur = cur->_right;
            } else if (kot(cur->_data) > kot(data)) {
                parent = cur;
                cur = cur->_left;
            } else {
                return false; // 鍵已存在
            }
        }
        cur = new Node(data);
        Node* newnode = cur;
        cur->_col = RED;
        if (kot(parent->_data) < kot(data))
            parent->_right = cur;
        else
            parent->_left = cur;
        cur->_parent = parent;
        // 后續(xù)平衡處理(旋轉(zhuǎn)、變色)省略,完整代碼見文末
        return true;
    }
private:
    Node* _root = nullptr;
};

Mymap.h

namespace bit {
    template<class K, class V>
    class map {
        struct MapKeyOfT {
            const K& operator()(const pair<K, V>& kv) {
                return kv.first;
            }
        };
    public:
        bool insert(const pair<K, V>& kv) {
            return _t.Insert(kv);
        }
    private:
        RBTree<K, pair<K, V>, MapKeyOfT> _t;
    };
}

Myset.h

namespace bit {
    template<class K>
    class set {
        struct SetKeyOfT {
            const K& operator()(const K& key) {
                return key;
            }
        };
    public:
        bool insert(const K& key) {
            return _t.Insert(key);
        }
    private:
        RBTree<K, K, SetKeyOfT> _t;
    };
}

2.2 支持迭代器

迭代器的核心是 operator++operator--,實現(xiàn)中序遍歷的步進邏輯。

迭代器實現(xiàn)思路

  • begin():返回中序第一個結(jié)點(最左結(jié)點)。
  • end():返回 nullptr(或源碼中的哨兵頭結(jié)點)。
  • operator++()
    • 若右子樹非空,找右子樹的最左結(jié)點。
    • 若右子樹為空,向上找第一個“當前結(jié)點是左孩子”的祖先結(jié)點。
  • operator--():邏輯與 ++ 對稱,反向遍歷。

迭代器代碼

template<class T, class Ref, class Ptr>
struct RBTreeIterator {
    typedef RBTreeNode<T> Node;
    typedef RBTreeIterator<T, Ref, Ptr> Self;
    Node* _node;
    Node* _root; // 用于處理 end() 的情況
    RBTreeIterator(Node* node, Node* root) : _node(node), _root(root) {}
    Ref operator*() { return _node->_data; }
    Ptr operator->() { return &_node->_data; }
    Self& operator++() {
        if (_node->_right) {
            Node* leftMost = _node->_right;
            while (leftMost->_left) leftMost = leftMost->_left;
            _node = leftMost;
        } else {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right) {
                cur = parent;
                parent = cur->_parent;
            }
            _node = parent;
        }
        return *this;
    }
    Self& operator--() {
        if (_node == nullptr) { // 處理 --end()
            Node* rightMost = _root;
            while (rightMost && rightMost->_right) rightMost = rightMost->_right;
            _node = rightMost;
        } else if (_node->_left) {
            Node* rightMost = _node->_left;
            while (rightMost->_right) rightMost = rightMost->_right;
            _node = rightMost;
        } else {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left) {
                cur = parent;
                parent = cur->_parent;
            }
            _node = parent;
        }
        return *this;
    }
    bool operator!=(const Self& s) const { return _node != s._node; }
    bool operator==(const Self& s) const { return _node == s._node; }
};

在 RBTree 中集成迭代器

template<class K, class T, class KeyOfT>
class RBTree {
public:
    typedef RBTreeIterator<T, T&, T*> Iterator;
    typedef RBTreeIterator<T, const T&, const T*> ConstIterator;
    Iterator Begin() {
        Node* leftMost = _root;
        while (leftMost && leftMost->_left) leftMost = leftMost->_left;
        return Iterator(leftMost, _root);
    }
    Iterator End() { return Iterator(nullptr, _root); }
    // 同理實現(xiàn) ConstIterator
private:
    Node* _root = nullptr;
};

2.3 支持operator[]

map[] 需要借助 insert 的返回值實現(xiàn)。因此,RBTree::Insert 需返回 pair<Iterator, bool>。

pair<Iterator, bool> Insert(const T& data) {
    // 插入邏輯,返回插入位置的迭代器及是否成功
}

然后在 map 中:

V& operator[](const K& key) {
    pair<iterator, bool> ret = insert(make_pair(key, V()));
    return ret.first->second;
}

2.4 完整代碼

最終版Myset.h

#include "RBTree.h"
namespace bit {
    template<class K>
    class set {
        struct SetKeyOfT {
            const K& operator()(const K& key) { return key; }
        };
    public:
        typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
        typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator const_iterator;
        iterator begin() { return _t.Begin(); }
        iterator end() { return _t.End(); }
        const_iterator begin() const { return _t.Begin(); }
        const_iterator end() const { return _t.End(); }
        pair<iterator, bool> insert(const K& key) { return _t.Insert(key); }
        iterator find(const K& key) { return _t.Find(key); }
    private:
        RBTree<K, const K, SetKeyOfT> _t;
    };
}

最終版Mymap.h

#include "RBTree.h"
namespace bit {
    template<class K, class V>
    class map {
        struct MapKeyOfT {
            const K& operator()(const pair<K, V>& kv) { return kv.first; }
        };
    public:
        typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;
        typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator const_iterator;
        iterator begin() { return _t.Begin(); }
        iterator end() { return _t.End(); }
        const_iterator begin() const { return _t.Begin(); }
        const_iterator end() const { return _t.End(); }
        pair<iterator, bool> insert(const pair<K, V>& kv) { return _t.Insert(kv); }
        iterator find(const K& key) { return _t.Find(key); }
        V& operator[](const K& key) {
            pair<iterator, bool> ret = insert(make_pair(key, V()));
            return ret.first->second;
        }
    private:
        RBTree<K, pair<const K, V>, MapKeyOfT> _t;
    };
}

最終版RBTree.h

完整代碼請參考文末總結(jié)部分,或結(jié)合上述片段整合。核心包括:

  • 結(jié)點定義
  • 插入與平衡(旋轉(zhuǎn)、變色)
  • 迭代器實現(xiàn)
  • FindBegin、End 等接口

三、總結(jié)

通過封裝紅黑樹實現(xiàn) mapset,我們深入理解了 STL 中容器復用的設計思想:

  1. 泛型設計:紅黑樹通過 Value 模板參數(shù)決定存儲內(nèi)容,通過 KeyOfT 仿函數(shù)提取鍵值進行比較。
  2. 迭代器實現(xiàn):中序遍歷的步進邏輯是迭代器實現(xiàn)的核心,需同時處理左右子樹與祖先關(guān)系。
  3. map[] 實現(xiàn):依賴于 insert 的返回值,簡潔高效。
  4. 權(quán)限控制set 的迭代器不允許修改鍵值,通過將 Value 模板參數(shù)設為 const K 實現(xiàn);map 則通過 pair<const K, V> 保護鍵不被修改。

這種復用方式不僅減少了代碼量,還體現(xiàn)了面向?qū)ο笈c泛型編程的強大結(jié)合。

到此這篇關(guān)于C++封裝紅黑樹實現(xiàn)mymap和myset完整代碼的文章就介紹到這了,更多相關(guān)封裝紅黑樹mymap和myset內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于Qt?C++中connect的幾種寫法代碼示例

    關(guān)于Qt?C++中connect的幾種寫法代碼示例

    這篇文章介紹了Qt中connect函數(shù)的不同編寫方式,包括傳統(tǒng)的槽函數(shù)寫法、使用函數(shù)指針的寫法、Lambda表達式以及使用QOverload選擇重載信號的寫法,每種寫法都有其特點和適用場景,程序員應根據(jù)具體需求選擇最合適的方式,需要的朋友可以參考下
    2024-11-11
  • C語言數(shù)組實現(xiàn)打磚塊游戲

    C語言數(shù)組實現(xiàn)打磚塊游戲

    這篇文章主要為大家詳細介紹了C語言數(shù)組實現(xiàn)打磚塊游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • vscode配置遠程開發(fā)環(huán)境并遠程調(diào)試運行C++代碼的教程

    vscode配置遠程開發(fā)環(huán)境并遠程調(diào)試運行C++代碼的教程

    這篇文章主要介紹了vscode配置遠程開發(fā)環(huán)境并遠程調(diào)試運行C++代碼的教程,本文通過截圖實例相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • C語言修煉之路數(shù)據(jù)類型悟正法 解析存儲定風魔下篇

    C語言修煉之路數(shù)據(jù)類型悟正法 解析存儲定風魔下篇

    使用編程語言進行編程時,需要用到各種變量來存儲各種信息。變量保留的是它所存儲的值的內(nèi)存位置。這意味著,當您創(chuàng)建一個變量時,就會在內(nèi)存中保留一些空間。您可能需要存儲各種數(shù)據(jù)類型的信息,操作系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲什么
    2022-02-02
  • C++深入探究繼承的概念與使用

    C++深入探究繼承的概念與使用

    繼承是C++面向?qū)ο缶幊讨械囊婚T。繼承是子類繼承父類的特征和行為,或者是繼承父類得方法,使的子類具有父類得的特性和行為。重寫是子類對父類的允許訪問的方法實行的過程進行重新編寫,返回值和形參都不能改變。就是對原本的父類進行重新編寫,但是外部接口不能被重寫
    2022-05-05
  • DSP中浮點轉(zhuǎn)定點運算--浮點與定點概述

    DSP中浮點轉(zhuǎn)定點運算--浮點與定點概述

    本文主要介紹DSP中浮點與定點概述,很值得學習一下,需要的朋友可以參考一下。
    2016-06-06
  • C語言中類型捕獲(typeof)的使用

    C語言中類型捕獲(typeof)的使用

    C語言中typeof是一個編譯器擴展,支持泛型宏開發(fā),可避免表達式重復求值,提升代碼可讀性,本文就來詳細的介紹一下C語言中類型捕獲(typeof)的使用,感興趣的可以來了解一下
    2025-09-09
  • C字符串操作函數(shù)實現(xiàn)方法小結(jié)

    C字符串操作函數(shù)實現(xiàn)方法小結(jié)

    這篇文章主要介紹了C字符串操作函數(shù)實現(xiàn)方法,實例總結(jié)了C語言字符串操作的相關(guān)技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • VC程序設計中CreateProcess用法注意事項

    VC程序設計中CreateProcess用法注意事項

    這篇文章主要介紹了VC程序設計中CreateProcess用法注意事項,需要的朋友可以參考下
    2014-07-07
  • C語言實現(xiàn)漢諾塔游戲

    C語言實現(xiàn)漢諾塔游戲

    個人覺得漢諾塔這個遞歸算法比電子老鼠的難了一些,不過一旦理解了也還是可以的,其實網(wǎng)上也有很多代碼,可以直接參考。記得大一開始時就做過漢諾塔的習題,但是那時代碼寫得很長很長,也是不理解遞歸的結(jié)果。今天重新來實現(xiàn)一下
    2015-03-03

最新評論

江安县| 苍山县| 丰城市| 郑州市| 孟连| 古浪县| 洪洞县| 绥江县| 麻城市| 拉萨市| 兴国县| 武宣县| 繁峙县| 泰宁县| 老河口市| 武胜县| 运城市| 乌拉特前旗| 彩票| 海宁市| 海口市| 会东县| 乐至县| 永仁县| 巴林右旗| 丰城市| 长乐市| 留坝县| 北流市| 翁源县| 夹江县| 蓬溪县| 诸暨市| 壶关县| 泸州市| 雷波县| 双峰县| 驻马店市| 抚松县| 图片| 平果县|