顺序表一般使用数组实现,数组不仅逻辑连续,其物理也连续,下面我们将实现顺序表的基本操作(增删查改)

一、顺序表的创建

  1. 创建一个DynamicArray类,Dynamic为动态,因为假设我们创建了一个大小为10的数组,若后期想多增加一个元素,还得重新写,所以动态数组是最佳选择。
  2. 创建属性size用于存储动态数组的有效元素,创建数组elementData不初始化。
  3. 创建两个构造方法,一个无参构造(若用户不指定数组大小,则默认创建大小为10的数组);一个参数为整形的有参构造(输入的参数用于定义数组大小)。
  4. 创建一个方法grow,若数组长度满了之后用于对数组进行扩容。使用private 修饰该方法,因为使用者不需要知道这个方法。
public class DynamicArray {
    int[] elementData;
    int size;

    public DynamicArray(){
        elementData=new int[10];
    }
    public DynamicArray(int length){
        elementData=new int[length];
    }
    /**
     * 动态对数组进行两倍扩容
     */
    private void grow(){
        int oldLength=elementData.length;
        int newLength=oldLength << 1;
        int[] newArray=new int[newLength];
        elementData=Arrays.copyOf(newArray,newLength);
    }

二、顺序表添加元素

2.1 头部插入元素(头插法)

  1. 在插入元素之前我们需要比较size和elementData.length判断数组是否满了,若数组已满,需要调用grow方法对数组进行扩容。
  2. 在数组中的第一个元素插入元素data,只需要执行elementData[0]=data;但如果数组中第一个元素不为空,那么新插入的元素会将数组的第一个元素覆盖掉。所以我们需要先将数组中的有效元素向后移动一个单位(从后往前移),再插入元素。
  3. 插入元素后size++,记录数组中有效元素。
/**
     * 头部插入元素
     * @param data
     */
    public void addFirst(int data){
        if(size==elementData.length){
            grow();
        }
        for (int i = size-1; i >=0; i--) {
            elementData[i+1]=elementData[i];
        }
        elementData[0]=data;
        size++;
    }

2.2顺序表尾部插入元素(尾插法)

  1. 在插入元素之前我们需要比较size和elementData.length判断数组是否满了,若数组已满,需要调用grow方法对数组进行扩容。
  2. 执行elementData[size]=data;既将data元素插入顺序表最后一个位置。
  3. 插入元素后size++,记录数组中有效元素。
/**
     * 尾部插入元素
     * @param data
     */
    public void addLast(int data){
        if(size==elementData.length){
            grow();
        }
        elementData[size++]=data;
    }

2.3在顺序表index位置插入元素

这个方法其实和头插法差不多,就是一个将所有元素往后移然后插入,一个从index之后的元素往后移然后插入元素。

  1. 比较index和size,若index>size或者index<0;则直接终止函数。
  2. 在插入元素之前我们需要比较size和elementData.length判断数组是否满了,若数组已满,需要调用grow方法对数组进行扩容。
  3. 先将数组中的索引为index以后的有效元素向后移动一个单位(从后往前移),再插入元素。
  4. 插入元素后size++,记录数组中有效元素。
/**
     * 索引插入元素
     * @param index
     * @param data
     */
    public void index(int index,int data){
        if(index>size || index<0){
            System.out.println("插入位置不合法!!!");
            return;
        }
        if(size==elementData.length){
            grow();
        }
        if(index==0){
            addFirst(data);
        }else if(index==size){
            addLast(data);
        }else{
            for (int i = size-1; i>=index; i--) {
                elementData[i+1]=elementData[i];
            }
            elementData[index]=data;
            size++;
        }
    }

三、顺序表查找

3.1按值查找

  1. 循环遍历数组,若数组中有值为data的元素,则返回数组的索引;
  2. 若循环结束,则表示未找到,返回-1 。
/**
     * 按值查找
     * @param data
     * @return
     */
    public int findVal(int data){
        for (int i = 0; i < size; i++) {
            if(elementData[i]==data){
                return i;
            }
        }
        System.out.println("没有这个数!!!");
        return -1;
    }

3.2按索引查找

  1. 判断索引index是否超出顺序表范围,若超出,直接结束该函数。
  2. 返回elementData[index] .
/**
     * 按索引查找
     * @param index
     * @return
     */
    public int findIndex(int index){
        if(index>=size || index<0){
            System.err.println("查找位置不合法!!!");
            return -1;
        }
        return elementData[index];
    }

四、顺序表的删除

4.1按索引删除

顺序表中的删除操作很简单,比如要删除第2个元素,只需要将后面的元素往前移动一个单位,将其覆盖就行

  1. 判断索引index是否超出顺序表范围,若超出,直接结束该函数。
  2. 将index后面的元素向前移动一个单位。
  3. 将顺序表最后一个元素赋值为0;
  4. 插入元素后size++,记录数组中有效元素。
/**
     * 删除索引位置的值
     * @param index
     */
    public void delIndex(int index){
        if(!content(index)){
            System.out.println("该位置没有值!!!");
            return;
        }
        for (int i = index; i <size-1; i++){
            elementData[i]=elementData[i+1];
        }
        size--;
        elementData[size]=0;
    }

4.2按值删除

4.2.1删除首次出现的元素

