发布新日志

  • hash table

    2009-03-25 16:39:20

    什么叫哈希表(Hash Table)

    google搜索到的头条:散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
          我觉得这个解释太含糊,想要整明白哈希表,那就得明白哈希表到底有什么样的优势。
          数据结构中,有个时间算法复杂度O(n)的概念来衡量某种算法在时间效率上的优劣。哈希表的理想算法复杂度为O(1),也就是说利用哈希表查找某个值,系统所使用的时间在理想情况下为定值,这就是它的优势。那么哈希表是如何做到这一点的呢?
          我们定义一个很大的有序数组,想要得到位于该数组第n个位置的值,它的算法复杂度为O(1)。哈希表利用哈希函数将需要存储的内容的关键值转换为这个有序 数组中的某个值,在被存储内容和有序数组之间建立了映射关系。这样,下次我们对这个值进行查找时只要使用同一个哈希函数对关键值进行转换,找到这个数组值 就可以了。
          如果还没有明白是怎么回事的话,那我们来举个例子。假设我们要做个存储结构,需要存储下来三国中的人物,以及他们的详细信息。我们用他们的名字来作为存储 的关键值,例如:刘备,曹操,孙权,关羽,张飞……等等。这个时候我们如果想用一般的方法来查找这些英雄豪杰,需要遍历整个存储空间,如果这些英雄豪杰一 共有n个,那么这时候的时间算法复杂度为O(n)。显然如果n值很大,每次想要找到某个英雄就需要比较长的时间。
          此时我们先定义一个大的有序结构数组HashValue[m],用来存放各位英雄豪杰的信息。然后编写一个哈希函数ChangeToHashValue (name),函数的具体内容就不细说了,反正这个函数会将这些做为关键值的名字转换为HashValue[m]中的某个下标值x。然后可以将英雄的信息 放进HashValue[x]中去。这样,可以将所有英雄的信息存储起来。当查询的时候再使用哈希函数ChangeToHashValue(name)得 到这个下标值,这样就很容易得到了这个英雄的信息。例如:ChangeToHashValue(刘备)为10,那么就将刘备存储到HashValue [10]里面。当查询的时候再次使用ChangeToHashValue(刘备)得到10,这个时候我们就可以很容易找到刘备的所有信息。在实际应用中如 果我们想把所有的英雄豪杰都存储进系统时,需要定义m>n。就是数组的大小要大于需要存储的信息量,所以说哈希表是一个以空间换取时间的数据结构。
          这个时候问题来了,出现了这种情况ChangeToHashValue(关羽)和ChangeToHashValue(张飞)得到的值是一样的,都是 250,我们岂不是在存储过程中会遇到麻烦,怎么安排他们二位的地方呢(总不能让二位打一架,谁赢了谁呆在那吧),这就需要一个解决冲突的方法。当遇到这 种情况时我们可以这样处理,先存储好了关羽,当张飞进入系统时会发现关羽已经是250了,那咱就加一位,251得了,这不就解决了。我们查找张飞的时候也 是,一看250不是张飞,那就加个1,就找到了。这时还存在一个问题。直接用ChangeToHashValue(赵云)为251,张飞已经早早占了他的 地方,那就再加1存到252呗。呵呵,这时我们会发现,当哈希函数冲突发生的机率很高时,可能会有一群英雄豪杰在250这个值后面扎堆排队。要命的是查找 的时候,时间算法复杂度早已不是O(1)了(所以我们说理想情况下哈希表的时间算法复杂度为O(1))。      这就是说哈希函数的编写是哈希表的一个关键问题,会涉及到一个存储值在哈希表中的统计分布。如果哈希函数已经定义好了,冲突的解决就成为了改变系统性能的 关键因素。其实还有很多种方法来解决冲突情况下的存储和查找问题,不一定非要线性向后排队,如果有好的哈希表冲突的解决方法也能很大程度上提高系统的效 率。
  • perl学习2-连接数据库

    2009-03-25 15:24:43

      http://www.anysql.net/developer/perl_dbi_connection.html

    从data_sources函数知道了连接信息的格式后, 我们就可以连接了, 只要调用DBI的connect函数, 根据连接信息的格式, 可以自动区别数据库类型, 选择合适的数据库驱动进行连接. 一般写法如下:
    my $dbh = DBI->connect("data source", "username", "password");
    my $dbh = DBI->connect("data source", "username", "password", properties);

        connect函数如果连接失败会返回undef值, 因此很容易判断连接是否成功:

    my $dbh = DBI->connect("dbi:Oracle:test8i","anysql", "anysql")
                || die("Cannot connect to database!\n");

    my $dbh = DBI->connect("dbi:Oracle:test8i","anysql", "anysql");

    if (!defined($dbh)
    {
       ...
    }

        连接属性常用的有两个: RaiseError和PrintError. RaiseError如果设为1时, 如果DBI调用遇到错误, 将引起程序退出, 设为0时遇到错误后将继续执行后续的代码. PrintError如果设为1时则遇到错误时打印错误信息, 设为0时则不打印错误信息. 那么如何在程序中获得错误信息呢? 可以通过DBI中的变量或连接对象的几函数来获得:

    my $dbh = DBI->connect("dbi:Oracle:test8i","anysql", "anysql",
                {RaiseError=0,PrintError=0,});
    ......
    my $errcode = $DBI::err;
    my $errmsg  = $DBI::errstr;
    my $errcode = $dbh->err();
    my $errmsg  = $dbh->errstr();

        在程序中你可以随时更改PrintError和RaiseError的设定, 如下所示:

    $dbh->{PrintError} = ...;
    $dbh->{RaiseError} = ...;

        对于连接到Oracle这样的数据库时, 如果你不想再和数据库打交道了, 最好还是在代码中切断连接, 并在连接之前发一个commit或rollback(根据你的需要), 如下所示:

    $dbh->commit();
    $dbh->rollback();
    $dbh->disconnect();

        这一部分其实还是比较复杂的, 在这儿就写得太简单了.

  • perl 学习undef and defined

    2009-03-25 14:39:25

    undef值:在给一个标量变量赋值之前就使用这个变量,也不会出现什么问题,因为Perl变量在第一次赋值之前有特别的undef值,作为数值,它和0类似,作为字符串,其类似于空串。但是undef既不是数字也不是字符串,它是一个完全独立的标量值。'W*WA\aNNW0

    `0T^{k!s|0defined函数:要想知道一个值是undef还是非空字符串,可以使用defined函数,它对undef返回假,其他所有情况则返回真。例如:

    &_6BZ9G$n]K:V0 EDA中国门户网站.?!?'iwi

    $madonna = <STDIN>;

    )v1aY1CJ:]f0

    0hFx]2}3P8La0if ( defined($madonna) ) {

    e(uUQ C#~ `T3h9Mj0 EDA中国门户网站]{3W1G;w5eJu

      print "The input was $madonna";

    "?4g?H-O V te v\8aaj0

    .eGk Z1q0zAe'fE0} else {EDA中国门户网站.SM0a~h ? D"I

    EDA中国门户网站7Q:J NCH n&v(Jb4q(z%l

      print "No input available!\n";EDA中国门户网站`kod H J9o|Lm

    EDA中国门户网站;Z,O7^`6\1da9n1a}
Open Toolbar