您的位置:首页 > 教育 > 锐评 > 广州市软件开发有限公司_ecshop多商户源码_天津网站建设技术外包_网站推广文章

广州市软件开发有限公司_ecshop多商户源码_天津网站建设技术外包_网站推广文章

2025/5/13 6:05:26 来源:https://blog.csdn.net/yunbao00_/article/details/142900494  浏览:    关键词:广州市软件开发有限公司_ecshop多商户源码_天津网站建设技术外包_网站推广文章
广州市软件开发有限公司_ecshop多商户源码_天津网站建设技术外包_网站推广文章

set和map分别于key和key/value模型相类似  

容器分为序列式容器 和 关联式容器

序列式有:vector /list

关联式有:map/set

先进行一些简单的使用 

int main()
{set<int>s;s.insert(1);s.insert(15);s.insert(5);s.insert(6);s.insert(8);s.insert(4);s.insert(1);set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << endl;it++;}cout << endl;return 0;
}

 

int main()
{set<int>s;s.insert(1);s.insert(15);s.insert(5);s.insert(6);s.insert(8);s.insert(4);s.insert(1);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}

这里有三种删除 第一种是以迭代器位置进行删除 第二种以值进行删除 并且会返回值 这里的返回值代表删除元素的个数 如果返回为0 说明不存在 并没有删除成功   第三种是迭代器区间范围进行删除 

	int main()
{set<int>s;s.insert(1);s.insert(15);s.insert(5);s.insert(6);s.insert(8);s.insert(4);s.insert(1);s.erase(s.begin());//第一种删除int x;cin >> x;int num = s.erase(x);//第二种删除if (num == 0){cout << x << "不存在 " << endl;}for (auto e : s)
{cout << e << " ";
}
cout << endl;return 0;
}

这里的删除1是第一种删除造成的

第一种以迭代器方式删除也可以运用到find函数 find返回也是迭代器 但是find如果没找到 会返回end()迭代器 这时就需要判断一下 否则用end()迭代器去删除就会造成越界报错

auto e = s.find(x);
auto e1 = find(s.begin(), s.end(),x);

关于find 它与算法库中的find是有差别 算法库中使用的是暴力查找 o(n)  set库中的find 使用的是搜索二叉树遍历的方式 o(logN)

接下来讲解一下 lower_bound() 和upper_bound()   他们的返回值都是对应位置的迭代器    

接下来我们通过一段代码来结束他们的作用

