数据结构课程主页


 

上机题目

本部分内容随课程进度随时更新。

上机作业应按时独立完成,在本次作业的截止日期之前通过教学网提交。 超过截止日期一周以内按照本次作业的50%计入成绩,超过截止日期一周以上不计成绩。
作业文件命名方式:aaaaazzm.zip或aaaaazzm.rar,表示19级学号的最后5位为aaaaa姓名为zz的同学第m次作业,所有文件压缩后提交,提供单独文本文件说明所用的开发和编译环境。其他年级同学的文件名前加一个字母x,其余字母的编码方式同上。程序尽可能写得清晰规整,在必要的位置加上注释。

注意:上机程序作业必须通过编译和运行,否则将作为没有完成的作业,由辅导老师酌情处理。

 

序号 布置日期 截止日期
作业内容
1 10.12 10.30

设计并实现一个简单文本编辑器,至少实现以下功能:把指定文件读入编辑器、在编辑器中对文件进行编辑、将编辑的内容存入指定文件、把字符串或文本块插入编辑区指定位置、删除编辑区里的字符串或文本块、在编辑区里查找指定字符串、将文本里的“字符串1”替换为“字符串2”。

2 10.22 11.8

电梯模拟系统,可独立或合作完成,合作工作每组不超过2人,按时提交全部程序代码与上机报告。

项目描述:

请开发一个简单的电梯模拟系统,具体要求如下:

  • 假设电梯所在的建筑共计n层,从地面层(按习惯称1楼)直至最上层(n楼)。这里的n作为一个参数,可以修改。例如可以设置为5或9模拟5层或9层楼的电梯(如理科1号楼和2号楼的电梯)。
  • 每层电梯门边有一个上行按钮和一个下行按钮,最下层和最上层只有一个按钮。
  • 电梯里有一组按钮,供乘电梯人选择目标楼层。
  • 电梯从一层到其相邻层需要k秒时间。
  • 乘客按一定时间间隔到达某楼层,按电梯门边按钮表示要求上行或下行。乘客到达的时间间隔是区间[a, b] 里的某个随机值,到达楼层是[1, n] 中的随机值。
  • 乘客进电梯后选择搭乘的目标楼层(随机值)。
  • 乘客在电梯到达其目标楼层后离开电梯。
  • 我们希望模拟N秒的电梯运行情况,并在模拟中做一些统计。

考虑下面的数据统计:

模拟期间完成服务的共计人数;平均等电梯时间;电梯的平均负荷人数(请提出一种适当的统计方法);其他有意义的统计结果(自己考虑)。

项目要求:

根据题目要求设计并实现所需的功能,
1. 设计所需的数据结构。例如,用什么数据结构表示乘客、电梯、按钮等,模拟中的各种事件,怎样把它们组织起来形成完整的系统;
2. 可以参考课堂上给的实例,采用类似的实现技术。也可以完全自己设计一套实现方法。可以找到许多有关离散事件模拟方面的参考材料。
3. 要求实现一个名为demo的函数,它以适当参数运行开发的模拟系统(一次或几次,不 同参数) ,展示所做系统确实完成了要求的模拟工作。设一个全局变量verbose,当其值为True时模拟中输出所有事件的信息,其值为False时只输出最后的统计数据。

报告的要求:

上机报告不少于4000字,大致可以分为几个部分:
1. 对问题的分析和整体系统的设计概述;
2. 具体的数据结构和程序结构设计;
3. 实现中的关键问题和技术分析;
4. 系统完成的情况和实际效果的说明;
5. 重要算法的时间复杂性分析,并说明自己的程序没有不合理的空间浪费。
6. 完成了这个系统之后的回顾和分析:优点和缺点,改进和扩充的可能性;
7. 使用Python语言做这个工作的体会,在哪些方面Python很好用,使用方便;在那些情况或问题处理中不够方便,使你们的工作遇到了困难等(这部分非必要要求)。

