C++标准模板库编程实战 第四章

目录

4.1:map关联容器

4.2 map用法

4.2.3 在map中构造元素

4.2.4 访问map中的元素

4.2.5 删除元素 

4.3 pair<>和tuple<>

4.3.1 pair

4.3.2 tuple

4.4 multimap

4.5 改变比较函数

4.5.1 使用greater

4.5.2 自定义函数对象来比较元素

4.6 哈希

利用hash模板生成哈希值

4.7 unordered_map容器

4.7.1 生成和管理unordered_map容器

4.7.2 调整格子个数

4.7.3 插入元素

4.7.6 访问格子

4.8 unordered_multimap

课后练习


4.1:map关联容器

map容器的元素是pair<const K,T>类型的对象。

特性:

        1.每个键都是唯一,所以不允许有重复的键。但可以有重复的对象,只要键不一样。map容器都是有序的。默认使用less<K>进行比较。

        2.multimap<K,T>允许有重复的键。

        3.unordered_map<K,T>中元素的顺序不是直接由键确定的,二十由键的哈希值确定的。

        4.unordered_multimap<K,T>允许重复。

4.2 map用法

为了可以在必要的时候生成默认的元素,map容器保存的对象通常需要定义一个默认的构造函数。

元素组织方式一般是平衡二叉树。从包含n个元素的平衡二叉树检索一个随机元素用时O(log2n),从序列中要O(n)。

1.访问pair的成员变量的表达式是 ret_pr.first->first

访问map中每个元素:

for(const auto& p : people)
 std::cout << std::setw(10) << std::left << p.first << " " << p.second << " \n"

2.map中 的count()函数返回map中指定键对应元素的数目,可能是0或1:

if(!people.count("Ian"))
 people.insert(ret_pr.first, std::make_pair("Ian", 38));

3.可以将外部源的一段元素插入map,这些元素不必来自另一个map。但必须和被插入容器中的元素是同类型的。

std::map<std::string, size_t> crowd {{"May", 55}, {"Pat", 66}, {"Al", 22}, {"Ben", 44}};
auto iter = std::begin(people);
std::advance(iter, 4); // begin iterator+ 4
crowd.insert(++std::begin(people), iter); // Insert 2nd, 3rd, and 4th elements from people
4.2.3 在map中构造元素

4.emplace():

std::map<Name, size_t> people;
auto pr = people.emplace(Name{"Dan", "Druff"}, 77);

5.emplace_hint():必须提供一个指示元素生成位置的迭代器。

std::map<Name, size_t> people;
auto pr = people.emplace(Name{"Dan", "Druff"}, 77);
auto iter = people.emplace_hint(pr.first, Name{"Cal", "Cutta"}, 62);

和emplace()不同。emplace_hint()的返回值不是一个pair对象,是一个迭代器。如果有新元素被插入,返回指向新元素的迭代器。如果没有插入,返回和这个键匹配的现有元素的迭代器。如果没有插入???

4.2.4 访问map中的元素

6.map的成员函数at()返回参数键对应的对象,如果这个键不存在,就会抛出out_of_range异常:

需要在try代码块中调用at()函数----抛出的任何未捕获的异常都会导致程序的终止。

Name key;
try
{
 key = Name {"Dan", "Druff"};
 auto value = people.at(key);
 std::cout << key << " is aged " << value << std::endl;
 key = Name {"Don", "Druff"};
 value = people.at(key);
 std::cout << key << " is aged " << value << std::endl;
}
catch(const std::out_of_range& e)
{
 std::cerr << e.what() << '\n'
 << key << " was not found." << std::endl;
}

7. map容器提供了以键为参数的下标运算符,返回一个和键所关联对象的引用。

如果键不存在,会在容器中生成一个新对象:

auto value = people[Name {"Ned", "Kelly"}]; // Creates a new element if the key is not ther

下标运算符主要用来左赋值,修改已经存在的对象:

people[Name {"Ned", "Kelly"}] = 39; // Sets the value associated with the key to 3
4.2.5 删除元素 

8.erase()可以移除键和参数匹配的元素,然后返回所移除元素的个数。显然map容器返回值只能是0或1.

