你对数据结构的理解达到了什么层次?你需要达到的层次是什么?

我们对数据结构的理解达到了什么层次?我们需要达到的层次是什么?

第0层次:“数据结构是什么?”

第0层次是指对数据结构一无所知。我们从来没有听说过数据结构,从来没有注意到对数据进行合理的组织能够大幅度提升程序的运行效率。

第1层次:“我听说过散列表,虽然不太明白,但感觉它很强大。”

第1层次是鸡尾酒会[2]水平的认识度。在达到这个层次后,我们至少讨论过基本的数据结构。我们听说过一些像搜索树和散列表这样的基本数据结构,或许还注意到它们所支持的一些操作。但是,在程序中使用它们或者在技术面试中熟练分析它们仍然非常困难。

第2层次:“这个问题看来需要用堆才能搞定。”

在进入第2层次后,我们开始进入状态。我们已经熟练地掌握了数据结构的基础知识,可以在程序中熟练地使用各种数据结构,并对哪种类型的数据结构适用于哪种类型的编程任务有着良好的感觉。

第3层次:“我只用自己手工定制的数据结构。”

第3层次是最高级的层次,适合专家级程序员和计算机科学家,他们已经不满足仅仅以客户的身份使用现有的数据结构的实现。在进入这个层次之后,我们对基本数据结构的所有细节了如指掌,对它们的实现方式也是烂熟于心。

最大的提升空间就是提升到第2层次。大多数程序员总会在某个时刻需要以客户的身份使用基本的数据结构,如堆、搜索树和散列表。《算法详解(卷1)》第4章至卷2第6章的主要目标是帮助读者把数据结构的理解能力提升到这个层次,并把注意力集中在它们所支持的操作以及它们的标准应用上。大多数现代编程语言的标准库提供了这些数据结构,我们可以在程序中便捷地使用它们。

高级程序员有时候需要从头实现某种数据结构的自定义版本。第4-12章都包含一个关于这些数据结构的典型实现的小节。这些小节适合那些希望把自己对数据结构的理解提升到第3层次的读者。

《算法详解(卷1)》第4章至卷2第6章到底有哪些内容?

你对数据结构的理解达到了什么层次?你需要达到的层次是什么?_第1张图片

  • 主方法

本章讨论决定递归算法的运行时间的“黑盒”方法,并讨论递归算法的一些关键特性,然后推导出算法的运行时间上界。这种“主方法”适用于读者所看到的绝大多数分治算法,包括Karatsuba的整数相乘算法(第1.3节)和Strassen的矩阵相乘算法(第3.3节)[1]。本章还将描述算法研究中一个更通用的理论:对新奇的算法思路进行适当的评估常常需要不直观的数学分析。