  1. 遍历数组,若有值为data的数组元素,调用delIndex方法删除该元素
/**
     * 删除第一次出现的值为data的元素
     * @param data
     */
    public void delOne(int data){
        int index=-1;
        for (int i = 0; i < size; i++) {
            if(elementData[i]==data){
                delIndex(index);
                break;
            }
        }
        
    }

4.2.2删除所有值为data的元素

  1. 同样遍历数组,若找到值为data的元素,则删除,否则寻找下一个

值得注意的是,这里不能直接用if语句判断,因为若数组是这样[1,9,9,3],删除第一个9后,索引号为2的9索引号变成了1,你的循环又直接往后走了一次,直接判断索引号为2的元素,此时索引号为2的元素值为3,那么就少删除一个2,所以我们应该使用while判断,直到索引号为1的元素的值不是要删除的再往后走。

/**
     * 删除数组中所有data
     * @param data
     */
    public void delVal(int data){
        for (int i = 0; i < size; i++) {
            while(elementData[i]==data){
               delIndex(i);
            }
        }
    }

五、顺序表的修改

5.1按索引号修改

  1. 判断索引index是否超出顺序表范围,若超出,返回-1。
  2. 定义一个变量ret记录elementData[index]的值,将data赋值给elementData[index]。
  3. 返回ret。
/**
     * 按索引号修改元素
     * @param index
     * @param data
     * @return
     */
    public int changeIndex(int index,int data){
        if(index<0 || index>=size){
            System.err.println("该位置非法!!!");
            return -1;
        }else {
            int ret=elementData[index];
            elementData[index]=data;
            return ret;
        }
    }

5.2按值修改

  1. 遍历数组,若遇到值为data的元素,直接修改
/**
     * 按值修改
     * @param data
     */
    public void changeVal(int data){
        for (int i = 0; i < size; i++) {
            if (elementData[i]==data){
                elementData[i]=data;
            }
        }
    }

六、顺序表的优缺点分析

6.1优点

  1. 可以快速存取表中任意位置元素
  2. 由于顺序表的物理连续及逻辑连续,所以无需为表中的元素间的逻辑关系增加额外的存储空间。

6.2 缺点

  1. 插入和删除需要移动大量元素
  2. 当顺序表中长度变化较大时,难以确定存储空间的容量
  3. 造成存储空间的碎片(比如数组大小为100单位,只使用了60个,那么剩下的40个就浪费掉)

七、顺序表源码

package seqList;

import java.util.Arrays;

public class DynamicArray {
    int[] elementData;
    int size;

    public DynamicArray(){
        elementData=new int[10];
    }
    public DynamicArray(int length){
        elementData=new int[length];
    }
    /**
     * 动态对数组进行两倍扩容
     */
    private void grow(){
        int oldLength=elementData.length;
        int newLength=oldLength << 1;
        int[] newArray=new int[newLength];
        elementData=Arrays.copyOf(newArray,newLength);
    }
    /**
     * 头部插入元素
     * @param data
     */
    public void addFirst(int data){
        if(size==elementData.length){
            grow();
        }
        for (int i = size-1; i >=0; i--) {
            elementData[i+1]=elementData[i];
        }
        elementData[0]=data;
        size++;
    }

    /**
     * 尾部插入元素
     * @param data
     */
    public void addLast(int data){
        if(size==elementData.length){
            grow();
        }
        elementData[size++]=data;

    }

    /**
     * 索引插入元素
     * @param index
     * @param data
     */
    public void index(int index,int data){
        if(!content(index)){
            System.out.println("插入位置不合法!!!");
            return;
        }
        if(size==elementData.length){
            grow();
        }
        if(index==0){
            addFirst(data);
        }else if(index==size){
            addLast(data);
        }else{
            for (int i = size-1; i>=index; i--) {
                elementData[i+1]=elementData[i];
            }
            elementData[index]=data;
            size++;
        }
    }

    /**
     * 存在返回true;否则返回false
     * @param index
     * @return
     */
    private boolean content(int index){
        if(index<0 || index>size){
            return false;
        }
        return true;
    }
    /**
     * 按值查找
     * @param data
     * @return
     */
    public int findVal(int data){
        for (int i = 0; i < size; i++) {
            if(elementData[i]==data){
                return i;
            }
        }
        System.out.println("没有这个数!!!");
        return -1;
    }

    /**
     * 按索引查找
     * @param index
     * @return
     */
    public int findIndex(int index){
        if(!content(index)){
            System.err.println("查找位置不合法!!!");
            return -1;
        }
        return elementData[index];
    }

