返回首页

简介
每一个C#程序员可能会使用的类??代码>的Hashtable??一个Hashtable是一种机制来存储和检索的键/值对。 Hashtable是有效率在很多方面,数据存储在RAM,使得它非常快速。如果键/值对的数目是非常大的?替代品是Windows注册表或关系数据库表。显然,人们可能不希望大量的应用程序数据存储在Windows注册表和数据库是饥饿和昂贵的资源。
HashFile类是试图找到问题的答案。HashFile类
HashFile是一种技术,插入/删除/在硬盘中的文件中找到键值对。它采用固定长度的记录存储数据和索引。有两个文件EM> name.dat和em> name.idx对应一个quot;??????namequot; "namequot;确定键/值对,并在初始化的时候。
"name.dat???
这是数据文件。数据文件存储键/值对固定长度的记录。应在初始化时指定的键/值对,密钥长度和价值的名称。数据文件的最大尺寸可以延伸到2 ^ 32字节,这是无符号整数的最大值(UINT32)。
?EM> name.idx???
这是索引文件。它存储固定长度的记录,记录指针和索引指针。记录指针和索引指针是无符号整数。索引技术
使用指数为91 × 2矩阵块(IB)来存储记录和索引指针。 Hashfile首次初始化时,将创建一个空的IB和每个元素将被填充的数据类型为uint的最大价值。为什么91行? 91中的字符的ASCII范围32-122。在IB的每一行代表一个ASCII字符。 IB的列记录指针和索引指针。列的数据类型是无符号整数。记录指针的起始字节数据记录的索引的起源,同样索引的指针起始字节索引记录的索引号的起源。
InsertKey方法的伪代码如下:以一个新的密钥字节如果字节范围内32-122的,然后跳左字节对应的距离内的IB匹配的索引记录,否则返回错误读取记录指针和索引指针如果索引指针等于最大值的数据类型为uint,然后,保存记录指针和索引指针,保存数据记录中的键和值,并返回记录指针否则记录指针读取数据记录比较新的密钥和现有关键 如果新的密钥相匹配现有的数据记录的关键,然后转到步骤10 如果新的关键是大于现有的关键,然后转到步骤11否则,第13步如果数据记录的状态,然后删除,保存新值,更改已删除标志设置为false,返回记录指针,否则返回错误如果索引指针指向未来的IB,采取下一步的字节,并跳转到第2步否则,创建新的IB,保存在新的IB的记录指针和索引指针,将启动新的IB指数的指针旧的IB,在数据记录保存键和值,返回记录指针如果索引指针指向下一个兴业,分配新的记录指针的索引记录,交换新的和现有的键跳转到第2步否则新的记录指针分配的索引记录,创造新的IB,分配现有的记录指针,新的索引指针,以新的IB,指定旧的IB开始新的IB指数指针,保存数据记录中的键和值,返回记录指针
听起来有点模糊,是不是?但该技术似乎在测试环境中工作。由于添加了新的密钥,索引机制,将尝试放置在尽可能从根兴业的最小距离记录指针。二进制树搜索算法消除了一半搜查后,每一个分支项目,而上面介绍的技术,无需担心的优秀记录90/91th可能后每IB假设人口分布。测试结果表明,平均IB读取找到约6.2记录,在528461键的人口,这听起来不错。详情请参阅测试结果部分。使用HashFile类
测试代码是hashfileTest.cs。一个方法测试HashFile.InsertKey{C}测试结果InsertKey
键= 528461,蜱= 1022397419386,频率= 299256万,平均写入时间(毫秒)= 0.646493162076644,平均读取= 5.77592859264922
键= 8125,蜱= 10044699390,频率= 299256万,平均写入时间(毫秒)= 0.413114755979444,平均读取= 5.50141538461538FindKey
键= 528461,蜱= 201771307445,频率= 299256万,平均读取时间(毫秒)= 0.127586169617676,平均读取= 6.14659738372368= 8125
键,滴答= 2945715784,频率= 299256万,平均读取时间(毫秒)= 0.121150331139174,平均读取= 5.48246153846154备注
释放类的版本只是一个原型,这显然意味着,该软件不应该在生产环境中使用。在这个版本的软件错误或错误引起的任何损失的最终用户的唯一责任。
任何建议,以改善HashFile类是最欢迎的。历史 2009年10月4日:初始版本

回答

