2017-2018-2 《程序设计与数据结构》第五周学习总结

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>\n";
for (T element:stack){
rlt += element + "\n";
}
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>\n";
for(int index=count-1; index >= 0;index --){
rlt += stack[index] + "\n";
}
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自带的函数能够提高代码的可读性。

代码调试中的问题和解决过程

一开始忘记了单步跟踪在设置完断点后怎么使用,后来在娄老师的博客中找到了解决方案。

代码托管

  • 代码提交过程 & 代码量截图:
  • 2017-04-30.png

结对及互评

点评模板:

  • 博客中值得学习的或问题:

其他

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 - 1 10
第二周 - 2 20
第三周 - 3 30
第四周 - 4 40
第五周 - 5 50
  • 计划学习时间:20小时

  • 实际学习时间:10小时

  • 改进情况:

参考资料

posted @ 2017-10-15 14:56  20162308马平川  阅读(204)  评论(1编辑  收藏  举报