数据结构和算法 – 7.散列和 Hashtable 类
7.1.散列函数
散列是一种常见的存储数据的技术,按照这种方式可以非常迅速地插入和取回数据。散列所采用的数据结构被称为是散列表。尽管散列表提供了快速地插入、删除、以及取回数据的操作,但是诸如查找最大值或最小值这样的查找操作,散列表却无法执行地非常快。对于这类操作,其他数据结构会更适合.
7.2.选择散列函数
选择数组大小的时候,一个重要的原则就是要选择素数。
10007是素数,而且他没有大到会使用大量的内存来降低程序的内存。
下面例子中,散列函数SimpleHash利用霍纳(Horner)法则来计算(关于37的)多项式函数。
static void Main()
{
string[] names = new string[10007];
string name; string[] somenames = new string[]
{ "David", "Jennifer", "Donnie","Mayo",
"Raymond","Bernica","Mike", "Clayton","Beata","Michael"}; int hashVal; for (int i = 0; i < 10; i++)
{
name = somenames[i];
hashVal = SimpleHash(name, names);
names[hashVal] = name;
}
ShowDistrib(names); Console.Read();
} public static int SimpleHash(string s, string[]arr)
{
int tot = 0;
char[] cname;
cname = s.ToCharArray();
for (int i = 0; i < cname.GetUpperBound(0); i++)
{
tot += 37 * tot + (int)cname[i];
}
tot = tot % arr.GetUpperBound(0);
if (tot < 0)
{ tot += arr.GetUpperBound(0); }
return (int)tot;
} static void ShowDistrib(string[] arr)
{
for (int i = 0; i < arr.GetUpperBound(0); i++)
{
if (arr[i] != null)
{ Console.WriteLine(i+" "+arr[i]); }
}
}
7.3.查找散列表中数据
在散列表中查找数据,需要计算键的散列值,然后访问数组中的对应元素。这样的查找方式很明显要比逐个查找要效率的多。
7.4.解决冲突
7.4.1.桶式散列法
桶,是一种存储在散列表元素内的简单数据结构 ,它可以存储多个数据项。大多数实现中,这种数据结构就是一个数组,例如ArrayList类。
桶式散列法,最终要的事情,就是保持所用数组的数量尽可能地少。
插入一个数据项
用散列函数来确认用哪个数组(散列键)来存储数据项,然后查看此数据项是否已经在数组内。如果存在,就不做。如果不存在,就将数据项添加进这个数组。
移出一个数据项
用散列函数来确认用哪个数组(散列键)来移出数据项,然后查看此数据项是否已经在数组内。如果存在,就移出数据项。如果不存在,就不做。
7.4.2.开放定址法
开放定址函数会在散列表数组内寻找空单元来防止数据项。
两种不同的开放定址策略:
线性探查
采用线性函数来确认试图插入的数组单元。顺次尝试单元直到找到一个空单元为止。
会出现的问题是数组内相邻单元中的数据元素会趋近成聚类,从而使得后续空单元的探查时间变得更长且效率更低。
平方探查
平方函数来确认要尝试哪个单元。
平方探查法的有趣属性是在散列表空余单元少于一半的情况下总能保证找到空的单元。
7.4.3.双重散列法
两个条件:散列函数不应该曾经计算到0,;表的大小必须是素数
7.5.5 Hashtable 类
可以实例化具有初始容量的散列表,或者使用默认容量。当然还可以同时指定初始容量和初始负载系数。
Hashtable symbols = new Hashtable();
Hashtable symbols = new Hashtable(50);
HashTable symbols = new Hashtable(25, 3.0F);
7.5.1.从散列表中分别取回关键字和数值
Hashtable 类有两个非常有用的方法用来从散列表中取回关键字和数值:即 Keys 和 Values。这些方法创建了一个 Enumerator 对象,它允许使用 For Each 循环或者其他一些技术来检查关键字和数值。
Hashtable symbols = new Hashtable(25);
symbols.Add("salary", 100000);
symbols.Add("name", "David Durr");
symbols.Add("age", 45);
symbols.Add("dept", "Information Technology");
symbols["sex"] = "Male";
Console.WriteLine("The keys are: ");
foreach (Object key in symbols.Keys)
Console.WriteLine(key);
Console.WriteLine();
Console.WriteLine("The values are: ");
foreach (Object value in symbols.Values)
Console.WriteLine(value);
7.5.2.Hashtable 类的应用程序:计算机术语表
散列表的常见应用之一就是构造术语表或术语词典。本小节会举例说明使用散列表的一种方法就是为了这样一个应用—即计算机术语表。
程序首先从一个文本文件中读入一系列术语和定义。这个过程是在子程序 BuildGlossary 中编码实现的。文本文件的结构是:单词,定义,用逗号在单词及其定义之间进行分隔。这个术语表中的每一个单词都是单独一个词,但是术语表也可以很容易地替换处理短语。这就是用逗号而不用空格作分隔符的原因。此外,这种结构允许使用单词作为关键字,这是构造这个散列表的正确方法。
另一个子程序 DisplayWords 把单词显示在一个列表框内,所以用户可以选取一个单词来获得它的定义。既然单词就是关键字,所以能使用Keys 方法从散列表中正好返回单词。然后,用户就可以看到有定义的单词了。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Hashtable glossary = new Hashtable(); private void Form1_Load(object sender, EventArgs e)
{
BuildGlossary(glossary);
DisplayWords(glossary);
} private void BuildGlossary(Hashtable g)
{
StreamReader inFile;
string line;
string[] words;
inFile = File.OpenText(@"c:\111.txt");
char[] delimiter = new char[] { ',' };
while (inFile.Peek() != -1)
{
line = inFile.ReadLine();
words = line.Split(delimiter);
g.Add(words[0], words[1]);
}
inFile.Close();
}
private void DisplayWords(Hashtable g)
{
Object[] words = new Object[100];
g.Keys.CopyTo(words, 0);
for (int i = 0; i <= words.GetUpperBound(0); i++)
if (!(words[i] == null))
lstWords.Items.Add((words[i]));
} private void lstWords_SelectedIndexChanged(object sender, EventArgs e)
{
Object word;
word = lstWords.SelectedItem;
txtDefinition.Text = glossary[word].ToString();
}
}
}
数据结构和算法 – 7.散列和 Hashtable 类的更多相关文章
- JavaScript--数据结构与算法之散列
散列:实现散列表的数据后可以快速地实现插入或者删除.但是对于实现查找操作则效率非常的低.散列表的底层是数组实现的,长度是预先设定,可以随时根据需求增加.所有的元素根据和该元素对应的键,保存在特定的位置 ...
- 数据结构与算法分析java——散列
1. 散列的概念 散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存 ...
- 非对称算法,散列(Hash)以及证书的那些事
转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/35389657 作者:小马 这几个概念在金融电子支付领域用得比較多,我忽然认为把它们 ...
- 散列之HashTable学习
1,什么是散列? 举个例子,在日常生活中,你将日常用品都放在固定的位置,当你下次需要该东西时,直接去该地方取它.这个过程就相当于散列查找. 若将它们随意杂乱无章地存放,当需要某件东西时,只能一个地方一 ...
- 哈希表(散列)HashTable实现
近期刷Leetcode发现凡是找字符串中反复字符或者数组中找反复数据的时候就不知道从何下手了. 所以决定学习一下哈希表解题.哈希表的原理主要是解决分类问题,hash表是介于链表和二叉树之间的一种中间结 ...
- 数据结构和算法 – 6.构建字典: DictionaryBase 类和 SortedList 类
6.1.DictionaryBase 类的基础方法和属性 大家可以把字典数据结构看成是一种计算机化的词典.要查找的词就是关键字,而词的定义就是值. DictionaryBase 类是一种用作专有字 ...
- 数据结构和算法 – 番外篇.时间测试类Timing
public class Timing { //startingTime--用来存储正在测试的代码的开始时间. TimeSpan startingTime; //duration--用来存储正在测试的 ...
- Java 散列集笔记
散列表 散列表(hash table)为每个对象计算一个整数,称为散列码(hash code). 若需要自定义类,就要负责实现这个类的hashCode方法.注意自己实现的hashCode方法应该与eq ...
- 数据结构和算法(Golang实现)(26)查找算法-哈希表
哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...
随机推荐
- Lucene4.1 视频学习
1.将路径建立在内存中 Directory d = new RAMDirectiry(); 2.Filed Index(索引选项):Index.ANALYZED:进行分词和索引,适应于标题,内容等In ...
- SVN迁移到Git的过程(+ 一些技巧)
SVN迁移到Git的过程(+ 一些技巧) 李顺利 Key Words SVN,Git,Clone,Conversion,Tips,VCS,Pro Git 关于在VCS中SVN和Git之间的迁移(Clo ...
- innerHtml innerText textContent兼容性问题
innerHtml,innerText,textContentinnerHtml获取元素带标签的内容:innerText只获取元素的文本:火狐不支持innerText,支持textContent: / ...
- 2.6---找有环链表的开头结点(CC150)
public ListNode detectCycle(ListNode head) { ListNode fast = head; ListNode slow = head; int flag = ...
- XAMPP端口占用启动不了
skype默认会占用80和443端口 如果在apache之前启动skype,apache就会启动不了了!! 解决办法很简单: 1. 先启动apache再启动skype,这样skype就会换其他的端口监 ...
- 教程和工具--用wxPython编写GUI程序的
wxPython是个很好的GUI库,对底层的C++库进行了封装,调用起来很方便,尤其是操作前台UI界面和后台多线程,两者配合很方便,做GUI程序最难是写界面尤其是布局. 关于wxPython,自己正在 ...
- php中的钩子(hook插件机制)
对"钩子"这个概念其实不熟悉,最近看到一个php框架中用到这种机制来扩展项目,所以大概来了解下. hook插件机制的基本思想: 在项目代码中,你认为要扩展(暂时不扩展)的地方放置一 ...
- 基于MATLAB的离散小波变换
申明,本文非笔者原创,原文转载自: 基于Matlab的离散小波变换 http://blog.sina.com.cn/s/blog_725866260100ryh3.html 简介 在 ...
- poj 1789
http://poj.org/problem?id=1789 这是一道图论的题,个人觉得和那个POJ1258是差不多的,就是多了一步,题目难以读懂 题目的意思:就是给你一群字符串要你找字符串对应的字符 ...
- POJ 1917
http://poj.org/problem?id=1917 poj的字符串的一道水题. 题意么无关紧要, 反正输出的第一行就是把那个<>去掉,s1<s2>s3<s4&g ...