20202315 2020-2021-2《数据结构与面向对象程序设计》 课程总结
课程内容总结
·第一章
现在回想关于第一章的内容,剩的确实不多,翻阅笔记与资料之后有了以下想法与收获:
①程序语言,程序语言分为机器语言、汇编语言、高级语言及第四代语言四类,其中我们主要学习的高级语言包括Java、C、C++、python等编程语言。编译与解释的作用是把高级语言转变成机器语言,由于一个CPU只能读懂一种机器语言,所以编译执行速度快但是无法在不同的机器上执行,这限制了他的推广与发展。与之相对,只有要适当的解释器,同一种语言便可在不同平台上执行,但由于解释的过程是一边解释一遍执行,所以解释的执行速度慢。
②Java结构中立性促进了Java的发展,Java编译器将java源代码转化成了java字节码,而java字节码不是一种机器语言,它是一种类似机器语言代码的低级程序格式,字节码会被重新翻译成机器语言然后执行。
③注释:Java注释通常采用以下三种:// /* ...... */ /** .... */
④标识符和保留字。编写程序时使用的各种各样的字称为标识符,一般分为:自选、他选、特殊含义三类,标识符可以由任意字母、数字、下划线和美元符号组成,但是不能以数字开头,其长度也是任意的,值得一提的是,Java是大小写敏感的;保留字是已经被设定好的具有特定含义的标识符。
⑤Java应用程序的结构,初步了解了关于“类”“方法”的内容。
⑥关于虚拟机的内容应该也是在第一章中,Linux基本命令及vim的用法,Git上传到码云,JDB调试技能(这些都在第一次实验报告中有体现)
(没什么意思,主要是想显摆一下我的笔记)
·第二章
第二章的主要内容是数据和表达式
①Java实现字符串的拼接可以直接使用加号,c=a+b即可以表示把字符串a与b拼接起来;print和println方法,ln的作用就在于换行;转义字符(这一点其实和C很像)。
②变量和赋值:常量赋值:final int(大写字母命名)=(数值),变量赋值与C语言一致; java的基本数据类型:整型与浮点型、字符型、布尔型:boolean,true/false(只有两种情况); 同时输出两个类型不同的量 +“ ”+ 空字符串将前后类型改变,均改变为字符串型。
③表达式的内容:运算符(赋值运算符,算术运算符、自增自减运算符)及其优先级。
④读输入数据:下图是我当时记的笔记,并不是我懒,只是我觉得我当时的笔记简明精要地表达了我的想法!
·第三章
第三章的主要内容是关于类与对象(类是对象的蓝图)
①自定义类: 类=属性(变量/常量/对象)+方法(函数)
接口类(关键字为interface,abstract关键字可有可无)=属性(常量)+方法(抽象abstract方法) 实现是需要关键字implements
抽象类:属性(变量/常量/对象)+方法(抽象abstract/非抽象法/可有可无)(类名的声明必须用abstract及抽象方法需多加注意)
实现抽象方法也需要使用关键字implements 抽象类不能被实例化(instantiated)
②import声明,我的理解相当于是C语言的头文件
Random类,属于java.util包,属于伪随机数生成器;Math类提供了大量的用于计算的基本数学函数;NumberFormat类可以对数值进行格式化
③条件语句:if语句、switch语句。循环语句:while语句和for语句
④包:包装器类、枚举类、格式化输出
文件的读取操作:字节流读写:InputStream和OutputStream 字符流读写:Reader和Writer
(举个例子)//初始化你要写的文件
File file = new File("E:\\text", "ja.txt");
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream(file);
// 字符串转换为字节数组
byte[] b = "输入的字节".getBytes();
// 写出字节数组数据
fos.write(b);
// 关闭资源
fos.close();
·第四章
①可见性修饰符:Public(可在类外部访问)private(只能在类内部访问)protected(可以在继承类中访问)
②面向对象三要素:封装、继承、多态! 封装:类外部的代码难于访问和修改类内部的变量(private)
继承:关键字是extends 父类/子类 super/this Object类是万类之祖,可以是所有类的父类
类继承、抽象类继承(extends)、接口继承(implements)
重写:重写父类的方法 父类中的方法在子类中重写一遍 重载:方法(不同的参数、参数的个数、参数的类型等)
多态:多种形态,父类的对象可以指向多个子类的对象,调用子类的方法
③UML类图,使用图来表达、获取并交流程序的主要内容
④静态类成员:静态变量及静态方法 局部参数、局部变量 this引用,通常用于构造方法中 形参(formal parameter):方法声明头部的参数名称 实参(actual parameter):调用方法时传给方法的值
⑤类间关系:
(1)依赖:在A的方法需使用类B的方法。AnimalTest—>Animal
静态方法:在A中直接使用B.xxxx()
非静态方法:在A中需要实例化B b= new B(); b.xxx()
(2)聚合:has-a关系,聚合关系是依赖关系的特殊类型
⑥最后就是掌握对类的基本编写,用book类和student类小试牛刀了还
·第五章
①数组的内容,包括初始化,赋值语句,作为参数如何传递,spilt的用法,二维数组。
②异常,即不处理进行不下去,所以要用特殊语句来处理异常
处理异常的语句示例:
try { }catch(Exception ex){ }
finally{(无论是否异常都会执行finally语句)}
③文件的读取操作:字节流读写:InputStream和OutputStream 字符流读写:Reader和Writer
(举个例子)//初始化你要写的文件
File file = new File("E:\\text", "ja.txt");
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream(file);
// 字符串转换为字节数组
byte[] b = "输入的字节".getBytes();
// 写出字节数组数据
fos.write(b);
// 关闭资源
fos.close();
·第六章
①递归思想及递归程序设计,我理解的递归就是一个套一个套一个套一个......
②算法分析:时间复杂度及空间复杂度(O()量级越低,效率越高)、算法效率(通常用CPU的使用时间来表示)、增长函数和大O
③软件开发(程序)
程序=数据结构+算法 软件=程序+软件工程
确定软件需求——软件设计——实现软件设计——软件测试
伪代码:将算法描述清楚,不一定可以执行 产品代码(开发代码) 测试代码(这个想不起来在哪讲的了,插到这)
④数据结构是计算机存储、组织数据的方式,包括逻辑结构、物理结构(存储结构)、数据运算
逻辑结构:线性结构(线性表List、栈、队、串、数组)和非线性结构(树结构、图结构) 物理结构:顺序存储结构(ArrayList)、链式存储结构(LinkedList)、索引结构、散列结构 数据运算:插入运算、删除运算、查找运算、修改运算、排序运算
·第七章
①线性表是一个长度为n的有限序列,他可以在表中任何地方添加、删除元素,栈和队列是特殊的线性表。
②线性表的基本操作主要包括添加(add)、取值(get)、移除(remove)、是否为空(isEmpty)、长度(size),其余的不过多赘述了
③线性表的实现可以利用数组,但由于其移动会很麻烦,所以java语言中有自己的链表
④Stack:栈是一个只允许在表尾(栈顶)插入和删除的线性表,遵循先入后出的原则。它可以应用于数制转换(取余进栈再除)和表达式求值及标识方法(前、中、后缀)。
⑤利用栈来实现用原表达式求得后缀式:设立一个操作符的栈,存放运算符,首先栈为空;操作数直接输出,两个操作数之间有空格;运算符与栈顶元素比较,比栈顶级别高则进栈,级别低则退出栈顶元素输出(右括号的优先级比左括号高);括号右括号抵消左括号,左括号进栈,右括号退栈输出,退到左括号为止。
后缀表达式求值:设立一个操作数的栈,首先栈为空;从左到右扫描表达式,遇操作数,进栈;遇操作符,弹出两个操作数,操作结果再入栈
⑥Queue:队列是限定在队头进行删除,在队尾进行插入的线性表,遵循先入先出的原则。队列的链式表示结构、队列的假溢出、改进为循环队列。 例:把队列设想成环形,让sq[0]接在sq[M-1]之后,即:若rear+1==M,则令rear=0。此时,移动指针不能用i=i+1,要用(i+1)%M
·第八章
①查找与排序:这一章主要介绍了多种查找方法及排序方法及其不同的优劣。(这个在书中位置比较靠前,讲的时候比较靠后,跟)
②查找方法:
顺序查找:是一种无序查找方法,从数据列的某一位置开始顺序扫描(时间复杂度为O(n))
二分查找:是一种有序查找,从中间分成两个子数据列,然后比较,然后重复上述操作,一定要先排序(时间复杂度为O(log2n)
插值查找:二分查找的一种优化,将取中值点改为取一个low + (target - arr[low]) / (arr[high] - arr[low] * (high - low))的点
斐波那契查找:先对数据列进行一个有序分割然后再查找
哈希表查找,直接通过关键字找到存储地址,使得查找时间可以是常数级
③构造哈希函数:
(1)直接定址法:线性函数,没有冲突!
(2)除留余数法:(模法) 类似H(k)=k%m
可能冲突,解决方法有:
·开放定址法:线性探测、二次探测、伪随机探测
从发生冲突的那个单元开始,按照一定的次序,从哈希表中找出一个空闲的存储单元。
·再哈希法:H(k)=k%m +a H(k)=k%m +b
·链地址法:将所有相互发生冲突的同义词存储在同一个单链表中,若干同义词可以组成若干单链表
④排序算法好坏的衡量:时间效率、空间效率、稳定性。
插入排序:将序列分为两部分,然后依次将未排序序列的第一个元素,插入到排序序列的适当位置;
折半插入排序:跟插入排序差不多,多分了一个s,m,j
2—路插入排序:从前往后看,然后将遍历过的按照顺序插入另一路
希尔排序:缩小增量排序,取希尔增量,一趟分组,一趟排序,减少移动的次数,提高效率。
交换排序:每次比较两个数据,然后交换位置;
选择排序:选取未排序序列的合适元素,安排在排序序列的最后位置;
基数排序:根据数据的个位数、十位数、百位数依序安排其数据位置,得到排序结果的过程。不需要数据的比较。
内部排序与外部排序:在内存中进行的排序称为内部排序,
将带排序的记录存储在外存上,排序时再把数据一部分一部分的调入内存进行排序称为外部排序。
⑤算法效率分析:
直接插入排序最好情况:待排序数据已经有序,比较次序是 n-1
直接插入排序最坏情况:待排序数据完全逆序,比较次序是(n+2)(n-1)/2
折半插入排序:具有稳定性,最大值节点及最小值节点在不断移动,顺序相反时即确定插入位置
插入排序之—希尔排序,即缩小增量排序,增量gap=length/2,性能取决于步长序列的选择。
·第九章
这一章主要讲的是关于树的定义及基本操作、二叉树的性质、二叉树基本操作、二叉树的遍历与排序
①树是一种非线性的结构、树的结点、树的叶子、结点的度、树的深度,树的基本操作有查找类、插入类和删除类。
②二叉树是一种特殊的树,他有三条性质,满二叉树和完全二叉树是两个特殊的二叉树,一个是结点全满,一个是全满结点最后一层从右开始删减
③(虽然我不大理解为什么要用树来排序,这不直接有手就行?)二叉排序树是二叉树的一种应用,根据左小右大的原则对一个无序序列进行遍历就可以生成一个二叉排序树,在二叉排序树上的查找就是根据左小右大的原则进行的,二叉树的平衡化有助于提高查找效率
④二叉树的遍历有先序遍历(根左右)、中序遍历(左根右)、后序遍历(左右根)、层序遍历(从上往下,从左往右),二叉树的遍历是很多操作的基础,查找、插入、删除、排序等这些操作都是建立在遍历的基础上实施的。
⑤哈夫曼树:前缀码左零右一,按照路径可读取每一个叶子的哈夫曼编码,哈夫曼编码及最优前缀码,是编码长度最小的一个二叉树,也是最优二叉树
·第十章
最后讲的是关于“图”的性质和操作
①实际生活中其实存在很多与“图”有关的问题,课堂上讲过的地图着色问题、架线搭桥问题这些都可以转化为数据结构中的图来解决问题,其实说白了,图就是一些点和一些边的结合,然后连一连、画一画、走一走
②对于图的存储、我们学习了好几种方法,其中最为重要的便是邻接表和邻接矩阵;邻接矩阵其实就是用一个一维数组存放点,用一个二维数组存放边;邻接表就是用链表跟指针实现
③对于图的基本遍历,有深度优先遍历和广度优先遍历两种,深度优先遍历跟邻接表有点像就是从一个点开始一层一层往下走,广度优先遍历就是一圈一圈往下走,先把第一圈走完再找下一圈。
④图中的树问题,有生成树及最小生成树,图的生成树就是在保证一个整体的前提下去掉边,而最小生成树是在保证一个整体的前提下让边的权值之和最小,prim算法和kruskal算法就是求做小生成树的两种方法,一个是从点往外延伸,一个是连边成一个整体。
⑤图中的最短路径问题,我们详细讲了的只有迪杰斯特拉算法,即根据权值大小,逐个加入顶点之后再求最短路径。拓扑排序:拓扑排序是一种可以判断图中是否有环的排序方法,对入度为零的点进行入栈,再出栈删除以之为起点的边,重复操作以得结果。
以上便是我对这学期学习内容的总结,很多内容用语言表示很容易,但是写成代码得以实现往往需要耗费很大的精力和时间,可见对java的掌握仍然不精通,仍需继续努力。
总结做过的作业
·作业一
第一章和第二章测试活动,根据错题知识点总结链接
·作业二
·作业三
·作业四
·作业五
编写一组程序,要体现以下知识点:
(1)继承
(2)多态
(3)重写
(4)重载
(5)目录创建
(6)文件创建
(7)字节流读写
(8)字符流读写
·作业六
·作业七
1.编写自己的ArrayList类
要求:实现增加、删除、修改、查找、判断是否为空、返回list长度等操作。
2.测试。
·作业八
·作业九
(1)撰写自己的类;
(2)提供StackADT,ArrayStack(框架),实现ArrayStack里面的剩余方法;
(3)编写测试类,测试所写的方法是否正确。
·作业十
已知一个单链表(没有头节点),其头指针/引用为head,要插入一个节点element,写出尾插法的方法伪代码:
public LinearNode insertTail(LinearNode head, LinearNode element){
·作业十一
·作业十二
·作业十三
1.画出Prim算法的最小生成树的生成过程
2.画出Kruscal算法的最小生成树的生成过程
3.计算最小权值
·作业十四
·作业十五
3,44,38,5,47,15,36,26,27,2,46,4,19,50,48
快速排序给出第一趟快速排序的结果!
·作业十六
实验报告链接汇总
实验一
基于命令行进行简单的Java程序编辑、编译、运行和调试。
练习Linux基本命令;
学习Java程序的JDB调试技能:https://www.cnblogs.com/rocedu/p/6371262.html
编写简单的Java程序。
编写简单的计算器,完成加减乘除模运算。
要求从键盘输入两个数,使用判定语句选择一种操作,计算结果后输出,然后使用判定和循环语句选择继续计算还是退出。
编写测试代码,测试验证。
下载安装并使用IDEA,完成下面实验(https://www.cnblogs.com/rocedu/p/6371315.html)。
初步掌握单元测试和TDD
理解并掌握面向对象三要素:封装、继承、多态
初步掌握UML建模
完成蓝墨云上 (1)-(5)实验。
(一)Java Socket编程
1.学习蓝墨云上教材《Java和Android编程》“第16章 输入/输出 ”和“第22章 网络”,学习JavaSocket编程
2.结对编程。结对伙伴A编写客户端SocketClient.java,结对伙伴B编写服务器端。
3.截图加学号水印上传蓝墨云,代码push到码云,并撰写实验报告。
(二)Java和密码学
参考 http://www.cnblogs.com/rocedu/p/6683948.html
以结对的方式完成Java密码学相关内容的学习(帖子中所有代码和相关知识点需要学习)。提交学习成果码云链接和代表性成果截图,要有学号水印。
(三)编写有理数/复数计算器
结对编程,结对伙伴A编写有理数计算器。结对伙伴B编写复数计算器。截图加水印上传蓝墨云,代码push码云。
(四)远程有理数计算器
结对编程,结对伙伴A编程实现客户端,结果伙伴B实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴B(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端A,A收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
(五)远程复数计算器
结对编程,结对伙伴B编程实现客户端,结果伙伴A实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴A(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端B,B收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
1.链表练习,要求实现下列功能:
通过键盘输入一些整数,建立一个链表;
这些数是你学号中依次取出的两位数。 再加上今天的时间。
例如你的学号是 20172301
今天时间是 2018/10/1, 16:23:49秒
数字就是
20, 17,23,1, 20, 18,10,1,16,23,49
打印所有链表元素, 并输出元素的总数。
在你的程序中,请用一个特殊变量名来纪录元素的总数,变量名就是你的名字。 例如你叫 张三, 那么这个变量名就是
int nZhangSan = 0; //初始化为 0.
做完这一步,把你的程序签入源代码控制(git push)。
2.链表练习,要求实现下列功能:
实现节点插入、删除、输出操作;
继续你上一个程序, 扩展它的功能,每做完一个新功能,或者写了超过10行新代码,就签入代码,提交到源代码服务器;
从磁盘读取一个文件, 这个文件有两个数字。
从文件中读入数字1, 插入到链表第 5 位,并打印所有数字,和元素的总数。 保留这个链表,继续下面的操作。
从文件中读入数字2, 插入到链表第 0 位,并打印所有数字,和元素的总数。 保留这个链表,并继续下面的操作。
从链表中删除刚才的数字1. 并打印所有数字和元素的总数。
3.链表练习,要求实现下列功能:
使用冒泡排序法或者选择排序法根据数值大小对链表进行排序;
如果你学号是单数, 选择冒泡排序, 否则选择选择排序。
在排序的每一个轮次中, 打印元素的总数,和目前链表的所有元素。
在(2)得到的程序中继续扩展, 用同一个程序文件,写不同的函数来实现这个功能。 仍然用 nZhangSan (你的名字)来表示元素的总数。
4.在android上实现实验(1)和(2)
5.在android平台上实现实验(3)
1.定义一个Searching和Sorting类,并在类中实现linearSearch,SelectionSort方法,最后完成测试。
要求不少于10个测试用例,提交测试用例设计情况(正常,异常,边界,正序,逆序),用例数据中要包含自己学号的后四位
2.重构你的代码
把Sorting.java Searching.java放入 cn.edu.besti.cs2023.(姓名首字母+四位学号) 包中(例如:cn.edu.besti.cs1823.G2301)
把测试代码放test包中
重新编译,运行代码,提交编译,运行的截图(IDEA,命令行两种)
3.参考http://www.cnblogs.com/maybe2030/p/4715035.html ,学习各种查找算法并在Searching中补充查找算法并测试
提交运行结果截图
4.实现排序方法等(至少3个)
测试实现的算法(正常,异常,边界)
提交运行结果截图(如果编写多个排序算法,即使其中三个排序程序有瑕疵,也可以酌情得满分)
5.编写Android程序对实现各种查找与排序算法进行测试
提交运行结果截图
推送代码到码云(选做,额外加分)
1.参考教材PP16.1,完成链树LinkedBinaryTree的实现(getRight,contains,toString,preorder,postorder)
用JUnit或自己编写驱动类对自己实现的LinkedBinaryTree进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
2.基于LinkedBinaryTree,实现基于(中序,先序)序列构造唯一一棵二㕚树的功能,比如给出中序HDIBEMJNAFCKGL和后序ABDHIEJMNCFGKL,构造出附图中的树
用JUnit或自己编写驱动类对自己实现的功能进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
3.自己设计并实现一颗决策树
提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
4.输入中缀表达式,使用树将中缀表达式转换为后缀表达式,并输出后缀表达式和计算结果(如果没有用树,正常评分。如果用到了树,即使有小的问题,也酌情给满分)
提交测试代码运行截图,要全屏,包含自己的学号信息
1.初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)
2.图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)
3.完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环
4.完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出
5.完成有向图的单源最短路径求解(迪杰斯特拉算法)
代码托管链接:
给出statistic.sh的运行结果,统计本学期的代码量。
课程收获与不足
收获:首先最大的收获肯定是掌握了一门新的课程,也有幸觅得良师。对Java这门语言是从入门到熟练地一个过程,我还记得前期面对那么多奇奇怪怪的定义,我根本不知道如何去设计去实现一个代码,但是在后期做实验的过程中,我发现我已经可以在不依靠任何参考书、任何资料的情况下,独立地把在脑海中设计的思路转换成Java语言,这无疑是一个很大的收获与提升。对于数据结构的学习我认为是很两极分化的,课堂上我很认真地在听老师讲的内容也掌握理解了,但是课下用Java语言去实现就很困难。所以那段时间我一度很喜欢听王老师讲课,很苦恼于编写程序,我想主要还是由于前期对Java语言的练习不够到位,掌握不够熟练。但总的来说,一学期的课程下来,不论是编程能力、逻辑思维能力还是在耐性方面都得到了很长的提升。我在之前的实验中就说过这样一句话,每一个代码都是自己精心打磨出来的一个孩子、一枚润玉,都是倾注了编程人的心血与智慧。
不足:在上边也提到了,我的实践能力及动手能力仍有不足,而且我自认为我的编程水平还是沧海之一粟,需要对Java语言进行更为深层次、更为细致的学习。对部分代码还不甚理解,只是生搬硬套,没有办法熟练地转化运用。
最后,很喜欢王老师的教学风格,幸得良师,亦如益友。