报告可以考虑分为几节(仅供参考,实际报告不必拘泥于这里列出的项目):
1. 问题分析和系统整体设计;
2. 数据结构和程序结构设计;
3. 关键问题和算法;
4. 系统完成情况;
5. 算法性能分析;
6. 可能的改进和扩充;
7. 总结和回顾;
8. Python语言的使用情况。

注:

如果要更真实地模拟电梯系统的运行,可能还需要考虑许多细节,例如:

  • 电梯的承重限额,即最大容纳人数;
  • 模拟电梯的启动和减速过程(启动和减速需要时间,和正常运行不同);
  • 模拟电梯开门/关门的时间消耗;
  • 电梯运行经过某一层之前有人按了按钮,在什么样的情况下电梯能停(需要一定的提前量以保证机械装置操作和安全性);
  • 在一层上下电梯的人数决定了电梯的停留时间(假定每个人上下用某个常量时间);
  • 调度策略,多电梯控制,乘客的随机分布情况,等等

以上这些为选作内容。

3 10.26 11.10

1. 给定一个二叉树,分别采用深度优先和广度优先的方法返回所有从根结点到叶结点的路径。

2. 给定一个由 '1'(陆地)和 '0'(水)组成的的二维矩阵,分别采用深度优先和广度优先的方法计算其中岛屿的数量并对两种方法的时间代价进行比较。岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成,可以假设该矩阵外面四条边均被水包围。

示例1:

输入:

[

['0','0','0','0','0','0'],

['0','1','1','1','1','0'],

['0','1','1','0','1','0'],

['0','1','1','0','0','0'],

['0','0','0','0','0','0']

]

输出:1

示例2:

输入:

[

['0','0','0','0','0','0'],

['0','1','1','0','0','0'],

['0','1','1','0','0','0'],

['0','0','0','1','0','0'],

['0','0','0','0','1','0'],

['0','0','0','0','0','0']

]

输出:3

4 11.15 1.2

从以下两个项目中选做其一:

一、图书索引处理(可独立或合作完成,同组合作者不得超过2人):

本项目基于真实的索引处理工具makeindex[1,2]、xindy[3]等,我们将使用Python语言实现这些工具功能的一个子集。在项目中,我们将熟悉文件处理类程序的组织和编写,可能会涉及表(数组)、集合、字典、栈、正则表达式等数据结构及排序等算法的灵活使用。

篇幅较长的科技图书经常会有关键词索引。索引的格式是:将关键词按字母顺序分类排序,在关键词的后面标记出关键字所在的页码。本项目说明的末尾就有一个简单的名词索引。在现代图书出版中,名词索引通常是使用如下方式生成的:(1) 作者在撰写图书时,在正文中标记出需要做索引的词汇。(2) 排版软件处理图书正文时,将标记出的词汇与词汇所在的页码从正文中提取出来,成为单独的索引文件。(3) 索引处理工具对提取出的索引文件按字母分类、排序,并且将相同的条目合并起来。本项目的任务是要编写一个索引处理工具,完成上面的第3个步骤。

1. 索引的输入

不同的排版软件可能生成不同格式的索引文件,为方便计,我们采用比较简单的一种格式,它也是计算机科学的经典著作《The Art of Computer Programming》的索引文件样式。每个索引文件许多行构成,每行是一个索引条目。一个索引条目分为两个部分,索引词和词条所在的页码。索引词与页码之间用一个空格与感叹号分隔开。简单的条目如:

Fibonacci sequence !13

它表示索引词是“Fibonacci sequence”(斐波那契数列),出现在全书的第13页。

索引词可能会在多处出现,因此同一个索引词可能会有多个页码;同一页的索引词也可能被多次标记。因此,有可能出现这样的索引:

Fibonacci sequence !13

Fibonacci sequence !13

golden ratio !13

Fibonacci sequence !27

有时,作者在书中的一整段内容都是关于一个名词的,因而会为这个名词标记一个页码区间。可以使用如下两种方式:

