Shoping(map)
ACM之map
- 關(guān)于map:
- hash_map
- 默認(rèn)hash 和比較函數(shù)
- hash_map 的比較函數(shù)
- hash_map(size_type n)
- map與hash_map
- 題目:
- 我的代碼:
關(guān)于map:
map的特性是,所有元素都會(huì)根據(jù)元素的減值自動(dòng)被排序。 map的所有元素都是pair,同時(shí)擁有實(shí)值(value)和鍵值(key)。
pair的第一個(gè)元素會(huì)被視為鍵值,第二個(gè)元素會(huì)被視為實(shí)值。 map不允許兩個(gè)元素?fù)碛邢嗤逆I值。
key值不可修改!
map中插入元素:
注意后加入的在 begin一側(cè),即后入的排在前面;
可利用rbegin 和 rend 反轉(zhuǎn)輸出,得到正確的順序
begin() 返回指向map頭部的迭代器
end() 返回指向map末尾的迭代器
clear() 刪除所有元素
count() 返回指定元素出現(xiàn)的次
empty() 如果map為空則返回true
erase() 刪除一個(gè)元素
find() 查找一個(gè)元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比較元素key的函數(shù)
lower_bound() 返回鍵值>=給定元素的第一個(gè)位置
max_size() 返回可以容納的最大元素個(gè)數(shù)
rbegin() 返回一個(gè)指向map尾部的逆向迭代器
rend() 返回一個(gè)指向map頭部的逆向迭代器
size() 返回map中元素的個(gè)數(shù)
swap() 交換兩個(gè)map
upper_bound() 返回鍵值>給定元素的第一個(gè)位置
value_comp() 返回比較元素value的函數(shù)
hash_map
hash_map是基于hash table(哈希表)。
哈希表最大的優(yōu)點(diǎn),就是把數(shù)據(jù)的存儲(chǔ)和查找消耗的時(shí)間大大降低,幾乎可以看成是常數(shù)時(shí)間;而代價(jià)僅僅是消耗比較多的內(nèi)存。然而在當(dāng)前可利用內(nèi)存越來越多的情況下,用空間換時(shí)間的做法是值得的。另外,編碼比較容易也是它的特點(diǎn)之一。
基本原理:使用一個(gè)下標(biāo)范圍比較大的數(shù)組來存儲(chǔ)元素。可以設(shè)計(jì)一個(gè)函數(shù)(哈希函數(shù),也叫做散列函數(shù)),使得每個(gè)元素的關(guān)鍵字都與一個(gè)函數(shù)值(即數(shù)組下標(biāo),hash值)相對(duì)應(yīng),于是用這個(gè)數(shù)組單元來存儲(chǔ)這個(gè)元素;也可以簡(jiǎn)單的理解為,按照關(guān)鍵字為每一個(gè)元素“分類”,然后將這個(gè)元素存儲(chǔ)在相應(yīng)“類”所對(duì)應(yīng)的地方,稱為桶。
不能夠保證每個(gè)元素的關(guān)鍵字與函數(shù)值是一一對(duì)應(yīng)的,因此極有可能出現(xiàn)對(duì)于不同的元素,卻計(jì)算出了相同的函數(shù)值,這樣就產(chǎn)生了“碰撞” —— 把不同的元素分在了相同的桶之中
hash_map,首先分配一大片內(nèi)存,形成許多桶。是利用hash函數(shù),對(duì)key進(jìn)行映射到不同區(qū)域(桶)進(jìn)行保存
插入過程:
得到key
利用hash函數(shù)得到hash值
得到桶值(一般用hash值對(duì)桶的個(gè)數(shù)求余)
存放key和value在桶內(nèi)
取值過程:
得到key值
計(jì)算hash值
得到桶號(hào)
查找該桶內(nèi)是否有和key值相同的,若無,則未找到(比較函數(shù))
若有,返回找到的值
默認(rèn)hash 和比較函數(shù)
#include<iostream> using namespace std; #include<hash_map> #include<string>hash_map<int,string> myHash; myHash[100] = "100"; myHash[900] = "900";hash_map::iterator iter =myHash.find(100); if(iter != myHash.end()) ..... //未聲明hash函數(shù)和比較函數(shù)的,將使用默認(rèn)的; hash_map<int, string> myMap; //等同于: hash_map<int, string, hash<int>, equal_to<int> > myMap; struct hash<int> {size_t operator()(int __x) const { return __x; } };key值只要是下列的類型,就可以不寫hash函數(shù)
struct hash<char*> struct hash<const char*> struct hash<char> struct hash<unsigned char> struct hash<signed char> struct hash<short> struct hash<unsigned short> struct hash<int> struct hash<unsigned int> struct hash<long> struct hash<unsigned long>若沒有則必須自定義hash函數(shù),如string類
struct str_hash{size_t operator()(const string& str) const{unsigned long __h = 0;for (size_t i = 0 ; i < str.size() ; i ++)__h = 5*__h + str[i];return size_t(__h);} }; //如果你希望利用系統(tǒng)定義的字符串hash函數(shù),你可以這樣寫: struct str_hash{size_t operator()(const string& str) const{return __stl_hash_string(str.c_str());} };在聲明自己的哈希函數(shù)時(shí)要注意以下幾點(diǎn):
使用struct,然后重載operator().
返回是size_t
參數(shù)是你要hash的key的類型。
函數(shù)是const類型的。
hash_map 的比較函數(shù)
在map中的比較函數(shù),需要提供less函數(shù)。
如果沒有提供,缺省的也是less< Key>
在hash_map中,要比較桶內(nèi)的數(shù)據(jù)和key是否相等,因此需要的是是否等于的函數(shù):equal_to< Key> 。
equal_to 源碼:
若是自定義的類型,則需要自己構(gòu)建compare函數(shù):
使用equal_to< mystruct>作為比較函數(shù)
struct mystruct{int myID;int value;bool operater== (const mystruct &my) const{return (myId == my.myID) && (value == my.value);}};實(shí)現(xiàn):
hash_map(mystruct,int,hash_str,equal_to<mystruct>) myHash;構(gòu)建函數(shù)對(duì)象
struct compare_str{bool operature()(const char* p1, const char* p2) const{return strcmp(p1,p2)==0;}};實(shí)現(xiàn):
hash_map(const char*,string,hash<char*>, compare_str);hash_map(size_type n)
如果講究效率,這個(gè)參數(shù)是必須要設(shè)置的。
n 主要用來設(shè)置hash_map容器中hash桶的個(gè)數(shù)。桶個(gè)數(shù)越多,hash函數(shù)發(fā)生沖突的概率就越小,重新申請(qǐng)內(nèi)存的概率就越小。
n越大,效率越高,但是內(nèi)存消耗也越大。
const_iterator find(const key_type& k) const. 用查找,輸入為鍵值,返回為迭代器。
data_type& operator[](const key_type& k)
像使用數(shù)組一樣使用。
不過需要注意的是,當(dāng)你使用[key]操作符時(shí),如果容器中沒有key元素,這就相當(dāng)于自動(dòng)增加了一個(gè)key元素。因此當(dāng)你只是想知道容器中是否有key元素時(shí),你可以使用find。如果你希望插入該元素時(shí),你可以直接使用[ ]操作符。
insert
在容器中不包含key值時(shí),insert函數(shù)和[]操作符的功能差不多。但是當(dāng)容器中元素越來越多,每個(gè)桶中的元素會(huì)增加,為了保證效率,hash_map會(huì)自動(dòng)申請(qǐng)更大的內(nèi)存,以生成更多的桶。
因此在insert以后,以前的iterator有可能是不可用的
erase 函數(shù)。
在insert的過程中,當(dāng)每個(gè)桶的元素太多時(shí),hash_map可能會(huì)自動(dòng)擴(kuò)充容器的內(nèi)存。
erase并不自動(dòng)回收內(nèi)存。因此你調(diào)用erase后,其他元素的iterator還是可用的。
map與hash_map
構(gòu)造函數(shù)。hash_map需要hash函數(shù),等于函數(shù);map只需要比較函數(shù)(小于函數(shù)).
存儲(chǔ)結(jié)構(gòu)。hash_map采用hash表存儲(chǔ),map一般采用紅黑樹(RB Tree)實(shí)現(xiàn)。因此其memory數(shù)據(jù)結(jié)構(gòu)是不一樣的。
總體來說,hash_map 查找速度會(huì)比map快,而且查找速度基本和數(shù)據(jù)數(shù)據(jù)量大小,屬于常數(shù)級(jí)別;而map的查找速度是log(n)級(jí)別。并不一定常數(shù)就比log(n)小,hash還有hash函數(shù)的耗時(shí),明白了吧,如果你考慮效率,特別是在元素達(dá)到一定數(shù)量級(jí)時(shí),考慮考慮hash_map。但若你對(duì)內(nèi)存使用特別嚴(yán)格,希望程序盡可能少消耗內(nèi)存,那么一定要小心,hash_map可能會(huì)讓你陷入尷尬,特別是當(dāng)你的hash_map對(duì)象特別多時(shí),你就更無法控制了,而且hash_map的構(gòu)造速度較慢。
#include <hash_map> #include <string> #include <iostream>using namespace std; //define the class class ClassA{public:ClassA(int a):c_a(a){}int getvalue()const { return c_a;}void setvalue(int a){c_a;}private:int c_a; };//1 define the hash function struct hash_A{size_t operator()(const class ClassA & A)const{// return hash<int>(classA.getvalue());return A.getvalue();} };//2 define the equal function struct equal_A{bool operator()(const class ClassA & a1, const class ClassA & a2)const{return a1.getvalue() == a2.getvalue();} };int main() {hash_map<ClassA, string, hash_A, equal_A> hmap;ClassA a1(12);hmap[a1]="I am 12";ClassA a2(198877);hmap[a2]="I am 198877";cout<<hmap[a1]<<endl;cout<<hmap[a2]<<endl;return 0; } -bash-2.05b$ make my c++ -O -pipe -march=pentiumpro my.cpp -o my -bash-2.05b$ ./my I am 12 I am 198877題目:
Shopping
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6924 Accepted Submission(s): 2438
Problem Description
Every girl likes shopping,so does dandelion.Now she finds the shop is increasing the price every day because the Spring Festival is coming .She is fond of a shop which is called “memory”. Now she wants to know the rank of this shop’s price after the change of everyday.
Input
One line contians a number n ( n<=10000),stands for the number of shops.
Then n lines ,each line contains a string (the length is short than 31 and only contains lowercase letters and capital letters.)stands for the name of the shop.
Then a line contians a number m (1<=m<=50),stands for the days .
Then m parts , every parts contians n lines , each line contians a number s and a string p ,stands for this day ,the shop p 's price has increased s.
Output
Contains m lines ,In the ith line print a number of the shop “memory” ‘s rank after the ith day. We define the rank as :If there are t shops’ price is higher than the “memory” , than its rank is t+1.
Sample Input
3
memory
kfc
wind
2
49 memory
49 kfc
48 wind
80 kfc
85 wind
83 memory
Sample Output
1
2
我的代碼:
#include <bits/stdc++.h>using namespace std;int main() {int n, m, p;map< string, int> shop;while(cin>>n){string s; //僅用于輸入商店名字for(int i=1; i<=n; i++)cin>>s;cin>>m;while(m--){for(int i=1; i<=n; i++){cin>>p>>s;shop[s] += p;}int rank = 1; //排名map<string,int>::iterator it;for(it = shop.begin(); it != shop.end(); it++)if(it->second > shop["memory"])rank++;cout<<rank<<endl;}shop.clear();}return 0; }總結(jié)
以上是生活随笔為你收集整理的Shoping(map)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么弄c币
- 下一篇: 岗位竞聘机制如何引入?