对map的value进行排序的方法

对map的value进行排序的方法,注意思路,以及CMPBYVALUE的用法
<h1 class="title" style="margin: 10px 0px; font-family: 'lucida grande', 'lucida sans unicode', lucida, helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 1.5; color: rgb(85, 85, 85); text-rendering: optimizelegibility; font-size: 32px; word-break: break-all;">map按键排序和按值排序</h1><div class="show-content" style="color: rgb(47, 47, 47); font-size: 16px; line-height: 1.7; font-family: 'lucida grande', 'lucida sans unicode', lucida, helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif;"><p style="margin-top: 0px; margin-bottom: 25px; text-align: justify; word-break: break-word;">前几天做了一个关于字符串的题,题目要求寻找一个字符串中出现最多的子串是哪一个,没想到什么很有技巧的想法,于是就打算遍历所有的子串,利用一个map实现,其键值为对应的子串,value为子串出现的个数,遍历玩所有的子串后,只要寻找最大的value的键值就可以了,这里就想到一个问题,map一般是按键排序,能否按value排序?</p><p style="margin-top: 0px; margin-bottom: 25px; text-align: justify; word-break: break-word;">首先给出上述题目的一个解法,然后再继续讨论:map按键排序和按值排序的问题。如下所示,map查询采用find不要直接查询(find要是没找到则返回MAP.end()),否则会将map中不存在的键值直接插入。</p><pre class="hljs cpp" style="padding: 9.5px; font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; font-size: 13px; color: rgb(101, 123, 131); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 20px; line-height: 20px; word-break: break-all; word-wrap: normal; background-color: rgb(253, 246, 227); border: 1px solid rgba(0, 0, 0, 0.14902); overflow: auto;"><code class="cpp" style="padding: 0px; font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; font-size: 12px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: transparent; border: none;"><span class="hljs-function"><span class="hljs-keyword" style="color: rgb(133, 153, 0);">void</span> <span class="hljs-title" style="color: rgb(38, 139, 210);">substrCount</span><span class="hljs-params">(<span class="hljs-built_in" style="color: rgb(38, 139, 210);">string</span> str)</span>
</span>{
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">map</span><<span class="hljs-built_in" style="color: rgb(38, 139, 210);">string</span>,<span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span>> substr;
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">string</span> subs;
    <span class="hljs-keyword" style="color: rgb(133, 153, 0);">for</span>(<span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span> i =<span class="hljs-number" style="color: rgb(42, 161, 152);">1</span>; i<str.size();i++)
        <span class="hljs-keyword" style="color: rgb(133, 153, 0);">for</span>(<span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span> j =<span class="hljs-number" style="color: rgb(42, 161, 152);">0</span>; j<=str.size()-i;j++)
        {
            subs = str.substr(j,i);                    <span class="hljs-comment" style="color: rgb(147, 161, 161);">//遍历每一个子串</span>
            <span class="hljs-keyword" style="color: rgb(133, 153, 0);">if</span>(substr.find(subs)==substr.end())        <span class="hljs-comment" style="color: rgb(147, 161, 161);">//判断map中是否存在,存在则+1,不存在则插入</span>
                substr[subs] = <span class="hljs-number" style="color: rgb(42, 161, 152);">1</span>;
            <span class="hljs-keyword" style="color: rgb(133, 153, 0);">else</span>
                substr[subs] = substr[subs]+<span class="hljs-number" style="color: rgb(42, 161, 152);">1</span>;
        }

    pair<<span class="hljs-built_in" style="color: rgb(38, 139, 210);">string</span>, <span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span>> maxpair = *(substr.begin());     <span class="hljs-comment" style="color: rgb(147, 161, 161);">//寻找出现次数最多的子串</span>
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">map</span><<span class="hljs-built_in" style="color: rgb(38, 139, 210);">string</span>,<span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span>>::iterator it = substr.begin();
    <span class="hljs-keyword" style="color: rgb(133, 153, 0);">while</span>(it!=substr.end())
    {
        <span class="hljs-keyword" style="color: rgb(133, 153, 0);">if</span>(it->second >maxpair.second )
            maxpair = *it;
    }
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">cout</span><<maxpair.first<<endl;
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">cout</span><<maxpair.second<<endl;
}</code>


