关联式容器--树形结构(map&set)

关联式容器

什么是关联式容器:
关联式容器也是用来存储数据的,与序列式容器(vector, list, deque…)不同的是,关联式容器是通过key来存储和读取元素的,在数据检索时比序列式容器效率更高
键值对:
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值, value表示与key对应的信息, 这类似于字典中的一一对应关系.
实现构造键值对pair(粗略的实现, 主要是看整体结构):

#pragma once    
namespace sock {
         
  template<class T1, class T2>    
    struct pair {
         
      T1 first;    
      T2 second;    
      pair() : first(T1()), second(T2()) {
     }    
      pair(const T1& f, const T2& s)    
        : first(f), second(s) {
     }                                                                                
    };    
}    

树形关联式容器

树型结构的关联式 容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树) 作为其底层结果,容器中的元素是一个有序的序列。
set:
set的特性:
1.set的底层是红黑树, 按照一定次序来存储
2.其元素为key, 不允许修改, 并且是唯一的
3.默认中序遍历二叉搜索树, 结果为升序

set的简单使用:
key的唯一性:

int main() {
         
  set<int> s;    
  s.insert(9);    
  s.insert(5);    
  s.insert(2);    
  s.insert(5);    
  s.insert(7);    
  set<int>::iterator sit = s.begin();    
  while (sit != s.end()) {
         
    cout << *sit << " ";    
    ++sit;    
  }    
  cout << endl;                                                                                                 
  return 0;    
}    

在这里插入图片描述
移除key对应的结点:

int main() {
         
  set<int> s;    
  s.insert(9);    
  s.insert(5);    
  s.insert(2);    
  s.insert(5);    
  s.insert(7);    
    
  set<int>::iterator it = s.find(5);    
  s.erase(it);                                                                                                  
    
  set<int>::iterator sit = s.begin();    
  while (sit != s.end()) {
         
    cout << *sit << " ";    
    ++sit;    
  }    
  cout << endl;    
  return 0;    
}    

在这里插入图片描述

set中元素的插入就是在树中插入结点, 调整树结构的过程. 迭代器指针始终指向当前结点, 因为key是唯一的, 因此对于已经存在的key不再进行插入(可以通过s.count(key)来验证, 并且也能说明set中是否有该key值).

map:
map的特性:
1.map的底层是红黑树, 按照一定次序来存储
2.其元素为pair, key不能修改, 但是val可以修改, 并且key是唯一的
3.默认中序遍历二叉搜索树, 结果为升序

map的简单使用:
key的唯一性:

int main() {
         
  map<string, string> m;    
  m.insert(pair<string, string>("sort", "排序"));    
  m.insert(make_pair("search", "搜索"));    
  m.insert(make_pair("release", "发行"));    
  m.insert(make_pair("release", "释放"));    
  map<string, string>::iterator mit = m.begin();    
  while (mit != m.end()) {
         
    cout << mit->first << ":" << mit->second << endl;    
    ++mit;    
  }    
  return 0;    
}                        

关联式容器--树形结构(map&set)_第1张图片
移除key对应的结点:

int main() {
         
  map<string, string> m;    
  m.insert(pair<string, string>("sort", "排序"));    
  m.insert(make_pair("search", "搜索"));    
  m.insert(make_pair("release", "发行"));    
  m.insert(make_pair("release", "释放"));    
    
  // find(key) 返回指向map的迭代器类型    
  map<string, string>::iterator it = m.find("release");    
  m.erase(it);    
      
  map<string, string>::iterator mit = m.begin();    
  while (mit != m.end()) {
         
    cout << mit->first << ":" << mit->second << endl;    
    ++mit;    
  }    
  return 0;                                                                                                     
}    

在这里插入图片描述

key/val:

key的唯一性与不可变性:

int main() {
           
  map<string, string> m;      
  m.insert(make_pair("sort", "排序"));      
  m.insert(make_pair("search", "搜索"));      
  m.insert(make_pair("release", "发行"));      
  m.insert(make_pair("release", "释放"));      
  map<string, string>::iterator mit = m.begin();      
  while (mit != m.end()) {
         
    //if (mit == m.find("search")) { //error    
    //  mit->first = "find";    
    //}    
    cout << mit->first << ":" << mit->second << endl;    
    ++mit;    
  }    
  return 0;    
}                              

唯一性在上述上述代码中已经判断过了, 对于不可变性, mit->first = "find"这段代码会报错—"no viable overloaded ‘=’ ", 提示你不能对first进行赋值. 但是second却可以.
key的多样性:
在multiset和multimap中实现了key的多样性, 这也是multiset&multimap与set&map最显著的区别:

int main() {
         
  int arr[] = {
     9, 5, 5, 2, 7};    
  multiset<int> ms(arr, arr + sizeof(arr) / sizeof(int));     
  multiset<int>::iterator msit = ms.begin();    
  while (msit != ms.end()) {
         
    cout << *msit << " ";    
    ++msit;    
  }    
  cout << endl;    
  multimap<string, string> mm;    
  mm.insert(make_pair("sort", "排序"));    
  mm.insert(make_pair("search", "搜索"));    
  mm.insert(make_pair("release", "发行"));    
  mm.insert(make_pair("release", "释放"));    
  multimap<string, string>::iterator mmit = mm.begin();    
  while (mmit != mm.end()) {
         
    cout << mmit->first << ":" << mmit->second << endl;    
    ++mmit;    
  }    
  return 0;    
}                                       

关联式容器--树形结构(map&set)_第2张图片
map的operator[]:

int main() {
         
  map<string, string> m;    
  m.insert(make_pair("sort", "排序"));    
  m.insert(make_pair("search", "搜索"));    
  m["release"] = "发行";    
  m["release"] = "释放";    
  map<string, string>::iterator mit = m.begin();    
  while (mit != m.end()) {
         
    cout << mit->first << ":" << mit->second << endl;    
    ++mit;    
  }    
  return 0;    
}                          

关联式容器--树形结构(map&set)_第3张图片operator[]与insert的效果是不同的, insert遇到重复的key则不进行插入, 而operator[] 是先进行insert(key, V())的操作, 然后将新的val赋给second.
operator[]的实现:

mapped_type& operator[](const key_type& key) {
     
	// 如果key不存在, 则正常插入返回ret, 其iterator指向刚插入的pair
	// 如果key存在, 则返回ret, 其iterator指向已存在的pair
	pair<iterator, bool> ret = insert(make_pair(key, mapped_typed()));
	return ret.first->second; // 返回val
} 

静态的insert与erase:
insert:

//set&map
pair<iterator,bool> insert (const value_type& val);
iterator insert (iterator position, const value_type& val);

erase:

//set&map
void erase (iterator position);
size_type erase (const value_type& val);

与序列式容器不同的是, 对关联式容器进行插入删除操作, 会整体改变其内部的存储顺序, 这是由于底层是搜索二叉树(红黑树)的原因, 因此其插入或删除后的调整顺序是未知的, 一般不会在循环迭代中进行此类操作.
一句话来说, 就是insert和erase会影响整个树的布局, 一般不会边迭代边做insert和erase操作.

你可能感兴趣的:(面向对象,c++,Linux,C++的故事有点长,关联式容器--树形结构)