本人小白,仅供自己学习参考!
使用STL库的vector 和 unordered_map
先巩固一下基础知识!!!
1.创建一个vector并直接赋值
std::vector<int> b{ 1,2,3,4,5,6,7,1 };
2.用数组给向量赋值
int a[6]={1,2,3,4,5,6};
vector<int>c(a,a+4);//把数组a的前四个数据赋值给向量c
3.定义一个全是1的向量
vector<int>a(10,1);
4.用向量b给向量a赋值,向量a中的值完全等于向量b中的值
vector<int>a(b);
5.将向量b的前三个数值赋值给向量a
vector<int>a(b.begin() , b.begin()+3 );
vector对象的常用内置函数使用(举例说明)
#include<vector>
vector<int> a,b;
//b为向量,将b的0-2个元素赋值给向量a
a.assign(b.begin(),b.begin()+3);
//a含有4个值为2的元素
a.assign(4,2);
//返回a的最后一个元素
a.back();
//返回a的第一个元素
a.front();
//返回a的第i元素,当且仅当a存在
a[i];
//清空a中的元素
a.clear();
//判断a是否为空,空则返回true,非空则返回false
a.empty();
//删除a向量的最后一个元素
a.pop_back();
//删除a中第一个(从第0个算起)到第二个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)结束
a.erase(a.begin()+1,a.begin()+3);
//在a的最后一个向量后插入一个元素,其值为5
a.push_back(5);
//在a的第一个元素(从第0个算起)位置插入数值5,
a.insert(a.begin()+1,5);
//在a的第一个元素(从第0个算起)位置插入3个数,其值都为5
a.insert(a.begin()+1,3,5);
//b为数组,在a的第一个元素(从第0个元素算起)的位置插入b的第三个元素到第5个元素(不包括b+6)
a.insert(a.begin()+1,b+3,b+6);
//返回a中元素的个数
a.size();
//返回a在内存中总共可以容纳的元素个数
a.capacity();
//将a的现有元素个数调整至10个,多则删,少则补,其值随机
a.resize(10);
//将a的现有元素个数调整至10个,多则删,少则补,其值为2
a.resize(10,2);
//将a的容量扩充至100,
a.reserve(100);
//b为向量,将a中的元素和b中的元素整体交换
a.swap(b);
//b为向量,向量的比较操作还有 != >= > <= <
a==b;
顺序访问vector的几种方式,举例说明
1.向向量a中添加元素
vector<int>a;
for(int i=0;i<10;++i){
a.push_back(i);
}
2.从文件中读取元素向向量中添加
ifstream in("data.txt");
vector<int>a;
for(int i; in>>i){
a.push_back(i);
}
3 从向量中读取元素
3.1通过下标方式获取
int a[6]={1,2,3,4,5,6};
vector<int>b(a,a+4);
for(int i=0; i<=b.size()-1; ++i){
cout<<b[i]<<endl;
}
3.2通过迭代器方式读取
int a[6]={1,2,3,4,5,6};
vector<int>b(a,a+4);
for(vector<int>::iterator it = b.begin(); it != b.end(); it++){
cout<<*it<<" ";
}
4 map
优点:有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作。红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高。
缺点:空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点,孩子节点以及红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些。
5 unordered_map
优点:内部实现了哈希表,因此其查找速度是常量级别的。
缺点:哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
特性
- 关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同)
- 无序性:使用hash表存储,内部无序
- Map : 每个值对应一个键值
- 键唯一性:不存在两个元素的键一样
- 动态内存管理:使用内存管理模型来动态管理所需要的内存空间
6 Hashtable和bucket
由于unordered_map内部采用的hashtable的数据结构存储,所以,每个特定的key会通过一些特定的哈希运算映射到一个特定的位置,我们知道,hashtable是可能存在冲突的(多个key通过计算映射到同一个位置),在同一个位置的元素会按顺序链在后面。所以把这个位置称为一个bucket是十分形象的(像桶子一样,可以装多个元素)。
所以unordered_map内部其实是由很多哈希桶组成的,每个哈希桶中可能没有元素,也可能有多个元素。
unordered_map实现原理
unordered_map内部是一个hash_table,是由一个大vector,vector的每个元素节点挂一个链表来实现的(就是开链法实现的哈希桶)。
unordered_map的插入过程:
1.得到key值
2.通过hash函数得到hash值,即为对应的bucket索引号
3.存放key和value在bucket内。
unordered_map的查询过程:
1.得到key值
2.通过hash函数得到hash值,即为对应的bucket索引号
3.比较buckut内元素key值是否和要查找的key值相等,若都不相等则没找到
4.若相等则取出相等key值对应的value。
找到数组中相同的元素
方法一:哈希表
#include<iostream>
#include<vector> //向量头文件
#include<unordered_map>//无序字典头文件
class Solution {
public:
void findRepeatNumber(std::vector<int>& nums) {
std::unordered_map<int, bool> map;
map.reserve(nums.size());
for (int i = 0; i < nums.size(); ++i) { //遍历
if (map.find(nums[i]) == map.end()) { //如果找不到该元素,就把该元素插入
map.insert({ nums[i] , true });
}
else {
std::cout << nums[i]<<std::endl; //如果能找到该元素,就是重复的,输入它
}
}
}
};
void main()
{
int a[7] = { 3,2,2,4,4,5,6,};
std::vector<int> b(a,a+7); //用数组给vector向量赋值
// for (int i = 0; i <= b.size() - 1; ++i) { std::cout << b[i] << std::endl; }
Solution cc;
cc.findRepeatNumber(b);
}
方法二:遍历对比
遍历两次,取数组中每一个数与数组后面的数进行对比
#include<iostream>
#include<vector>
class Solution {
public:
void findRepeatNumber(std::vector<int>& nums) {
for (int i = 0; i < nums.size(); i++) {
for (int j = i+1; j < nums.size(); j++) {
if (nums[i] == nums[j]) { //遍历两次,取数组中每一个数与数组后面的数进行对比
std::cout << nums[j] << std::endl;
}
}
}
}
};
void main()
{
std::vector<int> b{ 1,2,3,4,1,1,2 ,3,44,5,5};
//for (int i = 0; i < b.size() ; i++) { std::cout << b[i] << std::endl; }
Solution cc;
cc.findRepeatNumber(b);
}