评论会员:阿尼尔塔瓦 时间:2012/01/25
当我运行的程序
抛出以下错误
Errornbsp; 1nbsp; 纲要"C:\ Documents和Settings \ ADMIN \我的文档\ Visual Studio中局长有否超过一个切入点定义为:"WindowsFormsApplication1.Program.Main()" 编译/主指定的类型,它包含的条目point.nbsp; NBSP,C:\ Documents和Settings \ ADMIN \我的文档\ Visual Studio 2008中\ \ WindowsFormsApplication1 \ WindowsFormsApplication1 \ Program.csnbsp; 14nbsp; 21nbsp; WindowsFormsApplication1
我该怎么办?
感谢
阿尼尔塔瓦(印度)
评论会员:Bizken 时间:2012/01/25
Reelix,

感谢测试hashfile类。我是想解决C#程序员曾试图Hashtable类。我同意测试结果部分是模糊的,将尝试在下一个版本中存在于每个字节循环​​(CPB)的测试结果。

{S0}
评论会员:Reelix 时间:2012/01/25
从别人从未与哈希表的前处理,我必须说,这看起来像一个相当有趣的方法,用于存储一双值
! 有一件事我必须说,虽然,你的"测试结果"有点模糊。
它可以简化如:

InsertKey

新增键:X
全部插入钥匙的时间为:Y MS
FindKey

共有键:X
寻找最后的关键时间:Y MS
可能比较SQL SELECT语句的速度上的一个大数额(10,000 / 100,000 / 1,000,000)的记录。

不管怎么说,大文章!

时间尝试一些我自己的
标杆
- 编辑 -
附加的例子,你应该使用相对路径,因为不是每个人都有:

D:\ Documents和Settings \所有用户\文档\ VS \ EmailIDTEst \ EmailIDTEst \ BIN \调试\ keys1.txt


- 编辑2 -

一个HashFileTest.cs
取代
using System;

using System.Collections.Generic;

using System.Text;

using System.IO;

using HashFile;

using System.Diagnostics;

 

namespace HashFileTest1

{

    class Program

    {

        public static HashFile.HashFile HashFileTest1 = new HashFile.HashFile();

        static void Main(string[] args)

        {

            InsertKeys();

            FindKeys();

 

            Console.ReadLine();

        }

 

        public static void InsertKeys()

        {

            HashFileTest1.Initialize("Test1", 1, 1); // Not sure what this does, but changing it to 1,1 instead of 50,50 makes adding ALOT faster!

            Stopwatch StopWatchtest1 = new Stopwatch();

            Console.WriteLine("Adding 50000 keys - Please wait...");

            for (int i = 0; i < 50000; i++)

            {

                {

                    StopWatchtest1.Start();

                    HashFileTest1.InsertKey(i.ToString(), (i+5).ToString(), false); // Call to HashFile.InsertKey

                    StopWatchtest1.Stop();

                }

            }

            Console.WriteLine("50000 keys added in " + StopWatchtest1.ElapsedMilliseconds + "ms.");

        }

 

        public static void FindKeys()

        {

            Console.WriteLine("Please Wait...");

            Stopwatch StopWatchtest1 = new Stopwatch();

            string TestKeyRecord = "49995";

            //while (TestKeyRecord != null)

            {

                //for (int i = 0; i < HashFileTest1.Count; i++)

                {

                    //Console.WriteLine("Searching key " + i.ToString() + " of " + HashFileTest1.Count);

                    //Console.ReadLine();

                    StopWatchtest1.Start();

                    uint success = HashFileTest1.FindKey(TestKeyRecord); // Call to HashFile.FindKey

                    StopWatchtest1.Stop();

 

                    if (success == uint.MaxValue) // Failure to find a key

                    {

                        Console.WriteLine("Failed.");

                    }

                    else

                    {

                        Console.WriteLine("Found: " + HashFileTest1.Key + " = " + HashFileTest1.Value + " in " + StopWatchtest1.ElapsedMilliseconds + "ms.");

                      Console.ReadLine();

                    }

                }

            }

 

            Console.ReadLine();

        }

    }

}

输出:

添加50000键 - 请稍候...
50000键在49ms
请稍候...
:49995 = 50000在1ms

- 编辑3 -

我上面的例子中使用的高金额产生一些奇怪的结果:

添加70000键 - 请稍候...
70000键在67ms
请稍候...
共找到:69995 = 700??
在1ms。
重点69995应该是70000,没有700?? (不知道铁锹来自:P)

- 编辑4 -

UINT可支持多达65535个:P
时间过长大规模转换到一个更高的数据类型的一切,但是,记录,您可以添加约。 5万5秒记录

-= Reelix =-上周二,2009年10月13日上午03:49
修改