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 类的更多相关文章

  1. JavaScript--数据结构与算法之散列

    散列:实现散列表的数据后可以快速地实现插入或者删除.但是对于实现查找操作则效率非常的低.散列表的底层是数组实现的,长度是预先设定,可以随时根据需求增加.所有的元素根据和该元素对应的键,保存在特定的位置 ...

  2. 数据结构与算法分析java——散列

    1. 散列的概念 散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存 ...

  3. 非对称算法,散列(Hash)以及证书的那些事

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/35389657 作者:小马 这几个概念在金融电子支付领域用得比較多,我忽然认为把它们 ...

  4. 散列之HashTable学习

    1,什么是散列? 举个例子,在日常生活中,你将日常用品都放在固定的位置,当你下次需要该东西时,直接去该地方取它.这个过程就相当于散列查找. 若将它们随意杂乱无章地存放,当需要某件东西时,只能一个地方一 ...

  5. 哈希表(散列)HashTable实现

    近期刷Leetcode发现凡是找字符串中反复字符或者数组中找反复数据的时候就不知道从何下手了. 所以决定学习一下哈希表解题.哈希表的原理主要是解决分类问题,hash表是介于链表和二叉树之间的一种中间结 ...

  6. 数据结构和算法 – 6.构建字典: DictionaryBase 类和 SortedList 类

      6.1.DictionaryBase 类的基础方法和属性 大家可以把字典数据结构看成是一种计算机化的词典.要查找的词就是关键字,而词的定义就是值. DictionaryBase 类是一种用作专有字 ...

  7. 数据结构和算法 – 番外篇.时间测试类Timing

    public class Timing { //startingTime--用来存储正在测试的代码的开始时间. TimeSpan startingTime; //duration--用来存储正在测试的 ...

  8. Java 散列集笔记

    散列表 散列表(hash table)为每个对象计算一个整数,称为散列码(hash code). 若需要自定义类,就要负责实现这个类的hashCode方法.注意自己实现的hashCode方法应该与eq ...

  9. 数据结构和算法(Golang实现)(26)查找算法-哈希表

    哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...

随机推荐

  1. [转载]MySQL5.5 配置文件 my.ini 1067错误

    原文链接:http://blog.csdn.net/xiaochunyong/article/details/7438200 解压mysql-5.5.22-win32.zip后的目录中有5个my-xx ...

  2. PHP中面相对象对象的知识点整理

    面向对象 万物皆对象,将构成问题的事务分解到各个对象上,建立对象的目的不是为了完成一个工作,而是为了描述某个事务在解决问题中的行为,更符合人的思维习惯,代码重用性高,可扩展性. ___________ ...

  3. postgresql 函数&存储过程 ; 递归查询

    函数:http://my.oschina.net/Kenyon/blog/108303 紧接上述,补充一下: 输入/输出参数的函数demo(输入作为变量影响sql结果,输出作为结果返回) create ...

  4. Android Service1

    一.Service的种类 按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...

  5. win7下配置Apache本地虚拟主机

    我们有时候从网上下载下来的php源码很多都是应用在网站根目录下的,而我们又想在本地先测试一遍确定没有问题了再上传空间,但一换到子目录下的时候因为路径问题,使得许多图片.内容都无法显示. 这个时候我们就 ...

  6. Binary Tree Non-recursive Traversal

    Preorder: public static void BSTPreorderTraverse(Node node) { if (node == null) { return; } Stack< ...

  7. NGUI 滑动页(UIToggle和UIToggledObjects)

    1.NGUI->Create->Scroll View 2.给Scroll View添加一个 UIGrid,自己设置Arragement(横向竖向) 3.给Grid添加元素 4.给元素添加 ...

  8. ios 使用xib时,在UIScrollView中添建内容view时,使用约束的注意

    请参与一下链接:http://segmentfault.com/a/1190000002462033 简单的说下,就是必须写满一个view的6个约束,就是上下左右高宽,让scrollview 能够根据 ...

  9. 手动编译并运行Java项目的过程

    现在Java开发基本上就是IDE调试,如果跨平台打个jar包过去运行一般就可以了,但是有些情况比如需要引入外部依赖的时候,这个时候是不能直接运行的,还需要引入一些外部的参数,并不是简单的javac和j ...

  10. reportng的使用

    1.首先安装testng 2.下载reportng jar包 http://pan.baidu.com/s/1i3KdlQH 3.添加到project build path 注意:需要同时引入goog ...