20162320刘先润大二第5周学习总结
学号20162320 《程序设计与数据结构》第5周学习总结
教材学习内容总结
- 1.集合(collection),是收集并组织其他对象的对象,它定义了访问及管理称为集合元素(element)的其他对象的一种具体方式。
线性集合是集合中的元素排成一行。
非线性集合是按不同于一行的方式来组织元素。
集合中的元素一般由加入集合的次序或元素之间某些固有的关系而组织。
集合是隐藏其实现细节的一个抽象名称。
抽象数据类型(abstract data type,ADT)是其值和操作都没有在程序设计语言中定义的一种数据类型,它是抽象的,因为其实现细节必须要定义,而且要对用户隐蔽。
数据结构是用来实现集合的基本程序设计结构集合。
- 2.栈集合,栈(stack)是一个线性集合,其元素的添加及删除都在一端进行。
栈以LIFO(last in,first out)的方式处理元素——最后进入的元素最先离开。 程序员应该选择与所需管理的数据的类型相匹配的数据结构。栈中ADT的基本操作有push、pop、peek、isEmpty、size。
下图是关于入栈的概念示意图
- 3.继承、多态和泛型
多态引用使用对象的类型而不是引用的类型来判定要调用的是哪个方法。
复用是指一旦编写代码并且编译为字节码后创建的集合,能够安全、高效、有效地处理保存在其中的任意对象,所以我们必须考虑类型兼容(将一个对象赋给一个引用是否合法)及类型检查。
泛型来定义类,定义一个类,它保存、操作并管理直到实例化时才确定类型的对象,很安全有效。注:类似于T这样的泛型不能被实例化,它相当于一个占位符,允许我们定义可管理实例化时才确定类型的对象的类。
- 4.栈的ADT
Java接口定义了一组抽象方法,能用来将抽象数据类型概念与它的实现分开。
通过使用接口名作为返回值类型,接口机制可让方法与实现栈的具体类分开。
- 5.使用栈计算后缀表达式
展示计算后缀表达式时使用的理想数据结构。
例:(12-4) /(37-19) ——→12 4 - 3 7 * 19 - / *
- 6.异常
错误和异常代表不常见或不正确的处理
例如在PostfixEvaluator示例中会出现的异常:1.在栈满时入栈 2.在栈空时出栈 3.扫描完表达式时栈中的值多于1个
- 7.使用数组实现栈
集合操作的实现细节不应该影响使用者与集合进行交互的方式。
处理异常情形的方式,决定是集合还是集合的使用者来控制具体的行为。
考虑到效率,数组实现的栈将栈底放在下标为0的位置。
附上我的ArrayStack实现代码,这个类的两个构造方法,一个是使用默认容量,另一个是扩容。
push操作,在确保栈不满的情况下,数组count位置的引用指向入栈的对象,然后count+1。注:时间复杂度为O(1)。
pop操作,在确保栈中有元素的情况下,返回下标为count-1的元素。注:时间复杂度为O(1)。
peek操作,返回count-1位置处的引用。
- 8.使用链表实现栈
可用对象引用变量来创建链式结构,链表由对象组成,其中每个对象指向表中下一个对象。
链表根据需要动态变大,本质上没有容量限制,除非计算机内存耗尽。
修改引用的次序对链表的维护很重要。
实现带哨兵结点或虚位结点作为第一个结点的表,可以去掉第1个结点这种特殊情况。
有效实现了相关操作的集合的任何一种实现方案都能用来解决问题。
链式结构是使用对象引用变量来建立对象之间联系的一种数据结构。所谓链表就是一个链式结构,一个对象指向下一个对象,建立了表中对象之间的线性关系。
访问元素,使用李安表示,在表中维护一个指向第一个元素的指针,因为访问元素的唯一方法是从第一个元素开始,从前向后沿表前进。
插入结点,结点可以插入到表中任何位置。
删除结点,删除一个结点,需要将前面的引用重新指向后面的引用,如下图所示。
- 9.没有链的元素
保存在集合中的对象不能包含所用数据结构的任何实现细节
定义一个独立的结点类,用来将元素连在一起,如图所示
教材学习中的问题和解决过程
- 问题1:为什么链表结点应该与表中保存的元素分开?
解答:没有理由假定我们想要放到集合中的每个对象都能符合集合的实现。此外,实现细节应与集合的使用者分开,包括用户选择添加到集合中的元素。 - 问题2:LinkedStack
和ArrayStack 有什么共同之处吗?
解答:两个类都实现了StackADT接口,都提供使用栈所需的操作,功能是可以进行互换的。 - 问题3:如果选择在表尾而不是在表头进行push操作,该操作的时间复杂度是什么?
解答:如果要在表的尾端入栈,则必须便历表到达最后一个元素。这个遍历将导致时间复杂度为O(n)。另一个修改方案是增加rear引用,它总是指向表的最后一个元素。这对于add操作的时间复杂度是有用的,但如果想删除最后一个元素,仍无济于事。
代码调试中的问题和解决过程
- 问题1:教材PostfixEvaluator代码的思路?
while (tokenizer.hasNext()) {
token = tokenizer.next();
if (isOperator(token)) {
op2 = (stack.pop()).intValue();
op1 = (stack.pop()).intValue();
result = evalSingleOp (token.charAt(0), op1, op2);
stack.push (result);
}
else
stack.push (Integer.parseInt(token));
}
return result;
解答:通过反复阅读代码,我的理解是首先创建一个栈,默认容量为10,然后建立扫描方法,扫描后把操作的数压入栈中,当扫描到操作符,从栈中弹出最近的两个数,通过扫描到的操作符实现对应的方法进行计算,然后再压入栈。
- 问题2:如何实现LinkedStack的push操作?
public void push(T element) {
LinearNode<T> now = new LinearNode<T>(element);
now.setNext(top.getNext());
top.setNext(now);
count++;
}
解答:通过和王彪同学结对编程,我们实现首先创建用来保存加入元素的结点类的实例now,让后让其指向front指向的元素,让给让front指向now。
代码托管
(statistics.sh脚本的运行结果截图)
上周考试错题总结
第四周错题还没订正,哇,而且我在第一次做题的时候还没有学第14章,我以为我们学过了,所以就得了8分,然后我手残地又点了返回键,把两次答题机会都用了,很烦。学了14章后那些题很多我基本上上感觉都会了,如果能再做一次的话。
结对及互评
点评过的同学博客和代码
- 本周结对学习情况
其他(感悟、思考等,可选)
刘老师说的话很关键,一个代码看懂了和会写是完全两个概念,而且这周的学习内容就有让我们补全书上的代码作业。虽然不是特别难,但还是考察了能力。希望同学们能够真正提高代码能力,不要再让老师们多费心去检查了。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 188 | 1/1 | 25 | 算法分析 |
第二周 | 70/258 | 1/2 | 15/40 | 《构建之法》7-9章 |
第三周 | 474/732 | 1/3 | 20/60 | 查找和排序 |
第四五六周 | 1313/2045 | 5/8 | 12/72 | 栈和队列 |
第七周 |
- 计划学习时间: 25+小时
- 实际学习时间: 25小时
(有空多看看现代软件工程 课件 软件工程师能力自我评价表)