实验一 线性结构
实验一 线性结构
实验内容
实验一 线性结构-1
ArrayList和LinkedList测试:查看ArrayList和LinkedList的Java API帮助文档,参考http://www.cnblogs.com/rocedu/p/4837092.html 用Junit对ArrayList和LinkedList的方法进行测试,要尽量覆盖正常情况,异常情况,边界情况。
使用JUnit测试了ArrayList和LinkedList类的add,get,remove,isEmpty,remove等方法。
实验一 线性结构-2
分别用Java的ArrayList和LinkedList实现有序线性表的合并:aList,bList都是非递减线性表,合并后也是非递减 public static List<? extends Comparable> mergeSortedList(List<? extends Comparable> aList, List<? extends Comparable> bList) 测试mergeSortedList的正确性,要尽量覆盖正常情况,异常情况,边界情况,提交测试代码运行截图,包含学号信息。课下把代码推送到代码托管平台
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class exp2 {
public static List<? extends Comparable> mergeSortedList(List<? extends Comparable> aList,
List<? extends Comparable> bList){
if(aList instanceof ArrayList && bList instanceof ArrayList){
for(Object o:bList)((ArrayList) aList).add(o);
Collections.sort(aList);
return aList;
}
if(aList instanceof LinkedList && bList instanceof LinkedList){
for(Object o:bList)((LinkedList) aList).add(o);
Collections.sort(aList);
return aList;
}
return new ArrayList<>();
}
}
通过在aList后追加元素,然后对aList进行排序,实现序列的有序合并
实验一 线性结构-3
参考Java Foundation 3rd 第15.6节,用数组实现线性表List。用JUnit或自己编写驱动类对自己实现的ArrayList进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
public class MyArrayList<T> {
private T[] list = null;
private int cursor = -1;
public boolean add(T t){
if(this.list==null){
this.list = (T[]) new Object[10];
this.list[0] = t;
cursor=0;
}
else {
for(int i=0;i<this.list.length;i++){
if(this.list[i]==null){
this.list[i]=t;
return true;
}
}
T[] temp = (T[]) new Object[this.list.length+10];
for(int i=0;i<this.list.length;i++){
temp[i] = this.list[i];
}
temp[this.list.length] = t;
this.list = temp;
cursor += 1;
return true;
}
return true;
}
public boolean isEmpty(){
return this.list==null ? false:true;
}
public T get(int index){
if(index<0 || index>cursor)return null;
return this.list[index];
}
}
通过申请Object数组,然后强制类型转换来实现泛型数组,每次预留10个容量,超出时,申请一个大小为array.lenght+10的数组。
实验一 线性结构-4
参考Java Foundation 3rd 第15.7节,用链表实现线性表List。用JUnit或自己编写驱动类对自己实现的LinkedList进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
public class MyLinkedList<T> {
private Node<T> firstNode;
public MyLinkedList(){
firstNode = null;
}
public void addFirst(T t){
Node<T> node = new Node(t);
node.next = firstNode;
firstNode = node;
}
public Node rmFirst(){
Node<T> node = firstNode;
firstNode = node.next;
return firstNode;
}
public void add(int index,T t){
Node newNode = new Node(t);
Node currentNode = firstNode;
Node previousNode = firstNode;
if(index==0)addFirst(t);
for(int i = 1;i<=index;i++){
previousNode = currentNode;
currentNode = currentNode.next;
}
previousNode.next = newNode;
newNode.next = currentNode;
}
public T get(int index){
Node currentNode = firstNode;
Node previousNode = firstNode;
if(index==0)return firstNode.data;
for(int i = 1;i<=index;i++){
previousNode = currentNode;
currentNode = currentNode.next;
}
return (T) currentNode.data;
}
public void remove(int index){
Node previousNode = firstNode;
Node currentNode = firstNode;
if(index==0)rmFirst();
for(int i = 1;i<=index;i++){
previousNode = currentNode;
currentNode = currentNode.next;
}
previousNode.next = currentNode.next;
}
}
class Node<T>{
protected Node next;
protected T data;
public Node( T data){
this. data = data;
}
}
设计了Node类,包括数据域和指针,然后在MyLinkedList中通过改变不同Node的指针来实现链表的增加、删除和查看操作。
实验一 线性结构-5
源码分析:参考http://www.cnblogs.com/rocedu/p/7483915.html对Java的ArrayList,LinkedList按要求进行源码分析,并在实验报告中体现分析结果
ArrayList继承了抽象类AbstractList,实现了List、RandomAccess、Cloneable、java.io.Serializable接口,可以看到,类内部实现了很多函数,实现了低耦合和高内聚。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public boolean add(T t){
if(this.list==null){
this.list = (T[]) new Object[10];
this.list[0] = t;
cursor=0;
}
else {
for(int i=0;i<this.list.length;i++){
if(this.list[i]==null){
this.list[i]=t;
return true;
}
}
T[] temp = (T[]) new Object[this.list.length+10];
for(int i=0;i<this.list.length;i++){
temp[i] = this.list[i];
}
temp[this.list.length] = t;
this.list = temp;
cursor += 1;
return true;
}
return true;
}
以add方法为例,比较我和Java的实现,可以看到的就是,Java把容量的扩增写进了ensureCapacityInternal方法,然后ensureCapacityInternal又有其他的几个方法来支撑,到最后整个add方法看起来就很简洁。
事实上,在ArrayList类和LinkedList中,很少会看到一个超过20行的方法,所以说程序的逻辑更多地通过方法名来体现(而非代码),这种设计实现了代码的模块化,提高了可读性。
总结
这周进行了数组的相关实验,通过自己写方法,更深入地理解了数组的实现,比较Java的代码,进一步发现了自己在编码过程中所存在的问题(代码耦合度太高)。
王垠在编程的智慧中说:“编程是一种创造性的工作,是一门艺术。精通任何一门艺术,都需要很多的练习和领悟。”
真正的模块化,并不是文本意义上的,而是逻辑意义上的。一个模块应该像一个电路芯片,它有定义良好的输入和输出。实际上一种很好的模块化方法早已经存在,它的名字叫做“函数”。每一个函数都有明确的输入(参数)和输出(返回值),同一个文件里可以包含多个函数,所以你其实根本不需要把代码分开在多个文件或者目录里面,同样可以完成代码的模块化。我可以把代码全都写在同一个文件里,却仍然是非常模块化的代码。
尤其是这一段,其实真正意义上的模块化是各个组件和部分各司其职,然后尽可能地将操作“原子化”,尽可能实现代码的复用(而非通用)。另外一方面,是尽可能地写出可读的代码,我读过一些同学的代码,包括变量的命名、函数的命名、注释等等因素,都很难为提升代码可读性做出贡献。读Java的源码,一个非常明显的特征就是,注释和命名都是高度标准化的,通过有意义的命名方式、声明代码位置和变量名缩写,可以实现代码高度可读和工程化。
虽然自己这回在实验中写的代码可能永远也用不到,但是只有自己亲自去尝试一回,才能高山仰止,发现自己和优秀程序员之间的差距,看到自己代码内部存在的一些问题。