std::map<std::string, size_t> people {{"Fred", 45}, {"Joan", 33}, {"Jill", 22}};
std::string name{"Joan"};
if(people.erase(name))
 std::cout << name << " was removed." << std::endl;
else
 std::cout << name << " was not found." << std::endl;

也可以用指向删除元素的迭代器作为erase()的参数。这个参数必须是有效迭代器,不能是结束迭代器。

auto iter = people.erase(std::begin(people));
if(iter == std::end(people))
 std::cout << "The last element was removed." << std::endl;
else
 std::cout << "The element preceding " << iter->first << " was removed." << std::endl;

也可以删除两个迭代器范围内的元素。

如果想删除所有元素可以使用clear().

4.3 pair<>和tuple<>

4.3.1 pair

1.创建pair

std::string s1 {"test"}, s2{"that"};
std::pair<std::string, std::string> my_pair{s1, s2};
std::pair<std::string, std::string> your_pair{std::string {"test"}, std::string {"that"}};
std::pair<std::string, std::string> his_pair{"test", std::string {"that"}};
std::pair<std::string, std::string> her_pair{"test", "that"}

通过tuple构造pair 

std::pair<Name, Name> couple{std::piecewise_construct,
 std::forward_as_tuple("Jack", "Jones"), std::forward_as_tuple("Jill", "Smith")};

std::piecewise_construct作用就是其字面意思:分段构造。具体来说,因pair的key和value均可以是构造函数复杂类型,因而pair的初始化相对复杂,通过带有std::piecewise_construct_t类型参数,后跟两个tuple类型参数的构造函数,用第一个tuple类型的元素来构造pair的key, 用第二个tuple类型的元素来构造pair的value,从而实现pair的初始化。

 forward_as_tuple: 用于接受右值引用数据生成tuple。

2.pair对象有全套的运算符:

只有当pair.first和pair.second都相等时,两个pair才相等。

对于小于或大于,pair对象的成员变量是按字典顺序比较的。当new_pair.first小于old_pair.first时,new_pair<old_pair会返回true。当new_pair.first ==old_pair.first,但new_pair.second<old_pair.second,new_pair<old_pair也返回true。

4.3.2 tuple

1.make_tuple()函数接受不同类型的任意个数的参数,返回的tuple类型由参数的类型决定。

可以用pair对象构造tuple对象,此时tuple只能有两个元素。

auto the_pair = std::make_pair("these", "those");
std::tuple<std::string, std::string> my_t4 {the_pair};
std::tuple<std::string, std::string> my_t5 {std::pair <std::string, std::string > {"this", "that"}}

2.也可以用任何比较运算符来比较相同类型的tuple对象,按照字典顺序比较(元素依次比较)。

3.tuple是pair的泛化,工作方式不同。pair的对象个数是固定的,因此他们有成员名。

tuple的对象数目是不固定的,

函数模板get<>()可以返回tuple中的一个元素,具体哪一个由给定的模板类型参数确定:

auto my_tuple = std::make_tuple(Name{"Peter", "Piper"}, 42, std::string{"914 626 7890"});
std::cout << std::get<Name>(my_tuple)
 << " age = " << std::get<int>(my_tuple)
 << " tel: " << std::get<std::string>(my_tuple) << std::endl;

也可以用基于类型的get<>()模板从tuple中获取元素,这要求tuple中只有一个这种类型的元素:

auto my_tuple = std::make_tuple(Name{"Peter", "Piper"}, 42, std::string{"914 626 7890"});
std::cout << std::get<Name>(my_tuple)
 << " age = " << std::get<int>(my_tuple)
 << " tel: " << std::get<std::string>(my_tuple) << std::endl;

4.全局的tie<>()函数模板定义在tuple头文件中,tie<>()的模板类型参数是从函数参数中推导的。

auto my_tuple = std::make_tuple(Name{"Peter", "Piper"}, 42, std::string{"914 626 7890"});
Name name{};
size_t age{};
std::string phone{};
std::tie(name, age, phone) = my_tuple; 

可以选择要保存哪些值:

std::tie(name, std::ignore, phone) = my_tuple;

可以用tie<>()来实现对类的数据成员的字典比较:

bool Name::operator<(const Name& name) const
{
 return std::tie(second, first) < std::tie(name.second, name.first);
}

