数据结构学习指导文档格式.docx
《数据结构学习指导文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构学习指导文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
public,private和protected。
放在public域中表示对于其他程序都是可用的;
放在private域中表示对于其他程序是不可用的,对于其派生类也是不可用的;
放在protected域中表示对于其他程序是不可用的,对于其派生类是可用的。
(4)在C++中的动态存储分配和动态存储回收方式。
(5)类的实例对象的建立和回收方式,构造函数和析构函数的使用,对象数据成员初始化的方式等。
特别注意成员函数的作用域。
(6)在C/C++中的输入/输出流文件的定义和使用。
特别注意文件的连接、ifstream和ofstream类,以及文件的打开与关闭、文件模式的作用。
(7)友元类和友元函数的定义和使用。
(8)模板类的定义和模板类的使用。
2、在学习《数据结构》时,要注意知识体系
数据结构课程中的知识本身具有良好的结构性。
从总体上来说,课程的主要内容是围绕着数组、线性表、顺序表、链表、栈、队列、优先级队列、广义表、树与二叉树、图、集合与搜索结构、索引与散列结构等常用的数据结构和递归、排序等常用算法来组织的。
其中有些结构是面向应用的,有些结构是面向实现的。
在课文中要注意这两个层次以及它们之间的联系。
为了完全了解数据结构的机制以及为便于数据结构的复用,课文中对每一个结构都做了较为完整的介绍,学习者最好将课文中介绍的每一结构都能以“模板类”和“模板类的成员函数的实现”的形式存于“.h”文件中,并在后续的算法或类的实现中直接复用它们。
3、注意比较
在学习中应当注意从“横向”和“纵向”进行对比以加深理解。
纵向对比将一种结构与它的各种不同的实现加以比较,从继承的角度或从聚合的角度建立类的实例之间的联系;
横向对比包括具有相同逻辑结构的不同数据结构(如线性表、栈、队列、优先级队列和串)的比较,具有相同功能的不同算法的比较等,了解类的层次结构和利用包的概念将不同语义的类关联起来,从而加深对抽象类和虚函数的使用。
4、注意复习和重读
有些内容在初读时难以透彻理解或熟练掌握,或者看起来似乎明白了,但用的时候容易犯晕。
在继续学习的过程中如遇到或用到有关内容时,应当及时复习或重读,这往往能够化难为易,温故知新。
5、充分利用考核说明及有关学习的难点和重点的说明
在进入每一章学习之前或在每一章学习之后,仔细阅读考核说明和各章学习的难点和重点,有助于集中思路和自我检查。
每一章自我检查的效果不理想时,千万不要将就,更不要急于向后读,应回过头来把握住要求,有计划地重读课本,重看学习导引,重做习题,直到本章内容掌握为止。
6、注意循序渐进
在进入具体内容(如类的定义和类的成员函数的实现)之前,首先领会基本概念、基本思想,这一点极为重要。
特别是在阅读算法之前,一定要先弄清其基本思想、基本步骤,这将大大降低理解算法的难度。
如果读“懂”了算法而不知其基本思想,仍不算是真懂。
可以通过事例学习以加深理解。
7、注意练习
习题练习是课程的基本要求之一。
只看书不做题,不可能真正学会有关知识,更不能达到技能培养的目的。
另一方面,做题也是自我检查的重要手段。
此外,在做算法设计型的习题时,应优先考虑数据结构的定义,可以直接使用以前定义的类和相应的操作(成员函数),综合已学过的知识,以提高编程的能力。
为此,可以逐渐积累学过的数据结构的实现,以模板类的方式标准化,以方便在后续学习中复用它们。
面向对象软件工程告诉我们,这样做所获得的回报是相当丰厚的,但不要指望立即获得回报。
8、算法思路的理解
算法及其思想、评价是本课程的重点之一,在课文中占了相当大的比例。
在学习每一个算法时,建议首先理解问题的要求,在此基础上利用一个事例来模拟问题的求解,自己试着构思一下解题的思路,能够写出来更好。
然后再阅读算法,在读懂之后,不要急于往下进行,而应停下来思考下列问题:
该算法从逻辑上可以划分为哪几个部分(步骤)?
每一部分的功能是什么?
这一功能又是如何实现的?
能否有别的方法实现?
各部分之间的关系如何?
如果问题的要求有所不同,应当如何修改算法?
将思考的结果记载下来,在复习时会有很大帮助。
另外,这样的分析也是灵活运用所学知识的关键。
9、努力培养算法设计的能力
在课程学习中最令学习者感到吃力的是设计和编写算法。
算法设计水平是软件设计的基础。
要提高算法的设计水平,首先需要掌握问题要求的基本内容,通过反复体会和练习来实现。
通常需要根据具体问题的要求,选择合适的数据结构,设计有效的算法。
有条件的学生应当在机器上多做练习。
10、在学习完每一章、节后,要及时地进行总结,用简短的文字记录这部分的内容,尽可能用自己的话复述一遍。
在本课程全部学完后应对本课程进行全面系统的复习和总结,认真做模拟试卷。
在进行总复习时,可通过对比各种数据结构的异同和他们之间的相互关系,加深对各种数据结构的理解。
在复习时,可以按所记录的要点反向地进行,即依据要点找出其具体内容。
按这样的方法进行,也许还能够节省时间,提高学习效果。
最后应当强调的是,学习方法主要靠自己摸索,多总结,多思考,勤上机,勤交流,是把数据结构这门课程真正学好的关键。
四、考试指导
数据结构考试可能的题型有以下5种:
单选题:
给出一些有关数据结构性质、特点及一些简单算法性能的不完全叙述,要求学生从题后给出的供选择的答案中选择合适的答案,补足这些叙述。
填空题:
给出程序说明及一段部分语句缺失的程序,让学生补充成为完整的程序。
简答题:
应用作图方法或简单计算,使用给定数据建立或操作一些数据结构。
判断题:
给出一些有关数据结构或算法的叙述,要求学生回答这些叙述正确与否。
综合算法题:
给出算法设计要求,编制出部分算法程序,用来考察几个知识点的综合应用。
下面根据各种题型举例分析,说明解题方法及考试时的注意事项。
例题1单选题
[从供选择的答案中选出正确的答案,将其编号填入下列叙述中的()内]
(1)向一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变,平均要移动(A)个元素。
(2)设有一个二维数组A[m][n],假设A[0][0]存放位置在644(10),A[2][2]存放位置在676(10),每个元素占一个空间,则A[4][5]在(B)位置,(10)表明用10进数表示。
(3)一个有序顺序表有255个对象,采用顺序搜索法查表,平均搜索长度为(C)。
(4)含5个结点(元素值均不相同)的二叉搜索树有(D)种。
(5)在分析折半搜索的性能时常加入失败结点,即外结点,从而形成扩充的二叉树。
若设失败结点i所在层次为li,那么搜索失败到达失败结点时所做的数据比较次数是(E)。
(6)设有一个含200个表项的散列表,用线性探查法解决冲突,按关键码查询时找到一个表项的平均探查次数不超过1.5,则散列表项应能够至少容纳(F)个表项。
(设搜索成功的平均搜索长度为Snl={1+1/(1-α)}/2,其中α为装填因子)
(7)n个顶点的连通图至少有(G)条边。
(8)一个二叉树按顺序方式存储在一个一维数组中,如图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
A
B
C
D
E
F
G
H
I
J
则结点E在二叉树的第(H)层。
【供选择的答案】
A:
①8②63.5③63④7
B:
①692(10)②626(10)③709(10)④724(10)
C:
①128②127③126④255
D:
①54②42③36④65
F:
①li+1②li+2③li-1④li
G:
①400②526③624④676
I:
①n-1②n③n+1④0
J:
①1②2③3④4
解答:
②B:
③C:
①D:
②E:
④F:
①G:
①H:
②
分析:
此类题主要是考核学生对基本知识的掌握程度,涉及范围较广。
所有各章内容都可能牵涉到。
主要考察对各种数据结构的定义、特点、性质(包括公式计算)、主要操作的性能分析(包括算法中多趟执行时每一趟的通项公式),因此要求复习时必须仔细看书。
不提倡死记硬背,但要学会推导。
例题二判断题
[判断下列各个叙述的正误。
对,在题号前的括号内填入"
"
;
错,在题号前的括号内填入"
]
()
(1)有n个结点的不同的二叉树有n!
棵。
()
(2)直接选择排序是一种不稳定的排序方法。
()(3)在2048个互不相同的关键码中选择最小的5个关键码,用堆排序比用锦标赛排序更快。
()(4)当3阶B_树中有255个关键码时,其最大高度(包括失败结点层)不超过8。
()(5)一棵3阶B_树是平衡的3路搜索树,反之,一棵平衡的3路搜索树是3阶B_树。
()(6)在用散列表存储关键码集合时,可以用双散列法寻找下一个空桶。
在设计再散列函数时,要求计算出的值与表的大小m互质。
()(7)在只有度为0和度为k的结点的k叉树中,设度为0的结点有n0个,度为k的结点有nk个,则有n0=nk+1。
()(8)折半搜索只适用于有序表,包括有序的顺序表和有序的链表。
(1)
(2)(3)(4)(5)(6)(7)(8)
此类题要求对课文各章中许多细节比较清楚。
事实上,数据结构课程中讲到的许多数据结构的细节是最基础的知识,将这些内容理解透彻了,以后学生在自主开发软件时将会得到回报的。
在解答此类题时,不要立即提笔就答,应当把题看完,分析前后叙述是否矛盾,是否叙述中有漏洞,必要时,还需要做一下简单的推导。
例题三阅读理解题
[说明下列递归过程的功能]
intunknown(BinTreeNode*t){
//指针t是二叉树的根指针。
if(t==NULL)return0;
else
if(t->
leftChild==NULL&
&
t->
rightChild==NULL)return1;
elsereturnunknown(t->
leftChild)+unknown(t->
rightChild);
}
计算二叉树的叶结点的个数。
此类题是递归算法问题,一般要求读懂它即可。
但要理解它首先需要掌握递归算法的结构,以及相应问题的背景。
有时需要以一个简单的例子来帮助理解。
例题四简答题
1、如下所示的连通图,请画出
(1)以顶点①为根的深度优先生成树;
(2)如果有关节点,请找出所有的关节点。
(1)该连通图从①出发做深度优先搜索,得到的深度优先生成树为:
结果不唯一
(2)关节点为①、②、③、⑦、⑧
这是有关重连通图的问题。
深度优先搜索是一个需要重点掌握的方法,包括实例分析和算法。
它是一个带回溯的探索问题,需要用递归算法求解。
另外,关节点的判断准则有两个:
其一为根至少有两个或两个以上的子女;
其二为除根和叶结点外,其他结点的子女或子孙有指向该结点祖先的“回边”。
掌握了这些概念,此问题就迎刃而解了。
还需要了解:
重连通图中任意两个顶点之间至少有两条路径相通,这有助于将非重连通图改为重连通图。
2、设有13个初始归并段,其长度分别为28,16,37,42,5,9,13,14,20,17,30,12,18。
试画出4路归并时的最佳归并树,并计算它的带权路径长度WPL。
因为(13-1)%(4-1)=12%3=0,所以不需要添加空段。
最佳归并树为
WPL=(5+9+13+12+16+14+17+18+28+37+20+30)*2+42=4
这是外排序中求最佳归并树问题,它是只有度为0和度为k的正则k叉树,满足条件n0=(k-1)nk+1,其中,n0是度为0的结点个数,nk是度为k的结点个数,k是归并路数。
最佳归并树的构造仿照霍夫曼树,长度小的初始归并段离根远,长度大的初始归并段离根近。
需要注意的是:
当(n0-1)%(k-1)=m0时,需要补充k-m-1个空的初始归并段,才能构成正则k叉树。
3、设散列表为HT[0..12],即表的大小为m=13。
采用双散列法解决冲突。
散列函数和再散列函数分别为:
H0(key)=key%13;
注:
%是求余数运算
Hi=(Hi-1+REV(key+1)%11+1)%13;
i=1,2,3,,m-1
其中,函数REV(x)表示颠倒10进制数x的各位,如REV(37)=73,REV(7)=7等。
若插入的关键码序列为2,8,31,20,19,18,53,27。
试画出插入这8个关键码后的散列表。
散列表HT[0..12],散列函数与再散列函数为
H0(key)=key%13;
Hi=(Hi-1+REV(key+1)%11+1)%13;
插入关键码序列为{2,8,31,20,19,18,53,27}
H0
(2)=2,比较次数为1H0(8)=8,比较次数为1
H0(31)=5,比较次数为1H0(20)=7,比较次数为1
H0(19)=6,比较次数为1
H0(18)=5,冲突,H1=9,比较次数为2
H0(53)=1,比较次数为1
H0(27)=1,冲突,H1=7,冲突,H2=0,比较次数为3
插入8个关键码后的散列表
27
53
2
31
19
20
8
18
散列表长度和再散列函数的选取是关键。
由于要求再散列函数计算出来的结果,即发生冲突时向后跨多大距离找下一个“空位”,必须与表的长度互质。
因此为简化问题求解的难度,一般设表的长度为质数,本题设为13。
其次,再散列函数是待散列对象的关键码的函数,计算结果的取值范围在1n-1之间,其中n是表的长度。
因此选取REV(key+1)%11+1,其取值范围在111之间,除1退化为线性探查外,其他都与13互质。
需要注意的是,双散列法对表长度的要求不如二次探查法严格,那里要求表的长度一定是满足4j+3的质数且表的装载因子不超过0.5。
此题容易出错的地方是应用再散列函数处理冲突时发生简单计算错误,一处出错,会影响后面一连串出错,一定要仔细。
例题五综合算法题
有一种简单的排序算法,叫做计数排序(countSorting)。
这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中。
必须注意的是,表中所有待排序的关键码互不相同。
计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小。
假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序表中的合适的存放位置即为c。
(1)给出适用于计数排序的数据表定义;
(2)使用C++语言编写实现计数排序的算法;
(3)对于有n个记录的表,关键码比较次数是多少?
(1)数据表定义
constintDefaultSize=100;
template<
classType>
classdatalist//数据表的前视声明
classElement{//数据表元素类的定义
private:
Typekey;
//关键码
fieldotherdata;
//其它数据成员
public:
TypegetKey(){returnkey;
}//取当前结点的关键码
voidsetKey(constTypex){key=x;
}//将结点的关键码修改为x
}
classdatalist{
//用顺序表来存储待排序的元素,这些元素的类型是Type
datalist(intMaxSz=DefaultSize):
MaxSize(Maxsz),CurrentSize(0)
{Vector=newElement<
Type>
[MaxSz];
Element<
*Vector;
//存储待排序元素的向量
intMaxSize,CurrentSize;
//最大元素个数与当前元素个数
}
(2)计数排序的算法
解答1:
template<
voidcountsort(datalist<
&
initList,datalist<
resultList){
inti,j,c;
Typerefer;
for(i=0;
i<
initList.CurrentSize;
i++){
c=0;
refer=initList.Vector[i].getKey();
for(j=0;
j<
j++)
if(initList.Vector[j].getKey()<
refer)c++;
resultList.Vector[c]=initList.Vector[i]
resultList.CurrentSize=initList.CurrentSize;
解答2:
int*c=newint[initList.CurrentSize];
for(inti=0;
i++)c[i]=0;
for(i=0;
initList.CurrentSize-1;
i++)
for(intj=i+1;
initList.Vector[i].getKey())
c[i]++;
elsec[j]++;
resultList.Vector[c[i]]=initList.Vector[i];
resultList.CurrentSize=initList.CurrentSize;
(3)对于n个记录的表,解答1中关键码比较次数为n2,解答2中关键码比较次数为n(n-1)/2。
编写算法的题可能是学生比较棘手的问题,特别是在考试这样一个氛围,时间又短促,想编出一个好算法不太容易。
一个建议是首先仔细阅读试题,了解它到底要你干什么。
然后用一个简单的例子走