线性表的顺序存储结构是指:用一组连续的存储单元依次存储线性表中的每个数据元素。即中间不允许有空,所以插入、删除时需要移动大量元素。

   

JAVA顺序流 java顺序存储_数据结构

在JAVA中实现顺序存储结构---顺序表

首先,由于JAVA隶属于面向对象编程,所以这里大多数操作都是先定义(接口),然后实现相对于的接口也就实现了对“顺序表”的操作了。在这里,我们先定义一个myList

/**
 * Created by Troshin on 2018/1/13.
 */
public interface myList {
    //返回线性表大小
    public int getSize();

    //判断线性表是否为空
    public boolean isEmpty();

    //判断线性表是否包含元素e
    public boolean contains(Object e);

    //返回数据元素e在线性表中的序号
    public int indexOf(Object e);
    
    //将数据元素e插入到线性表i号位置
    public void insert(int i, Object e) throws OutOfBoundaryException;

    //将数据元素e插入到元素p之前
    public boolean insertBefore(Object obj, Object e);

    //将数据元素e插入到元素p之后
    public boolean insertAfter(Object obj, Object e);

    //删除线性表中序号为i的元素
    public Object remove(int i)throws OutOfBoundaryException;;

    //删除线性表中第一个与e相同的元素
    public boolean remove(Object e);

    //替换线性表中序号i的数据元素为e
    public Object replace(int i, Object e)throws OutOfBoundaryException;;

    //返回线性表中为i的数据元素
    public Object get(int i)throws OutOfBoundaryException;;
}




myList接口中,我们把数据类型定义为Object,这样提高了复用性,关于JAVA基础知识不多解释,可以查阅相关书籍。

其中的异常,为序号越界时定义的异常。

/**
 * Created by Troshin on 2018/1/13.
 */
public class OutOfBoundaryException extends RuntimeException{
    public  OutOfBoundaryException(String err){
        super(err);
    }
}

由于定义的数据类型为Object,所以关于每个元素的比较都有着不一样的方法,这里我们自定义一个比较方法,其优点在于,一旦不想继续使用原先的比较策略对象,随时可以使用另一个比较策略对象将其替换,而不同修改抽象数据类型的具体实现。

/**
 * Created by Troshin on 2018/1/13.
 */
public interface Strategy {
    //判断两个数据元素是否相等
    public boolean equal(Object obj1,Object obj2);

    /**
     * 比较两个数据元素的大小
     * 如果 obj1 < obj2 返回-1
     * 如果 obj1 = obj2 返回 0
     * 如果 obj1 > obj2 返回 1
     */
    public int compare(Object obj1,Object obj2);
}




前面说过,由于顺序存储结构在计算机内的存储位置是连续的,所以它的插入、删除等操作如图:

JAVA顺序流 java顺序存储_JAVA_02

JAVA顺序流 java顺序存储_JAVA_03

每次在第i个位置插入、删除都需要移动大量数据,所以时间复杂度为O(n)。具体实现:

/**
 * Created by Troshin on 2018/1/13.
 */
public class ListArray implements myList {
    private final int LEN=8;    //数组的默认大小
    private Strategy strategy;  //数据元素比较策略
    private int size;           //线性表中数据元素的个数
    private Object[] elements;  //数据元素数组

    //构造方法
    public ListArray() {
       this(new DefaultStrategy());
    }

    public ListArray(Strategy strategy){
        this.strategy=strategy;
        size=0;
        elements=new Object[LEN];
    }

    /**
     * 返回线性表的大小,即数据元素的个数
     * @return
     */
    @Override
    public int getSize() {
        return size;
    }

    /**
     * 如果线性表为空返回true,否则返回false
     * @return
     */
    @Override
    public boolean isEmpty() {
        return size==0;
    }

    /**
     * 判断线性表是否包含数据元素e,在就返回True,否则返回false
     * @param e
     * @return
     */
    @Override
    public boolean contains(Object e){
        for(int i=0;i<size;i++)
            if(strategy.equal(e,elements[i]))
            return true;

        return false;
    }