map按键排序和按值排序的问题内容来自C++ STL中Map的按Key排序和按Value排序

按键排序
  • 为了实现快速查找,map内部本身就是按序存储的(比如红黑树)。在我们插入<key, value>键值对时,就会按照key的大小顺序进行存储,其中key的类型必须能够进行<运算,且唯一,默认排序是按照从小到大便利记忆联想到需要支持小于运算
  • map的模板定义如下
    template < class Key, class T, class Compare = less<Key>,
             class Allocator = allocator<pair<const Key,T> > > class map;

    其中第三、四个均包含默认参数,可以不指定。我们可以通过指定Compare类来指定排序的顺序。其中less<Key>是stl里面的一个函数对象(即调用操作符的类,其对象常称为函数对象(function object),它们是行为类似函数的对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个 类,其实质是对operator()操作符的重载)其具体定义如下

    template <class T> struct less : binary_function <T,T,bool> {
    bool operator() (const T& x, const T& y) const
      {return x<y;}
    };

    它是一个带模板的struct,里面仅仅对()运算符进行了重载。与less相对的有greater,定义如下

    template <class T> struct greater : binary_function <T,T,bool> {
    bool operator() (const T& x, const T& y) const
      {return x>y;}
    };
  • 因此我们在定义map的时候,可以指定如下
    map<string,int,greater<string> >

    或者定义自己的比较类comLen如下

    struct comLen{
       bool operator(const string &lhs, const string &rhs)
       {return lhs.length()<rhs.length();}
    }
    map<string,int,comLen> LenLessMap;
按value排序
  • 如何实现Map的按Value排序呢?

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

  • 迂回一下,把map中的元素放到序列容器(如vector)中,然后再对这些元素进行排序。要对序列容器中的元素进行排序,也有个必要条件:就是容器中的元素必须是可比较的,也就是实现了<操作的。
  • map是元素为pair,其已实现<操作符的重载
    template<class T1, class T2>
    inline bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y)
    { return x.first < y.first   || (!(y.first < x.first) && x.second < y.second); }
    • x.first < y.first指键值小于的情况
    • (!(y.first < x.first) && x.second < y.second);结合前面的情况指键相等的情形下value的情况
    • 为什么不直接写 x.first == y.first 呢? 前面讲过,作为map的key必须实现<操作符的重载,但是并不保证==符也被重载了。
  • 但上述的<操作过程不太符合我们的要求,从sort角度考虑,其定义如下
    template <class RandomAccessIterator>
    void sort ( RandomAccessIterator first, RandomAccessIterator last );
    template <class RandomAccessIterator, class Compare>
    void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );

    与map一样均可以指定比较的类。可以定义如下的比较的类或者对象

    class combyValue
    {
       bool operator()(pair<string,int> &lhs,pair<string,int> &rhs)
       {return lhs.second<rhs.second;}
    }
  • 最后可以如下实现按照value排序
    map<string,int> m;
    元素插入过程
    vector<pair<string,int> > vec(m.begin(),m.end());
    sort(vec.begin(),vec.end(),combyValue);


因此最开始的那道题如果需要排序的话可以按如下方式写

struct CmpByValue {
  bool operator()(const pair<string,int> & lhs, const pair<string,int> & rhs)
  {return lhs.second > rhs.second;}
};

void substrcount(string str)
{
    map<string,int> substr;
    string subs;
    for(int i =1; i<str.size();i++)
        for(int j =0; j<=str.size()-i;j++)
        {
            subs = str.substr(j,i);
            if(substr.find(subs)==substr.end())
                substr[subs] = 1;
            else
                substr[subs] = substr[subs]+1;
        }

    vector<pair<string,int>> counts(substr.begin(),substr.end());
    sort(counts.begin(),counts.end(),CmpByValue());
    cout<<counts.begin()->first<<endl;
    cout<<counts.begin()->second<<endl;
}

