接上次的题目,这是考试的第二题
第一题在这里:项目题目1——字符串相关操作-CSDN博客
数据结构与算法(多键值排序)
无线基站邻区关系缓存表维护
无线通信移动性需要在基站上配置邻区(本端基站的小区LocalCell与周边邻基站的小区NeighborCell映射)关系,为了能够加速无线算法的计算效率,设计一个邻区关系缓存表,用于快速地通过本小区LocalCell查询到邻小区NeighborCell。但是缓存表有一定的规格限制,因此到达规格并且需要插入新的数据时,需要删除邻区数据,选择删除邻区数据对象的策略为:
1)使用次数最少的;
2)如果1)返回有多个对象,则选择最久未使用的。
请设计并实现一个满足以上要求的数据结构和算法实现
输入
1.首行以字符“capacity:”标识设置一个整数容量;
2.以“write:”标识开始进行若干组[LocalCell,NeighborCell]邻区数据的输入,每组数据为一行;如果“write:”已经存在的LocalCell数据,更新其对应的NeighborCell,并刷新使用时间和次数+1;如果某邻区数据被删除,缓存表不再保留其记录;
3.以“read:”标识进行一次读取LocalCell的使用操作,刷新使用时间和次数+1;
4.最后以“query:”标识查询输出操作,输入正整数LocalCell,查询NeighborCell;
注:
1)写入和读取都表示对LocalCell的使用操作;
2)capacity、LocalCell和NeighborCell都是正整数,范围在[1,10000];
3)输入的总行数不超过30000行。
输出
每个查询输入正整数LocalCell对应NeighborCell,表示在邻区关系缓存表中的记录。
1.找到,返回NeighborCell;
2.没有找到,返回-1。
此次没有写其他函数,直接在主函数里面完成了操作
很神奇,这道题90行左右,代码量是第一题的1/3
数据结构
用vector,所谓的动态数组存储write:的值
(LocalCell、NeighborCell各一个数组,二者下标对应,同时操作)
这时,你肯定想问了,为啥不用map或者哈希表存储呢?
因为map是按序存放,哈希表随机存放;那么我对于进入的顺序就不得而知了,以及此题考查更新的位置,那还是用有序的数组比较合适。
map<int,int>cnt 存储localcell与其访问次数
比较值得推敲的是,在判断该删除哪个数据时候的操作,具体看write:中的操作;
read:就更新访问的数据在最新的位置(最后面)cnt记录++。
解题代码
#include<iostream>
#include<cstring>
#include <map>
#include<vector>
using namespace std;
int main() {
vector<int> localcell;
vector<int> neicell;
map<int,int> cnt;//记录localcell值以及访问次数
int capacity = 0;//容量初始化
int now = 0;//记录现在的容量 初始化为0
string str;//输入的值
while(1) {
cin>>str;
if(str=="capacity:") {
cin>>capacity;
}
else if(str=="write:"){
int tmp;
cin>>tmp;
int a,b;
for(int i=0;i<tmp;i++){
cin>>a;
cin>>b;
for(int j=0;j<localcell.size();j++){
if(a==localcell[j]){
localcell.erase(localcell.begin()+j);
neicell.erase(neicell.begin()+j);
now--;
break;
}
}
localcell.push_back(a) ;
neicell.push_back(b) ;
cnt[a]++;
}
now += tmp;
if(now>capacity){//输入的数据量大于容量的时候
//判断要删除的对象 1.访问次数(cnt)最少的情况 2.最久未更新
int need = now-capacity;//需要删除的元素个数
int er = localcell[0];//要删除元素的localcell值
while(need){
for(int i=1;i<now-tmp;i++) {
er = cnt[er] <= cnt[localcell[i]] ? er : localcell[i];
}
for(int i=0;i<localcell.size() ;i++){
if(localcell[i]==er){
localcell.erase(localcell.begin()+i);
neicell.erase(neicell.begin()+i);
}
}
cnt.erase(er);
need--;
now--;
}
}
}
else if(str=="read:"){
int num;
cin>>num;
for(int i=0;i<now;i++){//更新位置在最后面
if(localcell[i]==num){
cnt[num]++;//访问次数+1
localcell.erase(localcell.begin()+i);
localcell.push_back(num);
int a;
a = neicell[i];
neicell.erase(neicell.begin()+i);
neicell.push_back(a);
}
}
}
else if(str=="query:"){
int n;
int flag = 0;
cin>>n;
for(int i=0;i<now;i++){
if(localcell[i] == n){
cout<<neicell[i]<<endl;
flag = 1;
break;
}
}
if(flag == 0){
cout<<-1<<endl;
}
break;
}
}
return 0;
}
用例输入
样例1
输入:
capacity:
3
write:
3
1 2
4 3
2 3
read:
2
write:
1
3 1
query:
1输出:
-1
解释:
1.设定容量capacity为3;
2.write输入3组数据;
3.read读取2使用,刷新该邻区对使用时间和次数;
4.再write输入1组数据,因为已经超过了容量3,所以把最早输入且未使用的数据“1 2”去除;
5.最后进行query查询1,因为已经删除,所以返回-1。
样例2
输入:
capacity:
4
write:
5
3 5
1 2
4 3
2 3
5 4
read:
4
read:
1
read:
2
read:
5
write:
1
6 1
query:
1输出:
2
解释:
1.设定容量capacity为4;
2.write输入5组数据,因为容量为4,最早输入的数据“3 5”被删除;
3.read依次先后读取4、1、2、5,刷新该邻区对使用时间和次数;
4.再write输入1组数据,因为已经超过了容量4,需要选择删除邻区的数据对象,四组邻区对象使用次数一样,所以把最久未使用的数据“4 3”去除;
5.最后进行query查询1,返回2。
样例3
输入:
capacity:
3
write:
5
3 5
1 2
1 3
2 4
5 4
read:
5
write:
1
6 1
query:
1输出:
3
解释:
1.设定容量capacity为3;
2.write输入5组数据,其中“1 3”会把“1 2”替换掉,并更新访问次数;因为容量为3,最早数据“3 5”去除;
3.read读取5,刷新该邻区对使用时间和次数;
4.再write输入1组数据,因为已经超过了容量3,选择删除邻区数据对象,把最久未使用的数据“2 4”去除;
5.最后进行query查询1,返回3。
不知道具体操作的可以加上这段代码,输出对应值:
cout<<capacity<<' '<<"now="<<now<<endl;
for(int i=0;i<now;i++){
cout<<"localcell"<<i<<" = "<<localcell[i]<<endl;
cout<<"neicell"<<i<<" = "<<neicell[i]<<endl;
}
for(auto it = cnt.begin() ;it!=cnt.end() ;++it) {
cout<<"cnt"<<it->first<<" : "<<it->second<<endl;
}
例如样例3:
通过这道题,让我更加熟悉对map、vector的内置函数的使用,也需要注意循环break;的问题;
第二题考试时候完成用例87%,估计有什么神奇的用例没有考虑到;
不知道这次写好的能不能AC;
继续加油啦!