    /**
     * 返回数据元素e在线性表中的序号
     * @param e
     * @return
     */
    @Override
    public int indexOf(Object e) {
        for(int i=0;i<size;i++)
            if(strategy.equal(e,elements[i]))
            return 1;
        return -1;

    }

    /**
     * 将数据元素 e 插入到线性表中 i 号位置
     * @param i
     * @param e
     * @throws OutOfBoundaryException
     */
    @Override
    public void insert(int i, Object e) throws OutOfBoundaryException {
        if (i<0 || i>size)
           throw  new OutOfBoundaryException("错误,指定插入的序号越界");
        if(size>=elements.length)
            expandSpace();
        for (int j=size;j>i;j--)
            elements[j]=elements[j-1];
        elements[i]=e;
        size++;
            return;
    }

    private void expandSpace(){
        Object[] a=new Object[elements.length*2];
        for(int i=0;i<elements.length;i++)
            a[i]=elements[i];
        elements=a;
    }

    /**
     * 将数据元素 e 插入到元素 obj 之前
     * @param p
     * @param e
     * @return
     */
    @Override
    public boolean insertBefore(Object p, Object e) {
        int i=indexOf(p);
        if (i<0) return false;
            insert(i,e);
        return true;
    }

    /**
     * 将数据元素 e 插入到元素 obj 之后
     * @param p
     * @param e
     * @return
     */
    @Override
    public boolean insertAfter(Object p, Object e) {
        int i=indexOf(p);
        if (i<0) return false;
            insert(i+1,e);
        return true;
    }

    /**
     * 删除线性表中序号为 i 的元素,并返回之
     * @param i
     * @return
     * @throws OutOfBoundaryException
     */
    @Override
    public Object remove(int i) throws OutOfBoundaryException {
        if (i<0 || i>= size)
             throw new OutOfBoundaryException("错误,指定删除的序号越界");
        Object obj=elements [i];
        for (int j=i;j<size;j++){
            elements[j]=elements[j+1];
        }
        elements[--size] =null;
        return obj;
    }

    /**
     * 删除线性表中第一个与 e 相同的元素
     * @param e
     * @return
     */
    @Override
    public boolean remove(Object e) {
        int i=indexOf(e);
        if (i<0) return false;
        remove(i);
        return true;
    }

    /**
     * 替换线性表中序号为 i 的数据元素为 e,返回原数据元素
     * @param i
     * @param e
     * @return
     * @throws OutOfBoundaryException
     */
    @Override
    public Object replace(int i, Object e) throws OutOfBoundaryException {
        if(i<0 || i>=size)
            throw  new OutOfBoundaryException("错误,指定的序号越界");
        Object obj=elements[i];
        elements[i]=e;
        return obj;
    }

    /**
     * 返回线性表中序号为 i 的数据元素
     * @param i
     * @return
     * @throws OutOfBoundaryException
     */
    @Override
    public Object get(int i) throws OutOfBoundaryException {
        if(i<0 || i>= size)
            return new OutOfBoundaryException("错误,指定的序号越界");
        return elements[i];
    }
}

其中 getSize()、isEmpty()、replace(int i, Object e)、get(int i) 方法的时间复杂度均为Θ(1)。

contains(Object e)、indexOf(Object e) 方法的运行时间为:T(n)= ((n+1)+1)/2 ≈ n/2。

insert(int i, Object e)、remove(int i) 方法的运行时间为:T(n)≈n/2。

insertBefore(Object obj, Object e)、insertAfter(Object obj, Object e)、remove(Object e) 方法的运行时间为: T(n) ≈ n。


初入数据结构,以学习总结为主,如果写的不详细或者有什么其它错误的地方希望各位dalao们指点指点。

参考的书籍:《数据结构-JAVA版》《数据结构与算法》