我自己的代码实现!
static map<int ,int> mapwords;
void main()
{

	vector<string> info;
	bool MeorCh=true;   //设置统计公式还是中文
	FILE *fpstatic = fopen("count.txt","w");
	char *dat="answer";
	const char *QuestionId = "045176078D274A3A9CC7E5437FCFB95B" ;
	char *title="liang";
	int size=111;

	//size = ReadFile("E:\\梁栋凯\\countstestdata\\045176078D274A3A9CC7E5437FCFB95B.dat",dat);
	//cout<<"ReadFile: "<<size<<endl;

	//size = ReadAnswerFile("E:\\梁栋凯\\countstestdata",QuestionId,title,info) ;
 //   cout<<"ReadAnswerFile: "<<size;

	//int flag=ReadAnswerFile("E:\\梁栋凯\\countstestdata",QuestionId , &answer);
	//if(flag==0)cout<<"读取成功!" <<endl;

	//连续读取文件

	vector<string> files;
//  const char *pTag = ".dat";

    getFiles("E:\\梁栋凯\\countstestdata\\", files );
	std::string datFileName;

	//string dir=files[0].substr(0,25);
	//string ID=files[0].substr(25,files[0].size()-29);
	int i=0;
	if(i<12220)
	{
		QUESTIONANSWER answer1;
		for(i=0;i<files.size()&&i<=12220;i++)
		{
			string temp=files[i];
			string dir=files[i].substr(0,25);
			//路径长度+4
			string ID=files[i].substr(25,files[i].size()-29);

		    const char *sdir=dir.c_str();
		    const char *AnswerID=ID.c_str();

			int flag=ReadAnswerFile("E:\\梁栋凯\\countstestdata\\", AnswerID, &answer1);

		    if(flag==0)cout<<"读取"<<i<<"文件成功!" <<endl;
		}
		int flag1 = CountWords(answer1,MeorCh);

	}

	if(i>12220&&i<files.size())
	{
		QUESTIONANSWER answer2;
	   for(;i<files.size();i++)
		{
			string temp=files[i];
			string dir=files[i].substr(0,25);
			//路径长度+4
			string ID=files[i].substr(25,files[i].size()-29);

		    const char *sdir=dir.c_str();
		    const char *AnswerID=ID.c_str();

			int flag=ReadAnswerFile("E:\\梁栋凯\\countstestdata\\", AnswerID, &answer2);

		    if(flag==0)cout<<"读取"<<i<<"文件成功!" <<endl;
		}
		int flag1 = CountWords(answer2,MeorCh);

	}

	////统计字符出现的频率
	//int flag1 = CountWords(answer,MeorCh); 

struct CmpByValue {
  bool operator()(const pair<int,int> & lhs, const pair<int,int> & rhs)
  {return lhs.second > rhs.second;}
};
	//转存map到vector
	vector<pair<int,int> > vec(mapwords.begin() , mapwords.end());
	//排序
	cout<<"sort vector start!"<<endl;
	sort(vec.begin(),vec.end(),CmpByValue());

	for(int i=0; i<vec.size();i++)
	{
		fprintf(fpstatic, "%d,   %d\n", vec[i].first,vec[i].second );
		cout<<vec[i].first<<", "<<vec[i].second<<endl;
	}

	//

 //
	//map<int, int>::iterator iter ;

 //   for(iter = mapwords.begin(); iter != mapwords.end(); ++iter)
 //   {
	//	fprintf(fpstatic, "%d,   %d\n", iter->first,iter->second );
 //       cout << iter->first << "     "
 //            << iter->second << endl;
 //   }

}

