20202312 2020-2021-2《数据结构与面向对象程序设计》课程总结
一、课程内容总结
第一章 绪论
- Java是面向对象程序设计语言。
- 注释: 应阐明程序编写目的并描述处理步骤,一般用“//”或“/* */”或“/** */”来标明。
- 标识符: 由数字、字母、下划线及美元符号组成(数字不能做开头)(习惯上定义常数大写),空白: 空格键、Tab键、回车换行键(单词与符号的分隔符)。
- 计算机语言发展:机器语言、汇编语言、高级语言、第四代语言,Java语言是高级语言。
- 错误:1.编译时错误:发生语法错误。 2. 运行时错误:此时要进行异常处理。 3. 逻辑错误:编译运行没有问题,但是得到的结果与预期不符。
- 四个基本的开发行为: 1. 建立需求 2. 生成设计 3. 实现设计 4. 测试。
- 基本术语:对象 属性 方法 类 封装 继承 多态。
- 类由class定义,类是对象的蓝图,由一个类定义可以得到多个对象。
第二章 数据和表达式
- print及println方法
- 字符串连接:"+"
- 转义字符:\b:回退键 \t:制表符 \n;换行 \r:回车 \ ":双引号 \ ':单引号 \ \:反斜杠
- 变量声明:通知程序预留位置并标志存储位置名称
- 变量名=(赋值)变量值
- 常量:final,其值不能改变
- 基本数据类型: 8种(byte,short,int,long,float,double,boolean,char)
- boolean只有true和false
- 算术运算:+、-、*、/、%, 关系运算:、>、>=、<、<=、==、!=, 逻辑运算:&&、||、!
- 运算符优先级:相同优先级满足从左到右的结合律。
- 自增,自减:i++、i--、++i、--i
- 基本类型之间的转换:三种转换方法:1. 赋值类型转换。2. 提升类型转换。3. 强制类型转换。同时要注意避免压缩类型转换,可能会丢失信息。
- System.in 与System.out.println
- Scanner类方法:next();nextInt();nextFloat();useDelimiter()等
第三章 类与对象
- new:返回指向新创建对象的引用
- 多个引用变量可以指向同一个对象
- String类方法:compareTo (String str);equals();equalsIgnoreCase()(可以忽略大小写比较,在用户进行选择时常用);length()等。
- Java标准类库中的类按包来组织。每个类都属于一个具体的包。调用时用import java.util.*;import java.lang.*等。
- Random类:伪随机数生成器执行复杂的计算产生随机数
- Math类:方法都是静态的,可以直接调用。
- NumberFormat类:有两个方法getCurencyInstance和getPercentInstance返回用于格式化数值的对象。getCurencyInstance返回货币格式对象,getPercentInstance返回百分比格式对象。
- DecimalFormat类:按惯例使用new运算符来实例化对象。
- 包装器类:Integer.parselnt( ) Integer.toHexString( )分别是字符串转为int类型,以及将int类型转为字符串类型。
第四章 编写类
- 类:数据声明(变量/常量)+方法(函数)。
- 类是对象的抽象\蓝图,而对象是类的具体实例。
- UML类图:实现、关联、聚合、组合、继承。
- 封装:有些对象要进行封装,从而防止对该对象的数据进行不适当的访问。常用的修饰符有public、private。
- 静态类
1.静态变量(static):有时也称类变量,它由类的所有实例共享,在一个对象中修改静态变量的值,就等于修改了其他所有对象中该静态变量的值。
2.静态方法:不需要为了调用方法而实例化类的一个对象,只能访问静态变量或局部变量。 - 类关系:依赖,聚合。
第五章 条件判断与循环
- if与if-else语句
- 浮点数的比较:计算两个差值的绝对值,在与公差进行比较。
- 字符比较:Unicode顺序,大小写字母,数字要联系ASCII表中的编码。
- 对角比较:equals。
- switch语句:switch(){case :break;default:}
- while语句 break跳出循环。
- do-while 语句:do{}while();
- for 语句:for( ; ; ),与while等价
第六章 面向对象设计
- 封装继承多态。
- extends继承,代码复用,Java只支持单继承。
- super与this常用于调用构造方法。
- 方法重载与重写:重载:根据参数类型与数量确定初始化方法 重写:重新编写父类方法。
- Object类是所有类的父类。
- abstract抽象类达抽象概念,不能用new实例化。
- 抽象类的子类:实现父类的抽象方法变成具体类,不实现父类抽象方法仍要用abstract修饰。
- this关键字的使用时调用自己类中的方法,主要是为了避免与其他类中相同名称的方法弄混。
- 多态引用在不同的时候可以指向不同类型的对象。
- 多态引用运行时才将方法调用与它的定义绑定在一起。
- 引用变量可以指向声明继承于它的任意类的任何对象。
- 接口是一组抽象方法,与抽象类一样不能被实例化。
- 接口层次:接口可以继承接口;类可以实现接口,但不能继承接口。
- Comparable接口:compareTo()
- 和class一样,接口可以用来声明对象引用变量。
- 接口引用可以指向实现这个接口的任意类的作何对象。
- 方法的参数可以是多态的。
第七章 异常
- 错误和异常(exception)都是对象,代表非正常情况或无效处理。
- 错误(Error)不用捕获。
- 处理异常:在异常发生的地方处理;在程序的其他地方处理。
- 程序中出现异常不捕获异常,程序会崩溃。
- try-catch 语句: Java中把正常流程放try块中,错误(异常)处理放catch块中,每个catch 子句处理try块中可能抛出的一种特定类型的异常,注意多个catch一定把父类放后面处理, finally:总会执行,用于资源管理。
- finally语句:无论try语句处理情况如何,最后都将执行finally语句。同时,如果有finally子句,则必须跟在catch子句后面。
- 如果没有在异常发生处捕获及处理,异常会被传播给调用的方法。
- throw:方法中抛出Checked Exception,方法声明中必须有throws。
- Java异常处理是要处理Exception类及其子类。
- 产生RuntimeException的问题在调用代码。
- I/O异常: 几乎所有的IO API都可能抛出异常。
第八章 栈
- 栈是一种线性集合,遵循先进后出(LIFO)原则,
- 栈常见的方法
- push():将元素添加到栈顶
- pop():删除栈顶元素
- peek():查看栈顶元素
- isEmpty():判断栈是否为空
- size():判断栈中元素的个数
- 使用栈计算后缀表达式:算术表达式有三种写法,前缀,中缀,后缀表达式。用栈来计算后缀表达式时,在从左到右扫描表达式,操作数入栈,遇到操作符则pop两个数计算后再push。
- 用数组实现栈的操作,ArrayStack类,用链表实现,LinkedStack类。
- 链表:与有固定大小的数组不一样,链表没有容量上限。
- 链表被看成是一个动态结构,它的大小总随着所保存的元素个数在变大或变小。
- 链表是由具有相同数据类型的元素构成的序列。
- 在使用链表时,需要定义结点,通常,我们采用LinearNode类来实现。
第九章 队列与列表
- 队列是一个线性集合,它在一端添加元素,在另一端删除元素————先进先出(FIFO),第一个进入的元素,也就是第一个退出的元素。
- 一般把一端作为队列的前端(front/head),一端作为末端(rear/tail)。
- 队列常见方法
- enqueue():向队列末端添加一个元素
- dequeue():向队列前端删除一个元素
- first():查看队列前端元素
- isEmpty():判断队列是否为空
- size():判断队列中元素的个数
- 由于队列操作会修改集合的两端,所以我们可以在一端固定一个索引为0的元素。
- 队列与列表都可用数组与链表来实现。对于队列,有LinkedQueue与ArrayQueue,对于列表,则有LinkedList与ArrayList。
- 特别的,对于ArrayList类,集合是可变大小的,是按所需来进行空间分配的,这是由列表的特性决定的。因此,这种类在空间管理上十分高效,不会造成浪费。
- 列表里定义了Iterator方法,该方法是在集合上进行迭代操作,并返回一个Iterator对象。
- 队列常见方法
- removeFirst():从列表中删除第一个元素
- removeLast():从列表中删除最后一个元素
- first():查看列表第一个元素
- last():查看列表最后一个元素
- contains:确定列表是否包含某种特定元素
- isEmpty():判断列表是否为空
- size():判断列表中元素的个数
- 对有序列表 add:向列表中添加元素
- 对无序列表 addToFront(添加元素到列表头), AddToRear(添加元素到列表尾), AddAfter(添加元素到某个特定元素之后)。
第十章 选择与查找
- 线性查找:设置哨兵在数组开头或结尾,以便提高查找效率。
- 二分查找:从中间开始,要求表是有序的,每次比较后可以减少查找池中的一半元素
- 分块查找:先二分查找,再线性查找
- 哈希查找:直接通过关键字找到存储地址。
- 散列查找
排序
- 选择排序:分别将每个值放在排好序的最终位置,从而完成一组值的排序。
- 插入排序:将一个具体的值插入到表中已有序的子系列中,从而完成一组值的排序。
- 冒泡排序:重复地比较表中的相邻元素,如果它们不符合要求则交换他们。
- 快速排序:根据一个任意选定的划分元素来对表进行划分,然后再递归地对划分元素两边的字段进行排序,从而完成对表的排序。
- 归并排序:递归地对分表,知道每个子表只含有一个元素时为止,然后再将子表按序合并,从而完成对表的排序。
第十一章 树
- 树:节点+边
- 完全二叉树(满二叉树也是完全二叉树)
- 树的遍历: 先序遍历、 中序遍历、 后序遍历、 层序遍历
- 二叉树的实现
- 决策树:用二叉树来表示。
- 二叉查找树: 查找、插入、 删除
- 二叉查找树的实现
- 平衡二叉查找树
第十二章 堆
- 堆:完全二叉树(根节点小于左右孩子)
- 堆的实现
- 堆排序
- 优先队列:具有更高优先级的项排在前面,具有相同优先级的项按先进先出的规则排列。
第十三章 图
- 无向图:图中表示边的顶点对是无序的图是无向图,意味着两点间的连接是双向的。
- 有向图:图中的边是顶点的有序对的图为有向图,意味着有向图的边是有方向的边。
- 带权图:图中每条边都对应一个权值的图成为带权图,有时也称为网络。
- 图遍历:广度优先遍历、 深度优先遍历
- 无向图的最小生成树(Prim算法或Kruscal算法)
- 有向图的拓扑排序 有向图的最短路径求解: Dijkstra算法。
- 图的实现策略:邻接表邻接矩阵
二、作业总结
作业1:面向对象程序设计1 ,面向对象程序设计2 ,面向对象程序设计3 ,面向对象程序设计4 ,面向对象程序设计5
- 提交最后三个JUnit测试用例
- 以 TDD的方式研究学习StringBuffer。
- 对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式
- 以TDD方法开发一个复数类Complex
- 使用StarUML进行建模
编写一组程序,要体现一下知识点:
(1)继承
(2)多态
(3)重写
(4)重载
(5)目录创建
(6)文件创建
(7)字节流读写
(8)字符流读写
作业3:实现自己的ArrayList
- 编写自己的ArrayList类
-
实现增加、删除、修改、查找、判断是否为空、返回list长度等操作。
- 测试
作业4:实验四 (1)Java Socket编程
(2)Java和密码学
(3)编写有理数/复数计算器
(4)远程有理数计算器
(5)远程复数计算器
作业5: ArrayStack类测试
- 撰写自己的类;
- 提供StackADT,ArrayStack(框架),实现ArrayStack里面的剩余方法;
- 编写测试类,测试所写的方法是否正确。
作业6:栈应用-进制转换
- 要求输入一个十进制数,转换成任意进制数并输出
作业7:最小生成树测试
- 画出Prim算法的最小生成树的生成过程
- 画出Kruscal算法的最小生成树的生成过程
- 计算最小权值
作业8:最后一次测试
三、实验报告链接汇总
实验一:linux基础与java开发环境
- 基于命令行和IDEA(Intellj IDEA 简易教程]进行简单的Java程序编辑、编译、运行和调试。
- 练习Linux基本命令;
- 学习Java程序的JDB调试技能
- 编写简单的Java程序。
实验二:Java基础(数据/表达式、判定/循环语句)
- 编写简单的计算器,完成加减乘除模运算。
- 要求从键盘输入两个数,使用判定语句选择一种操作,计算结果后输出,然后使用判定和循环语句选择继续计算还是退出。
- 编写测试代码,测试验证。
实验三:面向对象程序设计
- 初步掌握单元测试和TDD
- 理解并掌握面向对象三要素:封装、继承、多态
- 初步掌握UML建模
实验四:Java Socket编程与密码学
- Java Socket编程
- Java和密码学
- 编写有理数/复数计算器
- 远程有理数计算器
- 远程复数计算器
实验五和六:线性结构之链表
- 链表练习,要求实现下列功能:通过键盘输入一些整数,建立一个链表;这些数是你学号中依次取出的两位数。 再加上今天的时间。打印所有链表元素, 并输出元素的总数。
- 链表练习,要求实现下列功能:实现节点插入、删除、输出操作;继续你上一个程序, 扩展它的功能;从磁盘读取一个文件,完成相关操作。
- 链表练习,要求实现下列功能:用冒泡排序法或者选择排序法根据数值大小对链表进行排序;
- 在android上实现实验(1)和(2)
- 在android平台上实现实验(3)
实验七:查找与排序
- 定义一个Searching和Sorting类,并在类中实现linearSearch,SelectionSort方法,最后完成测试
- 重构你的代码
- 参考http://www.cnblogs.com/maybe2030/p/4715035.html ,学习各种查找算法并在Searching中补充查找算法并测试
- 补充实现课上讲过的排序方法:希尔排序,堆排序,二叉树排序等
- 编写Android程序对实现各种查找与排序算法进行测试
实验八:树
- 参考教材完成链树LinkedBinaryTree的实现(getRight,contains,toString,preorder,postorder)
- 基于LinkedBinaryTree,实现基于(中序,先序)序列构造唯一一棵二㕚树的功能,比如给出中序HDIBEMJNAFCKGL和后序ABDHIEJMNCFGKL,构造出附图中的树
- 自己设计并实现一颗决策树
- 输入中缀表达式,使用树将中缀表达式转换为后缀表达式,并输出后缀表达式和计算结果
实验九:图
- 初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)
- 图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)
- 完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环
- 完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出
- 完成有向图的单源最短路径求解(迪杰斯特拉算法)
四、代码托管链接
给出statistic.sh的运行结果,
总计:3076行,(截图如下)
ps:有许多代码之前都被自己删了,就连考试时的代码也基本都被自己删完了,有些dat文件之类的也没了,感觉少了好多代码,基本idea里只剩了几次实验的。我太难了
课程收获或不足
1.自己的收获:java作为自己学习的第二门语言学科,本以为在学习了C后应该会比较简单,但随着学习进度的逐渐延伸,慢慢发现java的难度远超预期,尤其是数据结构,里面有很多知识点,需要自己去理解,去掌握,最后用代码将其实现。在学习java的过程中,最大的收获就是锻炼了自己的抽象思维能力。在学习数据结构相关内容时,里面的结构很多都是比较抽象的,需要自己课下花大量时间去琢磨,钻研。尽管过程很痛苦,因为实在是看不懂,但当自己成功的将代码实现,自己会感到特别的惬意,那是自己努力了很久,终于把这个问题解决了的感觉。忽然之前难受也就感觉没啥了。并且,还认识了这么一位好的老师,答疑解惑耐心负责,我也因此才能在课下练习和课上听讲上有所收获。最后,自己的自学能力得到了极大的强化,因为实在有很多知识点不了解,只能逼着自己去上网找相关解读,比如CSDN,去B站找相关视频,课下找相关辅导书,不管如何,自己的自学能力总算有了不小的进步。
2.自己需要改进的地方:学习的效率有时候确实有些低下,就感觉不知道该往哪走,就胡乱看书,搞了半天,还是啥也不会。感觉自己遇到问题可以多向老师或者同学请教,给自己指明方向,这样自己会节约很多不必要的时间。效率也能提高不少。再就是,相关理性思维能力仍需提高,平时学习中,很多时候自己确实看了想关知识点,但总感觉不是很能完全吃透,很难做到举一反三这类。最后,就是自己在课下学习的时间应该增加,学习还是得靠自己,光靠上课是不够的,自己平时花的时间确实少了,以后,要钻研透,还是得多磨。不管怎样,路漫漫其修远兮,吾将上下而求索。