李晓明
(北京大学 计算机系,北京 100871)
近一年来,由于参与一套高中信息科技教材的编写,回过头来思考了一些关于算法和数据结构的认识问题,其中就包括本文的标题。
记得40年前上大学的时候,上郭福顺老师教的数据结构课,对“数据结构”这个术语是感到完全新奇的。因为“数据结构”不像“高等数学”,至少以前还听说过“数学”,于是“高等数学”也就不陌生(尽管其内容和原来知道的数学很不一样)。由此我联想到,在给中学生介绍数据结构相关知识的时候,是不是首先得回答一下“为什么会有‘数据结构’”这个问题,说说“数据结构”这样一个概念在计算机科学中的意义。
为此,首先翻书,国内的、国外的,在相关的资料遍历之后发现,不少作者也都感觉需要在一开始就谈谈“数据结构”的重要性,于是常常会有几句相关的话放在绪论甚至前言中。概括起来大致有这样几种情况。其一,不回答为什么会有“数据结构”,只是讲“数据结构”作为一门课程在计算机专业课程中的基础地位;其二,引用Niklaus Wirth的经典观点:程序=算法+数据结构,佐证学习“数据结构”概念的重要性;其三,一开始只是讲“什么是数据结构”,而让对“为什么会有‘数据结构’”的认识隐含在其中。例如,维基百科上关于“data structure”的描述就是后者的一个代表。
In computer science, a data structure is a data organization, management and storage format that enables efficient access and modification. More precisely, a data structure is a collection of data values, the relationships among them, and the functions or operations that can be applied to the data.
翻译过来就是:
计算机科学中的数据结构,是数据组织、管理和存储的形态,以支持对数据的高效访问和修改。更准确地讲,一个数据结构是由若干数据、它们之间的关系以及能在其上施行的操作构成的一个集合。
其中的“以支持对数据的高效访问和修改”应该就是关于数据结构的目的性或意义的隐含。这段话一句句读来应该找不出错。我的看法在于它描绘了一种“重心”偏离的意境,容易对回答“为什么会有‘数据结构’”这样的问题产生误导,所以愿在此和有兴趣的同仁商榷。
首先,关键问题是这里提到的“数据”指的是什么?是计算机应用层的数据还是计算机程序在运行时“看到的”任何0或1串?我认为大多数人的理解会是前者(在一些教材的描述中明显是这个意思),尤其对刚开始接触计算机科学知识的人更是如此(恰恰是他们应该作为这些描述的读者对象)。于是,这里给出的画面就是,数据结构是将计算机应用数据按照某种方式组织起来的结构,以便对它们进行高效处理。
需不需要这么做?当然需要,但我以为那不是“数据结构”的主要意义。
虽然数据结构的采用在许多情况下就是应用数据的一种组织,如工程计算中用的数组,每个元素就对应一个现实中的物理量;社会网络分析中的图,每一个节点就对应一个人的有关属性参数。但在我看来,计算机程序用数据结构,本质上是为了支持算法逻辑,而不是应用层数据的组织。常常,一个数据结构的采用与应用层数据并没有直接的关系,而是旨在对计算过程的有效引导。
稍微考虑一下就能想到许多例子。例如,为了实现广度优先搜索,典型做法是用一个队列(一种数据结构)控制搜索的过程,而不是把被搜索的数据组织成队列结构;再如二叉树的采用,常常就是因为算法逻辑的需要,树中非叶节点包含的,就不是输入的应用层数据,而是程序运行中产生的中间数据或控制数据。也许我们可以说,数据结构更多地是为了“控制”,而不是为了“数据”。为了“提高效率”没错,但要认识到既包括执行效率,又包括编程效率。
因此,显式或隐含强调数据结构是应用问题数据的组织形态,在我看来,是学理重心的偏离。如果要强调数据,则应该指明是程序“看见的”、编程人员体会得到的数据含义会更有教益。那样的数据除了程序的输入数据外,还包含中间结果数据和控制数据。
简言之,在数据结构课程(和教材)中,我们应该开宗明义地讲数据结构是为算法逻辑服务的(而不讲是应用数据之间关系的表达),从而让学生从一开始就试图体会,并在后续学习过程中不断磨砺一种更有价值的观念,这种磨砺包括认识到是计算机存储器线性编址的简单性与程序逻辑的复杂性之间的鸿沟,导致了数据结构的必要性,等等。我想,这也是对Niklaus Wirth的“程序=算法+数据结构”的一种恰当解释。