搜狗面试的经典题(C++map按值排序,class struct的区别)

一:起因

(1)java  Map排序(key,value),请看另一篇博客 java Map排序 

(2)c++ map排序(key,value),可以对c++ map和java Map进行对比:之一,c++的map默认按照key值进行排序,而且就是map了;java Map HashMap是随

的,不进行排序的。之二,c++声明对象直接Map map(^)的,不用= new的

(3)c++ 按value值排序,map是不能直接排序的,它虽然也是一个数据集合,第一反应是利用stl中提供的sort算法实现,这个想法是好的,不幸的是,sort算法有个限制,利用sort算法只能对序列容器进行排序,就是线性的(如vector,list,deque)map也是一个集合容器,但是它里面存储的元素是pair,它不是线性存储的(前面提过,像红黑树),所以利用sort不能直接和map结合进行排序。

(4)  main函数中也可以实现函数重载,例如下面的 ostream& operator<<(ostream& out, const PAIR& p);还有就是定义的struct类(类似于class的)官方的说明见  (四)

(5) 按照value值进行排序:把值定义为一个结构体,包括你原本的值元素,还有键的值,  这样当你要按照值排序的时候,把map的值也就是结构体放

进vector中,剩下的按照你原来的值进行排序就行了。

这样是不行的,因为key是确定的,而value是可以改动的     如果按value自动排序的话map会变得极不稳定。你想,如果每次改变value整个map都要重新

排序的话不是性能损耗会很大吗?所以当初压根就没设计按照value排序的功能


二:代码实现

(1)先看pair类

template <class T1, class T2> struct pair  
{  
	 typedef T1 first_type;  
	 typedef T2 second_type;    
	 T1 first;  
	 T2 second;  
	 pair() : first(T1()), second(T2()) {}  
	pair(const T1& x, const T2& y) : first(x), second(y) {}  
	template <class U, class V>  
    pair (const pair<U,V> &p) : first(p.first), second(p.second) { }  
}
pair也是一个模板类,这样就实现了良好的通用性。它仅有两个数据成员firstsecond,即 key value,而且

(2)再看sort类

template <class RandomAccessIterator>  
void sort ( RandomAccessIterator first, RandomAccessIterator last );  
	  
template <class RandomAccessIterator, class Compare>  
void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp ); 

我们看到,令人兴奋的是,sort算法和map一样,也可以让我们指定元素间如何进行比较,即指定Compare

(3)完整代码

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

typedef pair<string, int> PAIR;
// 原来还可以这样的重载的(⊙o⊙)哦,长见识了
ostream& operator<<(ostream& out, const PAIR& p)
{
    return out << p.first << "\t" << p.second;
}
template<class T1>
struct compareByKeyLen
{// 从短到长
    bool operator()(const T1 &s1,const T1 &s2)
    {
        return s1.length()<=s2.length()?true:false;// 记得有等号的哦,否则,长度相等的就舍去了
    }
};
template<class T1>
struct compareByValue
{
    bool operator()(const T1 &lhs, const T1 &rhs)
    {
        return lhs.second<=rhs.second ? true:false;
    }
};

int main()
{
    //map<string, int> name_score_map;//字典的顺序,从小到大
    //默认的是map<string,int,less<string>>

    //map<string, int, greater<string> > name_score_map;// 注意> >有空格的,否则cin>>了;
    //字典的逆序,从大到小

    //map<string, int, compareByKeyLen<string> > name_score_map;
    // 自己写的compareByKeyLen<>结构体

    map<string, int> name_score_map;

    name_score_map["ZhaoBo2"] = 90;
    name_score_map["XuQingzhu"] = 79;
    name_score_map["LiBing"] = 92;
    name_score_map.insert(make_pair("ChiXiaotong",99));
    name_score_map.insert(make_pair("WangZhaoxian",86));

    vector<PAIR> name_score_vec(name_score_map.begin(),name_score_map.end());
    sort(name_score_vec.begin(),name_score_vec.end(),compareByValue<PAIR>());
    for(int i=0;i<name_score_vec.size();i++)
    {
        cout << name_score_vec[i] << endl;
    }
//    for (map<string, int>::iterator iter = name_score_map.begin();
//               iter != name_score_map.end();++iter)
//    {
//       cout << *iter << endl;
//    }
    return 0;
}
(4)运行结果:



三:按key值排序(c++ map 带有比较类的,这和java一样,java也带有类似的比较类)

(1)compare类自己定义

比如,按照学生姓名的长短排序进行存储,那该怎么做呢?

其实很简单,只要我们自己写一个函数对象,实现想要的逻辑,定义map的时候把Compare指定为我们自己编写的这个就ok啦。

template<class T1>
struct compareByKeyLen
{// 从短到长
    bool operator()(const T1 &s1,const T1 &s2)
    {
        return s1.length()<=s2.length()?true:false;// 记得有等号的哦,否则,长度相等的就舍去了
    }
};

是不是很简单!这里我们不用把它定义为模板,直接指定它的参数为string类型就可以了。

(2)参考代码

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

typedef pair<string, int> PAIR;
// 原来还可以这样的重载的(⊙o⊙)哦,长见识了
ostream& operator<<(ostream& out, const PAIR& p)
{
    return out << p.first << "\t" << p.second;
}
template<class T1>
struct compareByKeyLen
{// 从短到长
    bool operator()(const T1 &s1,const T1 &s2)
    {
        return s1.length()<=s2.length()?true:false;// 记得有等号的哦,否则,长度相等的就舍去了
    }
};
int main()
{
    //map<string, int> name_score_map;//字典的顺序,从小到大
    //默认的是map<string,int,less<string>>

    //map<string, int, greater<string> > name_score_map;// 注意> >有空格的,否则cin>>了;
    //字典的逆序,从大到小
    map<string, int, compareByKeyLen > name_score_map;
    name_score_map["ZhaoBo"] = 90;
    name_score_map["XuQingzhu"] = 79;
    name_score_map["LiBing"] = 92;
    name_score_map.insert(make_pair("ChiXiaotong",99));
    name_score_map.insert(make_pair("WangZhaoxian",86));
    for (map<string, int>::iterator iter = name_score_map.begin();
               iter != name_score_map.end();++iter)
    {
       cout << *iter << endl;
    }
    return 0;
}

(3)运行结果


这一点有点类似javamap但是还是不一样的,感觉java倒是麻烦一些了。


四:从语法上,在C++中(只讨论C++中)。class和struct做类型定义时只有两点区别

从语法上,在C++中(只讨论C++中)。class和struct做类型定义时只有两点区别:

(一)默认继承权限。如果不明确指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理;

(二)成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。

除了这两点,class和struct基本就是一个东西。语法上没有任何其它区别。

不能因为学过C就总觉得连C++中struct和class都区别很大,下面列举的说明可能比较无聊,因为struct和class本来就是基本一样的东西,无需多说。但这些说

明可能有助于澄清一些常见的关于struct和class的错误认识:

(1)都可以有成员函数;包括各类构造函数,析构函数,重载的运算符,友元类,友元结构,友元函数,虚函数,纯虚函数,静态函数;

(2)都可以有一大堆public/private/protected修饰符在里边;

(3)虽然这种风格不再被提倡,但语法上二者都可以使用大括号的方式初始化:Aa={1,2,3};不管A是个struct还是个class,前提是这个类/结构足够简单,比如所有的成员都是public的,所有的成员都是简单类型,没有显式声明的构造函数。

(4)都可以进行复杂的继承甚至多重继承,一个struct可以继承自一个class,反之亦可;一个struct可以同时继承5个class和5个struct,虽然这样做不太好。

(5)如果说class的设计需要注意OO的原则和风格,那么没任何理由说设计struct就不需要注意。

(6)再次说明,以上所有说法都是指在C++语言中,至于在C里的情况,C里是根本没有“class”,而C的struct从根本上也只是个包装数据的语法机制。
最后,作为语言的两个关键字,除去定义类型时有上述区别之外,另外还有一点点:“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。


  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值