20162308 2017-2018-2 《程序设计与数据结构》第五周学习总结
教材学习内容总结
学习目标
- 掌握Java Collections API的基本结构
- 理解Collection的抽象设计
- 掌握Collection实现的Java相关技术:继承/多态/泛型/接口
- 掌握栈的应用
- 掌握栈的实现(数组,链式)
- 分析Java Stack API
学习内容
- Stack
本周学习了数据结构中栈的应用,但是在实际上,上学期在进行“四则运算”大作业的时候,在中缀表达式转后缀表达式的代码中就已经初步接触过栈了。
private ArrayList<String> getRPN(ArrayList<String> inOrderList) {
ArrayList<String> RPN = new ArrayList<String>();
Stack<String> stack = new Stack<String>();
for (String item : inOrderList) {
if (Character.isDigit(item.charAt(0))) RPN.add(item);
else {
while (!stack.isEmpty() && compare(stack.peek(), item)) RPN.add(stack.pop());
stack.push(item);
}
}
while (!stack.isEmpty()) RPN.add(stack.pop());
return RPN;
}
在上述代码中先判断表达式中的元素是否为数字,如果是,则直接加入后缀表达式,如果不是,则与栈顶的元素比较优先级,如果优先级较大,则在后缀表达式中加入栈顶的元素,重复上述操作,直到栈顶元素优先级相同,最后将该元素压入栈中。
栈作为一种常见的数据结构,能够与算法协作,解决各种各样的问题。
在这周的学习中,结合上周的内容,分别学习了栈的数组实现和链表实现。
import java.util.Arrays;
import java.util.LinkedList;
public class MyLinkedStack<T> {
private LinkedList<T> stack = new LinkedList<>();
public T push(T element){
stack.add(element);
return element;
}
@Override
public String toString() {
String rlt = "<TOP OF STACK>
";
for (T element:stack){
rlt += element + "
";
}
return rlt + "<BOTTOM OF STACK>";
}
public boolean isEmpty(){
return stack.isEmpty();
}
public T pop() {
if(!isEmpty()){
T rlt = stack.getLast();
stack.removeLast();
return rlt;
}else return null;
}
public T peek(){
if (!isEmpty()){
return stack.getLast();
}else return null;
}
public int size(){
return stack.size();
}
}
import java.util.Arrays;
import java.util.Stack;
public class MyArrayStack<T>{
private final int DEFAULT_CAPACITY = 10;
private int count;
private T[] stack;
public MyArrayStack(){
count = 0;
stack = (T[]) (new Object[DEFAULT_CAPACITY]);
}
public T push(T element){
if(count == stack.length){
expandCapacity();
}
stack[count] = element;
count += 1;
return element;
}
@Override
public String toString() {
String rlt = "<TOP OF STACK>
";
for(int index=count-1; index >= 0;index --){
rlt += stack[index] + "
";
}
return rlt + "<BOTTOM OF STACK>";
}
public void expandCapacity(){
stack = Arrays.copyOf(stack,stack.length + 100);
}
public boolean isEmpty(){
if(count>0)return false;
else return true;
}
public T pop() {
if(!isEmpty()){
count -= 1;
return stack[count];
}else return null;
}
public T peek(){
if (!isEmpty()){
return stack[count-1];
}else return null;
}
public int size(){
return count;
}
}
主要的一些方法还是基于原来的实现,然后将数组封装为栈,提供了用于外部访问的方法接口,包括push、pop、peek、isEmpty、size方法。
教材学习中的问题和解决过程
在实现的过程中,因为上周剖析了ArrayList的源代码,所以对expandCapcity有比较深的印象,其中,Java官方的实现相比书上的实现方法,个人认为更加简洁明了,同时也支持更多的边界情况。
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != EMPTY_ELEMENTDATA)
// any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
在书上的代码中,只是新建了一个为原有数组两倍大小的新数组,并,但是Java内部并不支持下标大于2^32-1的数组,所以在用户试图申请过大的栈的时候,在书上的代码中并没有引入有效合理的异常处理机制,导致无法正确处理异常。另外一个方面就是,在Java的代码中是使用Arrays.copyOf()
方法来增大队列,虽然功能上是一样的,但是使用Java自带的函数能够提高代码的可读性。
代码调试中的问题和解决过程
一开始忘记了单步跟踪在设置完断点后怎么使用,后来在娄老师的博客中找到了解决方案。
代码托管
- 代码提交过程 & 代码量截图:
结对及互评
点评模板:
- 博客中值得学习的或问题:
其他
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | - | 1 | 10 | |
第二周 | - | 2 | 20 | |
第三周 | - | 3 | 30 | |
第四周 | - | 4 | 40 | |
第五周 | - | 5 | 50 |
-
计划学习时间:20小时
-
实际学习时间:10小时
-
改进情况: