数据结构讨论课1-什么是数据结构

实际问题:假设你在一家杂货店上班。有顾客来买东西时,你得告诉他商品的价格。

解决方案:

方案一:在一个本子中查找价格。

1.如果本子的内容不是按字母顺序排列的,你可能为查找苹果(apple)的价格而浏览每一行,但这需要很长时间(时间复杂度为O(n))。

2.如果本子内容是按字母排序的话你可以用二分法查找,二分法查找是很快的(时间复杂度为O(logn))。

但作为收银员,在本子上查找价格是一件很痛苦的事情哪怕本子的内容是有序的。在查找价格时,你都感觉到顾客的怒气。

方案二:看来真的需要一名能够记住所有商品价格的售货员,这样你就不用查找了,问她就能马上知道答案。不管商品有多少,这位雇员(假设有她的名字为Maggie)报出任何商品价格速度比二分法还快(时间复杂度为O(1))。

下面从数据结构的角度来看看,你可以用一个二维数组来存储商品名和商品价格,如果这个数组按商品名排序,就可以用二分法查找商品的价格。然而,你希望查找商品价格能像Maggie那么快,这是散列表的用武之地。

Ps:散列函数是将输入映射到数字的函数,通俗来说,无论你给散列函数什么数据,它都还给你一个数字。你可能觉得散列函数没有什么规律,但其实散列函数必须满足一些要求:

1.它必须是一致的。例如,假设你输入apple时得到的是4,那么每次输入apple时,得到的都必须是4。如果不是这样,散列表将毫无用处。

2.它应将不同的输入映射到不同的数字。例如,如果一个散列函数不管输入是什么都返回1,它就不是好的散列函数。最理想的情况是将不同的输入映射到不同的数字。

哈希函数的五种常用构造方法:

1.数字分析法

2.平方取中法

3.分段叠加法

4.除留余数法

5.伪随机数法

散列函数将输入映射为数字,这有何用途呢?你可使用它来打造你的“Maggie”!

算法步骤:

首先创建一个空数组。你将在这个数组中存储商品的价格。

下面将apple作为输入交给散列函数,来将苹果的价格加入到这个数组中。散列函数的输出为3,因此我们将苹果的价格存储到数组的引索3处。

下面将milk作为散列函数的输入,来将牛奶(milk)的价格存储到数组中。散列的输出为0,因此我们将牛奶的价格存储到数组的引索0处。

不断地重复这个过程,最终整个数组将填满价格。

算法分析:现假设需要知道鳄梨(avocado)的价格,你无需在数组中查找,只需要将avocado作为输入交给散列函数,它将告诉你鳄梨的价格存储在引索4处。果然你在那里找到了。时间代价为O(1)。散列函数准确的指出了价格的存储位置,你根本不用查找!原因如下:

1.散列函数总是将同样的输入映射到相同的引索

2.散列函数将不同的输入映射到不同的引索

3.散列函数找到数组有多大,只返回有效的引索。

刚才你就打造了一个“Maggie“!你结合使用散列函数和数组创建了一种被称为散列表(hash table)(也被称为哈希表,散列映射,映射,字典和关联数组)的数据结构。散列表是一种包含额外逻辑的数据结构。数组和链表都被直接映射到内存,但散列表更复杂,它使用散列函数来确定元素的存储位置。

应用案例

1.模拟映射关系,将散列表用于查找

例如手机内的电话簿,其中每一个姓名都有对应的电话号码

2.防止重复

例如,假设你负责一个投票站,一个人只能投一票,就可以建立一个散列表来避免重复投票,因为散列函数对于同一个人会返回同一个引索,你就可以很快地判断这个人是否投过票。

3.缓存/记住数据,以免服务器再通过处理来生成他们

例如,你有一个侄女,总是没完没了地问你有关星球的问题,每次你都要通过百度搜索来告诉她答案,这需要几分钟。现在假设她老是问你月球离地球有多远,很快你就记住了是238900英里,这样你就不必百度,而是直接告诉她答案。这就是缓存的工作原理:网站将数据记住,而不再重新计算。

小结:经典数据结构是所有问题的基础,高级数据结构与算法是在这些经典数据结构与算法的基础上进行组合和灵活运用的结果。合适的数据结构可以使问题的解决更高效。

下附数据结构图一张:

参考文献

[1] 吴昊,蒋斌,廖波,朱宁波.ACM程序设计培训教程。北京:中国铁道出版社,2007.8.

[2] Aditya Bhargava. Grokking Algorithms.北京:人民邮电出版社,2018.4

[3] 钟志永,姚珺.大学计算机应用基础重庆重庆大学出版社2012215

[2] 彭军、向毅主编.数据结构预算法人民邮电出版社2013年

在这里插入图片描述