哈希表hashTable及其应用的一个小例子

  1. 数据结构:哈希表:冲突处理有哪几种方法?其中链地址法有什么缺点吗?怎么改进?

链地址法缺点:1.时间复杂度较其他的高(因为可能要遍历链表)2.有的关键字得到的哈希地址频次交高,则该节点对于的链表就非常长?怎么改进?(再哈希法!)

首先你要知道哈希表是干嘛的啊?!

哈希表是一种查找表!哈希函数、地址冲突、平均查找长度、装填因子等概念!

一旦哈希表建立好了,一来一个关键字,我用哈希函数一算就可与算出其在表中的地址,就可与直接去该地址处看这个关键字对应的元素存在吗?如果存在就找到了,如果不存在则查找失败!

哈希函数表的定义:

根据设定的哈希函数H(key)和一种冲突处理方法将一组关键字映像到一个有限连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便是哈希表,这一映像过程称为哈希造表或散列,所得存储位置成为哈希地址或散列地址!

    1. 哈希函数的构造方法
  1. 直接定址法
  2. 数字分析法
  3. 平方取中法
  4. 折叠法
  5. 除留余数法
  6. 随机数法

选择哈希函数要考虑的因素:

  1. 哈希函数的复杂度(计算哈希函数所需要时间)
  2. 关键字的长度
  3. 哈希表的大小
  4. 关键字的分布情况
  5. 记录的查找频率

2.哈希表是一个压缩映像,所有会出现冲突。

假设哈希表的地址集为0~(n-1),冲突是指由关键字得到的哈希地址为j(0<=k<=n-1)的位置上已经存在有记录,则“处理冲突“就是为该关键字的记录找到另外一个”空“的哈希地址。在处理冲突的过程中可能得到一个地址序列Hi,i=1,2,...,k,(Hi属于[0,n-1]),依次类推,直到Hk不发生冲突为止,则Hk为记录在表中的地址。

处理冲突的方法:

1)开发定址法

Hi=(H(key)+di)MODm i=1,2,...,k(k<=m-1)

H()为哈希函数,k为哈希表长度,di为增量序列:

di=1,2,3,...,m-1,成为线性探测再散列法

di=12,-12,22,...,+-k2(k<=m/2)称为二次探测再散列法

di=伪随机数序列,则称为随机探测再散列法。

线性探测再散列法容易引起“二次聚集“现象。

  2)再哈希法

                     Hi=RHi(key) i=1,2,...,k

              RHi均是不同的哈希函数。

 3)链地址法

       将所有关键字为同义词的记录(具有相同函数值的关键字对该哈希函数来说称为同义词synonym)存储在同一线性链表中。假设某个哈希函数产生的哈希地址在区间[0,m-1]上,则设立一个指针型向量

Chain ChainHash[m];

其每个分量的初始状态都为空指针。凡哈希地址为i的记录都插入到头指针为ChainHash[i]的链表中,在链表中插入的位置要保证同义词在同一线性列表中按关键字有序(以便进行二分查找)

 4)建立公共溢出区

        HashTable[0..m-1]为基本表

        OverTable[0...v]为溢出表

参考

[1] 严蔚敏, 吴伟民. 数据结构(C语言版)[J]. 计算机教育, 2012, No.168(12):62-62.

[2]STL的map、hash_map的使用https://blog.csdn.net/q_l_s/article/details/52416583

2.哈希表应该的一个例子:《剑指offer》第5章优化时间和空间效率 

面试题50:求一字符串中只出现一次的字符

/*
《剑指offer》求一个字符串中第一个只出现一次的字符:
如输入"abaccdeff"则应该输出:'b'
*/
 

//法2:哈希表映射法:时间复杂度O(n),空间复杂度O(1)
//字符出现了多少次?:统计的思维(很优雅)
/*
我们定义哈希表的键是字符的ASCII值,值是该字符出现的次数。
只需扫描字符串两次:
第一次是统计每个字符出现的次数。
第二次是将第一个只出现一次的字符输出。
处理特殊情况:没有只出现一次的字符,每个字符都出现了两次或两次以上。
*/

char getFirstNotRepeatingChar(string str)
{
	if (str.size() == 0)
		return '\0';
	//ASCII码总共有256个
	const int hashTableSiez = 256;
	unsigned int* hashTable = new unsigned int[hashTableSiez]();//数组元素全初始化为0

	for (int i = 0; i < str.size(); i++)
	{
		hashTable[str[i]]++;
	}
	
	for (int i = 0; i < str.size(); i++)
	{
		if (hashTable[str[i]] == 1)
			return str[i];
	}
	//处理特殊情况:没有只出现一次的字符,每个字符都出现了两次或两次以上。
	return '\0';
}

另外附上暴力搜索法:苦逼的上下而求索啊!(思路简单,但难写更难看!)

/*
最直观的暴力扫描法:对于每一个字符,分别在其前、其后的子串中查找该字符,如都没有出现,则为只出现一次的字符,找到这样的第一个字串!
*/

char getFirstNotRepeatingCharBruteForce(string str)
{
	if (str.size() == 0)
		return '\0';
	string::size_type pos_after;
	string::size_type pos_before;
	string substr = str;
	string substr_after;
	string substr_before;
	for (int i = 0; i < str.size(); i++)
	{
		/*
		size_type find(_Elem _Ch, size_type _Off = 0) const
		{	// look for _Ch at or after _Off
		return (find((const _Elem *)&_Ch, _Off, 1));
		}
		注意是at or after _Off!!
		*/
		if (i == 0)
		{
			substr = str.substr(i + 1);
			pos_after = substr.find(str[i]);
			if (string::npos == pos_after)
			{//没找到就输出该字符
				return str[i];
			}
			else
			{
				continue;
			}
		}
		else if (i > 0 && i < str.size() - 1)
		{
			/*
			_Myt substr(size_type _Off = 0, size_type _Count = npos) const
			{	// return [_Off, _Off + _Count) as new string
				return (_Myt(*this, _Off, _Count, get_allocator()));
			}
			*/
			//在str[i]之前找
			substr_before = str.substr(0, i);
			pos_before = substr_before.find(str[i]);
			//在str[i]之后找
			substr_after = str.substr(i + 1, string::npos);
			pos_after = substr_after.find(str[i]);

			if (pos_before == string::npos&&pos_after == string::npos)
			{
				return str[i];
			}
			else
			{
				continue;
			}

		}
		else//对于最后一个字符:
		{
			substr_before = str.substr(0, i);
			pos_before = substr_before.find(str[i]);
			if (pos_before == string::npos)
			{
				return str[i];
			}
			else
			{
				return '\0';
			}
		}
	}
}

下面是几个测试例子:

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	string str = "abaccdeff";
	string str2 = "aabbccdde";
	string str3 = "";
	string str4 = "aabbcc";

	char firstNotRepeatChat = getFirstNotRepeatingCharBruteForce(str4);
	cout << "First Not Repeating Char in " << str4 << " is " << firstNotRepeatChat << endl;

	system("pause");
	return 0;
}

哈希表  哈希表应用 剑指offer

猜你喜欢

转载自blog.csdn.net/m0_37357063/article/details/81710821
今日推荐