(1) 在索引词的后面加上若干个加号,表示这个词条的会向后延续加号这么多页。例如:

memory+ !4

assertions+++ !15

表示“memory”这个词条出现在第4页到第5页,而“assertions”词条会出现在第15-18页。

(2) 在索引词的后面与前面加上两个减号,分别表示词条的开始与结束的位置。例如:

arithmetic operators of MIX-- !131

--arithmetic operators of MIX !133

表示词条“arithmetic operators of MIX”从131页延续到133页。

索引条目的页码都是阿拉伯数字。但是,并不保证索引输入文件中的索引条目是按页码顺序排列的。

如果对项目进行扩充,可以在上述描述的基础上,支持更多或更复杂的输入格式。

2. 索引的排序

索引处理程序的主要工作就是对索引进行排序。

2.1 索引词排序与分类

大体上,需要将索引词逐字符按字典序进行从小到大排序。但有如下特殊规则:

(1) 如果字符串只包含阿拉伯数字(自然数),则数字大小比较。例如,“9”应该排在“10”之前,尽管按字符串序符号“1”在符号“9”之前。

(2) 以符号开头的字符串总是先于排在以数字开头的串,而这又先于纯数字的排序项和以字母开头的串。

(3) 在比较两个字符串时,索引处理程序应该首先忽略字母大小写进行比较,如果此时结果相等,再按区分大小写进行比较,将大写字母排在小写字母之前。

排序后的索引将进行分组。共分为28个组:完全由阿拉伯数字的组成的条目(自然数)分入“Numbers”组,以符号开头的条目(包括数字开头但不是纯数字的条目)分为“Symbols”组,其他条目按首字母分为26个组。不需要考虑希腊字母、汉字等无关的内容。

2.2 页码排序与合并

同一索引词的输入条目将会合并为一项,该项可能会有多个页码。

对合并后的每个索引项,需要对页码从小到大排序,去除重复的页码。例如,输入的索引项为

Fibonacci sequence !13

Fibonacci sequence !27

golden ratio !13

Fibonacci sequence !13

输出应只包含两项,形如:

Fibonacci sequence, 13, 27

golden ratio, 13

需要注意页码区间的合并,例如:

item-- !1

item !5

item++ !7

--item !10

item !10

应该直接合并为

item 1-10

并且注意相邻的页码区间也要合并为同一项,如

item-- !1

--item !3

item-- !3

--item !5

item !6

应合并为

item 1-6

可以对项目进行扩充,在上述描述的基础上,支持更多或更复杂的排序规则。

3. 索引结果输出

索引处理程序在对读入的索引项排序整理后,需要将结果输出。

结果按28个分组分别进行输出,即按数字组、符号组、26个字母组输出,输出时跳过没有条目的分组。输出每个分组时,先输出分组名称(Symbols, Numbers, A, B, . . . , Z),空一行后开始输出这一分组的条目。分组之间空两行。

对于每个条目,分别输出词条本身,与词条所在的页码。词条与页码之间、页码与页码之间用一个逗号和一个空格分隔。页码经过排序和合并,3页或3页以上连续的页码区间在起迄页码中间用两个减号分开。词条最后输出一个西文句号。

下面是一个输出的例子:

可以对项目进行扩充,在上述描述的基础上,支持更多或更复杂的输出格式。

4. 可能的扩展功能

索引程序可以有多方面的扩展,例如支持不同的输入格式,支持更复杂的结构等。

(1) 考虑如何在输入中进行转义处理。例如,当使用感叹号、加号、减号作为特殊字符时,如何处理索引条目中的感叹号、加号和减号。

(2) 考虑如何使输入输出的条目的格式变成可配置的,如让程序读入一个配置文件,在配置文件里面决定输入的特殊符号、输出的模板等。

(3) 考虑支持更复杂的结构,例如多级条目,一个条目下又可以有多个子条目。又如多级数字(可以表示章节编号而不只是页码)。