在第4.1节介绍了递归过程之后,我们将在第4.2节提供主方法的正式定义,并观察它的6个应用例子(第4.3节)。第4.4节讨论了主方法的证明,着重强调它的3种著名情况背后的含义。这个证明非常优雅地建立在第1.5节对MergeSort算法分析的基础之上。

  • 快速排序(QuickSort

本章讨论快速排序(QuickSort)。如果要排个“算法名人堂”,快速排序应该能够第一批入选。在高级层次上地描述了该算法的工作原理之后(第5.1节),我们讨论怎样在线性时间内根据一个“基准(pivot)元素”对数组进行划分(第5.2节),并讨论如何选择良好的基准元素(第5.3节)。第5.4节讨论了随机化的QuickSort,第5.5节证明了它对n个元素的数组进行排序的渐进性平均运行时间为O(nlogn)。第5.6节证明不会有任何“基于比较”的排序算法能够比O(nlogn)更快,从而为排序的讨论画上了一个完美的句号。

  • 线性时间级的选择

本章研究选择问题,它的目的是在一个未排序的数组中寻找第i小的元素。如果使用排序方法,很容易在O(n log n)时间内解决这个问题,但是我们想要做得更好。

第6.1节描述了一种极端实用的随机化算法,它的精神与随机化的QuickSort非常相似,但它的平均运行时间达到了线性时间。第6.2节提供了这个算法的优雅分析,有一种很好的方法可以按照简单的掷硬币试验来推进这个算法,证明它具有线性时间期望值。

倾向于理论的读者可能会疑惑怎么可能在不借助随机化的情况下在线性时间内解决选择问题。第6.3节描述了该问题的一种著名的确定性算法,参与该算法的图灵奖得主多于我所知道的其他任何算法的。它是一种确定性的算法(即不允许使用随机化),建立在一种独特的“中位的中位元素”思路之上,以保证选择了良好的基准元素。第6.4节证明了它的线性时间上界,这可不是个简单的任务!

本章假设读者已经熟悉第5.2节的可以在线性时间内围绕一个基准元素对数组进行划分的Partition子程序,并对基准元素的好坏具有良好的直觉。

  • 图的基础知识免费

本章将会简单地介绍图的概念、图的用途以及计算机程序中常见的图表示形式。接下来的两章将深入讨论一些著名的与图有关的实用算法。

  • 图的搜索及其应用

本章讨论与图的搜索及其应用有关的基础知识。本章讨论的内容有一个特点,就是我们将要讨论的所有算法都具有令人惊叹的高速度(具有较小常数因子的线性时间),但它们的工作方式并不是特别容易理解。本章的重点——只用两遍深度优先的搜索就完成了有向图的强连通分量的计算(见2.6节),生动地描述了高速的算法往往需要我们对问题的结构具有深刻的洞察力。

本章首先是概述内容(见2.1节),描述了一些为什么要关注图的搜索的原因,并描述了在不进行任何冗余工作的前提下对图进行搜索的一种通用策略。本节还对两种重要的搜索策略——宽度优先的搜索(BFS)和深度优先的搜索(DFS)——进行了高层次的描述。2.2节和2.3节详细描述了BFS,包括它在最短路径计算和无向图的连通分量的计算方面的应用。2.4节和2.5节深入探讨了DFS,并讨论了如何用它计算有向无环图的拓扑顺序(相当于在遵循优先级约束的前提下对任务进行序列化)。2.6节使用DFS在线性时间内计算有向图的强连通分量。2.7节解释了为什么这种快速图元可用于对Web的结构进行探索。

  • Dijkstra最短路径算法

Dijkstra最短路径算法[1]。这个算法适用于边的长度均不为负数的有向图,它计算从一个起始顶点到其他所有顶点的最短路径的长度。在正式定义这个问题(3.1节)之后,我们讲解这个算法(3.2节)以及它的正确性证明(3.3节),然后介绍一个简单直接的实现(3.4节)。在第4章中,我们将看到这种算法的一种令人惊叹的快速实现,它充分利用了堆这种数据结构。

  • 堆数据结构

本书剩余的3章分别讨论3种极为重要并且广泛使用的数据结构:堆、搜索树和散列表。我们的目标是了解这些数据结构所支持的操作(以及它们的运行时间),并通过应用实例培养读者识别哪种数据结构适用于哪种类型问题的能力。另外,我们还可以对它们的幕后实现方式有所了解。我们首先讨论堆,这种数据结构可以帮助我们实现最小值或最大值的快速计算。

  • 搜索树

与堆相似,搜索树也是一种存储一个不断变化的与键相关联的对象(可能还有大量其他数据)集合的数据结构。它维护它所存储的对象的整体顺序,并支持比堆更丰富的操作集合,其代价就是需要更多的额外空间,并且有些操作的运行速度比堆更慢一些。在讨论“为什么(应用)”和“怎么样(可选的实现细节)”之前,我们首先讨论“什么(即支持的操作)”。

  • 散列表和布隆过滤器

在本书的最后一章,我们讨论一种极其实用并且被广泛使用的数据结构,即散列表(又称散列映射)。与堆和搜索树相似,散列表维护一组不断变化的与键相关联的对象(每个对象可能还包含许多其他数据)。与堆和搜索树不同,散列表并不维护与顺序有关的信息。散列表的存在意义是因为它支持超级快速的搜索,在这种场合下又称为查找。散列表可以告诉我们数据结构中是否存在某个对象,并且真的能够做到极端快速(远远快于堆或搜索树)。与往常一样,我们首先讨论散列表所支持的操作(见6.1节),然后讨论它的应用(见6.1节)以及一些可选的实现细节(见6.3节和6.4节)。6.5节和与6.6节讨论了布隆过滤器,它与散列表相似,它需要的空间更少,但付出的代价是偶尔会出现错误。

选择正确的数据结构

在软件的主要部分中,经常会用到数据结构。因此,对于严谨的程序员而言,知道在什么时候以及怎样使用数据结构是一项重要的基本技巧。数据结构的存在意义是它可以对数据进行组织,使我们可以快速、实用地访问数据。我们已经看到了数据结构的一些例子。2.2节介绍的用于实现线性时间的宽度优先的搜索的队列数据结构采用了线性形式组织数据,可以实现在常数级时间内从队列的头部删除对象或者在队列的尾部添加对象。2.4节介绍了在深度优先的搜索的迭代性实现中起到重要作用的堆栈数据结构,它允许我们在常数级时间内在堆栈的头部添加或删除对象。

我们可以使用的数据结构还有很多。在本系列图书中,我们将看到堆、二叉搜索树、散列表、布隆过滤器以及并查集(union-find,详见本系列图书的卷3)。为什么要列出这几个看上去颇为复杂的例子呢?因为不同的数据结构支持不同的操作集合,所以它们适用于不同类型的编程任务。例如,宽度优先的搜索和深度优先的搜索具有不同的需求,分别由两种不同的数据结构满足。Dijkstra最短路径算法的快速实现(见4.4节)还有一些不同的需求,需要使用更为复杂的堆数据结构。

不同的数据结构的利弊是什么?我们应该怎样在程序中选择具体的数据结构呢?一般而言,一种数据结构所支持的操作越多,这些操作的速度也就越慢,它们所需要的空间开销也就越大。爱因斯坦的这句名言恰如其分地说明了这一点:“尽可能让事情变得简单,但不能过于简单。”

在实现一个程序时,重要的是认真考虑它需要频繁执行的操作。例如,我们是不是只关心一些对象是否存储在一个数据结构中?或者还需要以一种特殊的方式对它们进行排序?一旦理解了程序的需要,我们就可以遵循精简原则,选择一种支持所有必要的操作同时又没有太多不必要操作的数据结构。

精简原则
选择能够支持应用程序所需要的所有操作的最简单数据结构。

你可能感兴趣的:(数据结构,算法,计算机科学)