本书是一本介绍数据结构与算法的优秀书籍。
本书系统介绍了C++面向对象程序设计、算法复杂度、链表、栈、队列、递归、树、图、排序和查找算法、散列技术、数据压缩算法、内存管理等内容;尤其对递归算法进行了深入剖析。在附录中详细介绍了大O符号与标准模板库;在大多数章中提供了相应的实例分析和程序设计作业。
本书适合作为计算机软件专业或其他相关专业的教科书。对于需要参加计算机考试,或者希望自学计算机软件开发的人员也有非常大的帮助。
本书以案例驱动的方式,全面介绍了计算机科学的重要领域——数据结构,并以目前应用最为广泛的C++语言实现相关的算法。书中不仅特别强调了数据结构与算法之间的联系,包括算法复杂度分析,而且介绍了面向对象程序设计环境中的数据结构,重点讲述了隐藏信息封装和分解处理的原理。
与同类教材相比,本书不仅提供了任何软件系统从设计、实现、测试到维护所需的基本概念,详尽地讨论了同类教材中少见的内存管理和数据压缩主题,还将对递归的讨论置于运行时堆栈环境中,使读者对递归有更明晰的理解。此外,本书各章(第2章除外)提供了一个可供测试的程序分析以演示特定的数据结构和算法,并将相关C++标准模板库应用在程序分析中。贯穿全书的C++示例代码演示了数据结构的实践价值,精心设计的程序设计课后作业可以使学生能够学以致用。因此,无论是对数据结构的初学者,还是对有一定基础的学生,本书都是一本不可多得的新型数据结构教材。
第1章 C++面向对象程序设计
1.1 抽象数据类型
1.2 封装
1.3 继承
1.4 指针
1.4.1 指针和数组
1.4.2 指针和复制构造函数
1.4.3 指针和折构函数
1.4.4 指针和引用变量
1.4.5 函数指针
1.5 多态性
1.6 C++和面向对象程序设计
1.7 标准模板库
1.7.1 容器
1.7.2 迭代器
1.7.3 算法
1.7.4 函数对象
1.8 标准模板库中的向量
1.9 数据结构与面向对象编程
1.10 实例分析:随机访问文件
1.11 习题
1.12 程序设计作业
第2章 复杂度分析
2.1 计算复杂度和渐进复杂度
2.2 大O符号
2.3 大O符号的性质
2.4 符号与O符号
2.5 可能的问题
2.6 复杂度举例
2.7 寻找渐近复杂度举例
2.8 最好平均和最坏情况
2.9 阻尼复杂度
2.10 习题
第3章 链表
3.1 单链表
3.1.1 插入
3.1.2 删除
3.1.3 查找
3.2 双链表
3.3 循环链表
3.4 跳跃链表
3.5 自组织链表
3.6 稀疏表
3.7 标准模板库中的链表
3.8 标准模板库中的双端队列
3.9 总结评价
3.10 实例分析:图书馆
3.11 习题
3.12 程序设计作业
第4章 栈与队列
4.1 栈
4.2 队列
4.3 优先队列
4.4 标准模板库中的栈
4.5 标准模板库中的队列
4.6 标准模板库中的优先队列
4.7 实例分析:迷宫问题
4.8 习题
4.9 程序设计作业
第5章 递归
5.1 递归定义
5.2 函数调用与递归实现
5.3 递归调用的剖析
5.4 尾部递归
5.5 非尾部递归
5.6 间接递归
5.7 嵌套递归
5.8 不合理递归
5.9 回溯
5.10 结束总结
5.11 实例分析:递归下降解释器
5.12 习题
5.13 程序设计作业
第6章 二叉树
6.1 树二叉树和二叉搜索树
6.2 二叉树的实现
6.3 搜索一棵二叉搜索树
6.4 树的遍历
6.4.1 广度优先遍历
6.4.2 深度优先遍历
6.4.3 不用栈实现的深度优先遍历
6.5 插入
6.6 删除
6.6.1 通过合并进行删除
6.6.2 通过复制进行删除
6.7 平衡树
6.7.1 DSW算法
6.7.2 AVL树
6.8 自调整树
6.8.1 自重新构造树
6.8.2 “倾斜(splaying)”策略
6.9 堆
6.9.1 将堆作为优先队列
6.9.2 将数组组织为难
6.10 波兰式表示和表达式树
6.11 实例分析:计算单词频率
6.12 习题
6.13 程序设计作业
第7章 多叉树
7.1 B-树家族
7.1.1 B树
7.1.2 B*-树
7.1.3 B+树
7.1.4 前缀B+树
7.1.5 位树
7.1.6 R树
7.1.7 2-4树
7.1.8 在标准模板库中的集和多集
7.1.9 在标准模板库中的映射和多映射
7.2 trie
7.3 结束总结
7.4 实例分析:拼写检查器
7.5 习题
7.6 程序设计作业
第8章 图
8.1 图的表示法
8.2 图的遗历
8.3 最短路径
8.4 环的检测
8.5 生成树
8.5.1 勃赫如夫加算法
8.5.2 克鲁斯卡尔算法
8.5.3 普里姆算法
8.5.4 迪杰斯特拉方法
8.6 连通性
8.6.1 无向图中的连通性
8.6.2 有向图中的连通性
8.7 拓扑排序
8.8 网络
8.8.1 最大流
8.8.2 最小代价的最大流
8.9 匹配
8.9.1 分配问题
8.9.2 非二分图中的匹配
8.10 欧拉(Eulerian)图与汉密尔顿(Hamiltonian)图
8.10.1 Eulerian图
8.10.2 Hamiltonian图
8.11 实例分析:惟一代表(Distinct Representatives)
8.12 习题
8.13 程序设计作业
第9章 排序
9.1 基本的排序算法
9.1.1 插入排序
9.1.2 选择排序
9.1.3 冒泡排序
9.2 决策树
9.3 高效排序算法
9.3.1 希尔排序
9.3.2 堆排序
9.3.3 快速排序
9.3.4 归并排序
9.3.5 基数排序
9.4 标准模板库中的排序
9.5 小结
9.6 实例分析:多项式相加
9.7 习题
9.8 程序设计作业
第10章 散列
10.1 散列函数
10.1.1 除余法
10.1.2 折叠法
10.1.3 平方取中法
10.1.4 提取法
10.1.5 基数转换法
10.2 冲突解决方法
10.2.1 开放定址法
10.2.2 拉链法
10.2.3 桶定址
10.3 删除
10.4 理想散列函数
10.4.1 Cichelli方法
10.4.2 FHCD算法
10.5 可扩展文件的散列函数
10.5.1 可扩展散列
10.5.2 线性散列
10.6 实例分析:使用桶的散列
10.7 习题
10.8 程序设计作业
第11章 数据压缩
11.1 数据压缩的条件
11.2 Huffman编码
11.3 Shannon-Fano编码
11.4 Run-Length编码方式
11.5 Ziv-Lempel编码方式
11.6 实例分析:Huffman方法和Run-Length编码方式
11.7 习题
11.8 程序设计作业
第12章 内存管理
12.1 sequential-fit方法
12.2 Nonsequential-fit方法
12.3 无用单元回收
12.3.1 标记和清除
12.3.2 复制方法
12.3.3 递增的无用单元回收
12.4 结束总结
12.5 实例分析
12.6 习题
12.7 程序设计
附录A 计算大O
A.1 调和数序列n
A.2 函数lg(N!)的近似值
A.3 快速排序中平均情况的大O
A.4 随机二进制树中的平均路径长度
附录B 标准模板库中的算法
数据结构知识是计算机科学教育的一个基本组成部分, 其他许多计算机科学领域都是构建在这个基础之上。 对于想要从事实际的软件设计、实现、测试、维护工作的学生而言, 掌握基本数据结构的知识是非常必要的。 本书介绍的内容将会给从事以上工作的读者提供必要的知识。
本书突出了数据结构中三个重要方面。 首先, 强调了数据结构与它们的算法之间的联系, 包括分析算法的复杂度。 接着, 依照当前的设计和实现范例, 使用面向对象的方法来介绍数据结构。 特别强调了有助于信息的封装与分解的信息隐藏原理。 最后, 本书的一个重要组成部分是数据结构的实现, 它选择C++作为程序语言。
C++语言, 作为C语言面向对象的后裔, 在业界和学术界得到了广泛的应用, 是一种非常优秀的程序语言。 自然地, 我们就选用C什来介绍数据结构。 虽然人们也使用过Modula-2和Ada语言来讲授数据结构, 但是传统上一直是使用Pascal来讲授数据结构。 而且, 由于C++语言在应用程序设计中的广泛使用以及这门语言面向对象的特性, 使用它来讲授数据结构和算法课程(即使是入门级的课程)是非常合理的。
这本书适合作为教材, 它包括旧的ACM(美国计算机协会)课程中CS2和CS7下所列的全部主题。 同样, 它也能满足新的ACM课程中CA202、CD202和CF204的大部分要求。
我们在大多数章节中都包括了一个实例分析, 它阐明了一个完整的。 使用特定算法和数据结构的环境为了说明所论述的主题的广泛应用范围, 这些实例分析都是从计算机科学的不同领域中挑选出来, 包括解释程序。 符号计算和文件处理。
本书自始至终包含了简要的C++程序例子, 举例说明数据结构在实践中的重要性。 然而, 理论分析同样也很重要, 所以算法的介绍都结合了对算法效率的分析。
要特别留意关于递归的介绍, 因为即使是最高明的学生在这个方面往往也会出现一些问题。 经验表明, 如果考虑运行时栈的话, 就可以极好地说明递归的含义。 当对一个递归函数进行跟踪的时候, 我们不但在此章节里面显示出了栈的变化, 而且在其他章节里同样也做到了这一点。 比如说, 如果我们不对系统在运行时栈上所做的工作进行解释的话, 那么就算是一个短小的树遍历函数也可能难于理解。 在讨论数据结构和算法的时候, 脱离系统和纯理论的方法没有什么用处。
这本书讨论的重点是数据结构, 而附带介绍其他一些主题仅仅是为了更好地理解数据结构。 算法都是从数据结构的角度来进行讨论的, 所以读者将无法找到各种算法的全面讨论, 也无法找到完整介绍一个算法所需要的各方面的内容。 然而, 正如前面所提到过的, 本书对递归的介绍具有一定的深度。 另外, 对算法的复杂度分析也比较详细。
第1—8章介绍了许多不同的数据结构以及使用这些数据结构的算法。 并且分析了每一种算法的效率, 同时给出了改进算法的建议。
●第1章介绍了面向对象程序设计的基本原理, 介绍了动态内存分配。 指针的使用以及标准模板库(Standard Template Library, STL)。
●第2章讲述了一些评价算法效率的方法。
●第3章介绍了不同类型的链表, 并且着重阐述了其指针实现。
●第4章介绍了栈。 队列及其应用。
●第5章对递归进行了详细讨论。 讨论了不同类型的递归, 并对其中的一个递归调用进行了剖析。
●第6章讨论了二叉树, 包括二叉树的实现、遍历和搜索。 在这一章中还介绍了平衡树。
●第7章详细介绍了更一般化的树, 比如森林、2—4树、B树。
●第8章介绍图。
第9—12章给出了在前面的章节里所介绍的数据结构的不同应用, 并强调了这些应用在数据结构方面的问题。
●第9章详细介绍了排序, 以及一些基础的和非基础的方法。
●第10章讨论了散列(hashing), 它是搜索算法中最重要的主题之一。 在强调数据结构使用的同时介绍了各种各样的技术。
●第11章讨论了数据压缩算法和相应的数据结构。
●第12章介绍了内存管理的多种方法和相应的数据结构。
●附录A详细介绍了在第2章中提到的大O符号。
●附录B介绍了标准模板库(STL)中的标准算法。
每一章都包含了对一些材料的讨论, 并配以合适的图表和表格。 除第2章外, 所有的章节都包括一个实例分析, 这个实例分析是该章所讨论的特性的一个范例。 所有的实例分析都在PC上用Visual C十十编译器测试过, 只有von Koch snowflake除外, 它是在PC上用Turbo C十十测试的。 每一章最后是一些不同难度的练习题。 除了第2章之外, 所有的章节都包括了课外作业以及最新的相关参考书籍。
第1—6章(2.9、3.4、6.4.3、6.7、6.8节除外)包含了构成任何数据结构课程基础的核心内容。
这些章应该按照顺序来学习。 其后的6章内容可以按照任意次序进行学习。 一个学期的课程可以包括1—6章。 第9章, 以及10.1和10.2节。 整本书可以在一个学年中学习。
本书中的文本示例程序的源代码可以通过WWW站点进行访问, 站点地址为:http://www.mathcs.duq.edu/drozdek/DSinCpp。
第2版的改动
近年来C++最重要的发展就是引入标准模板库(STL)。 STL是一个可重用组件的大集合, 这些可重用组件是一些通用的(模板化)类和函数。 它将程序员从实现许多标准的数据结构和算法的工作中解脱出来, 从而大大地加快了程序设计进程。 然而, 只有很好地理解它们的函数和行为(这包括数据结构的复杂知识), 才能够合理地使用STL组件。 本书的目的就是要向读者提供这样的知识。 由于这个原因, 本书中介绍的许多数据结构并没有或者并不局限于使用STL来实现。 然而, 由于关于如何使用STL的知识对于C什程序员来说是必不可少的, 所以实例分析尽可能地使用了STL组件。 通过这种方式, 读者既可以获得关于数据结构机制的详细知识, 也可以获得由STL提供的。 将来可能要用到的代码实现知识。
因此, 本书的一个新的特色就是通过以下形式介绍STL:
●在1.7节对STL进行了概括性介绍
●在1.8、3.7、3.8、4.4~6.7.1.8、7.1.9、9.4节介绍了与STL件相关的数据结构和算法。
●附录B
●在实例分析中使用STL
其他一些加入到本书的新内容包括:在2.9节中的阻尼(amortized)分析, 在8.9节中对匹配技术的分析, 以及在8.9节和8.10节中对欧拉图和哈密顿图的讨论。
第1章重新编写了对C++的面向对象特性的讨论。 还重新编写了1.4节中对指针的介绍和3.1—3.3节中对指针在链表中应用的介绍。 第4章, 对栈和队列的介绍也作了重大改动, 并且包括了一个新的实例分析。 同样, 在整本书中都存在着许多小的改动。