算法竞赛入门经典授课教案第6章数据结构基础(精心排版,并扩充部分内容)

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第6章数据结构基础

【教学内容相关章节】

6.1栈和队列 6.2链表 6.3二叉树 6.4图

【教学目标】

(1)熟练掌握栈和队列及其实现;

(2)了解双向链表及其实现;

(3)掌握对比测试的方法;

(4)掌握随机数据生成方法;

(5)掌握完全二叉树的数组实现;

(6)了解动态内存分配和释放方法及其注意事项;

(7)掌握二叉树的链式表示法;

(8)掌握二叉树的先序、后序和中序遍历和层次遍历;

(9)掌握图的DFS及连通块计数;

(10)掌握图的BFS及最短路的输出;

(11)掌握拓扑排序算法;

(12)掌握欧拉回路算法。

【教学要求】

掌握栈和队列及其实现;掌握对比测试的方法;掌握随机数据生成方法;掌握完全二叉树的数组实现和链式表示法;掌握二叉树的先序、后序和中序遍历和层次遍历;掌握图的DFS和BFS遍历;掌握拓扑排序算法;掌握欧拉回路算法。

【教学内容提要】

本章介绍基础数据结构,包括线性表、二叉树和图。有两种特殊的线性表:栈和队列。对于树型结构主要讨论二叉树,还有二叉树的先序、中序和后序的遍历方式。对于图主要讨论图的DFS和BFS的遍历方法。这些内容是很多高级内容的基础。如果数据基础没有打好,很难设计正确、高效的算法。

【教学重点、难点】

教学重点:

(1)掌握栈和队列及其实现;

(2)掌握对比测试的方法;

(3)掌握随机数据生成方法;

(4)掌握完全二叉树的数组实现和链式表示法;

(5)掌握二叉树的先序、后序和中序遍历和层次遍历;

(6)掌握图的DFS和BFS遍历;

(7)掌握拓扑排序算法和欧拉回路算法。

教学难点:

(1)掌握完全二叉树的数组实现和链式表示法;

(2)掌握二叉树的先序、后序和中序遍历和层次遍历;

(3)掌握图的DFS和BFS遍历;

(4)掌握拓扑排序算法和欧拉回路算法。

【课时安排(共9学时)】

6.1栈和队列 6.2链表 6.3二叉树 6.4图

6.1 栈和队列

线性表是“所有元素排成一行”的数据结构。除了第一个元素之外,所有元素都有一个“前一个元素”;除了最后一个元素外,所有元素都有“后一个元素”。

线性结构是重要的算法和数据结构的基础。下面介绍两种特殊的线性表:栈和队列。

6.1.1 卡片游戏

桌上有叠牌,从第一张牌(即位于顶面的牌)开始从上往下依次编号为1~n。当至少还剩两张牌时进行以下操作:把第一张牌扔掉,然后把新的第一张放一整叠牌的最后。输入n,输出每次扔掉的牌,以及最后剩下的牌。

样例输入:7

样例输出:1 3 5 7 4 2 6

【分析】

本题中牌像在排队。每次从排头拿到两个,其中第二个再次排到尾部。这种数据结构称为队列。在数据结构称为FIFO(First in First out,先进先出)表。

用一个数组queue来实现这个队列,可设两个指针front和rear。

完整的程序如下:

#include

const int MAXN = 50;

int queue[MAXN];

int main() {

int n, front, rear;

scanf("%d", &n);

for(int i = 0; i < n; i++) queue[i] = i+1; //初始化队列

front = 0; //队首元素的位置

rear = n; //队尾元素的后一个位置

while(front < rear) { //当队列非空

printf("%d ", queue[front++]); //输出并抛弃队首元素

queue[rear++] = queue[front++]; //队首元素转移到队尾

}

return 0;

}

注意:上面的程序有bug。如果在最后把rear的值打印出来,rear比n大。即在程序运行的后期,queue[rear++]=queue[front++]读写了非法内存。也可以采取将数组空间开大些,或采取一种称为循环队列的技术,重用已出队元素占用的空间。

C++提供了一种更加简单的处理方式——STL队列。下面是代码:

#include

#include

using namespace std;

queue q;

int main() {

int n, front, rear;

scanf("%d", &n);

for(int i = 0; i < n; i++) q.push(i+1); //初始化队列

while(!q.empty()) { //当队列非空

printf("%d ", q.front()); //打印队首元素

q.pop(); //抛弃队首元素

q.push(q.front()); //把队首元素加入队尾

q.pop(); //抛弃队首元素

}

return 0;

}

上面的程序的可读性大大增强了,体现在“queue”、“front”见名知义的命名,使用了C++ STL。除此之外,上面的代码还有两个附加的好处。首先,不需要事先知道n 的大小;其次,可以少用两个变量front和rear。减少魔术数(magic number)和变量个数都是提高代码可读性、减少错误可能性的重要手段。

相关文档
最新文档