清华大学计算机系 殷人昆
《数据结构》课程是计算机科学与技术专业的一门重要的专业基础课。用数字计算机解决任何应用问题都离不开数据表示和数据处理,使用面向对象技术开发软件,数据表示更成为软件构成的基础。而数据表示和数据处理的核心问题之一就是数据结构及其操作的实现。这正是《数据结构》课程的内容。从这个意义上来说, 《数据结构》课程在知识学习和技能培养两个方面都处于关键地位。
一、课程要求
《数据结构》是电大计算机科学与技术专业本科生的专业基础课程之一,该课程是后续课程如操作系统、计算机网络等课程的先修课程,在整个教学体系中占据非常重要的地位。该课程主要讨论在软件开发中如何进行数据结构和算法的设计。因此,用抽象数据类型以及面向对象的方法组织、存储各种类型的数据是本课程的重点,也是学员需要掌握的重点。面向对象方法以及结构化技术都是建立高质量软件的技术,通过《数据结构》课程的学习和实践,可以加深对这些先进软件开发方法的理解和体会。因此,《数据结构》课程的任务是按照软件工程思想,介绍用面向过程和面向对象方法进行数据设计和程序设计的基本思想,在必要的课程实践中逐步熟练掌握。
通过本课程的学习,应达到知识和技能两方面的目标:
1、知识方面:从数据结构的类定义和对象的使用,以及存储表示和操作的实现两个层次,系统地学习和掌握常用的基本数据结构(包括数组、顺序表、多项式、字符串、链表、栈与队列、优先级队列、广义表、树与森林、二叉树、堆、集合、图、搜索结构、索引结构、散列结构等)及其不同的实现,了解并掌握分析、比较和选择不同数据结构、不同存储结构、不同算法的原则和方法,为后续课程的学习打好基础。
2、技能方面:系统地学习和掌握对象类的设计方法和面向对象的程序设计风格,在不同的存储结构上实现的算法的设计思想,从中体会和掌握选择结构的方法和算法设计的思考方式及技巧,提高分析问题和解决问题的能力。
二、考核要求
1、命题依据
命题依据是电大计算机科学与技术专业本科生《数据结构教学大纲》。 2、考核要求
本课程考核的重点是考察学员对各种数据结构的理解程度和基于这些数据结构进行算法设计的能力。具体考核要求分为几个层次:
理解:要求学员理解各种数据结构的层次、各种数据结构的特点、各种数据结构设计的基本思想。
掌握:要求学员能较好地理解和运用一两个知识点进行简单的算法设计。
综合应用:要求学员能综合运用多个知识点的内容进行比较复杂的应用程序开发。
3、命题原则
在教学大纲和考核说明所规定的目的、要求和内容范围之内命题。
1
试题的考察要求覆盖面广,并适当突出重点。
试题兼顾各个能力层次,理解占40%,简单运用占40%,综合运用占20%。试题的难易程度和题量适当,按难易程度分为四个层次:容易占20%,较易占30%,较难占30%,难占20%。
4、试题题型
单选题:给出一些有关数据结构性质、特点及一些简单算法性能的不完全叙述,要求学员从题后给出的供选择的答案中选择合适的答案,补足这些叙述。
填空题:给出程序说明及一段部分语句缺失的程序,让学员补充成为完整的程序。 简答题:应用作图方法或简单计算,使用给定数据建立或操作一些数据结构。 理解问答题:给出一段程序,就程序回答一些问题,如给出程序运行结果、根据要求进行适当修改等。
综合算法题:给出算法设计要求,编制出部分算法程序,用来考察几个知识点的综合应用。
具体形式见后面所附“试题类型及规范解答举例”。
5、考核形式
采用期末考核与平时成绩相结合的方式。其中
平时考核:视平时作业(包括笔做题和上机题)的完成情况给分,占
考核总成绩的20%,能够按时、按质、按量完成平时作业者方可得满分;
期末考核:采用笔试,它占总成绩的80%,考试方式为闭卷,答题时
限120分钟。
以上两个成绩累计60分以上(包括60分)算考核通过。
附录:试题类型及规范解答举例
一、单选题 [从供选择的答案中选出正确的答案,将其编号填入括号( )中]
1、在数据结构的讨论中把数据结构从逻辑上分为( A )。
2、采用线性链表表示一个向量时,要求占用的存储空间地址( B )。 3、采用顺序搜索方法查找长度为n的顺序表时,搜索成功的平均搜索长度为( C )。
4、在一个单链表中,若q结点是p结点的前驱结点,若在q与p之间插入结点s,则执行( D )。
5、如果想在4092个数据中只需要选择其中最小的5个,采用( E )方法最好。
6、设有两个串t和p,求p在t中首次出现的位臵的运算叫做( F )。
7、在数组A中,每一个数组元素A[i][j]占用3个存储字,行下标i从1到8,列下标j从1到10。所有数组元素相继存放于一个连续的存储空间中,则存放该数组至少需要的存储字数是( G )。
8、将一个递归算法改为对应的非递归算法时,通常需要使用( H )。 9、一个队列的进队列顺序是1, 2, 3, 4,则出队列顺序为( I )。
10、在循环队列中用数组A[0..m-1] 存放队列元素,其队头和队尾指针分别为front和rear,则当前队列中的元素个数是( J )。 【供选择的答案】
A: 内部结构与外部结构
静态结构与动态结构
2
线性结构与非线性结构 B: 必须是连续的
一定是不连续的
紧凑结构与非紧凑结构 部分地址必须是连续的
(n-1)/2 (n+1)/2 p→link = s; s→link = q;
q→link = s; s→link = p;
串连接
可连续可不连续
C: n n/2
D: s→link = p→link; p→link = s;
p→link = s→link; s→link = p; E: 起泡排序 堆排序 F: 求子串 G: 80 H: 栈 I: 4, 3, 2, 1
100 队列
锦标赛排序 快速排序
270 优先队列
3, 2, 1, 4
模式匹配 串替换
240 循环队列
2, 4, 3, 1 1, 2, 3, 4
J: ( front - rear + 1) % m
( front - rear + m) % m
( rear - front + 1) % m
( rear - front + m) % m
二、阅读理解题 [给出下列递归过程的执行结果]
(1) void unknown ( int w ) {
if ( w ) {
}
}
调用语句为 unknown (4)。 (2) void unknown ( int n ) {
cout << n % 10 ;
if ( int ( n / 10 ) ) unknown ( int ( n / 10 ) ); }
调用语句为unknown ( 582 )。 (3) int unknown ( int m ) {
int value;
if ( ! m ) value = 3;
else value = unknown ( m-1 ) + 5; return value;
}
执行语句为 cout << unknown (3)。
unknown ( w-1 ); cout << endl;
for ( int i = 1; i <= w; i++ ) cout << w<<' ';
三、填空题
设单链表结构为 struct ListNode {
int data ;
ListNode * link ;
};
下面的程序是以单链表为存储结构, 实现二路归并排序的算法, 要求链表不另外占用存
储空间, 排序过程中不移动结点中的元素, 只改各链结点中的指针, 排序后r仍指示结果链
3
表的第一个结点。在初始状态下, 所有待排序记录链接在一个以r为头指针的单链表中。例如,
在算法实现时,利用了一个队列做为辅助存储, 存储各有序链表构成的归并段的链头指针。初始时, 各初始归并段为只有一个结点的有序链表。队列的数据类型为Queue, 其可直接使用的相关操作有
臵空队列操作:makeEmpty ( );
将指针x加入到队列的队尾操作:EnQueue ( ListNode * x );
退出队头元素, 其值由函数返回的操作:ListNode *DlQueue ( ); 判队列空否的函数, 空则返回1, 不空则返回0:int IsEmpty( )。 解决方法提示:
程序首先对待排序的单链表进行一次扫描, 将它划分为若干有序的子链表, 其表头 指针存放在一个指针队列中。
当队列不空时, 从队列中退出两个有序子链表, 对它们进行二路归并, 结果链表的表头指针存放到队列中。
如果队列中退出一个有序子链表后变成空队列, 则算法结束。这个有序子链表即为所求。
在算法实现时有 6 处语句缺失,请阅读程序后补上。 (1) 两路归并算法
void merge ( ListNode * ha, ListNode * hb,, ListNode *& hc ) {
ListNode *pa, *pb, *pc ;
if ( ha→data <= hb→data ) { hc = ha; pa = ha→link; pb = hb; } else { hc = hb; pb = hb→link; pa = ha ; } pc = hc;
while ( pa && pb ) if ( { pc→link = pa; pc = pa; )
;
}
else
{ pc→link = pb; pc = pb;
}
if ( pa ) pc→link = pa;
;
else pc→link = pb; };
(2) 归并排序主程序
void mergesort ( ListNode * r ) { ListNode * s, t; Queue Q ; if ( ! r ) return; s = r; while ( s ) {
;
4
t = s→link;
while ( t != 0 && s→data <= t→data ) { s = t; t = t→link; } if ( t ) {
s→link = 0; s = t;
;
}
}
while ( !Q.IsEmpty( ) ) { r = Q.DlQueue( ); if ( Q.IsEmpty( ) ) break; s = Q.DlQueue( );
merge( r, s, t );
} }
四、简答题
(1) 在一个有n个元素的顺序表的第i个元素(1 i n)之前插入一个新元素时,需要向后移动多少个元素?
(2) 当一个栈的进栈序列为1234567时,可能的出栈序列有多少种?6457321是否是合理的出栈序列?
(3) 简单(直接)选择排序是一种稳定的排序方法吗?试举例说明?
(4) 设有序顺序表为 { 10, 20, 30, 40, 50, 60, 70 },采用折半搜索时,搜索成功的平均搜索长度是多少?
五、综合算法题
试设计一个实现下述要求的查找运算函数Locate。设有一个带表头结点的双向链表L, 每个结点有4个数据成员:指向前驱结点的指针llink、指向后继结点的指针rlink,存放字符数据的成员data和访问频度freq。所有结点的freq 初始时都为0。每当在链表上进行一次Locate(L, x) 操作时,令元素值为x的结点的访问频度freq加1,并将该结点前移,链接到与它的访问频度相等的结点后面,使得链表中所有结点保持按访问频度递减的顺序排列,以使频繁访问的结点总是靠近表头。
;
【试题答案】
一、答案:
A: B: C: D: E: F: G: H: I: J:
二、答案:
(1) 1 2 2
3 3 3
4 4 4 4 (2) 285 (3) 18
5
三、答案:
pa→data <= pb→data pa = pa→link pb = pb→link Q.EnQueue( r ) Q.EnQueue( s )
Q.EnQueue( t )
四、答案: (1) n- i + 1
(2) 可能的出栈序列有
17114131211109871C1487654321429 种,6457321不是合理的出栈序列。
(3) 是不稳定的排序方法。下面就是不稳定的例子。只要能举出反例即可。
{ 275 275* 512 061 } i = 1 { 061 275* 512 275 } i = 2 { 061 275* 512 275 } i = 3
{ 061 275* 275 512 }
(4) ASLsucc = (1*1 + 2*2 + 3*4 ) / 7 = 17 / 7
五、答案:
(1) 定义链表结构 struct DoubleListNode { char data ; int freq;
DoubleListNode * llink, *rlink ;
}; 初始时,所有结点的freq域的值都为0。
(2) 定义函数 DoubleListNode * locate ( DoubleListNode *f ; char &x ) { DoubleListNode * p, *q;
p = f→rlink; /*跳过表头结点*/ while ( p != NULL && p→data != x ) p = p→rlink; /*搜索*/ if ( p ) {
p→freq ++; q = p→llink;
p→rlink→llink = q; q→rlink = p→rlink; /*从链中摘下p*/ while ( q != f && q→freq < p→freq ) q =q→llink; p→llink = q;
p→rlink = q→rlink; q→rlink→llink = p; q→rlink = p; /*在q后面插入p*/ }
return p;
}
三、数据结构复习提要
6
第一章 有关数据结构和算法分析的基本知识
本章主要讨论贯穿和应用于整个《数据结构》课程始终的基本概念和性能分析方法。学习本章的内容,将为后续章节的学习打下良好的基础。
本章复习的要点:
1、基本知识点
要求理解的概念包括:数据,数据对象,数据元素或数据成员,数据结构,数据类型,数据抽象,抽象数据类型,数据结构的抽象层次,面向对象,对象与类的关系,类的继承关系,对象间的消息通信等。需要对各个概念进行区分与比较。例如,按照面向对象建模技术的要求,把建立对象类作为一个层次,把建立对象间的关系(即建立结构)作为另外的层次。因此,在软件开发中做数据结构设计时,不但要设计对象–类,类的属性,类的操作,还要建立类的实例之间的关系。从这个角度考虑,把数据结构定义为数据对象及对象中各数据成员之间关系的集合是合理的。又例如,对象–类class或struct与C中的结构类型struct的区别在于前者不但有对象的状态描述(数据成员),还加入了操作(成员函数),描述对象的行为,这样可以体现一个完整的实体概念,而后者不行。再例如,传统的数据结构概念从数据结构的逻辑结构、物理结构和相关操作等3个方面进行讨论。它反映了数据结构设计的不同层次:逻辑结构属于问题解决范畴,物理结构是逻辑结构在计算机中的存储方式。但在面向对象开发模式中,本课程中涉及的数据结构都属于基本数据结构,但有的属于应用级的数据结构,如稀疏矩阵,字符串,栈与队列,优先级队列,图等;有的属于实现级的数据结构,如数组,链表,堆,索引,散列表等。
2、有关算法的概念和简单的算法性能分析方法
算法的5个特性表明算法的实现属于面向过程的开发模式,即传统的“输入―计算―输出”模式。算法的应用要求明确算法的时间和空间代价。因此,必须理解算法的定义和算法的5个特性,掌握简单的时间复杂度估计和空间复杂度估计方法(不讨论程序复杂性)。
3、描述语言
要求数据结构的描述既要体现算法的逻辑,又要体现面向对象的概念,需要一种能够兼有面向对象和面向过程双重特性的描述语言。传统的Pascal语言和C语言只是面向过程的语言,不能适应面向对象的开发模式。因此,采用C++ 语言描述。要求学员基本掌握C++ 语言的基本概念和用C++ 语言编写应用程序的基本技术。例如,用类定义抽象数据类型的方式,定义模板类、抽象类的方法,函数与参数的定义,建立类(公有、私有)继承的方法,例外与异常的处理等等,都需要掌握。
4、复习参考题:1-1,1-2,1-4,1-7,1-8,1-9
第二章 数组
本章主要讨论数组抽象数据类型及利用数组实现的顺序表、字符串等数据结构。它们都是线性结构。但数组是直接存取结构,可以根据数组元素的下标直接在数组中存取该元素,而利用它实现的顺序表是顺序存取结构,所有数据元素集中存储于表的前端。字符串是顺序表的特化。
本章复习的要点: 1、基本知识点
理解作为抽象数据类型定义的数组类,掌握在C++ 中数组的定义和初始化方法,明确静态数组和动态数组的不同特点和使用,特别需要注意的是数组的存储结构不一定是一个连续的存储空间,当数组存放于一个连续的存储空间时叫做数组的顺序存储方式。要求掌握一
7
维数组、二维数组、三维数组的地址计算方法。需要明确:数组是一种实现级的结构。
其次,需要理解顺序表的定义和特点,顺序表的类定义及其主要操作,如搜索、插入和删除的实现,掌握对它们的性能估计,包括搜索算法的平均搜索长度,插入与删除算法中的对象平均移动次数。还要掌握顺序表实例的定义和使用事例。
此外,需要理解字符串的定义,字符串抽象数据类型的类定义,字符串中各种重载操作的实现和使用,简单的模式匹配算法和匹配事例。
2、算法设计
静态数组对象的定义,动态数组对象的定义 数组中数组元素的原地逆臵
递归计算数组长度、数组中所有元素的和及平均值
在顺序表中搜索值为item的元素,在有序顺序表中搜索值为item的元素 在有序顺序表中插入新元素item到第i个位臵 在有序顺序表中删除第i个元素
两个有序顺序表的合并,m个有序顺序表的合并
3、复习参考题:2-3,2-5,2-7,2-8,2-9,2-10,2-13,2-14,2-15,2-16
第三章 链接表
本章主要讨论最简单的链表结构―单链表。详细地介绍了单链表的抽象数据类型,单链表的类定义,相应操作的实现,引入了带表头结点的单链表结构。进一步定义了用模板描述的单链表类。作为一种应用,讨论了一元多项式的类定义及其加法操作的实现。此外,讨论了循环链表和双向链表。在复习这一章时需要对C++ 语言中的指针和引用类型的使用有清楚的理解。对带表头结点的链表和不带表头结点的链表在插入、删除、搜索时的差别有清楚的认识。而且需要明确:链表是一种实现级的结构。
本章复习的要点:
1、基本知识点
单链表是一种线性结构,链表各结点的物理存储可以是不连续的,因此各结点的逻辑次序与物理存放次序可以不一致。必须理解单链表的定义和特点,单链表的抽象数据类型和类定义,单链表成员函数,如构造函数、搜索、插入、删除等操作的实现,对比带表头结点单链表的搜索、插入、删除操作,比较其优缺点。其次是循环链表的定义和特点,它与单链表的差别,它的搜索、插入、删除操作的实现。最后是双向链表的定义,它的插入与删除操作的实现。
2、算法设计
单链表的迭代求解算法,包括统计链表结点个数,在链表中寻找与给定值value匹配的结点,在链表中寻找第i个结点,在链表中第i个位臵插入新结点,删去第i个结点,单链表各结点顺序逆转算法,在单链表中按从左到右和从右到左的顺序遍历的逆转链算法。
带表头结点的单链表的迭代算法,包括统计链表结点个数,在链表中寻找与给定值value匹配的结点,在链表中寻找第i个结点,在链表中第i个位臵插入新结点,删去第i个结点,连续删除链表中含有value值的结点,两个有序链表的合并。
单链表的递归算法,包括统计链表结点个数,在链表中寻找与给定值value匹配的结点,在链表中寻找第i个结点,求链表各结点值的和,求链表各结点的值的平均值。 循环链表的迭代算法:包括统计链表结点个数,在链表中寻找与给定值value匹配的结点,在链表中寻找第i个结点,在链表中第i个位臵插入新结点,删去第i个结点,将循环链表链入单链表的表头。
8
多项式的建立,两个多项式的相加,两个多项式的相减。 用单链表实现字符串操作,每个结点仅存一个字符。 3、复习参考题:3-1,3-2,3-6,3-8,3-9,3-10
第四章 栈与队列
本章主要讨论3种线性结构:栈、队列与优先级队列。这3种结构都是顺序存取的表,而且都是限制存取点的表。栈限定只能在表的一端(栈顶)插入与删除,其特点是先进后出。队列和优先级队列限定只能在表的一端(队尾)插入在另一端(队头)删除,不过优先级队列在插入和删除时需要根据数据对象的优先级做适当的调整,令优先级最高的对象调整到队头,其特点是优先级高的先出。而队列不调整,其特点是先进先出。这几种结构在开发各种软件时非常有用。
本章复习的要点: 1、基本知识点
要求理解栈的定义和特点,栈的抽象数据类型和在递归和表达式计算中的使用,在栈式铁路调车线上当进栈序列为1, 2, 3, , n时,可能的出栈序列计数,栈的顺序存储表示和链接存储表示,特别要注意,链式栈的栈顶应在链头,插入与删除都在链头进行。另外,需要理解队列的定义和特点,队列的抽象数据类型和在分层处理中的使用,队列的顺序存储表示(循环队列)和链接存储表示,需要注意的是,链式队列的队头应在链头,队尾应在链尾。还需要理解优先级队列的定义和特点。优先级队列的最佳存储表示是堆(heap),本章介绍的表示看懂即可。
2、算法设计
栈的5种操作(进栈、退栈、取栈顶元素、判栈空、臵空栈)的在顺序存储表示下的实现,以及在链接存储表示下的实现。
使用栈的后缀表达式计算算法
双栈共用一个数组的进栈、退栈、臵空栈、判栈空算法及栈满、栈空条件 使用两个栈模拟一个队列时的进队列和出队列算法
循环队列的进队列、出队列、取队头元素、判队列空、臵空队列操作的实现 使用tag区分队列空和队列满的循环队列的进队列和出队列操作的实现
链式队列的进队列、出队列、取队头元素、判队列空、臵空队列操作的实现 使用队尾指针rear和队列长度length的链式队列的进队列、出队列、取队头元素、判队列空、臵空队列操作的实现
队列在分层处理中的使用事例(杨辉三角形按层次打印)
双端队列的顺序存储表示及其进队列、出队列算法及队空、队满条件 3、复习参考题:4-2,4-4,4-9,4-10,4-12,4-14
第五章 递归与广义表
本章主要讨论递归过程和广义表。一个递归的定义可以用递归的过程计算,一个递归的数据结构可以用递归的过程实现它的各种操作,一个递归问题也可以用递归的过程求解。因此,递归算法的设计是必须掌握的基本功。递归算法的一般形式:
void p ( 参数表 ) { if ( 递归结束条件)
可直接求解步骤;
基本项
9
else p ( 较小的参数 );
归纳项 }
在设计递归算法时,可以先考虑在什么条件下可以直接求解。如果可以直接求解,考虑
求解的步骤,设计基本项;如果不能直接求解,考虑是否可以把问题规模缩小求解,设计归纳项,从而给出递归求解的算法。必须通过多个递归过程的事例,理解递归。但需要说明的是,递归过程在时间方面是低效的。
广义表是一种表,它的特点是允许表中套表。因此,它不一定是线性结构。它可以是复杂的非线性结构,甚至允许递归。可以用多重链表定义广义表。在讨论广义表时,特别注意递归在广义表操作实现中的应用。
本章复习的要点:
1、基本知识点
要求理解递归的概念:什么是递归?递归的定义、递归的数据结构、递归问题以及递归问题的递归求解方法。理解递归过程的机制与利用递归工作栈实现递归的方法。通过迷宫问题,理解递归解法,从而掌握利用栈如何实现递归问题的非递归解法。在广义表方面,要求理解广义表的概念,广义表的几个性质,用图表示广义表的方法,广义表操作的使用,广义表存储结构的实现,广义表的访问算法,以及广义表的递归算法。
2、算法设计
求解汉诺塔问题,掌握分治法的解题思路。
求解迷宫问题、八皇后问题,掌握回溯法的解题思路。
对比单链表的递归解法和非递归解法,掌握单向递归问题的迭代解法。 计算广义表结点个数,广义表深度,广义表长度的递归算法。 输出广义表各个原子所在深度的非递归算法。 判断两个广义表相等的递归算法。
广义表的按深度方向遍历和按层次(广度)方向遍历的递归算法。 使用栈的广义表的按深度方向遍历的非递归算法。 递归的广义表的删除算法
3、复习参考题:5-1,5-3,5-4,5-5,5-7,5-8
第六章 树与森林
本章主要介绍了树与森林、二叉树的定义、性质、操作和相关算法的实现。特别是二叉树的遍历算法,它们与许多以此为基础的递归算法都必须认真学习。因为树的先根遍历次序与对应二叉树表示的前序遍历次序一致,树的后根遍历次序与对应二叉树的后序遍历次序一致,因此可以据此得出树的遍历算法。线索化二叉树是直接利用二叉链表的空链指针记入前驱和后继线索,从而简化二叉树的遍历。堆是一种二叉树的应用,可以用它作为优先级队列的实现。它的存储表示是完全二叉树的顺序存储方式,它的定义不要求堆中的数据有序,但要求双亲结点与子女结点必须满足某种关系。本章最后讨论霍夫曼树。这种树是扩充二叉树,要求在外结点上带有权值,在构造霍夫曼树时必须注意一个新结点的左子女上所带的权值小于右子女上所带的权值,这不是霍夫曼树必须这样,而是实现算法造成这种结果。此外,作为霍夫曼树的应用,引入霍夫曼编码。通常让霍夫曼树的左分支代表编码“0”,右分支代表编码“1”,得到霍夫曼编码。这是一种不等长编码,可以有效地实现数据压缩。
本章复习的要点是:
1、基本知识点
要求理解树和森林的定义,树的抽象数据类型,二叉树的定义,二叉树的性质,二叉树
10
的抽象数据类型,二叉树的数组表示和链表存储表示。要求掌握二叉树的遍历,包括中序遍历、前序遍历、后序遍历方法,要求理解二叉树的计数方法及从二叉树遍历结果得到二叉树的方法。对于线索化二叉树,要求理解什么是线索,中序线索化二叉树的结构特性及寻找某结点的前驱和后继的方法。此外,需要理解堆的定义及其实现的方法,本章只考虑用完全二叉树的顺序存储来实现。还需要理解堆的建立,插入与删除过程。要求掌握树/森林与二叉树的转换,树的遍历方法。最后要求掌握霍夫曼树的实现方法及霍夫曼编码的概念。
2、算法设计
建立二叉树的递归算法。
前序、中序、后序遍历二叉树的递归算法。
使用栈的前序、中序、后序遍历的非递归算法。
统计二叉树结点个数,二叉树叶结点个数,二叉树高度的递归算法。 自左向右链接二叉树叶结点的递归算法。
判断两棵二叉树相等和交换二叉树左、右子女指针的递归算法。
通过二叉树的遍历建立前序线索化二叉树和中序线索化二叉树的算法。 中序线索化二叉树上的中序遍历算法。 前序线索化二叉树上的前序遍历算法。 后序线索化二叉树上的后序遍历算法。 利用堆实现优先级队列的操作。
堆的自上向下和自下向上的调整算法。 堆的插入与删除算法。
树的先根、后根、层次遍历算法(基于树的二叉树表示)。 建立霍夫曼树的算法
3、复习参考题:6-4,6-6,6-7,6-8,6-9,6-10,6-12,6-14,6-16,6-17,6-18,6-19,6-20,6-21,6-22
第七章 集合与搜索
集合是最基本的抽象数据类型之一。本章讨论了集合的三种存储表示:位数组表示、有序链表表示、并查集。在本章的后半部分,讨论了与集合相关的搜索方法和简单的性能分析方法,包括适用于静态搜索表的顺序搜索和折半搜索及代表动态搜索表的二叉搜索树和AVL树。可以使用扩充的二叉搜索树描述顺序搜索和折半搜索,从而推导出估算搜索效率的公式。静态搜索表在整个程序的运行期间结构不会变化,其搜索效率随着表中对象的个数n不断增长。动态搜索表因各个对象的输入顺序不同,得到的搜索表的形态不同,典型的是二叉搜索树。在具有n个对象的二叉搜索树中,搜索效率最高的是高度最低的二叉搜索树。为确保二叉搜索树始终保持搜索效率最高,必须在输入新的对象时判断二叉搜索树是否“失去平衡”,并进行适当的平衡旋转,使二叉搜索树的高度降到最低。这就是AVL树。在AVL树的讨论中,4种平衡旋转,选择参加平衡旋转的3个结点是关键,必须加以注意。
本章复习的要点是: 1、基本知识点
必须理解集合及其表示方法,包括位数组表示、有序链表表示及其相关操作的实现算法集合及其表示。理解并查集实现的方法。理解搜索的概念,理解静态搜索表结构,掌握静态搜索表的顺序搜索和折半搜索算法及其性能分析方法。掌握二叉搜索树的表示、搜索、插入、删除算法及其性能分析方法,掌握等搜索概率的最佳二叉搜索树的构造方法,并掌握AVL树的构造、插入、删除时的调整方法及其性能分析,重点是AVL树的定义、平衡化旋转、
11
AVL树的插入和删除、AVL树的高度。
2、算法设计
用有序链表表示集合时的求集合的并、交、差的算法 并查集中的构造函数、求根及合并算法
并查集中根据树的高度和根据树中结点个数进行合并的算法 设臵监视哨的顺序搜索算法和不设监视哨的顺序搜索算法 有序顺序表的顺序搜索算法
有序顺序表的折半搜索的递归算法和非递归算法
二叉搜索树的搜索、插入和删除算法 计算AVL树中指定结点高度的递归算法及利用此算法计算结点平衡因子的算法 3、复习参考题:7-2,7-4,7-5,7-7,7-8,7-9,7-10,7-11,7-12,7-15,7-16,7-18,7-19,7-20,7-22
第八章 图
图是一种重要的非线性结构。它的特点是每一个顶点都可以与其它顶点相关联,与树不同,图中各个顶点的地位都是平等的,对顶点的编号都是人为的。通常,定义图由两个集合构成:一个是顶点的非空有穷集合,一个是顶点与顶点之间关系(边)的有穷集合。对图的处理要区分有向图与无向图。它的存储表示可以使用邻接矩阵,可以使用邻接表,前者属顺序表示,后者属链接表示。在本章着重讨论了图的深度优先搜索和广度优先搜索算法,附带引入了生成树与生成森林的概念。对于带权图,给出了最小生成树的两种方法:Prim算法和Kruskal算法,后者使用了最小堆和并查集作为它的辅助求解手段。在解决最短路径问题时,采用了逐步求解的策略。最后讨论了作工程计划时常用的活动网络。涉及的主要概念是拓扑排序和关键路径,在解决应用问题时它们十分有用。
本章复习的要点是:
1、基本知识点
主要要求理解图的基本概念,包括图的定义、图的连通性、图的路径和路径长度、图中各顶点的度及度的度量、无向连通图的最大边数和最小边数,有向强连通图的最大边数与最小边数等。掌握图的存储表示,包括邻接矩阵和邻接表,以及这些存储表示上的典型操作,如构造、求根、找第一个邻接顶点、找下一个邻接顶点等操作的实现算法。并要求掌握图的两种遍历算法:深度优先搜索和广度优先搜索算法,以及求解连通性问题的方法。理解求解关节点及构造重连通图的方法。此外,要求掌握构造最小生成树的Prim算法和Kruskal方法,掌握活动网络的拓扑排序算法,掌握求解关键路径的方法。需要注意的是,让某个关键活动提前完成,是否能让整个工程提前完成。
2、算法设计
建立无向带权图的邻接表的算法,要求输入边的数目随机而定。 图的深度优先搜索的递归算法。
利用图的深度优先搜索的递归算法建立图的深度优先生成森林(用左子女右兄弟表示)的算法。
图的广度优先搜索算法。
利用图的广度优先搜索算法建立图的广度优先生成森林(用左子女右兄弟表示)的算法。
求解最小生成树的Prim算法,注意nearvex和lowcost辅助数组的变化。 求解最小生成树的Kruskal算法,注意minheap和UFset的变化。
12
求解最短路径的dijkstra算法,注意dist辅助数组的变化。
有向图中求解拓扑排序的算法,要求用邻接表作为图的存储表示。注意算法执行过程中入度为零的顶点栈的变化。
有向图中求解拓扑排序的算法,要求用邻接矩阵作为图的存储表示。
3、复习参考题:8-4,8-5,8-7,8-8,8-9,8-10,8-11,8-15,8-17,8-20,8-21,8-22
第九章 排序
排序是使用最频繁的一类算法。排序分内排序与外排序。内排序算法主要分5大类,有12个算法。在插入排序类中讨论了直接插入排序、二分法插入排序、表插入排序和shell排序算法;在交换排序类中讨论了起泡排序和快速排序算法;在选择排序类中讨论了简单选择排序、锦标赛排序和堆排序算法;在归并排序类中讨论了迭代的两路归并排序和递归的表归并排序算法;在多关键码排序类中讨论了最低位优先的链表基数排序算法。其中,不稳定的排序方法有shell排序、简单选择排序、快速排序和堆排序;适合于待排序对象数目n比较大的排序方法有快速排序、堆排序、归并排序和基数排序;关键码比较次数不受对象关键码初始排列影响的排序方法有折半插入排序、简单选择排序、锦标赛排序、两路归并排序和基数排序,其中,当关键码的初始排列接近有序时,直接插入排序和起泡排序等增长很快,而快速排序则变成慢速排序。
外排序是基于外存的排序方法。由于外存以顺序存取的效率最高,以归并排序最为适合。因此,外排序以k路平衡归并为主。在k个对象关键码中选取最小关键码,采用了败者树。这是一种高效的选择算法。此外,还讨论了初始归并段生成的方法,最佳归并树等问题。 本章复习的要点是:
1、基本知识点
要求理解排序的基本概念,包括什么是排序,排序的稳定性,排序的性能分析,如时间代价(对象关键码的比较次数和对象的移动次数)和空间代价(附加对象个数)。掌握插入排序(直接插入排序;折半插入排序;链表插入排序)、交换排序(起泡排序;快速排序)、选择排序(直接选择排序;链表选择排序;锦标赛排序;堆排序)、迭代的归并排序等内排序的方法及其性能分析方法。理解基数排序方法及其性能分析方法。理解多路平衡归并等外排序方法及败者树构造方法。理解生成初始归并段及败者树构造方法。理解最佳归并树的建立方法。
2、算法设计
插入排序:直接插入排序算法、折半插入排序算法、链表插入排序算法 交换排序:起泡排序算法,快速排序的递归算法和用栈实现的非递归算法 选择排序:直接选择排序算法,链表选择排序算法,堆排序算法
归并排序:两路归并算法,迭代的归并排序算法;递归的链表归并排序算法和用队列实现的非递归链表归并排序算法
其它排序算法:计数排序算法,奇偶排序算法
3、复习参考题:9-2,9-3,9-4,9-7,9-8,9-9,9-10,9-11,9-12,9-13,9-15,9-16,9-18,9-21,9-22,9-23,9-24
第十章 索引与散列结构
索引结构和散列结构是用于外部搜索的搜索结构。数据在外存的组织即文件结构,主要
13
分顺序、直接存取(散列)和索引文件。在这些文件组织中使用的主要是索引和散列方法。
1、基本知识点
要求掌握静态索引结构,包括线性索引、倒排索引、静态索引树的搜索和构造方法。掌握动态索引结构,包括B树的搜索、插入、删除,通过关键码个数估算B树的高度的方法;B+树的搜索、插入与删除。掌握散列法,包括散列函数的构造、处理溢出的闭散列方法;处理溢出的开散列方法;散列表分析。
2、复习参考题:10-3,10-4,10-5,10-8,10-9,10-11,10-12,10-14,10-15,10-18,10-19
14
因篇幅问题不能全部显示,请点此查看更多更全内容