(4) 考虑支持更复杂的排序与分组规则。可以允许在条目中指定输出的文字与用来排序的文字不同,如希腊字母可以按alpha来排序。设计对应的输入语法,输出的格式。

(5) 其他你认为有用的扩展功能。

其他可能的扩展功能可以看makeindex[1,2]、xindy[3]等工具。

5. 项目要求

完成下面的项目要求,将项目索引处理程序、测试用例文件、测试结果文件、项目报告一起打包,提交作业。

5.1 索引处理程序

编写索引处理程序,完成前述的基本功能,并在第4节中至少选择两种扩展功能加以实现。

程序由若干个模块组成,其中包含一个Python脚本indexing.py。脚本用法如下:

python indexing.py?输入文件名? ?输出文件名?

如果有扩展功能,可以在?输入文件名?之前增加其他的命令行参数。

5.2 索引表生成

自己设计一些用于测试的索引条目,生成索引表,验证程序的功能。你编写的测试示例应该能验证:

(1)条目分组与排序的规则。

(2)页码排序与合并的规则。

(3)你设计的各种扩展功能。

随项目附有《The Art of Computer Programming》原书第一章的真实的索引数据文件taocp-1.idx,请使用你编写的程序,根据此数据文件,完成索引表的生成。

5.3 项目报告

根据项目完成的情况,编写项目报告。报告内容包括:

(1)对问题的简要描述与分析。应具体说明在你的项目中决定提供哪些功能,提供了哪些扩充。对于本项目说明没有详细说明的扩充功能,应详细分析其效果和用法。

(2)程序模块划分与具体数据结构的设计。除了说明设计的结果,也要说明设计的原则与取舍过程。

(3)程序实现中的关键问题和技术分析。

(4)概述系统功能完成情况。分析测试用例的输出效果,加以适当说明。

(5)程序重要算法的时间复杂性分析,及程序过程的空间复杂度分析。除了进行数学化的渐近复杂度分析,也可以给出实际运行的时间数据,说明程序的实际有效性。

(6)进行系统完成后的回顾和分析。说明程序的优点、缺点,可能的改进问题,在编写项目中曾经遇到的困难与解决方案,走过的弯路等。

项目报告使用PDF格式提交。报告写清楚标题、项目参与人的姓名学号。报告应按内容合理划分章节,注意算法、公式和代码的格式,使内容清楚,易于阅读。

参考材料

[1]Leslie Lamport.MakeIndex: An Index Processor For LATEX, February 1987. URLhttp://mirror.bjtu.edu.cn/CTAN/indexing/makeindex/doc/makeindex.pdf.

[2]Pehong Chen and Michael A. Harrison. Index preparation and processing.Software—Practice andExperience, 19(9):897-915, September 1988. ISSN 0038-0644. URLhttp://mirror.bjtu.edu.cn/CTAN/indexing/makeindex/paper/ind.pdf.

[3]Roger Kehr.xindy Manual, January, 2004. URLhttp://xindy.sourceforge.net/doc/manual.html

这里有一个文件,是一部著名计算机专著的一部分索引,作为本项目的参考数据文件。

二、LTL/CTL模型检验(可独立或合作完成,同组合作者不得超过3人):

有限状态迁移系统(Finite Labelled Transition System) 是形式化验证中常用的模型之一。一个有限状态迁移系统包含有限个状态(State)和一系列的迁移(Transition),每个迁移包括起始状态,后继状态和一个动作,当系统处于起始状态时,可以执行该动作并跳转到其后继状态。一个简单有限状态迁移系统的例子(Coffee Machine)定义如下所示:
idle paid
idle
coin idle paid
coffee paid idle
第一行给出所有状态的名称(名称只能包含大小写英文字母和数字,用空格隔开)。在这个例子中,咖啡机共有两个状态,分别是待机(idle)以及已付款(paid)。第二行给出系统的初始状态,在这个例子中为idle。之后每一行描述一个迁移(三个由空格分开的字符串,分别是动作名称,起始状态和后继状态)。其中起始状态和后继状态必须是第一行中出现过的。

