前因
今日在做项目时,用到了容器map。本身map是基于红黑树的结构,因此不支持索引查找,这点很好理解。但是因为需要对map中 “相邻两两元素” 做运算,在实现的时候犯了难,在进行了思考之后,提出了以下的方法,以作记录。
问题阐述
假如说对于这个问题:我们已经知道每一天中,不同时间点中有不同数量的任务指令产生。
其中每条指令都有时间戳,以及指令号。时间戳有可能一样,但是指令号都不相同。
问题实现
对于这个问题,我们用map来作为容器是最合适的。即:
- key:时间戳,int
- value:指令号,string
这样,就可以方便的整合同一时间戳的所有任务,以及让其按照时间戳从小到大的顺序实现排列。
map<int, string> time_jobMap;
但是,如果我们想要计算相邻两个时间点的任务数量与时间间隔之比,怎么办?
如果map像普通的vector一样,支持索引操作,就会非常简单了:
for(int i = 1;i<time_jobMap.size();i++)
{
float timeInterval = time_jobMap[i].first - time_jobMap[i-1].first;
float jobDifference = abs(time_jobMap[i].second - time_jobMap[i].second);
cout<< (jobDifference / timeInterval) <<endl;
}
以上是错的,并不能实现!因为map不支持索引! time_jobMap[i]只会返回key等于i的指令号,根本取不到first、second。
map可以可以进行遍历?可以!
我们可以直接用形如:
for(auto &j : time_jobMap)
{
...
}
这种形式来对map进行快速遍历,但是,这样并不能实现我们想要的相邻元素进行计算的任务。
而map是支持迭代器操作的,用迭代器能否实现我们的目的呢?
能,也不能。因为:
- map、set、multimap、multiset、list的迭代器是没有加减法的。他们仅支持++itr、–itr这些操作,itr+1、map.begin()+1这类操作是非法的。
因此,我们想要写一个:
for(auto itr = time_jobMap.begin();itr < time_jobMap.end()-1;itr++)
{
(itr + 1)->first = ...
}
愿望落空了。
最后,因为迭代器的特性,我们找到了如下的实现方法:
int counter = time_jobMap.size()-1;
auto it = time_jobMap.begin();
while (counter>0)
{
int time1 = it->first;
int jobNum1 = it->second;
it++;
int time2 = it->first;
int jobNum2 = it->second;
counter--;
float timeInterval = time2 - time1;
float jobDifference = abs(jobNum2 - jobNum1);
cout<< (jobDifference / timeInterval) <<endl;
}
以上,map相邻元素两两操作的功能就实现了。