    /**
     * 删除索引位置的值
     * @param index
     */
    public void delIndex(int index){
        if(!content(index)){
            System.out.println("该位置没有值!!!");
            return;
        }
        for (int i = index; i <size-1; i++){
            elementData[i]=elementData[i+1];
        }
        size--;
        elementData[size]=0;
    }

    /**
     * 删除第一次出现的值为data的元素
     * @param data
     */
    public void delOne(int data){
        int index=-1;
        for (int i = 0; i < size; i++) {
            if(elementData[i]==data){
                index=i;
                break;
            }
        }
        if(index==-1){
            return;
        }else {
            delIndex(index);
        }
    }
    /**
     * 删除数组中所有data
     * @param data
     */
    public void delVal(int data){
        for (int i = 0; i < size; i++) {
            while(elementData[i]==data){
               delIndex(i);
            }
        }
    }

    /**
     * 按值修改
     * @param data
     */
    public void changeVal(int data){
        for (int i = 0; i < size; i++) {
            if (elementData[i]==data){
                elementData[i]=data;
            }
        }
    }

    /**
     * 按索引号修改元素
     * @param index
     * @param data
     * @return
     */
    public int changeIndex(int index,int data){
        if(index<0 || index>=size){
            System.err.println("该位置非法!!!");
            return -1;
        }else {
            int ret=elementData[index];
            elementData[index]=data;
            return ret;
        }
    }
    /**
     * 清空数组
     */
    public void clear(){
        elementData=null;
    }
    /**
     * 返回有效数据的长度
     * @return
     */
    public int getSize(){
        return size;
    }
    @Override
    public String toString() {
        String ret="[";
        for (int i = 0; i < size; i++) {
            ret+=elementData[i];
            if(i!=size-1){
                ret+=", ";
            }
        }
        ret+="]";
        return ret;
    }

    public static void main(String[] args) {
        DynamicArray arr=new DynamicArray();
       arr.index(0,2);
        arr.index(0,2);
        arr.index(0,3);
        arr.delVal(2);
        System.out.println(arr);
    }
}

八、顺序表源码(使用泛型)

之前的代码只能创建整形的顺序表,加入泛型便可以存储任意类型。

package linklist;

import java.util.Arrays;

/**
 * @author 联想
 */
public class ArrayList<T> {
    private Object[] data;
    private int size;
    public ArrayList(){
        data=new Object[77];
    }
    public ArrayList(int num){
        data=new Object[num];
    }
    public boolean isFull(){
        if(size==data.length-1){
            return true;
        }
        return false;
    }
    public void grow(){
        Object[] newArray=new Object[data.length<<1];
        newArray= Arrays.copyOf(data,newArray.length);
        data=newArray;
    }
    public void addFrist(T val){
        if(isFull()){
            grow();
        }
        if(size==0){
            data[0]=val;
            size++;
            return;
        }
        for (int i = size; i >0 ; i--) {
            data[i]=data[i-1];
        }
        data[0]=val;
        size++;
    }
    public void addIndex(int index,T val){
        if(index<0 || index>size){
            System.err.println("该位置不合法!!!");
            return;
        }
        if(size==data.length){
            grow();
        }
        for (int i = size; i >index ; i--) {
            data[i]=data[i-1];
        }
        data[index]=val;
        size++;
    }
    public void addLast(T val){
        if(size== data.length){
            grow();
        }
        data[size]=val;
        size++;
    }
    public T  findIndex(int index){
        if(index<0 || index>=size){
            System.err.println("该位置不合法!!!");
            return null;
        }
        return (T) data[index];
    }
    public T findVal(T val){
        for (int i = 0; i < size; i++) {
            if(data[i]==val){
                return (T) data[i];
            }
        }
        System.err.println("没有这个元素!!!");
        return null;
    }
    public void removeOneVal(T val){
        for (int i = 0; i < size; i++) {
            if(data[i]==val){
                for (int j = i; j <size-1; j++) {
                    data[j]=data[j+1];
                }
                data[size-1]=0;
                size--;
                return;
            }
        }
    }
    public void removeAll(T val){
        for (int i = 0; i < size; i++) {
            while (data[i]==val){
                for (int j = i; j <size-1; j++) {
                    data[j]=data[j+1];
                }
                data[size-1]=0;
                size--;
            }
        }
    }
    public T removeIndex(int index){
        if(index<0 || index>size){
            System.err.println("该位置无数据!!!");
            return null;
        }
        T ret= (T) data[index];
        for (int i = index; i <size-1 ; i++) {
            data[i]=data[i+1];
        }
        size--;
        return ret;
    }
    public T modifyIndex(int index,int val){
        if(index<0 || index>size){
            System.err.println("该位置无数据!!!");
            return null;
        }
        T ret= (T) data[index];
        data[index]=val;
        return ret;
    }
    public static void main(String[] args) {

    }
    @Override
    public String toString() {
        String ret="[";
        for (int i = 0; i < size; i++) {
            ret+=data[i];
            if(size-1!=i){
                ret+=", ";
            }
        }
        ret+="]";
        return ret;
    }
}