这是因为通过tie()得到的tuple元素是按顺序比较的。

4.4 multimap

multimap保存的是有序的键值对,而且可以保存重复的元素。multimap大部分成员函数用法和map相同。

1.insert()可以插入一个或多个元素,并且总是成功的。

2.emplace()和emplace_hint() emplace_hint()函数总是尽可能近的在第一个参数所指向位置的前面生成一个新元素。如果只使用emplace(),他可能插入到当前所有键为“rabbit”的元素的后面。

auto iter = pets.emplace("rabbit", "Flopsy");
iter = pets.emplace_hint(iter, "rabbit", "Mopsy"); // Create preceding Flopsy

3. multimap不支持下标运算符,因为键不能确定一个唯一的元素,map中能用的at()函数multimap也不能用。

使用multimap的成员函数find()可以返回一个键和参数匹配的元素迭代器。

std::multimap<std::string, size_t> people{ {"Ann", 25}, {"Bill", 46}, {"Jack", 77},
 {"Jack", 32}, {"Jill", 32}, {"Ann", 35} };
std::string name {"Bill"};
auto iter = people.find(name);
if(iter != std::end(people)) std::cout << name << " is " << iter->second << std::endl;
iter = people.find("Ann");
if(iter != std::end(people)) std::cout << iter->first << " is " << iter->second << std::endl;

4.成员函数equal_range()可以访问给定键对应的所有元素,返回封装了两个迭代器的pair对象。

auto pr = people.equal_range("Ann");
if(pr.first != std::end(people))
{
 for(auto iter = pr.first ; iter != pr.second; ++iter)
 std::cout << iter->first << " is " << iter->second << std::endl;
}

 5.成员函数lower_bound()返回一个迭代器,指向键值和参数相等或大于参数的第一个元素,或者结束迭代器。

upper_bound()也返回一个迭代器,指向简直大于参数的第一个元素,或结束迭代器。

所以当有重复元素时,以上两个函数返回一个开始迭代器和一个结束迭代器。

6.可以用count()获取数量,将distance()函数运用到成员函数equal_range()lower_bound()upper_bound()上也行。

7.erase()三个版本:第一个以待删除元素的迭代器作为参数。没有返回值。

第二个以一个键作为参数,删除容器中所有含这个键的元素,返回删除个数。

第三个接受两个迭代器,删除范围元素,返回最后一个被删除元素的后一个位置。

4.5 改变比较函数

map容器的比较函数在相等时不能返回true!

如果key1<key2 和key2<key1结果都是false,那么key1和key2是等价的,即相等。

等价 即 !(key1<key2)&&!(key2<key1)结果为true。

如果我们实现了<=,当key1和key2相等时:key1<=key2   key2<=key1都为true,然而!(key1<=key2)&&!(key2<=key1)为false,这意味着来自容器的这两个键不相等。

4.5.1 使用greater<T>
std::map<Name, size_t, std::greater<Name>> people
 { {Name{"Al", "Bedo"}, 53}, {Name{"Woody", "Leave"}, 33}, {Name{"Noah", "Lot"}, 43} };

这要求类T 重载了 operator>()运算符。

4.5.2 自定义函数对象来比较元素

1.使用伪函数-函数对象

// Compares keys that are unique_ptr<string> objects
class Key_compare
{
public:
 bool operator()(const std::unique_ptr<string>& p1, const std::unique_ptr<string>& p2) const
 {
 return *p1 < *p2;
 }
};
std::map<std::unique_ptr<string>, std::string, Key_compare> phonebook;

unique_ptr对象是不能被复制的,所以不能用初始化列表对map进行初始化,因为初始化列表包含了副本。

使用emplace() insert()添加元素:

phonebook.emplace(std::make_unique<string>("Fred"), "914 626 7897");
phonebook.insert(std::make_pair(std::make_unique<string>("Lily"), "212 896 4337"));

4.6 哈希

哈希是用给定范围的基本类型的数据项或string这样的对象,生成整数值的过程。

理想情况下,每个对象对应唯一的哈希值.当不同的键值个数大于可能的哈希值的个数,就会出现重复的哈希值,叫做碰撞。

利用hash<K>模板生成哈希值

