示例代码参考代码随想录
哈希表,简单说吧,复杂的现在还没有弄明白怎么描述
1、就是按照一定的规则,将数据存入到数据结构中。而C语言中现在我们常见的就是数组,以及使用数组和链表的结合。还有C++,一般使用的都是unordered_set,unordered_map。
突出的就是一个存储位置和值的对应关系(书上写的是关键字,,实际上就是值,看书上的强迫症都犯了)
比如计算存储位置(索引)的方法之一 ? Hash(value) =? value %p,这个被称为除留取余法。不过这个方法,这样的表现形式是使用数字做取余运算的方式。如果存储其他类型数据可能需要看情况转化成可使用数字做索引的方式了。(突然发现,这个索引的计算,有点像是计算某个范围内随机值的感觉??)
2、还有一点,这个hash表,更多的是突出一个散列的存储
? ? ? ? 根据下面例子我们就可以发现,只是使用字符的ascii码差值做索引,来记录相同字符的个数,这字符的字符数据之间没有直接的关联关系什么的。
????????这个例子就有点像:点到原点的距离。这些字符串中的字符,有多少到原点a的距离是相同的比如:n - a = 20,就相当于我们设定好了,n的位置就存放在数组的位置 record [20]处,而我们需要计算的是有多少点的位置在里。直接给record[20] ++.
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
bool isAnagram(string s, string t);
int main()
{
string s("anagram");
string t("nagaram");
isAnagram(t,s);
}
bool isAnagram(string s, string t){ // s = anagram t = nagaram
int record[26] = {0};
if(s.size()!= t.size())
{
return false;
}
for(int i = 0; i < s.size(); i++)
{
record[s[i] - 'a']++; //一开始接触这个也是没反应过来,实际上就是 用字母去减字母,这种情况下,都是使用askii码进行相加减
} //这个操作就相当于记录一个标志值,因为26个英文字母在ascii中是连续的,所以其他字母和a的差值不会超过25/26
//至于我为啥用25/26呢,因为确实记不清a是多少了 不过作为数组record的下标,不会超过26
//上面的这个可以发现如果相同的字母减a,那么那个下标的值就会+1.
//当两个字符串的字母一样时,如果用同样的数组记录,结果应该就是一样的,字符串t
//比如 : t有三个a, 结果遍历字符的时候,a-a 的ascii值,是一样的,有三个,所以record['a' - 'a'] ==3;
//这个时候,如果我们做个相反的计算 record[]-=1; 是不是遍历结束后,record[0]的位置就是0 .其他的字符也一样
for(int i = 0; i < t.size(); ++i)
{
record[t[i]-'a']--;
}
//上面两步操作完,数组里如果都是0,就表示两个字符串的字符一样。顺序不同 。这有点那个信号量控制共享资源的感觉
for(int i = 0; i < 26; i++)
{
if(record[i]!=0){
return false;
}
}
cout << "t 和s 是互为字母异位词"<< endl;
return true;
}
? ? ? ? 基本上就是使用一个数组,去存储链表的头指针。然后将数据根据我们设定的索引规则,存储在特定的索引地址下。
这个我们也可以用来做索引数据结构啥的,在标准模板库STL中的无需关联式容器使用的就是链地址法。(用来解决hash冲突)????????
这个网上挺多的,就是需要注意一个装填因子的问题, 装填因子/装载因子= 元素个数/表长=0.5~0.75? ?这个值在这个范围之间就比较合适。再多了,可能需要更换数据结构。、
比如C++有序关联式容器中使用红黑树去存储数据(目前还没扣明白,等搞明白了写上。)
使用epoll 的时候,这个底层实现也是使用红黑树去实现的。(因为select 底层就是一个位图,可以当成个数组,大概能监听1024个文件描述符。而epoll好像在10万以上)
//哈希表的用途,可以用来做缓存(比如服务器使用哈希表做缓存机制,缓存用户的id,作为key;value 用来存储用户详细信息等,查询起来方便,就不用每次都向服务器发送请求了)