文章目录
实现线性表的方式有两种。
一种是使用数组( array) 存储线性表的元素。数组大小是固定的。如果元素个数超过了数组的容量,就创建一个更大的新数组,并将当前数组中的元素复制到新数组中。
另一种是使用链式结构( linked structure) 。链式结构由结点组成,每个结点都是动态创建的,用来存储一个元素。所有的结点链接成一个线性表。
这样,就可以给线性表定义两种类。为了方便起见,分别称这两种类为MyArrayList 和MyLinkedList 。这两种类具有相同的操作,但是具有不同的实现。
MyList 定义了MyAbstractList 、MyArrayList 和MyLinkedList 的通用接口
通用的操作可以归纳为一个接口或者一个抽象类。一个好的策略就是在设计中提供接口和便利抽象类,以整合接口和抽象类的优点,这样用户可以认为哪个方便就用哪个。抽象类提供了接口的骨架实现,可以更有效地实现接口。
两种方式复杂度的比较
第一步:在设计中提供接口。
首先,定义一个接口MyList 继承自Iterable。在接口里定义线性表会用到的方法。
public interface MyList<E> extends Iterable<E> {
public void add(E e);
public void add(int dex,E e);
public void clear();
public boolean contains(E e);
public E get(int index);
public int indexOf(E e);
public boolean isEmpty();
public int lastIndexOf(E e);
public boolean remove(E e);
public E remove(int index);
public Object set(int index,E e);
public int size();
}
第二步:实现通用类MyAbstractList。
MyAbstractList 声明变量size ,表示线性表中元素的个数。
MyList定义了操作线性表的许多方法。 MyAbstractList 提供 MyList 接口的【部分实现】
public abstract class MyAbstractList<E> implements MyList<E>{
protected int size = 0;
protected MyAbstractList() {
}
protected MyAbstractList(E[] objects) {
for(int i = 0; i < objects.length;i++)
add(objects[i]);
}
@Override
public void add(E e) {
add(size,e);
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public int size() {
return size;
}
@Override
public boolean remove(E e) {
if(indexOf(e) >= 0) {
remove(indexOf(e));
return true;
}
else
return false;
}
}
.
第三步(1):MyArrayList 的实现。
被保护的数据域一般很少使用,但是,将MyAbstractList 类中的size 数据域设直为被保护的是一个很好的选择。MyAbstractL;st 的子类可以访问s;ze ,但是,在不同包中的MyAbstractList 的非子类不能访问它。作为一个常用规则,可以将抽象类中的数据域声明为被保护的。
数据长度可扩:数组是一种大小固定的数据结构。数组一旦创建之后,它的大小就无法改变。尽管如此,仍然可以使用数组来实现动态的数据结构。处理的方法是,**当数组不能再存储线性表中的新元素时,创建一个更大的新数组来替换当前数组。**初始化时,用默认大小创建一个类型为E []的数组data 。向数组中插人一个新元素时,首先确认数组是否有足够的空间。若数组的空间不够,则创建大小为当前数组两倍的新数组,然后将当前数组中的元素复制到新的数组中。
指定下标插入元素:在指定下标处插入一个新元素之前,必须将指定下标后面的所有元素都向右移动一个位置并且将该线性表的大小增加1
指定下标删除元素:删除指定下标处的一个元素时,应该将该下标后面的元素都向左移动一个位置,并将线性表的大小减1
等方法…
package ReWrite;
import java.util.Iterator;
public class MyArrayList<E> extends MyAbstractList<E>{
public static final int INITIAL_CAPACITY = 16; // 初始数组大小16
private E[] data = (E[]) new Object[INITIAL_CAPACITY];
//由于泛型消除,所以不能使用语法new e[INITIAL_CAPACITY] 创建泛型数组。
//创建了一个Object 类型的数组,并将它转换为E[]类型
public MyArrayList() {
}
public MyArrayList(E[] objects) {
for (int i=0; i < objects.length; i++)
add(objects[i]);
}
/**
* 用于确保数组中是否有存储新元素的空间。
* 若空间已满,则创建容量x2的新数组,并把所有元素复制到新数组
*/
private void ensureCapacity() {
if(size >= data.length) {
E[] newData = (E[])(new Object[size*2+