需include function。operator()()接受K类型的单个参数,返回size_t类型的哈希值。

std::hash<int> hash_int; // Function object to hash int
std::vector<int> n {-5, -2, 2, 5, 10};
std::transform(std::begin(n), std::end(n), std::ostream_iterator<size_t>(std::cout, " "), hash_int);

也可以对指针,智能指针进行哈希:

std::hash<Box*> hash_box; // Box class as in Chapter 2
auto upbox = std::make_unique<Box>(1, 2, 3);
std::cout << "Hash value = " << hash_box(upbox.get()) 
<< std::endl; // Hash value = 1143026886 for me
std::hash<std::unique_ptr<Box>> hash_box; // Box class as in Chapter 2
auto upbox = std::make_unique<Box>(1, 2, 3); 
std::cout << "Hash value = " << hash_box(upbox) 
<< std::endl; // Hash value = 4291053140 for me

原生指针和unique_ptr的哈希值是相同的。

4.7 unordered_map容器

唯一键值对,无序。元素的位置由键的哈希值确定,必须有一个适用于键类型的哈希函数。

也必须能够判断元素是否相等,默认使用function中equal_to<K>模板。和map容器不同,map使用的是等价。如果使用的键类型没有operator==()就必须提供一个函数对象来比较键。

unordered_map中元素一般被保存在哈希表中,这个表的条目被称为格子,每个格子可以包含几个元素。

最大载入因子 = 元素个数  /  格子个数

组织格子的方式 :一种类似vector的序列,在哈希表中保存序列的地址。

一种将格子定义为链表,在哈希表中保存为根节点。

4.7.1 生成和管理unordered_map容器

1.两种方式生成unordered_map:(可以忽略格子个数)

std::unordered_map<std::string, size_t> people {{{"Jan", 44}, {"Jim", 33}, {"Joe", 99}}, 10};
std::vector<std::pair<string, size_t>> folks {{"Jan", 44}, {"Jim", 33}, {"Joe", 99},
 {"Dan", 22}, {"Ann", 55}, {"Don", 77}};
std::unordered_map<string, size_t> neighbors {std::begin(folks), std::end(folks), 500};

2.指定哈希函数构造unordered_map:此时不能省略格子数量。

class Name
{
 // Private and public members and friends as in Ex4_01...
public:
 size_t hash() const { return std::hash<std::string>()(first+second); }
 bool operator==(const Name& name) const { return first == name.first && second== name.second; }
};
class Hash_Name
{
public:
 size_t operator()(const Name& name) const { return name.hash(); }
};
std::unordered_map<Name, size_t, Hash_Name> people
 {{{{"Ann", "Ounce"}, 25}, {{"Bill", "Bao"}, 46}, {{"Jack", "Sprat"}, 77}},
 500, // Bucket count
 Hash_Name()}; // Hash function for keys

3.指定比较两个键对象是否相等的函数对象:此时不能省略格子数量

std::unordered_map<Name, size_t, Hash_Name, Name_Equal> people
 {{{{"Ann", "Ounce"}, 25}, {{"Bill", "Bao"}, 46}, {{"Jack", "Sprat"}, 77}},
 500, // Bucket count
 Hash_Name(), // Hash function for keys
 Name_Equal()}; // Equality comparison for keys
4.7.2 调整格子个数

rehash()

max_load_factor()

load_factor()

reverse()

4.7.3 插入元素

insert()

emplace()

emplace_hint()

2.和map一样,可以在下标运算符中使用键来获取对象的引用,在下标中使用不存在的键时,会生成新元素。

不想生成默认对象的元素时应该使用at()。

3.成员函数erase()移除元素,参数可以是表示一个元素的键(返回一个整数,移除元素的个数 0或1)或是指向它的一个迭代器(返回移除元素后的元素)。也可以移除元素序列。

4.7.6 访问格子

将索引值传给begin()获取给定位置格子中第一个元素的迭代器。

end() cbegin() cend()

成员函数bucket_count()返回格子个数。bucket_size()返回参数指定的格子中的元素个数。

bucket()传入键,返回格子的索引值。

4.8 unordered_multimap

允许有重复键的无序map。使用方法和unordered_map基本相同。

