红黑树实现Map

红黑树是一种类平衡树, 但它不是高度的平衡树, 但平衡的效果已经很好了. 为什么不用 AVL 树作为底层实现, 那是因为 AVL 树是高度平衡的树, 而每一次对树的修改, 都要 rebalance, 这里的开销会比红黑树大. 红黑树插入只要两次旋转, 删除至多三次旋转. 但不可否认的是, AVL 树搜索的效率是非常稳定的. 选取红黑树, 我认为是一种折中的方案

红黑树是一种比较宽泛化的平衡树,没AVL的平衡要求高,同时他的插入删除都能在O(lgN)的时间内完成,而且对于其性质的维护,插入至多只需要进行2次旋转就可以完成,对于删除,至多只需要三次就可以完成,所以其统计性能要比AVL树好

红黑树是每个节点都有颜色特性的二叉查找树,颜色的值是红色或黑色之一。除了二叉查找树带有的一般要求,我们对任何有效的红黑树加以如下增补要求:

1.节点是红色或黑色。

2.根是黑色。

3.所有叶子(外部节点)都是黑色。

4.每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

5.从每个叶子到根的所有路径都包含相同数目的黑色节点。

这些约束强制了红黑树的关键属性: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。

各种树的定义:

1、二叉查找树(二叉排序树)

  (图a)

二叉查找树是一种动态查找表(图a),具有这些性质:                                 
(1)若它的左子树不为空,则左子树上的所有节点的值都小于它的根节点的值;
(2)若它的右子树不为空,则右子树上所有节点的值都大于它的根节点的值;
(3)其他的左右子树也分别为二叉查找树;
(4)二叉查找树是动态查找表,在查找的过程中可见添加和删除相应的元素,在这些操作中需要保持二叉查找树的以上性质。

2、平衡二叉树(AVL树)

(图b)

  含有相同节点的二叉查找树可以有不同的形态,而二叉查找树的平均查找长度与树的深度有关,所以需要找出一个查找平均长度最小的一棵,那就是平衡二叉树(图b),具有以下性质:
(1)要么是棵空树,要么其根节点左右子树的深度之差的绝对值不超过1;
(2)其左右子树也都是平衡二叉树;
(3)二叉树节点的平衡因子定义为该节点的左子树的深度减去右子树的深度。则平衡二叉树的所有节点的平衡因子只可能是-1,0,1。

3、红黑树

  

(图c)

  红黑树是一种自平衡二叉树,在平衡二叉树的基础上每个节点又增加了一个颜色的属性,节点的颜色只能是红色或黑色。具有以下性质:
(1)根节点只能是黑色;
(2)红黑树中所有的叶子节点后面再接上左右两个空节点,这样可以保持算法的一致性,而且所有的空节点都是黑色;
(3)其他的节点要么是红色,要么是黑色,红色节点的父节点和左右孩子节点都是黑色,及黑红相间;
(4)在任何一棵子树中,从根节点向下走到空节点的路径上所经过的黑节点的数目相同,从而保证了是一个平衡二叉树。

4、B-树

(图d)

  B-树是一种平衡多路查找树,它在文件系统中很有用。一棵m阶B-树(图d为4阶B-树),具有下列性质:
(1)树中每个节点至多有m棵子树;
(2)若根节点不是叶子节点,则至少有2棵子树;
(3)除根节点之外的所有非终端节点至少有棵子树;
(4)每个节点中的信息结构为(A0,K1,A1,K2......Kn,An),其中n表示关键字个数,Ki为关键字,Ai为指针;
(5)所有的叶子节点都出现在同一层次上,且不带任何信息,也是为了保持算法的一致性

5、B+树

(图e)

  B+数是B-树的一种变形,它与B-树的差别在于(图e为3阶B+树):
