- 浏览: 131235 次
- 性别:
- 来自: 成都
最新评论
-
yi_chao_jiang:
你好,多谢分享,问个问题,在上传数据的时候判断文件是否有上传记 ...
断点续传和下载原理分析 -
a41606709:
为什么我的tabhost显示不出来? 怎么设置在全部页面中让他 ...
TabActivity中的Tab标签详细设置 -
Zero颴:
大神篇,思路,配图都很清晰,perfect!
Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解 -
QAZ503602501:
牛死人了!!!
B-树 -
mengsina:
很牛的文档。数学功底好啊
Android Matrix理论与应用详解
1.Set的简单实现
set是利用二叉查找树来实现的,而且为了查找方便,添加了另外两个指针,一个指向下一个最小结点,一个指向上一个最大结点。
iset.h
//利用二叉查找树实现set #ifndef ISET_H #define ISET_H template<class T> struct Node{ T data; Node<T> *rchild, *lchild; //左右孩子 Node<T> *parent; //父结点 Node<T> *next, *pre; //下一个最小和上一个最大的结点 Node(){ rchild = lchild = parent = 0; next = pre = 0; } }; template<class T> class ISet{ public: ISet(); ISet(T a[], int n); ~ISet(); int size(); bool isEmpty(); bool contains(T t); T* toArray(); void add(T t); void remove(T t); void addAll(T a[], int n); void removeAll(); void clear(); void print(); //下面实现迭代器 typedef Node<T>* iterator; typedef const Node<T>* const_iterator; iterator Iterator(); const_iterator Iterator() const; iterator next(); const_iterator next() const; iterator pre(); const_iterator pre() const; bool hasNext(); bool hasPre(); //还可以操作符重载,++,--,+实现通用的迭代器 private: Node<T>* root; Node<T> *head, *tail; //头(最小)和尾(最大) void clear(Node<T>* &root); int size(Node<T>* root); void print(Node<T>* root); void toArray(Node<T>* root, T* &a, int *i); void deleteNode(Node<T>* &root, Node<T>* r, Node<T>* pre);//删除结点p void preSet(Node<T>* t); void nextSet(Node<T>* t); }; #endif
iset.cpp
#include <iostream> #include "iset.h" using namespace std; template<class T> ISet<T>::ISet(){ head = tail = root = NULL; } template<class T> ISet<T>::ISet(T a[], int n){ head = tail = root = NULL; addAll(a, n); } template<class T> ISet<T>::~ISet(){ clear(); } template<class T> int ISet<T>::size(){ return size(root); } template<class T> bool ISet<T>::isEmpty(){ if(!root) return true; return false; } template<class T> bool ISet<T>::contains(T t){ Node<T>* r = root; while(r){ if(r->data == t) break; r = (r->data > t)?r->lchild:r->rchild; } //如果没找到,返回false if(!r) return false; return true; } template<class T> T* ISet<T>::toArray(){ T *a = new T[size()]; int i = 0; toArray(root, a, &i); return a; } template<class T> void ISet<T>::add(T x){ Node<T>* r = root, *m = NULL, *n = NULL; if(r == NULL){ Node<T>* t = new Node<T>; t->data = x; root = t;//必须设置新的root结点,因为t和root在内存指向位置不同 }else{ Node<T>* p = r; //查找待插入结点位置 while(r){ if(r->data == x){ return; } p = r; if(r->data > x){ n = r; r = r->lchild; }else{ m = r; r = r->rchild; } } Node<T>* t = new Node<T>; t->data = x; if(p->data > x){//插入左 p->lchild = t; p->pre = t; }else{ p->rchild = t; p->next = t; } t->parent = p; preSet(t); nextSet(t); if(m && m!=p) nextSet(m); if(n && n!=p) preSet(n); } } template<class T> void ISet<T>::remove(T x){ if(!root) return; Node<T>* pre = NULL, *r = root; //查找待删除结点位置(pre是r的前序结点) while(r){ if(r->data == x){ break; } pre = r; r = (r->data > x)?r->lchild:r->rchild; } //没找到 if(!r){ cout<<"没有待删除的值:"<<x<<endl; return;} //如果pre == NULL说明是root结点 deleteNode(root, r, pre); } template<class T> void ISet<T>::addAll(T a[], int n){ if(n <= 0) return; for(int i=0; i<n; i++){ add(a[i]); } } template<class T> void ISet<T>::removeAll(){ clear(); } template<class T> void ISet<T>::clear(){ clear(root); //注:当clear之后,root也被delete,故而重新置为NULL root = NULL; } template<class T> void ISet<T>::print(){ print(root); } template<class T> void ISet<T>::print(Node<T>* root){ if(root){ cout<<root->data<<" "; print(root->lchild); print(root->rchild); } } template<class T> void ISet<T>::clear(Node<T>* &root){ if(root){ clear(root->lchild); clear(root->rchild); delete root; } } template<class T> int ISet<T>::size(Node<T>* root){ if(!root) return 0; else{ return size(root->lchild)+size(root->rchild)+1; } } template<class T> void ISet<T>::toArray(Node<T>* root, T* &a, int *i){ if(root){ a[(*i)++] = root->data; toArray(root->lchild, a, i); toArray(root->rchild, a, i); } } //r为待删除结点,pre为r的双亲 template<class T> void ISet<T>::deleteNode(Node<T>* &root, Node<T>* r, Node<T>* pre){ Node<T>* p; //先修改待删除r的pre,next结点指针 if(r->pre){ r->pre->next = r->next; } if(r->next){ r->next->pre = r->pre; } if(!r->rchild && !r->lchild){ //如果是叶子结点 if(pre){ if(pre->lchild == r){ pre->lchild = NULL; }else{ pre->rchild = NULL; } }else{ root = NULL; } delete r; }else if(r->rchild && r->lchild){ //如果左右子树都有(还有一种处理办法就是用右子树的最左结点替换待删除结点,然后删除最左结点) p = r; //寻找右子树的最左结点 r = r->rchild; while(r->lchild){ r = r->lchild; } //将删除结点的左结点接到找到的最左结点之后 r->lchild = p->lchild; r->lchild->parent = r; //删除结点(如果pre是空,说明删除结点是根结点,不用改变前序结点指针) if(pre){ if(pre->lchild == p){ pre->lchild = p->rchild; }else{ pre->rchild = p->rchild; } p->rchild->parent = pre; }else{ p->rchild->parent = NULL; root = p->rchild; } delete p; }else if(r->lchild){ //如果只有左子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->lchild; else pre->rchild = r->lchild; r->lchild->parent = pre; }else{ r->lchild->parent = NULL; root = r->lchild; } delete p; }else{ //如果只有右子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->rchild; else pre->rchild = r->rchild; r->rchild->parent = pre; }else{ r->rchild->parent = NULL; root = r->rchild; } delete p; } } template<class T> void ISet<T>::preSet(Node<T>* t){ if(!t) return; Node<T>* p; //如果t有左孩子,则pre就是左孩子的最右结点 p = t->lchild; if(p){ while(p->rchild){ p = p->rchild; } t->pre = p; }else{//p是空 p = t; if(!t->parent){ t->pre = NULL; }else if(t->parent->lchild == t){//若p为左孩子,则回朔,直到遇到结点是右孩子 while(p->parent){ if(p->parent->rchild == p) break; p = p->parent; } t->pre = p->parent; }else{ //若p为右孩子,则pre是其父 t->pre = t->parent; } } } template<class T> void ISet<T>::nextSet(Node<T>* t){ if(!t) return; Node<T>* p; //如果t有右孩子,则next就是有孩子的最左结点 p = t->rchild; if(p){ while(p->lchild){ p = p->lchild; } t->next = p; }else{ p = t; if(!t->parent){ t->next = NULL; }else if(t->parent->rchild == t){ while(p->parent){ if(p->parent->lchild == p) break; p = p->parent; } t->next = p->parent; }else{ t->next = p->parent; } } } template<class T> typename ISet<T>::iterator ISet<T>::Iterator(){ if(!root) return NULL; Node<T>* p = root; while(p->lchild){ p = p->lchild; } head = p; p = root; while(p->rchild){ p = p->rchild; } tail = p; return head; } template<class T> typename ISet<T>::const_iterator ISet<T>::Iterator() const{ if(!root) return NULL; Node<T>* p = root; while(p->lchild){ p = p->lchild; } head = p; p = root; while(p->rchild){ p = p->rchild; } tail = p; return head; } template<class T> typename ISet<T>::iterator ISet<T>::next(){ Node<T>* t; if(head){ t = head; head = head->next; return t; } return NULL; } template<class T> typename ISet<T>::const_iterator ISet<T>::next() const{ Node<T>* t; if(head){ t = head; head = head->next; return t; } return NULL; } template<class T> typename ISet<T>::iterator ISet<T>::pre(){ Node<T>* t; if(tail){ t = tail; tail = tail->pre; return t; } return NULL; } template<class T> typename ISet<T>::const_iterator ISet<T>::pre() const{ Node<T>* t; if(tail){ t = tail; tail = tail->pre; return t; } return NULL; } template<class T> bool ISet<T>::hasNext(){ if(head) return true; return false; } template<class T> bool ISet<T>::hasPre(){ if(tail) return true; return false; }
main.cpp
#include <iostream> #include "iset.cpp" using namespace std; int main(){ int a[] = {19, 38,1,41,39,54,6,3}; ISet<int> s(a, 8); s.print(); cout<<endl; /* int n = s.size(); cout<<"size:"<<n<<endl; cout<<"isEmpty:"<<s.isEmpty()<<endl; cout<<"contains 4:"<<s.contains(4)<<endl; cout<<"contains 90:"<<s.contains(90)<<endl; int *k = new int[n]; k = s.toArray(); for(int i=0; i<n; i++){ cout<<k[i]<<" ";} cout<<endl; delete k; cout<<"添加5\n"; s.add(5); cout<<"size:"<<s.size()<<endl; s.print(); cout<<"\n添加10\n"; s.add(10); cout<<"size:"<<s.size()<<endl; s.print(); cout<<"\n删除10\n"; s.remove(10); s.print(); cout<<"\n添加三个集合(一个重合)"; int m[] = {4,12,6}; s.addAll(m, 3); cout<<"\nsize:"<<s.size()<<endl; s.print(); s.removeAll(); cout<<"\nsize:"<<s.size()<<endl; s.print(); */ ISet<int>::iterator ite = s.Iterator(); while(s.hasNext()){ cout<<s.next()->data<<" "; } s.remove(41); cout<<endl; ite = s.Iterator(); while(s.hasNext()){ cout<<s.next()->data<<" "; } s.add(10); cout<<endl; while(s.hasPre()){ cout<<s.pre()->data<<" "; } cout<<endl; return 0; }
2.Map的简单实现
map也是利用二叉树实现
imap.h
//二叉排序树 #ifndef IMAP_H #define IMAP_H //数据域,里面存放结点数据 template<class K, class V> struct Data{ K key; //结点数据 V value; }; template<class K, class V> struct Node{ Data<K, V> data; Node<K, V> *rchild, *lchild; Node(){ rchild = lchild = 0; } }; template<class K, class V> class IMap{ public: IMap(); ~IMap(); int size(); bool isEmpty(); bool containsKey(K key); bool containsValue(V value); V get(K key); void put(K key, V value); //若插入的值已经存在,则更新value V remove(K key); void clear(); void print(); private: Node<K, V>* root; Node<K, V>* pre;//用于递归插入时,记录前序结点 void print(Node<K, V>* root); void clear(Node<K, V>* &root); int size(Node<K, V>* root); void containsValue(Node<K, V>* root, V value, bool *b); void deleteNode(Node<K, V>* &root, Node<K, V>* r, Node<K, V>* pre);//删除结点p }; #endif
imap.cpp
#include <iostream> #include "imap.h" using namespace std; template<class K, class V> IMap<K, V>::IMap(){ pre = NULL; root = NULL; } template<class K, class V> IMap<K, V>::~IMap(){ clear(); } template<class K, class V> int IMap<K, V>::size(){ return size(root); } template<class K, class V> bool IMap<K, V>::isEmpty(){ if(!root) return true; return false; } template<class K, class V> bool IMap<K, V>::containsKey(K key){ Node<K, V>* r = root; while(r){ if(r->data.key == key) break; r = (r->data.key > key)?r->lchild:r->rchild; } //如果没找到,返回false if(!r) return false; return true; } template<class K, class V> bool IMap<K, V>::containsValue(V value){ bool b = false; containsValue(root, value, &b); return b; } template<class K, class V> V IMap<K, V>::get(K key){ Node<K, V>* r = root; while(r){ if(r->data.key == key) break; r = (r->data.key > key)?r->lchild:r->rchild; } if(!r) return 0; return r->data.value; } template<class K, class V> void IMap<K, V>::put(K key, V value){ cout<<"插入<"<<key<<", "<<value<<">\n"; Node<K, V>* r = root; if(r == NULL){ Node<K, V>* t = new Node<K, V>; t->data.key = key; t->data.value = value; t->lchild = t->rchild = NULL; root = t;//必须设置新的root结点,因为t和root在内存指向位置不同 }else{ Node<K, V>* p = r; //查找待插入结点位置 while(r){ //如果已经存在,则更新value if(r->data.key == key){ r->data.value = value; return; } p = r; r = (r->data.key > key)?r->lchild:r->rchild; } Node<K, V>* t = new Node<K, V>; t->data.key = key; t->data.value = value; t->lchild = t->rchild = NULL; if((p->data).key > key){//插入左 p->lchild = t; }else{ p->rchild = t; } } } template<class K, class V> V IMap<K, V>::remove(K key){ if(!root) return 0; Node<K, V>* pre = NULL, *r = root; //查找待删除结点位置(pre是r的前序结点) while(r){ if(r->data.key == key){ break; } pre = r; r = (r->data.key > key)?r->lchild:r->rchild; } //没找到 if(!r) return 0; //如果pre == NULL说明是root结点 deleteNode(root, r, pre); return r->data.value; } template<class K, class V> void IMap<K, V>::clear(){ clear(root); root = NULL; } template<class K, class V> void IMap<K, V>::print(){ print(root); } template<class K, class V> void IMap<K, V>::print(Node<K, V>* root){ if(root){ cout<<root->data.value<<" "; print(root->lchild); print(root->rchild); } } template<class K, class V> void IMap<K, V>::clear(Node<K, V>* &root){ if(root){ clear(root->lchild); clear(root->rchild); delete root; } } template<class K, class V> int IMap<K, V>::size(Node<K, V>* root){ if(!root) return 0; else{ return size(root->lchild)+size(root->rchild)+1; } } template<class K, class V> void IMap<K, V>::containsValue(Node<K, V>* root, V value, bool *b){ if(root){ if(root->data.value == value){ *b = true; return; } containsValue(root->lchild, value, b); containsValue(root->rchild, value, b); } } template<class K, class V> void IMap<K, V>::deleteNode(Node<K, V>* &root, Node<K, V>* r, Node<K, V>* pre){ Node<K, V>* p; if(!r->rchild && !r->lchild){ //如果是叶子结点 if(pre){ if(pre->lchild == r){ pre->lchild = NULL; }else{ pre->rchild = NULL; } }else{ root = NULL; } delete r; }else if(r->rchild && r->lchild){ //如果左右子树都有(还有一种处理办法就是用右子树的最左结点替换待删除结点,然后删除最左结点) p = r; //寻找右子树的最左结点 r = r->rchild; while(r->lchild){ r = r->lchild; } //将删除结点的左结点接到找到的最左结点之后 r->lchild = p->lchild; //删除结点(如果pre是空,说明删除结点是根结点,不用改变前序结点指针) if(pre){ if(pre->lchild == p) pre->lchild = p->rchild; else pre->rchild = p->rchild; }else{ root = p->rchild; } delete p; }else if(r->lchild){ //如果只有左子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->lchild; else pre->rchild = r->lchild; }else{ root = r->lchild; } delete p; }else{ //如果只有右子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->rchild; else pre->rchild = r->rchild; }else{ root = r->rchild; } delete p; } }
main.cpp
#include <iostream> #include "imap.cpp" using namespace std; int main(){ IMap<int, int> map; cout<<"当前map:"<<map.isEmpty()<<endl; cout<<"当前map长度:"<<map.size()<<endl; map.print(); int key[] = {0,1,2,3,4,5,6,7,8,9}; int value[] = {21,34,32,34,56,6,78,76,111,13}; for(int i=0; i<10; i++){ map.put(key[i], value[i]); } cout<<"当前map长度:"<<map.size()<<endl; map.print(); cout<<endl; bool b = map.containsKey(5); if(b) cout<<"包含键5:"<<map.get(5)<<endl; else cout<<"不包含键5\n"; b = map.containsKey(12); if(b) cout<<"包含键12:"<<map.get(12)<<endl; else cout<<"不包含键12\n"; b = map.containsValue(111); if(b) cout<<"包含值111:"<<111<<endl; else cout<<"不包含值111\n"; b = map.containsValue(211); if(b) cout<<"包含值211:"<<211<<endl; else cout<<"不包含值211\n"; cout<<"移除6\n"; map.remove(6); cout<<"当前map长度:"<<map.size()<<endl; map.print(); cout<<endl; cout<<"移除90\n"; map.remove(90); map.print(); cout<<endl; return 0; }
发表评论
-
排序方法总结
2012-08-12 11:34 1173这里面包含了所有常见的排序操作 1.性能等比较分析 2 ... -
常见字符串操作大全
2012-08-12 11:34 14571.常见的字符串操作 如计算长度,求子串等都是考验基本功的, ... -
KMP算法解析
2012-08-12 11:35 2829一.理论基础 1.什么 ... -
二叉堆的实现
2012-08-12 11:35 12081.堆的概念 这里只需要注意两点: a.堆的存储方式:就是 ... -
红黑树的插入总结
2012-08-10 11:25 14031.红黑树 这个在july的博客中有详尽的说明,我就不在赘述 ... -
B-树实现
2012-08-10 11:03 16231.什么是B-树? 这个在我的前一篇博客中已经详细的阐释过: ... -
平衡二叉树
2012-08-10 10:39 28391.问题描述 什么是平衡 ... -
二叉排序树
2012-08-10 10:25 14641.基本概念 二叉排 ... -
B-树
2012-07-04 22:48 56611.B-树的概念 是一种多 ... -
构造哈夫曼树
2012-07-04 10:40 12281.算法说明 就是建造哈夫曼树树,从而使得构造出的树带权路径 ... -
线索二叉树
2012-07-04 09:20 12681.算法描述 就是简单的线索二叉树的建立,遍历,查找等基本操 ... -
二叉树基本操作大全
2012-07-03 18:22 25951.二叉树的基本操作 这里我有一个疑问: 在使用构造 ... -
多种队列的实现
2012-06-29 10:09 15401.算法描述 a.数据结构与算法(Mark Allen We ... -
栈的各种实现
2012-06-28 16:34 11071.算法描述 a.实现二个栈,在一个数组里面,除非没有任何空 ... -
中缀表达式转换为后缀
2012-06-28 11:10 18201.算法描述 例如a+b*c这是常见的中缀表达式,但是 ... -
后缀表达式的值
2012-06-27 16:33 13301.算法描述 计算后缀表达式的值 2.事例 如:( ... -
Josephus问题
2012-06-21 15:30 9951.算法描述 简单的游戏:有N个人坐成一圈,编号1-N、从编 ... -
关于最长递增子序列的实际应用--动态规划
2012-06-07 11:35 1827参考链接: a.http://www.programfan. ... -
线性查找二维数组
2012-06-05 17:23 10271.算法描述 有序(行有序,列有序,且每行从左至右递增 ... -
整数的随机置换
2012-06-05 15:10 2311算法描述:生成前N个整 ...
相关推荐
本文将深入探讨如何通过封装红黑树来模拟实现Map和Set。 红黑树是一种自平衡二叉查找树,它的主要特性是每个节点都带有颜色属性(红色或黑色),并且遵循以下性质: 1. 每个节点要么是黑色,要么是红色。 2. 根节点...
总结,通过使用Java的Jedis库,我们可以轻松地实现对Redis的String、List和Map的操作。通过封装和单元测试,可以提高代码的可维护性和可靠性。在实际项目中,还可以考虑使用更高级的客户端如Lettuce,以及Spring ...
### JAVA Map、List、Set 的区别 #### 一、概述 在 Java 集合框架中,`Map`、`List` ...而在处理简单的元素列表时,`List` 和 `Set` 各自具有独特的功能和优势。理解这些基本概念是成为优秀 Java 开发者的基石之一。
### Map接口详解 #### 1. Map接口概览 ...通过以上对`Map`、`Set`、`Iterator`以及Java集合框架的详细介绍,我们不仅可以了解到这些接口和类的基本概念和使用方法,还能深入理解它们在实际编程中的应用价值。
在Java编程中,将List或Set转换为Map是一种常见的需求,特别是在数据处理和映射关系时。通常,我们可以通过循环遍历集合元素,然后逐个添加到Map中来实现这一转换。然而,Java标准库以及第三方库如Guava提供了更为...
这里提到的"Map_Set.zip_C Map_C语言map_map.c"文件包含了一个使用红黑树(Red-Black Tree)实现的C语言版本的map和set操作。 **红黑树**是一种自平衡二叉查找树,它的每个节点都带有颜色属性,可以是红色或黑色。...
本次我们关注的是Java集合框架中的三类接口:List、Set和Map,以及如何实现它们的特定功能,特别是关于`TreeSet`和`TreeMap`的按值排序。标题中提到的“JCF(List、Set、Map)学习,实现了,value>按value排序”是一个...
标题中的"PropertySet的map/xml/jdbc"暗示了我们将探讨一个与Java编程相关的主题,它涉及到数据存储、序列化和数据库交互。PropertySet通常是指Java中的一个概念,它可能指的是属性集或者配置设置,而map、xml和jdbc...
STL中的map和set是两种关联容器,它们都基于一种高效的数据结构——红黑树(Red-Black Tree)进行实现。这种数据结构是一种自平衡的二叉查找树,能够保证在最坏情况下的搜索、插入和删除操作的时间复杂度为O(log n)...
数据结构之 Map 和 Set ...二叉搜索树是 Map 和 Set 的一种实现方式,它可以提供高效的查找、插入和删除操作。在实际开发中,选择合适的数据结构和实现方式是非常重要的,可以提高程序的性能和可读性。
这个简单的`SimpleMap`类使用数组来存储键值对,并通过自定义方法实现`Map`的核心功能。虽然在性能和特性上可能不如原生的`Map`,但它能帮助我们理解`Map`的工作机制。 ### 5. 实例应用 实例一:缓存函数结果 ```...
这个简单的实现中,`Map`实例内部维护了一个数组`_data`,其中每个元素都是一个包含`key`和`value`的对象。`set`方法首先遍历数组,如果找到匹配的键,则更新对应的值;如果没有找到,就将新键值对添加到数组末尾。`...
通过上述示例可以看出,只需要简单地重载 `和 `==` 运算符,我们就可以方便地使用自定义类型作为 `set` 或 `map` 的key,从而有效地管理键值对或有序集合。 此外,对于 `map` 而言,键值(key)是唯一的,并且通常...
在C++编程语言中,`set`、`map`和`stack`是三种非常重要的容器,它们分别提供了不同的数据组织和操作方式。下面将详细解释这些容器的使用方法。 1. **Set(集合)** Set是一种关联容器,它包含唯一对象的集合,不...
### Collection、Map、List、Set、...以上就是关于 `Collection`、`Map`、`List`、`Set` 和 `Iterator` 的详细解析,这些概念和类是 Java 编程中非常基础且重要的部分,掌握它们有助于更好地理解和使用 Java 集合框架。
在实现上,`Map` 和 `Set` 通常基于红黑树(Red-Black Tree)数据结构,这种数据结构保证了插入、删除和查找操作的时间复杂度为 O(log n)。红黑树是一种自平衡的二叉查找树,能够在保持平衡的同时提供快速访问。这比...
在Java编程中,Java Bean和Map是两种常用的数据结构,它们在不同的场景下各有优势。Java Bean是一种符合特定规范的类,通常用于封装业务数据,而Map则是一种键值对的集合,便于灵活地存储和查找数据。在实际开发中,...
本文将深入探讨`Map`集合的特性和遍历方式,以及`Set`特性的排序,并介绍如何使用`IO流`,特别是字节流和字符流。 首先,我们来了解`Map`集合的基本概念。`Map`接口是Java集合框架的一部分,它不直接继承自`...
红黑树(Red-Black Tree)是一种自平衡二叉查找树,它在计算机科学中扮演着重要的角色,尤其是在实现高效的数据结构如哈希映射(Map)和集合(Set)时。红黑树的主要特性是它能保持近似的平衡状态,从而确保了插入、...