1.insert() emplace() 这两个函数unordered_multimap返回一个pair对象,用来说明插入是否成功,如果不成功会返回一个迭代器。

2.因为允许重复,没有at() operator[]()。

3.只能使用find() equal_range()访问元素。find()返回找到的第一个元素的迭代器,如果找不到这个键,会返回一个结束迭代器。

count()用来发现容器中给定键的元素个数。

std::string key{"Jan"};
auto n = people.count(key); // Number of elements stored with key
 if(n == 1)
 std::cout << key << " is " << people.find(key)->second << std::endl;
 else if(n > 1)
 {
 auto pr = people.equal_range(key); // pair of begin & end iterators returned
 while(pr.first != pr.second)
 {
 std::cout << key << " is " << pr.first->second << std::endl;
 ++pr.first; // Increment begin iterator
 }
 }

课后练习

pe4_1:

#include<iostream>
#include<map>
#include<list>
#include<string>
using namespace std;
//ostream& operator<<(ostream os, const list<string> & stu);

void showclass(const map<string, list<string>> & mmm);
void increase(map<string, list<string>>& mmm);
void delete_class(map<string, list<string>>& mmm);
void search(map<string, list<string>>& mmm);
int main() {
	list<string> student;
	map<string, list<string>> _class{ {"math",{"hhh","qqq","ccc"}},{"Biology",{"aaa","qqeeq","ccc"}}};
	cout << "initial map: " << endl;
	showclass(_class);
	cout << "increase one class." << endl;

	increase(_class);
	cout << "now wo have: " << endl;
	showclass(_class);

	cout << "search one class." << endl;
	search(_class);

	cout << "delete one class." << endl;
	delete_class(_class);
	cout << "now wo have: " << endl;
	showclass(_class);
	return 0;
}
//ostream& operator<<(ostream os, const list<string>& stu)
//{
//	for (auto value : stu) {
//		os << value << " ";
//	}
//	return os;
//}
void showclass(const map<string, list<string>>& mmm) {
	for (auto value : mmm) {
		cout << "课程:" << value.first << endl;
		cout << "学生:";
		for (auto vvv : value.second) {
			cout << vvv<<" ";
		}
		cout << endl;
	}
	
}
void increase(map<string, list<string>>& mmm) {
	cout << "Enter class name: ";
	string classname;
	getline(cin, classname);
	list<string> student;
	string sname;
	cout << "Enter student name: ";
	while (true)
	{
		if ((cin >> sname).eof()) {
			cin.clear();
			break;
		}
		student.push_back(sname);
	}
	if (!mmm.count(classname)) {
		mmm.insert(make_pair(classname, student));
	}
	else { cout << classname << " already exist;" << endl; };
	
}
void delete_class(map<string, list<string>>& mmm) {
	cout << "Enter class name: ";
	string classname;
	getline(cin, classname);
	if (mmm.erase(classname)) {
		cout << classname << " was removed." << endl;
	}
	else {
		cout << classname << " was not found." << endl;
	}
	
}
void search(map<string, list<string>>& mmm) {
	cout << "Enter class name: ";
	string classname;
	getline(cin, classname);
	auto iter = mmm.find(classname);
	if (iter == end(mmm) ) {
		cout << classname << " was not found." << endl;
	}
	else {
		for (auto value : ((*iter).second)) {
			cout << value << " ";
		}
	}
	cout << endl;
}

pe4_2:

#include<iostream>
#include<map>
#include<list>
#include<string>
using namespace std;
//ostream& operator<<(ostream os, const list<string> & stu);