(1)有n棵子树的节点含有n个关键字;
(2)所有的叶子节点包含了全部关键字的信息,及指向这些关键字记录的指针,且叶子节点本身按关键字大小自小到大顺序链接;
(3)所有非终端节点可以看成是索引部分,节点中仅含有其子树(根节点)中最大(或最小)关键字,所有B+树更像一个索引顺序表;
(4)对B+树进行查找运算,一是从最小关键字起进行顺序查找,二是从根节点开始,进行随机查找。

6、字典树(trie树)

(图f)

  字典树是一种以树形结构保存大量字符串。以便于字符串的统计和查找,经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。具有以下特点(图f):
(1)根节点为空;
(2)除根节点外,每个节点包含一个字符;
(3)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
(4)每个字符串在建立字典树的过程中都要加上一个区分的结束符,避免某个短字符串正好是某个长字符串的前缀而淹没。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然,我可以帮你实现一个基于红黑树Map数据结构。下面是一个简单的C++代码示例: ```cpp #include <iostream> enum Color { RED, BLACK }; template <typename K, typename V> struct Node { K key; V value; Color color; Node* left; Node* right; Node* parent; // 构造函数 Node(const K& k, const V& v, Color c = RED) : key(k), value(v), color(c), left(nullptr), right(nullptr), parent(nullptr) {} }; template <typename K, typename V> class RBTreeMap { public: RBTreeMap() : root(nullptr) {} // 向红黑树中插入键对 void insert(const K& key, const V& value) { Node<K, V>* node = new Node<K, V>(key, value); if (root == nullptr) { root = node; node->color = BLACK; } else { Node<K, V>* curr = root; Node<K, V>* parent = nullptr; while (curr != nullptr) { parent = curr; if (key < curr->key) curr = curr->left; else if (key > curr->key) curr = curr->right; else { curr->value = value; // 更新 return; } } node->parent = parent; if (key < parent->key) parent->left = node; else parent->right = node; insertFixup(node); } } // 查找指定键的 V find(const K& key) const { Node<K, V>* curr = root; while (curr != nullptr) { if (key < curr->key) curr = curr->left; else if (key > curr->key) curr = curr->right; else return curr->value; } return V(); // 未找到,返回默认 } private: Node<K, V>* root; // 对红黑树进行修复以维持红黑树的性质 void insertFixup(Node<K, V>* node) { while (node->parent != nullptr && node->parent->color == RED) { if (node->parent == node->parent->parent->left) { Node<K, V>* uncle = node->parent->parent->right; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->right) { node = node->parent; rotateLeft(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateRight(node->parent->parent); } } else { Node<K, V>* uncle = node->parent->parent->left; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->left) { node = node->parent; rotateRight(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateLeft(node->parent->parent); } } } root->color = BLACK; } // 左旋 void rotateLeft(Node<K, V>* node) { Node<K, V>* rightChild = node->right; node->right = rightChild->left; if (rightChild->left != nullptr) rightChild->left->parent = node; rightChild->parent = node->parent; if (node->parent == nullptr) root = rightChild; else if (node == node->parent->left) node->parent->left = rightChild; else node->parent->right = rightChild; rightChild->left = node; node->parent = rightChild; } // 右旋 void rotateRight(Node<K, V>* node) { Node<K, V>* leftChild = node->left; node->left = leftChild->right; if (leftChild->right != nullptr) leftChild->right->parent = node; leftChild->parent = node->parent; if (node->parent == nullptr) root = leftChild; else if (node == node->parent->left) node->parent->left = leftChild; else node->parent->right = leftChild; leftChild->right = node; node->parent = leftChild; } }; int main() { RBTreeMap<int, std::string> map; map.insert(1, "one"); map.insert(2, "two"); map.insert(3, "three"); map.insert(4, "four"); std::cout << map.find(2) << std::endl; // 输出: two std::cout << map.find(5) << std::endl; // 输出: 空字符串(默认) return 0; } ``` 这个示例使用红黑树实现了一个简单的Map数据结构。你可以使用`insert`方法向Map中插入键对,使用`find`方法查找指定键的。注意,这只是一个简单的实现,还可以根据需要进行扩展和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值