一个有限状态迁移系统的运行过程如下:
最开始,系统处于其初始状态
如果系统的当前状态上存在一个迁移,那么就执行这个迁移并跳转到它的后继状态
如果存在多个迁移,系统会随机选择一个执行
将系统执行过程中的状态序列记录下来,我们称为它的一个路径(Path)。例如,例子中系统的路径可以是如下的无限序列:
idle, paid, idle, paid, ...
显然,一般情况下,一个有限状态迁移系统所对应的路径不是唯一的,而是一个集合。

时序逻辑用于描述系统满足的时序性质,常用的时序逻辑包括线性时序逻辑、计算树逻辑等。例如线性时序逻辑(Linear Temporal Logic)可以描述一个系统在线性时间上的变化所要满足的条件。一个线性时序逻辑公式L的定义如下所示:

L::= True | a | L1 and L2 | not L | X L (next)| L1 U L2 (until)

具体含义见[1],[2]。

假设我们有一个线性时序逻辑公式(X paid),那么我们可以看出上述的系统是满足这个公式的。因为它唯一的一条路径上从初始状态开始,下一个状态就是paid(这很显然!因为总共只有两个状态……)

如果给定一个有限状态迁移系统TS和一个线性时序逻辑公式L。当且仅当TS所有可能的路径均满足L时,我们说TS满足L。

基本要求:

设计并实现一个LTL/CTL的模型检查工具,使得对给定的状态迁移系统TS和LTL/CTL公式L,可以判断TS是否满足L,若满足,返回True,若不满足,返回False并给出TS中一条不满足L的路径作为反例(CTL中对于存在量词公式成立时返回一条满足公式的路径作为witness)。并对所给出的实现进行性能分析。

示例输入文件格式:

第一行为n个用空格分开的字符串,描述状态迁移系统的每个状态名称。第二行为一个字符串,描述状态迁移系统的初始状态。之后的若干行为状态迁移系统的边,每行由三个字符串组成,分别是:动作,起始状态,目标状态。中间用空格隔开之后空一行。然后每一行是一条要检查的时序逻辑公式。为简化问题,我们假设任何运算都由括号括起,从而不存在优先级的问题。到文件结束为止。

示例输出文件格式:

m行(m为公式的条数),每行为True,或者False加上一个状态序列作为反例,表明该模型满足公式或者不满足且给出反例。

选作:

1. 在LTL/CTL公式中可使用其他扩充运算符,如eventually、always、weak until等。

2. 设计并实现其他时序逻辑(如CTL*、TCTL、PCTL等)的模型检验算法。

报告要求参见第一题。

注意:

1. 感兴趣的同学可以考虑选作内容,不做这部分的内容不会导致本次报告成绩降低。

2. 数据结构的设计和算法的效率是需要重点考虑的问题,不需要把太多的时间花在图形界面上。做了图形界面并不是加分项。

3. 可自己定义输入输出文件格式,但需在报告中说明。

参考文献([1]、[2]为院图馆藏):

[1] Christel Baier and Joost-Pieter Katoen. Principles of Model Checking. The MIT Press, 2008.

[2] Edmund M. Clarke, Jr., Orna Grumberg and Doron A. Peled. Model Checking, The MIT Press, 1999.

[3] Some widely used model checker: PRISM, UPPAAL, mCRL2

5 12.17 12.25

设计红黑树的存储结构,并实现红黑树的插入和删除算法。

6 12.31 1.7

除课上所讲shell排序的模式之外,自己从直接选择排序、堆排序、起泡排序和快速排序中另外选择一种模式给出shell排序的算法实现,要求算法实现中提供比较次数和移动次数统计功能,由计算机随机生成长度为1000,5000,10000的三种待排序序列,用课上所讲方法和你自己所设计方法分别对其进行排序,并对相应结果进行比较分析。(因已至期末,本次作业不接受延期提交。)

 


[ 回到主页 ]


Sun Meng