东北大学数据结构实验

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

课程编号:B080101050

1. 实验目的

实验一:

1.理解队列的概念以及用法

2.掌握queue类的使用

3.熟练运用队列先进先出,模拟打印机的工作过程

实验二:

1.理解图的概念

2.理解并掌握图的存储,并利用邻接表来存储图的信息

3.理解并掌握Dijkstra算法

4.运用Dijkstra算法解决最短路径的问题

针对每次实验,写出你认为比较重要的实验目的

2. 实验内容与实验步骤

2.1打印机模拟程序的内容与步骤

(1)简短明确地写出实验的内容

模拟打印机打印的过程,以先来先服务的策略来完成打印工作。先从一个文件中读取所有任务的大小与到达时间,并将其存储在workload队列中。使用一个计数器来模拟时间的流逝,当当前时间与workload队列中的一个任务的到达时间相等的时候,该任务被弹出,并被压入到另一个等待执行的队列中。该等待执行的队列以先入先出的准则依次弹出任务并执行。最后计算出任务总数与,总等待时间,平均等待时间。

(2)简短描述抽象数据类型或设计的函数描述,说明为什么要使用这种抽象数据类型,并说明你的解决设想

①一个simulator的抽闲类和它的实现类fifo类。该类的simulate函数用来实现

先进先出策略的打印算法。

②两个队列,一个workload队列,一个是等待执行队列。Workload队列中存

放的是所有的打印任务,通过文件读取并保存。而等待执行队列则是为了实现FIFO 功能的队列,即时间小的就先被压入等待执行队列,自然也就先被pop并执行。

解决设想:

利用一个int型变量模拟时间的流逝,然后当等待执行队列为空的时候,就不断循环检查workload队列中是否有任务到达,若有则将其弹出并push进等待执行

队列。而当等待执行队列中有任务时则执行它,并且同时判断workload队列中是

否有任务到达。若workload和等待执行队列同时为空了,则程序结束。

(3)简短明确地写出你实验所采用的存储结构及其用途,详细说明其中的属性的含

义。

①job类封装了一个任务的所有属性。包括任务的大小和该任务的用户:任务

的大小即为该打印任务一共需要打印的页数,而该任务来自哪个计算机。

②event类封装了一个打印事件的所有属性。任务本身并不包含打印的信息,

而一个打印事件则需要包含一个待执行的任务和该任务到达的时间。打印的时候

就是根据这些信息来执行它。而待执行的任务属性即是一个任务对象,而该任务到

达的时间即是该任务在某个时间到达打印机,并等待被执行。

③simulator类封装了所有打印机的操作,包括加载任务文件,执行打印任务

等。该类将从文件中加载的任务封装成对象,并存储于workload队列中。然后待

时间到时,将该任务pop并push到等待执行队列中。在该队列中自然就按FIFO

的策略来执行。

2.2欧洲旅行实验的内容与步骤

(1) 简短明确地写出实验的内容

该实验就是在互相连接的城市中寻找给定两个城市之间的费用最小的路径。用邻接表来存储整个图的信息,并用一个map对象来存储各个城市的信息,包括它上一个城市,从起点到该城市的费用和距离。最后利用Dijkstra算法来对任意给定的

两个城市,计算他们之间的费用最小的路径。

(2) 简短描述你在实验中使用的数据结构及算法的基本原理。

在本实验中,使用了邻接表,map集合,list集合。邻接表是用于存储整个图的信息的,即它用于存储每一个点,有多少个点与它相连。即对于每一个点,它的名称作为键,而有一个包含了与它相连的所有点的信息的list对象作为值。这样就完全保存了该图的全部信息。然后有了该图,就可以利用Dijkstra算法来计算任意两点之间的距离。而Dijkstra算法的基本思想就是,循环找出下一个离起点距离最短的点,并标上标记,纳入以找出最短路径的点的集合。而当找到的下一个里起点最近的点就是目的地,则循环结束,最短路径则通过map集合中每一个City对象的from_city属性来找到。

(3)描述你采用STL中的什么容器或者类实现图的存储,在算法应用过程中使用什么

数据结构或算法提高算法的效率。

我们使用STL中的map对象来存储图。即map中的每一个键都为一个城市名,然后它的值为与该城市直接相连的所有城市所形成的list对象。

我们使用了邻接表的数据结构,并使用了优先级队列来实现下一个最短路径的点的快速查找,极大地提高了算法的效率。并且使用了Dijkstra算法,利用优先级

队列逐渐寻找下一个里起点最短的点,并将它的visited属性标记为true,表示已经

访问过,并在每一次访问后,都会更新剩余点的费用和距离的值。然后再利用优先

级队列计算新一轮的距离最短的点。

3. 实验环境

操作系统、调试软件名称、版本号,上机地点,机器台号

操作系统:Windows 8.1

调试软件名称:Codeblocks 12.11

4. 实验过程与分析

4.1打印机模拟程序的过程分析

(1)描述你在进行实现时,主要的函数或操作内部的主要算法,分析这个算法的时、空复杂度,并说明你设计的巧妙之处。

simulate函数为主要的执行FIFO打印的函数。该算法首先是一个while循环,该循环中的部分,由三个判断与语句组成,如果workload队列和等待执行队列都为空,则可

以断定所有任务全部执行完;而如果等待执行队列为空,则表名现在还没有任务到达打

印机,此时需要循环判断是否有任务到达,并且计数器也循环+1;而如果等待执行队列

不为空,就意为着,需要执行任务,那么则立即执行当前队列顶部任务,计算该任务的

等待时间,加到总等待时间上,并把当前计数器时间加上该任务执行的时间。然后在workload队列中把任务的执行时间<=当前时间的任务给弹出并压入到等待执行队列中。

等着三个判断语句结束后进入while的下一次循环。

该算法具有很小的时间复杂度,O(n) = 2n + 打印机空闲的秒数。因为对于执行打印任务的时候,该算法是直接在计数器上加上该任务消耗的时间,而对于pop出workload的时间则是等于任务的个数,然后剩余消耗的时间就是在等待执行队列为空的时候,循环判断workload队列中是否有任务到达了,所以此时消耗的循环次数为打印机空闲的秒数。

而空间复杂度为:n+2。也就是任务的个数+队列个数。

此算法的巧妙之处就在于,并没有以计数器逐渐递增的方式来模拟时间的流逝,而是消耗多少时间,计数器直接加上该值,并不是等待计数器累加到该值才执行任务。

(2)你在调试过程中发现了怎样的问题?又做了怎样的改进(要求写出具体的事例)

在算平均等待时间的时候,把该总时间的类型设置成了整型,导致平均等待时间算错。

(3)你的实现是否具有可扩展性,如针对多个打印队列的仿真程序?

本实现具有可扩展性,即只要在原来判断单个打印队列是否为空的基础上,加上&&语句,即同时判断是否所有打印队列同时为空,如果都为空,则循环判断所有

workload队列中任务是否已到达时间,若到达了时间则弹出并push到相应的打印队列中,这就是由原来的单个workload判断变成了循环判断多个workload。而如果有任一一个打印队列不为空,那么则和原来一样进入第三个判断中,执行该打印任务,且循环所有打印队列并执行任务。

4.2欧洲旅行实验的过程分析

(1) 描述你在进行实现时,主要的函数或操作内部的主要算法,分析这个算法的时、空复杂度,并说明你设计的巧妙之处。

主要函数为calc_route函数。该函数运用的算法为Dijkstra算法,算出最小路径。

该算法从起点开始遍历,然后重新计算与该点相连的所有点到起始点的距离,然后把这些点

相关文档
最新文档