int CountWords(QUESTIONANSWER answer , bool MeorCh )
{
	bool MethorCh = MeorCh;
	if(MethorCh){
		for(unsigned int i = 0; i < answer.gramMe.size(); i++)
		{
			mapwords[answer.gramMe[i]]++;
		}
	}
	else
	{
		for(unsigned int i = 0; i < answer.gramCh.size(); i++)
		{
			mapwords[answer.gramCh[i]]++;
		}
	}
	return 1;
}

时间: 2024-08-08 01:28:50

对map的value进行排序的方法的相关文章

C++ STL中Map的按Key排序和按Value排序

原文  http://blog.csdn.net/iicy266/article/details/11906189 map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择. 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key:该学生的成绩用int类型,作为value.这样一来,我们可以根据学

C++ STL中Map的按Key排序跟按Value排序(转)

C++ STL中Map的按Key排序和按Value排序 map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区 分),我们用map来进行存储就是个不错的选择. 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key:该学生的成绩用int类型,作为value.这样一来,我们可以根据学生姓名快速的查找到 他的成绩. 但是,我们除了希望能够查询

Java8-2-Lambda表达式实战-一句话实现Map中按照Value排序

今天我们来实战一把, 对Map的Value值排序进行简化. 在以前的思路我们的做法如下: /** Map根据value排序; @param map @return*/public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {List<Map.Entry<K, V>> list = new LinkedList<

关于自定义 List集合排序的方法!

大致流程: 排序是用到排序的接口Comparator<T>你要先建一个类实现比较器Comparator //大致流程public class StuComp implements Comparator<Student> { public int compare(Student o1, Student o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } } 然后在Collections.sort(list);的

【工作中学习2】Map的使用及排序(第三个参数)

项目进行中,使用到Map(std::map),Map要点整理如下: 1. Map,也叫关联数组,提供key/value(键/值对),key用来索引,value是被存储和检索的数据. 2. key值唯一(Multimap除外). 3. Map的内部数据结构是红黑树. 3. 可以用下标操作符,添加Map中的数据,例如map[1] = 2;,用下标操作符查找数据时,如果数据不存在,会被自动插入到Map中. 4. Map中的数据默认按照由key从小到大排序(less),可以修改第三个参数(可选)来修改排

List对象排序通用方法

在数据库中查出来的列表list中,往往需要对不同的字段重新排序,一般的做法都是使用排序的字段,重新到数据库中查询.如果不到数据库查询,直接在第一次查出来的list中排序,无疑会提高系统的性能. 只要把第一次查出来的结果存放在session中,就可以对list重新排序了.一般对list排序可以使用Collections.sort(list),但如果list中包含是一个对象的话,这种方法还是行不通的.那要怎么排序呢?如果有一个UserInfo对象,包含如下字段: private java.lang.

Excel碰到空行无法筛选排序解决方法

Excel碰到空行无法筛选排序解决方法 有时候excel可真心考人智商,一列中有空行,那么你就只能筛选排序首个空行前的内容了,解决方法来了,做个小记录,以防今后忘了. 1.在首列插入一列: 2.全选该列输入1,使用快捷键"Ctrl+回车键"填充整列: 3.选择首行,点击"数据-->筛选-->自动筛选",现在可以全部筛选及排序了 Excel碰到空行无法筛选排序解决方法,布布扣,bubuko.com

实现jsp页面两级列表的显示(Map 传值到Jsp 页面;Map去key 和 value 的方法; 实例记载,备不时之需。

Action: List.vm 页面效果: 实现jsp页面两级列表的显示(Map 传值到Jsp 页面;Map去key 和 value 的方法: 实例记载,备不时之需.

Oracle中中文、数字,英文混杂形式的字段进行排序的方法

http://blog.csdn.net/p451933505/article/details/9272257 对Oracle中中文.数字.英文混杂形式的字段进行排序的方法: 例如: order by NLSSORT(字段名,'NLS_SORT = SCHINESE_PINYIN_M'), to_number(translate(字段名, '0123456789' || 字段名, '0123456789')) NLSSORT() 函数: 可以使用NLSSORT()函数可以改变Oralce 对汉字