int main()
{std::set<int> myset;std::set<int>::iterator itlow, itup;for (int i = 1; i < 10; i++) myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90// [30, 60]// >= 30itlow = myset.lower_bound(30);                //// > 60itup = myset.upper_bound(60);                 //               myset.erase(itlow, itup);                     // 10 20 70 80 90std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

这里的set库中erase使用的是第三种迭代器区间范围删除   lower_bound(x) 取的在set中最靠近 的大于等于 x位置的迭代器  而upper_bound(x)则是取最靠近的 大于x的值  

10 20 30 40 50 60 70 80 90 在这一串数中 lower_bound(30)就是返回30位置迭代器 lowe_bound(25)就是返回30位置迭代器  upper_bound(60)就是返回70位置的迭代器 upper_bound(65)也是返回70位置的迭代器  而erase是左闭右开   这样就能保证删除 set内容30-60的所有元素  

multiset  是set的变种 与set最大区别就是不去重 允许键值冗余  也会进行排序

multiset头文件也在set库中

int main()
{multiset<int>s;s.insert(1);s.insert(15);s.insert(5);s.insert(6);s.insert(8);s.insert(4);s.insert(1);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}


在find查找14中 如果是这种情况就会返回第一个14

 如果是下图 就会查找到箭头指向的位置的14  这样就表明了multiset查找规则  如果没有遇到14就按照比较大小走  如果相同 也不能先返回 首先要看左子树是否也相同  如果相同 返回左节点 如果不同返回单前节点  

 

int main()
{multiset<int> s;s.insert(5);s.insert(2);s.insert(7);s.insert(4);s.insert(9);s.insert(9);s.insert(9);s.insert(1);s.insert(5);s.insert(9);auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 11:50int x;cin >> x;auto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;cout << s.count(x) << endl;return 0;
}

 

这里更可以看出find 返回中序第一个相同位置迭代器好处 这样才能将所有的相同元素全部遍历出来   

我们接下来在看一下删除 这里的删除 是一次性删除所有x元素 这里想要一次性删除所有的x元素  也是用到了再find查找是返回中序第一个且与x元素相同的结点的位置迭代器  这样才能保证删除所有的x元素

	int main(){// 排序multiset<int> s;//构造s.insert(5);//插入s.insert(2);s.insert(7);s.insert(4);s.insert(9);s.insert(9);s.insert(9);s.insert(1);s.insert(5);s.insert(9);auto it = s.begin();//遍历while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 11:50int x;cin >> x;s.erase(x);//删除for (auto e : s){cout << e << " ";}cout << endl;return 0;
}

  

所以multiset和set的区别就是 1.find查找x时,多个x在树中 返回中序第一个

2.插入时 允许相等的值插入

接下来要介绍的是map 

map中的value_type是一个叫pair的东西  键值对

 

接下来通过一段代码来介绍map的构造和插入 还有pair的使用方式

  

	int main(){map <string, string> tt;//构造pair<string, string> a("left", "左边");//有名构造tt.insert(a);//插入 tt.insert(pair<string , string>("right", "右边"));//匿名构造tt.insert(make_pair("insert","插入"));//专用函数tt.insert({ "string", "字符串" });//隐式类型转换return 0;}
map<string, string> tt{ {"left", "左边"},{"right", "右边"},{"insert","插入"},{"string", "字符串"} };

这是因为在c++11之后都支持initializer_list 所以最外层的花括号代表initializer_list  里面的小花括号代表隐式类型转换  

接下来介绍map的遍历迭代器 这里的map是没有重载流插入和流提取的  

int main()
{//map <string, string> tt;//构造//pair<string, string> a("left", "左边");//有名构造//tt.insert(a);//插入 //tt.insert(pair<string , string>("right", "右边"));//匿名构造//tt.insert(make_pair("insert","插入"));//专用函数//tt.insert({ "string", "字符串" });//隐式类型转换map<string, string> tt{ {"left", "左边"},{"right", "右边"},{"insert","插入"},{"string", "字符串"} };map<string, string>::iterator it = tt.begin();while (it != tt.end()){cout << (*it).first << " :: " << (*it).second <<"   ";it++;}cout << endl;return 0;
}

可以看到这里与插入顺序是不一致的  这是因为map也要按照key的顺序进行排序  按照ascll码进行排序 

这是最常用的方法  operator->

	int main()
{map<string, string> tt{ {"left", "左边"},{"right", "右边"},{"insert","插入"},{"string", "字符串"} };map<string, string>::iterator it = tt.begin();while (it != tt.end()){//cout << (*it).first << " :: " << (*it).second <<"   ";cout << it->first << "::" << it->second << "  ";it++;}cout << endl;return 0;
}

范围for 

int main()
{map<string, string> tt{ {"left", "左边"},{"right", "右边"},{"insert","插入"},{"string", "字符串"} };for (const auto & t :tt){cout << t.first << "  " << t.second << endl;}cout << endl;return 0;}
for (auto & [x,y]  : tt)
{cout << x << "::" << y << endl;
}
cout << endl;

这种写法是在高版本下可以运行的 

int main()
{map<string, string> tt{ {"left", "左边"},{"right", "右边"},{"insert","插入"},{"string", "字符串"} };for (const auto & t :tt)
{cout << t.first << "  " << t.second << endl;
}
cout << endl;string str;
while (cin >> str)
{auto ret = tt.find(str);if (ret != tt.end()){cout << ret->first << "->" << ret->second << endl;}else{cout << "无此单词 请重新输入" << endl;}
}return 0;
}

接下来在看一下水果计数

int main()
{// 统计水果出现的次数string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉" };map<string, int> countTree;for (const auto& str : arr){// 先查找水果在不在搜索树中// 1、不在,说明水果第一次出现,则插入<水果, 1>// 2、在,则查找到的节点中水果对应的次数++//BSTreeNode<string, int>* ret = countTree.Find(str);auto ret = countTree.find(str);if (ret == countTree.end()){countTree.insert({ str, 1 });}else{ret->second++;}}for (auto& [x, y] : countTree){cout << x << "::" << y << endl;}cout << endl;return 0;
}

 

在map中对[]的运用     

	 int main()
{// 统计水果出现的次数string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉" };map<string, int> countTree;for (const auto& str : arr){countTree[str]++;}for (auto& [x, y] : countTree){cout << x << "::" << y << endl;}cout << endl;return 0;
}

在别的地方[]是下标返回对应位置的值

 这里的[]用意是用key返回对应的value 那么如果在map中没有这个key的时候 就会进行插入当前的key

这是[]的底层 使用的是insert  利用了insert 的返回值

insert的返回值是一个pair   这个pair的类型是<iterator,bool>如果为true插入成功 说明之前是没有这个值的 并且返回的迭代器是这个新插入位置    如果为false插入失败 说明之前已经有相同的值 返回迭代器是相同值位置的迭代器   

operator[]由于底层是insert  所以可以有很多的使用形式  不仅用于访问 还可以用与插入 和查找

int main()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));//插入+修改dict["right"] = "右边";//修改dict["right"] = "右边啊啊";//如果key不存在插入dict["left"];//key存在->查找cout << dict["insert"] << endl;return 0;
}

  set有multiset  map有multimap     

multimap与map的区别也是允许键值冗余  multimap头文件也是与map一样的

int main()
{multimap<string, string> dict;dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("sort", "xxx"));dict.insert(make_pair("sort", "排"));dict.insert(make_pair("sort", "序"));return 0;
}

find也是返回中序第一个相同的位置的迭代器 count也是计数    而与map的区别就是不在提供[]了

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com