﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-一步一个脚印-文章分类-数据结构</title><link>http://www.blogjava.net/flysky19/category/20413.html</link><description>java之路</description><language>zh-cn</language><lastBuildDate>Thu, 08 Mar 2007 17:27:02 GMT</lastBuildDate><pubDate>Thu, 08 Mar 2007 17:27:02 GMT</pubDate><ttl>60</ttl><item><title>hash函数学习总结，以及与hashcode()、hashMap的关系</title><link>http://www.blogjava.net/flysky19/articles/102289.html</link><dc:creator>不断前进的小乌龟</dc:creator><author>不断前进的小乌龟</author><pubDate>Tue, 06 Mar 2007 17:26:00 GMT</pubDate><guid>http://www.blogjava.net/flysky19/articles/102289.html</guid><wfw:comment>http://www.blogjava.net/flysky19/comments/102289.html</wfw:comment><comments>http://www.blogjava.net/flysky19/articles/102289.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/flysky19/comments/commentRss/102289.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/flysky19/services/trackbacks/102289.html</trackback:ping><description><![CDATA[
		<br />以前一直觉得hash函数很深奥，上王珊的《数据库实现原理》的时候，似乎明白了一点点，但是到学java<br />的时候，频繁接触到hashcode()，hashMap这些，就总在想这三者之间有关系吗？hash函数是什么？hashcode()，<br />hashMap和hash函数又有什么关系呢？<br /><br />今天终于对这个问题有了初步的学习和理解：<br /><br />1.什么是hash函数：<br />1）来自：http://beyond911.bokee.com/1047973.html<br /><br />什么是HASH函数(经典例子)                                   <br /><br />让我们先来了解一些基本知识，作作预热只有这样才能更好的了解hash。<br /><br />Hash，一般翻译做"散列"，也有直接音译为"哈希"的，就是把任意长度的输入（又叫做预映射， pre-image），通过散列算法，变换成固定长度的输出，该输出就是散列值。这种转换是一种压缩映射，也就是，散列值的空间通常远小于输入的空间，不同的输入可能会散列成相同的输出，而不可能从散列值来唯一的确定输入值。<br /><br />简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。<br /><br />HASH主要用于信息安全领域中加密算法，他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说，hash就是找到一种数据内容和数据存放地址之间的映射关系<br /><br />2）来自：http://www.hour41.com/blog/hour41/entry/200701255<br />计算理论中，没有Hash函数的说法，只有单向函数的说法。所谓的单向函数，是一个复杂的定义，大家可以去看计算理论或者密码学方面的数据。用“人类”的语言描述单向函数就是：如果某个函数在给定输入的时候，很容易计算出其结果来；而当给定结果的时候，很难计算出输入来，这就是单项函数。各种加密函数都可以被认为是单向函数的逼近。Hash函数（或者成为散列函数）也可以看成是单向函数的一个逼近。即它接近于满足单向函数的定义。<br /><br />Hash函数还有另外的含义。实际中的Hash函数是指把一个大范围映射到一个小范围。把大范围映射到一个小范围的目的往往是为了节省空间，使得数据容易保存。除此以外，Hash函数往往应用于查找上。所以，在考虑使用Hash函数之前，需要明白它的几个限制：<br /><br />1. Hash的主要原理就是把大范围映射到小范围；所以，你输入的实际值的个数必须和小范围相当或者比它更小。不然冲突就会很多。<br />2. 由于Hash逼近单向函数；所以，你可以用它来对数据进行加密。<br />3. 不同的应用对Hash函数有着不同的要求；比如，用于加密的Hash函数主要考虑它和单项函数的差距，而用于查找的Hash函数主要考虑它映射到小范围的冲突率。<br /><br />3）自己的总结：<br />   a）hash函数就是把任意长度的输入（又叫做预映射， pre-image），通过散列算法，变换成固定长度的输出，该输出就是散列值。这种转换是一种压缩映射，也就是，散列值的空间通常远小于输入的空间，不同的输入可能会散列成相同的输出，而不可能从散列值来唯一的确定输入值。<br />例如，散列算法为求余的hash函数。<br />   b）实际中的Hash函数是指把一个大范围映射到一个小范围。把大范围映射到一个小范围的目的往往是为了节省空间，使得数据容易保存。<br />   c）在数据结构中，hash就是找到一种数据内容和数据存放地址之间的映射关系，比如，31对10求余后得1，就把31存放到第一个桶里（或者是第一块内存单元中），即把数据和存放地址建立映射关系；<br />   d）所以，有了数据内容和数据存放地址之间的映射关系，Hash函数往往应用于查找上。不过，利用hash函数的查找跟以前自己理解的不同，以前自己以为是通过hash函数就能立即找到存储地址，就像HashMap中根据key立即能找到value一样，其实不是这样的，hash函数只不过是根据散列算法和解决冲突的方法来提供一种定位和查找的方式，hashmap中根据可以马上找到value值是理所当然的，但是根据hash函数找到key值就不是立即的了。当然，为了方便查找，尽量使得hash函数无冲突，可以唯一确定地址是最理想的。娃哈哈，终于弄清楚这一点了！<br />   e）Hash函数是指把一个大范围映射到一个小范围，所以hash函数是求余之类的压缩函数，（比如，11，13的范围压缩为1，3），而不是10x＋7这样的扩散函数，（比如，11，13的范围扩散为117，137）；<br />   f）由于Hash逼近单向函数；所以，你可以用它来对数据进行加密。<br />   g）不同的应用对Hash函数有着不同的要求；比如，用于加密的Hash函数主要考虑它和单项函数的差距，而用于查找的Hash函数主要考虑它映射到小范围的冲突率。<br /><br />2.散列表相关知识的系统学习：<br />数据结构自考网：http://student.zjzk.cn/course_ware/data_structure/web/chazhao/chazhao9.4.1.htm<br /><br />3.  JDK中HashMap的分析<br />1）来自：http://chinakite.javaeye.com/blog/25073<br />2）请问hashtable类里面的hash函数是怎么样的？<br />来自：http://topic.csdn.net/t/20020311/09/567386.html<br /><br />他是调用每个类自己本身的hashCode的方法来确定的  <br />  public   synchronized   Object   put(Object   key,   Object   value)   {  <br />  ...  <br />  int   hash   =   key.hashCode();//就是这里了  <br />  int   index   =   (hash   &amp;   0x7FFFFFFF)   %   tab.length;  <br />  ...  <br />          }  <br />  详细请看java的源文件<br /><br /><br />String的散列值是由内容转换来的，Object类的却省散列函数返回对象地址转换来的散列值。<br /><br />4.面试题：<br />来自：http://www.javaref.cn/topics/Question/10566.html<br /><br />问题：<br /><br />a)请问哈希表 (hashtable) 是如何存储数据的 ？<br /><br />答案： Hashtable 是用来存储 key 和 value 对的数据结构 , 根据设定的 hash 函数 H(key) 和处理冲突的方法将一组关键字（ key ）映象到一个有限的连续的地址集（区间）上，并以关键字在地址集中的“象”作为记录在表中存储位置，这种表便成为 hashtable.<br /><br />b)是否两个键值通过 hash 函数产生的映射地址会一样？怎么办？<br /><br />答案 : 是，一般情况下，完全避免冲突是很难的。因为通常关键字集合会比目标地址空间大。哈希函数要尽量避免冲突（避免不同的关键字产生相同的 hash 值），使一组关键字的哈西地址尽可能的均匀分布在整个地址区间。所以有一些冲突处理方法：开放定址法，再哈希法，链地址法（用链表保存冲突的值），公共溢出区。  <br /><br />关于哈希表，有个与实际编程更密切的问题可以一问：为保证逻辑上的正确性，哈希表对可以作为键值的类型有什么要求？  C++：除容器对元素类型的标准需求外，还需overload == 和 &lt; Java：需override equals(逻辑上的正确性)和hashCode(性能) C#：需override Equals(逻辑上的正确性)和HashCode(性能)     <br /><br /><br /><br /><img src ="http://www.blogjava.net/flysky19/aggbug/102289.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/flysky19/" target="_blank">不断前进的小乌龟</a> 2007-03-07 01:26 <a href="http://www.blogjava.net/flysky19/articles/102289.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>快速排序学习总结</title><link>http://www.blogjava.net/flysky19/articles/102285.html</link><dc:creator>不断前进的小乌龟</dc:creator><author>不断前进的小乌龟</author><pubDate>Tue, 06 Mar 2007 16:28:00 GMT</pubDate><guid>http://www.blogjava.net/flysky19/articles/102285.html</guid><wfw:comment>http://www.blogjava.net/flysky19/comments/102285.html</wfw:comment><comments>http://www.blogjava.net/flysky19/articles/102285.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/flysky19/comments/commentRss/102285.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/flysky19/services/trackbacks/102285.html</trackback:ping><description><![CDATA[快速排序学习总结<br /><br />昨天花了一天的时间学习总结冒泡排序，今天下决心把数据结构的相关内容，各种排序，树，<br />查找算法等都大概学习了一遍，把时间复杂度和空间复杂度等概念理清了，终于有了一点点<br />的踏实感，因为自己没考研，本科基础也没打牢，总感觉自己跟任何一个人都有一大段的差距，<br />连写程序和找实习工作都觉得自己很没信心，缺少底气，因为一些研究生里面大家都会的基础<br />知识我丝毫不懂，真是太打击自己了！！<br /><br />自己的近期安排：<br /><br />今天总结了快速排序，hash函数等知识之后，明天开始就要踏踏实实的看软件测试的论文了！！<br />在看论文的同时，如果想练练手，最好坚持把上学期的“决策树”的作业实现了，这样自己<br />就有信心面对一切了！！<br /><br />另外，好好上李老师数据挖掘的课！千万不要迟到，最好6点10分就要去到新信息楼！好好学习，<br />去图书馆借几本好书，提前学习和准备！<br /><br />还有，明天别忘了问问解婷婷和杨惠她们的英文论文都是从哪下的？怎么搜索，比如，Proges的使用？<br />怎么知道哪些英文论文比较好？<br /><br />好了，现在言规正传，学习快速排序：<br /><br />快速排序和冒泡排序都是交换排序类型，快排的算法思想是：<br />每次选一个基准值（比如第一个数），让小于这个基准值的数向左移，大于这个基准值的数向右移，<br />一趟移动之后，这个基准值就定位到合适的位置了，它的左边的数比它小，右边的数比它大；一趟可以<br />定位一个数，左边和右边分别递归，n-1趟后所有数就都定位到合适位置了！<br /><br />算法分析<br />    　快速排序的时间主要耗费在划分操作上，对长度为k的区间进行划分，共需k-1次关键字的比较。<br /><br />（1）最坏时间复杂度<br />    　最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录，划分的结果是基准左边的子区间为空(或右边的子区间为空)，而划分所得的另一个非空的子区间中记录数目，仅仅比划分前的无序区中记录个数减少一个。<br />    　因此，快速排序必须做n-1次划分，第i次划分开始时区间长度为n-i+1，所需的比较次数为n-i(1≤i≤n-1)，故总的比较次数达到最大值：<br />               Cmax = n(n-1)/2=O(n2)<br />    　如果按上面给出的划分算法，每次取当前无序区的第1个记录为基准，那么当文件的记录已按递增序(或递减序)排列时，每次划分所取的基准就是当前无序区中关键字最小(或最大)的记录，则快速排序所需的比较次数反而最多。<br /><br />（2） 最好时间复杂度<br />    　在最好情况下，每次划分所取的基准都是当前无序区的"中值"记录，划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数：<br />        0(nlgn)<br />注意：<br />    　用递归树来分析最好情况下的比较次数更简单。因为每次划分后左、右子区间长度大致相等，故递归树的高度为O(lgn)，而递归树每一层上各结点所对应的划分过程中所需要的关键字比较次数总和不超过n，故整个排序过程所需要的关键字比较总次数C(n)=O(nlgn)。<br />    　因为快速排序的记录移动次数不大于比较的次数，所以快速排序的最坏时间复杂度应为0(n2)，最好时间复杂度为O(nlgn)。<br /><br />具体的算法描述、代码实现、算法分析和动画演示参见：<br />数据结构自考网<br />http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.3.2.4.htm<br /><br /><br />附排序的面试题：<br />来自：http://www.javaref.cn/topics/Question/10566.html<br />问题：  <br /><br />a)冒泡 (bubble sort) 和快速排序 (quick sort) 的区别？它们的时间复杂度？<br /><br />冒泡：每趟排序将最大值安置到最后一个位置上，时间复杂度为 O(n 平方 ). <br />快速排序法是对起泡排序法的一种改进，<br />基本思想是通过一趟排序将待排序纪录分割成独立的两部分，其中一部分纪录的关键字<br />均比另一部分纪录的关键字小，则可以分别对这两部分纪录继续进行排序，以达到整个序列有序。<br />时间复杂度为 O(NlogN).  <br /><br />疑问：快排的最坏时间复杂度是O(n 平方 )，最好时间复杂度到底是 O(Nlog2N)，还是 O(NlgN)？？<br />按照“数据结构自考网”的分析应该是O(Nlog2N)，但是《数据结构》书上277上的分析，似乎O(Nlog2N)<br />和O(NlgN)都是合理的，到底是什么呢？明天问问解婷婷吧。<br /><br />b)在什么情况下快速排序的效果最差？ 答案：输入数据逆序排列时效果最差，蜕化成冒泡     <br /><img src ="http://www.blogjava.net/flysky19/aggbug/102285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/flysky19/" target="_blank">不断前进的小乌龟</a> 2007-03-07 00:28 <a href="http://www.blogjava.net/flysky19/articles/102285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>冒泡排序学习总结</title><link>http://www.blogjava.net/flysky19/articles/102043.html</link><dc:creator>不断前进的小乌龟</dc:creator><author>不断前进的小乌龟</author><pubDate>Mon, 05 Mar 2007 17:58:00 GMT</pubDate><guid>http://www.blogjava.net/flysky19/articles/102043.html</guid><wfw:comment>http://www.blogjava.net/flysky19/comments/102043.html</wfw:comment><comments>http://www.blogjava.net/flysky19/articles/102043.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/flysky19/comments/commentRss/102043.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/flysky19/services/trackbacks/102043.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.				参考资料：								1				）谭浩强				《				c				程序设计》				 124				页								2				）数据结构自考网（				very good				）								http://student.zjzk.cn/course_ware/data_structure/web/...&nbsp;&nbsp;<a href='http://www.blogjava.net/flysky19/articles/102043.html'>阅读全文</a><img src ="http://www.blogjava.net/flysky19/aggbug/102043.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/flysky19/" target="_blank">不断前进的小乌龟</a> 2007-03-06 01:58 <a href="http://www.blogjava.net/flysky19/articles/102043.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>