本博客讨论最简单最基本的三种数据结构,几乎所有程序都要显式的使用至少一种数据结构,本文重点为:抽象数据类型的概念、如何有效执行表的操作、栈和队列ADT及其应用、ArrayList和LinkedList的实现代码。
ADT概念
抽象数据类型(abstract data type 、ADT):
带有一组操作的一些对象的集合,可以有添加、删除、包含、查找等操作;
表ADT
形如 A0、A1、A2、A3、An 的表,我们称其大小为n。表的实现形式有数组实现、链表实现等。
in java Collection API
Collection接口
collection接口抽象出了集合的概念,即存储一组类型相同的对象。该接口的主要方法定义如下:
public interface Collection<AnyType> extends Iterable<AnyType>{
int size();
boolean isEmpty();
void clear();
boolean contains(AnyType x);
boolean add();
boolean reamove();
java.util.Iterator<AnyType> iterator();
}
方法名称都可以顾名思义,在此不做赘述。
Iterator接口
实现Iterable接口的集合必须提供一个称为iterator的方法,该方法返回一个Iterator类型的对象。Iterator为java.util中定义的一个接口:
//Iterator接口
public interface Iterator<AnyType>{
boolean hashNext();
AnyType next();
void remove();
}
//增强型for循环调用的print例程(利用Iterator进行遍历)
public static <AnyType> void print(Collection<AnyType> coll){
Iterator<AnyType> itr = coll.iterator;
while(itr.hashNext()){
AnyType item = itr.next();
System.out.println(item);
}
}
值得一提的是Iterator中的remove方法和Collection中的remove方法:如果对正在被迭代的集合进行结构上的改变(add、remove、clear)那么迭代器将不再合法(ConcurrentModificationException),而此时迭代器调用它自己的remove方法就仍然是合法的;
List接口、ArrayList类和LinkedList类
List接口由Java.util包中的List接口指定,List接口继承了Collection接口(包含了其所有方法)。List接口中比较重要的方法如下:
public interface List<AnyType> extends Collection<AnyType>{
AnyType get(int idx);
AnyType set(int idx,AnyType newVal);
void add(int idx,AnyType x);
void remove(int idx);
ListIterator<AnyType> listIterator(int pos);
}
List ADT 有两种流行的实现形式:ArrayList对于get和set的调用花费常数时间,但插入和删除代价昂贵;LinkedList插入删除都是常数时间的操作,但get方法代价昂贵;
ListIterator接口
ListIterator接口扩展了List的Iterator功能:
public interface ListIterator<AnyType> extends Iterator<AnyType>{
//完成list的反向遍历
boolean hasPrevious();
AnyType previous();
//遍历中执行的add、set方法
void add(AnyType x);
void set(AnyType newVal);
}
ArrayList类的实现
本节给出ArrayList泛型类的实现,为避免冲突我们的类叫做MyArrayList。其中细节点有:
- MyArrayList将保持基础数组,数组容量,以及存储在MyArrayList中的当前项数。
- MyArrayList提供一种机制来改变基础数组的容量。通过获得一个新数组并将老数组拷贝到其中,允许虚拟机回收老数组。
- MyArrayList提供get、set实现
- MyArrayList提供基本的方法实现(size、isEmpty、clear、add、remove)。
- MyArrayList提供一个实现Iterator接口的类
基本类实现:
public class MyArrayList<AnyType> implements Iterator<AnyType>{
private static final int DEFAULT_CAPACITY = 10;//初始容量
private int theSize;//现容量
private AnyType[] theItems;//存数据的数组
public MyArryList(){//构造方法
doClear();
}
public void clear(){//清除方法
doClear();
}
private void doClear(){//list置空,大小回复默认
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
public int size(){//返回当前list大小
return theSize;
}
public boolean isEmpty(){//判断size是否空
return size() == 0;
}
public void trimToSize(){//除去数组多余的容量以节省空间
ensureCapacity( size() );
}
public AnyType get( int idx ){//获得指定位置的数据
if( idx < 0 || idx >= size() )
throw new ArrayOutOfBondsException();
return theItems[ idx ];
}
public AnyType set(int idx,AnyType newVal){//设置指定位置数据
if(idx < 0 || idx >= size())
throw new ArrayIndexOutOfBoundsException();
AnyType old = theItems[ idx ];
theItems[ idx ] = newVal;
return old;
}
public void ensureCapacity(int newCapacity){//用容量更大的数组代替原有数组
if( newCapacity < theSize )
return;
AnyType[] old = theItems;
theItems = (AnyType []) new Object[ newCapacity ];
for(int i = 0;i < size();i++)
theItems[i] = old[i];
}
public boolean add(AnyType){//add方法一
add( size(),x);
return true;
}
public void add(int idx,AnyType x){//add方法二,扩容
if(theItems.length == size());
ensureCapacity(size()*2+1);
for(int i = theSize;i>ids;i--){
theItems[i] = theItems[i-1];
}
theItems[idx] = x
theSize++;
}
public AnyType remove(int idx){//删除方法,平移
AnyType removedItem = theItems[idx];
for(int i = idx;i<size()-1;i++)
theItems[i] = theItems[i+1];
theSize--;
return removedItem;
}
public java.util.Iterator<AnyType> iterator(){//遍历
return new ArrayListIterator;
}
private class ArrayListIterator implements java.util.Iterator<AnyType>{//内部类
private int current = 0;
public boolean hasNext(){
return current<size();
}
public AnyType next(){
if(!hasNext)
throw new java.util.NoSuchElementException;
return theItems[current++];
}
public void remove(){
MyArrayList.this.remove(--current);
}
}
}
代码展示了两个版本的add方法,第一个是添加到表的末端,并且通过调用添加到指定位置的版本得以实现。这个版本代价非常昂贵,它需要指定位置及其后面的元素后移,而且会涉及到扩容。
有关iterator(表遍历)的方法实现可以参考我的另一篇博文:设计模式之Iterator。
未完待续…
LinkedList类的实现
博主正在完善中,敬请期待…
栈ADT
博主正在完善中,敬请期待…
队列ADT
博主正在完善中,敬请期待…