• hash_set和hash_map


    1.hash_set集合容器

    hash_set利用链式哈希表,进行数据的插入、删除和搜索。与set容器同样,不同意插入反复键值的元素。SGIC++哈希表是一个链式的结构,由表头和一系列单链组成。表头是一个数组式的线性表,用vector向量泛化出来。每一个表头节点,称为桶(bucket),是一个指针域,指向链入的元素数据。

    表头的长度为向量容器的元素个数。

    哈希表中数据的遍历。迭代器从0号桶、1号桶、2号桶。······,逐一遍历每一个桶中的全部元素数据。

    哈希表的数据检索,是通过哈希函数。计算出数据所存放的哈希地址。即算出数据在哪个桶的单链中,然后对单链中的每一个数据进行比較,检索出所要的数据。因此,每一个桶中的数据越少,比較的次数就越少,检索的效率越高。

    实际应用中,详细将多少数据存入哈希表中是无法预先确定的,能够设定初始的哈希表长。随着数据量的增长,动态调整表长的大小。表长过长。会造成表头空间的浪费;表长过短。会造成每一个桶下面链的元素过多。导致检索效率不高。为了使每一个桶中的元素尽可能地少,SGI C++使用质数作为表长,并且使用表长作为求余运算的模。构造哈希函数。SGI C++ STL中,用作表长的的质数预先用一个28个元素的数组给出。这28个质数足够覆盖32bit的随意表长范围。

     

    1.1创建hash_set对象

    主要有下面几种方式。

    (1)    hash_set()

    创建一个空的hash集合容器。哈希表长取默认值193,哈希函数对象为默认的hasn<Value>。键值比較有用默认的函数对象equal_to<Value>。内存分配器也取默认值。

    hash_set<int> hs;

    (2)    hash_set(size_type n)

    从质数列表中找出第一个大于等于n的质数作为表长,创建一个空的哈希集合容器。哈希函数对象、键值比較函数对象和内存分配器也取默认值。

    hash_set<int> hs(300);//创建一个表长为389的哈希集合容器对象

    (3)    hash_set(size_type n,consthasher&h)

    用大于等于n的质数作为表长,哈希函数对象为h,创建哈希集合容器对象。

    structmyHash{

    size_t operator()(int x)const{return x+2;}

    };

    hash_set<int,myHash> hs(300,myHash());

    (4)    hash_set(size_type n,consthasher&h,const key_equal&k)

    用大于等于n的质数作为表长。哈希函数对象为h。键值比較函数对象k。创建哈希集合容器对象。

    structstrEqual{

    bool operator()(const char *s1,const char*s2)const

    {

               return strcmp(s1,s2)==0;

    }

    };

    hash_set<char*,hash<char*>,strEqual>hash(300,hash<char*>(),strEqual());

     

    (5)    hash_set(const hash_set&)

    拷贝构造函数。

    hash_set<int> hs1;

    hash_set<int> hs2(hs1);

    1.2元素的插入

    使用insert函数进行插入,哈希集合容器不同意插入反复的元素键值,否则插入失败。

    hash_set<int> hs;

    hs.insert(31);

    hs.insert(23);

    hs.insert(193);

    1.3元素的删除

    利用eraseclear函数能够删除某个迭代器位置上的元素、等于某个键值的元素、迭代器区间元素和容器上的全部元素。

    1.4元素的遍历

    利用迭代器实现哈希集合容器内元素的遍历。

    #include <iostream>
    #include <hash_set>
    using stdext::hash_set;
    using namespace std;
    int main()
    {
    	hash_set<int> hs;
    	hs.insert(1);
    	hs.insert(23);
    	hs.insert(193);
    	hash_set<int>::iterator begin,end;
    	end=hs.end();
    	for(begin=hs.begin();begin!=end;begin++)
    	{
    		cout<<*begin<<endl;
    	}
    	system("pause");
    	return 0;
    }
    

    注意:在vs2008中使用hash_set须要用usingstdext::hash_set;由于hash_setvs2008的一个扩展,并没有在标准C++库中。

    1.5元素的搜素

    利用find函数能够实现元素的搜索。返回搜索到的元素的位置。

    #include <iostream>
    #include <hash_set>
    using stdext::hash_set;
    using namespace std;
    struct strEqual{
    	bool operator()(const char* s1,const char* s2)const{
    		return strcmp(s1,s2)==0;
    	}
    };
    int main()
    {
    	hash_set<char *,hash_set<char *>,strEqual> hs;
    	hs.insert("apple");
    	hs.insert("pear");
    	hs.insert("banana");
    	hs.insert("orange");
    	//搜索元素banana
    	hash_set<char*,hash_set<char*>,strEqual>::iterator i;
    	i=hs.find("banana");
    	cout<<"查找结果:"<<*i<<endl;
    	system("pause");
    	return 0;
    }
    


     

    1.6其它经常使用函数

    hash_set容器还有其它经常使用函数。emptysizebucket_countswapresizeequal_range等函数能够获得容器的统计信息。

    #include <iostream>
    #include <hash_set>
    using stdext::hash_set;
    using namespace std;
    
    int main()
    {
    	hash_set<int> hs;
    	hs.insert(10);
    	hs.insert(30);
    	hs.insert(100);
    	hs.insert(23);
    cout<<hs.empty()<<endl;//是否为空
    	cout<<hs.size()<<endl;//统计元素个数
    	cout<<hs.bucket_count()<<endl;//统计表长
    	system("pause");
    	return 0;
    }
    

     

     

     

    2.hash_map哈希映射容器

    hash_map容器与map容器相似,都是将记录型的元素依据键值的大小将其插入容器。可是,hash_map使用的数据结构是哈希表。map使用的数据结构是红黑树。

    hash_map检索出来的元素是无序的,而map用迭代器遍历出来的元素是排序的,并且还提供了反向迭代器。

    2.1创建hash_map对象

    主要有下面几种方式。

    (1)    hash_map()

    hash_map<int,char*> hm;

    (2)    hash_map(size_type n)

    hash_map<int,char*> hm(300);

    (3)    hash_map(size_type n,consthasher& h)

    struct myhash{

    size_t operator()(int x)const{return x+2;}

    };

    hash_map<int,char*,myhash> hm(300,myhash());

    (4)    hash_map(size_type n,consthasher& h,const key_equal& k)

    structstrequal{

    bool operator()(const char* s1,const char*s2)const

    {

               return strcmp(s1,s2)==0;

    }

    };

    hash_map<char*,int,hash<char*>,strequal>hm(300,hash<char*>(),strequal());

    (5)    hash_map(const hash_map&)

    拷贝构造函数。

    hash_map<int,char*> hm1;

    hash_map<int,char*> hm2(hm1);

    2.2元素的插入

    利用insert函数能够将键值不反复的元素数据插入到容器的哈希表中。

    #include<iostream>
    #include<hash_map>
    using stdext::hash_map;
    using namespace std;
    int main()
    {
    	hash_map<const char*,float> hm;
    	hm["apple"]=3.6f;
    	hm["orange"]=2.0f;
    	hm["banana"]=1.5f;
    	cout<<"苹果价格"<<hm["apple"]<<"元/斤"<<endl;
    	cout<<"橘子价格"<<hm["orange"]<<"元/斤"<<endl;
    	cout<<"香蕉价格"<<hm["banana"]<<"元/斤"<<endl;
    	system("pause");
    	return 0;
    }
    


     

    注:在vs2008中使用hash_map须要用usingstdext::hash_map;由于hash_mapvs2008的一个扩展,并没有在标准C++库中。

     

    2.3元素的删除

    利用erase函数和clear函数能够实现删除某个迭代器位置上的元素、等于某个键值的元素、迭代器区间上的元素和容器的全部元素。

    2.4元素的遍历

    利用迭代器能够实现元素的遍历。

    #include<iostream>
    #include<hash_map>
    using stdext::hash_map;
    using namespace std;
    template<class Key, class NameType, class YearType, class AddrType>
    struct StudentRecord_tag{    //学生记录结构体
    	struct StudentInfo_tag{  //学生信息结构体
    		NameType name;
    		YearType year;
    		AddrType addr;
    	};
    	//提供类型信息
    	typedef Key IdType;
    	typedef StudentInfo_tag StudentInfo;
    	//数据成员
    	IdType id;              //学号,键值
    	StudentInfo sf;         //学生信息,作映照数据
    };
    
    int main(void){
    	//using namespace std;
    	typedef StudentRecord_tag<int, char*, int, char*> StudentRecord;
    	//学生数据
    	StudentRecord srArray[] = {  //3笔学生记录
    		{ 192, "李强", 21, "北京" },
    		{ 193, "王文", 29, "上海" },
    		{ 191, "张三", 38, "深圳" }
    	};
    	//创建hash_map容器对象hm,管理学生记录
    	hash_map<StudentRecord::IdType, StudentRecord::StudentInfo> hm;
    	//装入3笔学生记录
    	for(int j=0; j<3; j++)
    		hm[srArray[j].id]=srArray[j].sf;
    	//迭代器遍历元素
    	hash_map<StudentRecord::IdType, StudentRecord::StudentInfo>::iterator i,iend;
    	iend=hm.end();
    	cout << "学号	" << "姓名	" << "年龄	" << "地址	" << endl;  //Tab键分隔
    	for(i=hm.begin(); i!=iend; i++)
    		cout << (*i).first << '	'
    		<< (*i).second.name << '	'
    		<< (*i).second.year << '	'
    		<< (*i).second.addr << '	'
    		<< endl;
    	system("pause");
    	return 0;
    }
    


     

    2.5元素的搜索

    利用find函数能够搜索扫某个元素的位置。若不存在,则返回一个结束元素的位置。

    // hash_map<StudentRecord::IdType,StudentRecord::StudentInfo>::iterator i;

    i=hm.find(193);

    2.6其它经常使用函数

    hash_set容器一样,hash_map提供了emptysizebucket_countswapresizeequal_range等函数能够取得容器的统计数据。

    #include<iostream>
    #include<hash_map>
    using stdext::hash_map;
    using namespace std;
    int main(void){
    	//using namespace std;
    	hash_map<int, char> hm;
    	typedef pair<hash_map<int, char>::iterator, bool> ReturnPair;
    	typedef pair<int, char> InsertPair;
    	ReturnPair p;
    	InsertPair p1(10, 'a'), p2(20, 'c'), p3(80, 'e');
    	//插入p1
    	p=hm.insert(p1);
    	if(!p.second) cout << "插入p1失败
    ";
    	//插入p2
    	p=hm.insert(p2);
    	if(!p.second) cout << "插入p2失败
    ";
    	//插入p3
    	p=hm.insert(p3);
    	if(!p.second) cout << "插入p3失败
    ";
    	//打印统计数据
    	cout << hm.empty() << endl;          //打印是否为空(false为0)
    	cout << hm.size() << endl;           //打印元素个数(3)
    	cout << hm.bucket_count() << endl;   //打印表长(193)
    	system("pause");
    	return 0;
    }
    


     

  • 相关阅读:
    Java面试题(01)
    HTML学习笔记16——尺寸的表示_px、%、em三种
    HTML学习笔记14——HTML 有语义的标签3_字符实体
    HTML13_有语义的标签2_a标签(超链接,锚点,伪类)
    HTML学习笔记12——HTML 有语义的标签1(h,p标签,img标签,列表,表格_制作课程表)
    HTML学习笔记11——CSS 初始化
    HTML学习笔记9——CSS精确控制背景图片位置——background-position
    HTML学习笔记8——CSS设置背景图片
    CSS控制文字的一些基本属性的使用
    HTML学习笔记5——盒模型(这里有棵圣诞树。)
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8413243.html
Copyright © 2020-2023  润新知