java数据结构:表、栈、队列

来源:互联网 发布:所以国家域名后缀 编辑:程序博客网 时间:2024/06/05 19:38

本博客讨论最简单最基本的三种数据结构,几乎所有程序都要显式的使用至少一种数据结构,本文重点为:抽象数据类型的概念、如何有效执行表的操作、栈和队列ADT及其应用、ArrayList和LinkedList的实现代码。

    • ADT概念
    • in java Collection API
    • ArrayList类的实现
    • LinkedList类的实现
    • 栈ADT
    • 队列ADT

ADT概念

抽象数据类型(abstract data type 、ADT):
带有一组操作的一些对象的集合,可以有添加、删除、包含、查找等操作;
表ADT
形如A0A1A2A3An的表,我们称其大小为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。其中细节点有:

  1. MyArrayList将保持基础数组,数组容量,以及存储在MyArrayList中的当前项数。
  2. MyArrayList提供一种机制来改变基础数组的容量。通过获得一个新数组并将老数组拷贝到其中,允许虚拟机回收老数组。
  3. MyArrayList提供get、set实现
  4. MyArrayList提供基本的方法实现(size、isEmpty、clear、add、remove)。
  5. 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

博主正在完善中,敬请期待…

原创粉丝点击