void showclass(const multimap<string, list<string>, greater<string>>& mmm);
void increase(multimap<string, list<string>, greater<string>>& mmm);
void delete_class(multimap<string, list<string>, greater<string>>& mmm);
void search(multimap<string, list<string>, greater<string>>& mmm);
int main() {
	//list<string> student;
	multimap<string, list<string>,greater<string>> _class{ {"hhh",{"math","chinese","english"}},
			{"aaaa",{"science","math","biology"}},
			{"bbb",{"chinese","math","biology"}},
			{"bbb",{"math","music","biology"}} };
	cout << "initial map: " << endl;
	showclass(_class);
	cout << "increase one student." << endl;

	increase(_class);
	cout << "now wo have: " << endl;
	showclass(_class);

	cout << "search one student." << endl;
	search(_class);

	cout << "delete one student." << endl;
	delete_class(_class);
	cout << "now wo have: " << endl;
	showclass(_class);
	return 0;
}
void showclass(const multimap<string, list<string>, greater<string>>& mmm) {
	for (auto value : mmm) {
		cout << "学生:" << value.first << endl;
		cout << "课程:";
		for (auto vvv : value.second) {
			cout << vvv << " ";
		}
		cout << endl;
	}

}
void increase(multimap<string, list<string>, greater<string>>& mmm) {
	cout << "Enter student name: ";
	string classname;
	getline(cin, classname);
	list<string> student;
	string sname;
	cout << "Enter class name: ";
	while (true)
	{
		if ((cin >> sname).eof()) {
			cin.clear();
			break;
		}
		student.push_back(sname);
	}
	if (!mmm.count(classname)) {
		mmm.insert(make_pair(classname, student));
	}
	else { cout << classname << " already exist;" << endl; };
}
void delete_class(multimap<string, list<string>, greater<string>>& mmm) {
	cout << "Enter student name: ";
	string classname;
	getline(cin, classname);
	if (mmm.erase(classname)) {
		cout << classname << " was removed." << endl;
	}
	else {
		cout << classname << " was not found." << endl;
	}
}
void search(multimap<string, list<string>, greater<string>>& mmm) {
	cout << "Enter student name: ";
	string classname;
	getline(cin, classname);
	auto iter = mmm.find(classname);
	if (iter == end(mmm)) {
		cout << classname << " was not found." << endl;
	}
	else {
		for (auto value : ((*iter).second)) {
			cout << value << " ";
		}
	}
	cout << endl;
}

pe4_3:我自己写的版本:需要打印间隔时间>100才有非0数据,因为生成的随机数是0-100。

#include<iostream>
#include<map>
#include<queue>
#include<random>
using namespace std;
void in_queue(map<int, queue<int>> &mmm, int time);//选择一个收银台入队
void show_len(map<int, queue<int>>& mmm);
int main() {
	map<int, queue<int>> market;
	//map<int, int> market;//第二个参数 值代表队列长度
	cout << "Enter numbers of Cash register: ";
	int numbers = 0;
	cin >> numbers;
	for (int i = 0; i < numbers; i++) {
		auto value = market[i];
		//value = 0;
	}
	cin.get();
	float cus_come_time = 0.0;
	cout << "Enter show time: ";
	int time = 0;	//打印的时间间隔
	int serve_time = 0;		//服务时间
	while (!( (cin>>time).eof() ))
	{
		for (; time > 0; ) {
			cus_come_time = rand() % 100;	//产生0-100的随机数。
			serve_time = rand() % 100;
			for (; cus_come_time > 0;cus_come_time--) {
				//这个循环每次都走,服务时间应该随着这个时间--
				for (auto value : market) {
					if (!value.second.empty()) {
						if (value.second.front() == 0) {
							value.second.pop();
							cout << "服务完成走人。" << endl;
						}
						value.second.front()--; //如果队列不为空,队头被服务人服务时间--
					}
					
				}

				//
				time--;
				if (time == 0) break;
			}
			if(time == 0) break;
			in_queue(market, serve_time);
		}
		//报告平均和最长队列长度
		show_len(market);
	}
	return 0;
}
void in_queue(map<int, queue<int>>&mmm, int time) {
	int choose = 0;
	int min = 10000;
	for (auto value : mmm) {
		if (value.second.size() < min) {
			choose = value.first;
		}
	}
	mmm[choose].push(time);
	cout << "入队。"<<endl;
}
void show_len(map<int, queue<int>>& mmm) {
	int choose = 0;
	double mean_len = 0;
	int max_len = 0;
	for (auto value : mmm) {
		if (value.second.size() > max_len) {
			max_len = value.second.size();
			choose = value.first;
		}
		mean_len += value.second.size();
	}
	mean_len = mean_len / mmm.size();
	cout << "平均长度:" << mean_len << endl;
	cout << "最大长度:" << max_len << " 位于" << choose << "号收银台。" << endl;
}

