C++系列笔记(十)
【导读】《21天学通C++》这本书通过大量精小短悍的程序详细而全面的阐述了C++的基本概念和技术,包括管理输入/输出、循环和数组、面向对象编程、模板、使用标准模板库以及创建C++应用程序等。这些内容被组织成结构合理、联系紧密的章节,每章都可在1小时内阅读完毕,都提供了示例程序清单,并辅以示例输出和代码分析,以阐述该章介绍的主题。本文是系列笔记的第十篇,欢迎各位阅读指正!
对包含对象的list进行排序以及删除其中的元素
如果list的元素类型为类,而不是int等简单内置类型,如何对其进行排序呢?假设有一个包含地址簿条目的list,其中每个元素都是一个对象,包含姓名、地址等内容,如何确保按姓名对其进行排序呢?答案是采取下面两种方式之一:
- 在list包含的对象所属的类中,实现运算符<。
- 提供一个排序二元谓词——一个这样的函数,即接受两个输入值,并返回一个布尔值,指出第一个值是否比第二个值小。典型代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<list>
using namespace std;
template <typename T>
void DisplayContents(const T& Inputs)
{
for (auto iElements = Inputs.cbegin(); iElements != Inputs.cend(); ++iElements)
cout << *iElements << endl;;
cout << endl;
}struct ContactItem
{
string strname;
string strphone;
string strdisplayrep;
ContactItem(const string& strName, const string& strPhone)
{
strname = strName;
strphone = strPhone;
strdisplayrep = (strName + ": "+strPhone);
}
bool operator == (const ContactItem& itemToCompare) const
{
return (itemToCompare.strname == this->strname);
}
bool operator < (const ContactItem& itemToCompare) const
{
return (this->strname < itemToCompare.strname);
}
operator const char*() const
{
return strdisplayrep.c_str();
}
};
bool SortOnPhoneNumber(const ContactItem& item1, const ContactItem& item2)
{
return (item1.strphone < item2.strphone);
}
int main()
{
list<ContactItem> Contacts;
Contacts.push_back(ContactItem("xiewenrui,", "+15797639728"));
Contacts.push_back(ContactItem("chenchuanxi", "+1234567"));
Contacts.push_back(ContactItem("hezhiqiang", "+1345678"));
cout << "list in initial idea: " << endl;
DisplayContents(Contacts);
Contacts.sort();
cout << "order: " <<endl;
DisplayContents(Contacts);
Contacts.sort(SortOnPhoneNumber);
cout << "after sort in phone number: " <<endl;
DisplayContents(Contacts);
}
输出为:
list in initial idea:
xiewenrui,: +15797639728
chenchuanxi: +1234567
hezhiqiang: +1345678
order:
chenchuanxi: +1234567
hezhiqiang: +1345678
xiewenrui,: +15797639728
after sort in phone number:
chenchuanxi: +1234567
hezhiqiang: +1345678
xiewenrui,: +15797639728
C++11
从C++11起,您可以使用forward_list,而不是双向链表std::list。std::forward_list是一种单向链表,即只允许沿一个方向遍历。要使用std::forward_list,需要包含头文件#include<forward_list> forward_list 的用法与 list 很像,但只能沿一个方向移动迭代器,且插入元素时只能使用函数push_front(),而不能使用push_back()。当然,总是可以使用insert()及其重载版本在指定位置插入元素。 forward_list的优点在于,它是一种单向链表,占用的内存比list稍少,因为只需指向下一个元素,而无需指向前一个元素。
STL集合类
容器 set和 multiset让程序员能够在容器中快速查找键,键是存储在一维容器中的值。set和multiset之间的区别在于,后者可存储重复的值,而前者只能存储唯一的值。 要使用std::set或set::multiset类,需要包含头文件:位于set中特定位置的元素不能替换为值不同的新元素,这是因为set将把新元素同二叉树中的其他元素进行比较,进而将其放在其他位置。
STL set和multiset的基本操作
//实例化
std::set<int> setIntegers;
std::multiset<int> msetIntegers;
要声明一个指向set或multiset的迭代器
std::set<int>::const_iterator iElementInSet;
std::multiset<int>::const_iterator iElementInMultiset;
如果需要一个可用于修改值或调用非const函数的迭代器,应将const_iterator替换为iterator。 鉴于set和multiset都是在插入时对元素进行排序的容器,如果您没有指定排序标准,它们将使用默认谓词std::less,确保包含的元素按升序排列。要创建二元排序谓词,可在类中定义一个operator(),让它接受两个参数(其类型与集合存储的数据类型相同),并根据排序标准返回true。下面是一个二元谓词,他按降序排序:
template <typename T>
struct SortDescending
{
bool operator() (const T& lhs,const T& rhs) const
{
return (lhs > rhs);
}
};
然后实例化set或multiset时指定该谓词:
set<int, ortDescending<int>> setIntegers;
multiset<int,ortDescending<int>> msetIntegers;
在set和multiset插入元素
setIntegers.insert();
msetIntegers.insert()
multiset::count(value)
它返回multiset中有多少个元素存储了指定的值。
在set和multiset中查找元素
诸如set、multiset、map和multimap等关联容器都提供了成员函数find(),它让您能够根据给定的键来查找值:
auto iElementsFound = setIntegers.find(-1);
if (iElementsFound !=setIntegers.end())
cout<<"Element"<<*iElementsFound <<""found"<<endl;
else
cout<<"Elemenr not found in set!"<<endl;
删除set和multiset中的元素
诸如set、multiset、map和multimap等关联容器都提供了成员函数erase(),它让您能够根据键删除值:setObeject.erase(key)
; erase函数的另一个版本接受一个迭代器作为参数,并删除该迭代器指向的元素:setObeject.erase(iElement);
通过使用迭代器指定的边界,可将指定范围内的所有元素都从set或multiset中删除:setObeject.erase(iLowerBound,iUpperBound);
C++11
STL散列集合实现std::unordered_set和std::unordered_multiset。STL提供的容器类std::unordered_set就是基于散列的set。要使用STL容器std::unordered_set或std::unordered_multiset,需要包含头文件<unordered_set>:#include<unordered_set>
相比于std::set,这个类的用法差别不大。然而,unordered_set的一个重要特征是,有一个负责确定排列顺序的散列函数:
unordered_set<int>::hasher HFn = usetInt.hash_function();
典型代码如下:
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<unordered_set>
using namespace std;
template <typename T>
void DisplayContents(const T& Inputs)
{
cout << "number of elements,size()=" << Inputs.size()<<endl;
//最大桶数
cout << "Max bucket count=" << Inputs.max_bucket_count() << endl;
//负载系数
cout << "Load factor= " << Inputs.load_factor() << endl;
//最大负载系数
cout << "mx_load_factor= " << Inputs.max_load_factor() << endl;
cout << "unordered set contains:" << endl;
for (auto iElements = Inputs.cbegin(); iElements != Inputs.cend(); ++iElements)
cout << *iElements << endl;;
cout << endl;
}
int main()
{
unordered_set<int> usetInt;
usetInt.insert(1000);
usetInt.insert(-3);
usetInt.insert(2011);
usetInt.insert(100);
DisplayContents(usetInt);
usetInt.insert(999);
DisplayContents(usetInt);
return 0;
}
输出为:
number of elements,size()=4
Max bucket count=536870911
Load factor= 0.5
mx_load_factor= 1
unordered set contains:
1000
-3
2011
100
number of elements,size()=5
Max bucket count=536870911
Load factor= 0.625
mx_load_factor= 1
unordered set contains:
1000
-3
999
2011
100
相关文章
- C++学习——c++逗号操作符说明(附加全部运算符优先级)
- C++系列笔记(七)
- C++系列笔记(十二)
- 老梁聊C++,为什么不能修改set里的值?如果非要修改怎么办?
- 【笔记】《深入理解C++11》(上)
- c++之分支语句和逻辑运算符笔记
- c++之函数探幽笔记
- 【c++】【基础】【primer_plus】【第四章】指针与内存
- c++中无法打开源文件_无法打开源文件iostream
- 《SiamFC++:Towards Robust and Accurate Visual Tracking with Target Estimation Guidelines》论文笔记
- c++模版笔记(4)
- C++ 新特性学习(八) — 原子操作和多线程库[多工内存模型]
- C/C++ Qt 数据库与SqlTableModel组件应用
- c++的链表-C++实现简单链表
- C/C++ 结构体与指针笔记
- C/C++ 关于运算符重载笔记
- c++:指针和引用的区别
- 在 WebAssembly 中使用 C/C++ 和 libbpf 编写 eBPF 程序
- C++queue容器学习(详解)编程语言
- C++重载=(C++重载赋值运算符)
- C++Primer笔记之关联容器的使用详解