提供gpt版本的学习使用(顾客随机入队,不会找最短的队):

#include <iostream>
#include <map>
#include <queue>
#include <random>

// Function to generate a random number within a given range
int getRandomNumber(int min, int max) {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(min, max);
    return dis(gen);
}

// Function to simulate the supermarket
void simulateSupermarket(int numCheckouts, int simulationPeriod) {
    std::map<int, std::queue<int>> checkouts;

    // Initialize checkouts
    for (int i = 1; i <= numCheckouts; ++i) {
        checkouts[i] = std::queue<int>();
    }

    int currentTime = 0;
    int maxQueueLength = 0;
    int totalQueueLength = 0;

    while (currentTime < simulationPeriod) {
        // Check if a new customer arrives
        if (getRandomNumber(1, 5) == 1) {  // 1 in 5 chance of arrival
            int checkoutID = getRandomNumber(1, numCheckouts);
            int occupancyTime = getRandomNumber(1, 10);

            checkouts[checkoutID].push(occupancyTime);

            int queueLength = checkouts[checkoutID].size();
            if (queueLength > maxQueueLength) {
                maxQueueLength = queueLength;
            }

            totalQueueLength += queueLength;
        }

        // Serve customers
        for (auto& checkout : checkouts) {
            if (!checkout.second.empty()) {
                checkout.second.front()--;

                if (checkout.second.front() == 0) {
                    checkout.second.pop();
                }
            }
        }

        currentTime++;
    }

    // Calculate average queue length
    double avgQueueLength = static_cast<double>(totalQueueLength) / (simulationPeriod * numCheckouts);

    // Output results
    std::cout << "Simulation Results:" << std::endl;
    std::cout << "Number of Checkouts: " << numCheckouts << std::endl;
    std::cout << "Simulation Period: " << simulationPeriod << std::endl;
    std::cout << "Average Queue Length: " << avgQueueLength << std::endl;
    std::cout << "Maximum Queue Length: " << maxQueueLength << std::endl;
}

int main() {
    int numCheckouts;
    int simulationPeriod;

    std::cout << "Enter the number of checkouts: ";
    std::cin >> numCheckouts;

    std::cout << "Enter the simulation period: ";
    std::cin >> simulationPeriod;

    simulateSupermarket(numCheckouts, simulationPeriod);

    return 0;
}

pe4_4:

#include<iostream>
#include<map>
#include<unordered_map>
#include<string>
#include<algorithm>
using namespace std;

class Person {
private:
	string name;
	string position;
	int telephone;
public:
	Person() :name("NULL"), position("NULL"), telephone(0) {};
	Person(string nn, string po, int te = 0) :name(nn), position(po), telephone(te) {};
	string getname() { return name; };
	string getpo() { return position; };
	int get_tele() { return telephone; };
};

void show_pos_tele(const string& name,  unordered_map<string, Person>& mmm);
void Descending_show(unordered_map<string, Person>& mmm);
int main() {
	unordered_map<string, Person> tele_directory{ {"hhh",{"hhh","wuhan",123456}}, {"aaaa",{"aaaa","beijng",1234677}}, {"ddd",{"dddd","xinjiang",1456}}, };
	show_pos_tele("hhh", tele_directory);
	
	Descending_show(tele_directory);
	return 0;
}
void show_pos_tele(const string& name, unordered_map<string, Person>& mmm) {
	cout << "show " << name << " information." << endl;
	auto n = mmm.count(name);
	if (n == 1)
	{
		cout << name << ": " << mmm.find(name)->second.getpo() << " " << mmm.find(name)->second.get_tele() << endl;
	}
	else if (n > 1) {
		auto ptr = mmm.equal_range(name);
		while (ptr.first!=ptr.second)
		{
			cout << name << ": " << ptr.first->second.getpo() << " " << ptr.first->second.get_tele() << endl;
			ptr.first++;
		}
	}
}
void Descending_show(unordered_map<string, Person>& mmm) {
	vector<string> descend;
	for (auto value : mmm) {
		descend.push_back(value.first);
	}
	sort(begin(descend),end(descend),greater<string>());
	for (auto value : descend) {
		show_pos_tele(value, mmm);
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值