数据结构和算法:Java实现线性表简单的顺序存储

一、先定义简单的线性表规则,然后实现

1、接口

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/1/24  <br/>
 * [Description]: 简单的线性表定义<br/>
 *
 * @author YeXiangYang
 */
public interface SimpleList<E> {

    /**
     * 添加元素
     *
     * @param e 需要添加的元素
     * @return 添加成功返回<tt>true<tt/>
     */
    boolean add(E e);

    /**
     * 将元素添加到指定下标上,对应下标不存在抛出异常
     *
     * @param index 下标
     * @param e     元素
     * @return 添加成功返回<tt>true<tt/>
     */
    boolean add(int index, E e);

    /**
     * 删除最后一个元素,集合为空则抛出异常
     *
     * @return 被删除的元素
     */
    E removeLast();


    /**
     * 删除指定下标的元素,对应下标不存在抛出异常
     *
     * @param index
     * @return 被删除的元素
     */
    E remove(int index);

    /**
     * 删除集合中的对于元素
     *
     * @param e 需要被删除的元素
     * @return 删除成功返回<tt>true<tt/>
     */
    boolean remove(E e);

    /**
     * 将指定下标改成对应元素,对应下标不存在抛出异常
     *
     * @param index 下标
     * @param e     需要添加到指定位置为元素
     * @return
     */
    E set(int index, E e);

    /**
     * 获取指定下标的元素,对应下标不存在抛出异常
     *
     * @param index 下标
     * @return 下标对应的元素
     */
    E get(int index);

    /**
     * 返回元素对应的最小下标
     *
     * @param e 元素
     * @return 返回元素对应的最小下标,不存在返回<tt>-1<tt/>
     */
    int indexOf(E e);

    /**
     * 判断集合中是否包含目标元素
     *
     * @param o 目标元素
     * @return 该集合存在目标元素,返回<tt>true<tt/>
     */
    boolean contains(Object o);

    /**
     * 获取集合元素个数
     *
     * @return 集合中元素个数
     */
    int size();

    /**
     * 判断集合中是否为空
     *
     * @return 集合中为空返回<tt>true<tt/>
     */
    boolean isEmpty();

    /**
     * 清除集合中所有元素
     */
    void clear();

    /**
     * 重写toString方法
     *
     * @return 返回友好信息
     */
    String toString();
}
View Code

2、实现

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/1/23  <br/>
 * [Description]: 简单的线性表顺序存储实现<br/>
 *
 * @author YeXiangYang
 */
public class SimpleArrayList<E> implements SimpleList<E> {
    private static final int DEFAULT_CAPACITY = 10;
    private transient Object[] data;
    private int size;

    public SimpleArrayList() {
        data = new Object[DEFAULT_CAPACITY];
        size = 0;
    }

    @Override
    public boolean add(E e) {
        ensureCapacity();

        data[size] = e;
        size++;
        return Boolean.TRUE;
    }

    private void ensureCapacity() {
        if (size >= data.length) {
            int newLength = data.length << 1;
            Object[] newDataArray = new Object[newLength];
            for (int i = 0; i < size; i++) {
                newDataArray[i] = data[i];
                data[i] = null;
            }
            data = newDataArray;
        }
    }

    @Override
    public boolean add(int index, E e) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("index:" + index + ",size:" + size);
        }

        ensureCapacity();

        for (int i = size; i > index; i--) {
            data[i] = data[i - 1];
        }

        data[index] = e;
        size++;
        return Boolean.TRUE;
    }

    @Override
    public E removeLast() {
        return remove(size - 1);
    }

    @Override
    public E remove(int index) {
        rangeCheck(index);

        E oldData = (E) data[index];
        data[index] = null;

        for (int i = index; i < size - 1; i++) {
            data[i] = data[i + 1];
        }
        size--;
        return oldData;
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("index:" + index + ",size:" + size);
        }
    }

    @Override
    public boolean remove(E e) {
        int targetIndex = indexOf(e);
        if (targetIndex >= 0) {
            remove(targetIndex);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public E set(int index, E e) {
        rangeCheck(index);

        E oldData = (E) data[index];
        data[index] = e;
        return oldData;
    }

    @Override
    public E get(int index) {
        rangeCheck(index);

        return (E) data[index];
    }

    @Override
    public int indexOf(E e) {
        if (null == e) {
            for (int i = 0, len = size; i < len; i++) {
                if (data[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = 0, len = size; i < len; i++) {
                if (e.equals(data[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    @Override
    public boolean contains(Object o) {
        try {
            E e = (E) o;
            return indexOf(e) >= 0;
        } catch (Exception e) {
            // 转型出错则不包含
        }
        return Boolean.FALSE;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return 0 == size;
    }

    @Override
    public void clear() {
        for (int i = 0; i < size; i++) {
            data[i] = null;
        }
        size = 0;
    }

    @Override
    public String toString() {
        if (0 == size) {
            return "[]";
        }
        StringBuilder result = new StringBuilder();
        result.append("[");
        boolean isFirst = Boolean.TRUE;
        for (int i = 0; i < size; i++) {
            if (isFirst) {
                isFirst = Boolean.FALSE;
            } else {
                result.append(", ");
            }
            result.append(String.valueOf(data[i]));
        }
        result.append("]");
        return result.toString();
    }
}

3、测试

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/1/25  <br/>
 * [Description]:
 * <p><br/>
 *
 * @author YeXiangYang
 */
public class SimpleArrayListTest {

    SimpleList<Object> simpleList;
    List<Object> list;

    @Before
    public void before() {
        int len = 10;

        simpleList = new SimpleArrayList<>();
        list = new ArrayList<>();

        insertInitSimpleList(len);
        insertInitList(len);

        System.out.println("**************** Before ******************");
        System.out.println("自定义执行测试方法之前:	" + simpleList);
        System.out.println("官方的执行测试方法之前:	" + list);
    }

    private void insertInitList(int len) {
        for (int i = 0; i < len; i++) {
            if (len / 2 == i) {
                list.add(null);
            } else {
                list.add(i);
            }
        }
    }

    private void insertInitSimpleList(int len) {
        for (int i = 0; i < len; i++) {
            if (len / 2 == i) {
                simpleList.add(null);
            } else {
                simpleList.add(i);
            }
        }
    }

    @After
    public void after() {
        System.out.println("自定义执行测试方法之后:	" + simpleList);
        System.out.println("官方的执行测试方法之后:	" + list);
        System.out.println("**************** After *******************");
        System.out.println();
    }

    @Test
    public void addTest() {
        int index = 10;
        Object data = 123;
        try {
            simpleList.add(index, data);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            list.add(index, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void removeTest() {
        list.remove(list.size() - 1);
        simpleList.removeLast();

        Integer removeData = new Integer("5");
        list.remove(removeData);
        simpleList.remove(removeData);

        list.remove(null);
        simpleList.remove(null);
    }

    @Test
    public void setTest() {
        int index = 0;
        Object data = 233;
        try {
            System.out.println(simpleList.set(index, data));
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            System.out.println(list.set(index, data));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Test
    public void getTest() {
        int index = 0;
        try {
            System.out.println(simpleList.get(index));
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            System.out.println(list.get(index));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void isEmptyTest() {
        System.out.println(list.isEmpty());
        System.out.println(simpleList.isEmpty());
    }

    @Test
    public void containsTest() {
        Object object = 0;
        System.out.println(list.contains(object));
        System.out.println(simpleList.contains(object));
    }


    @Test
    public void clearTest() {
        list.clear();
        simpleList.clear();
    }
}
View Code

4、个人总结

     a、这个简单实现是加深自己对线性表的认识,写一遍就知道和源码的差距了,也知道为什么ArrayList查找快,而删除,增加扩容时慢。

     b、查看官方实现java.util.ArrayList源码可知,还需要考虑int类型溢出、扩容的效率、和实现迭代器时,删除,迭代下一个元素要考虑数据正确性等问题。

     c、源码毕竟是源码...

yexiangyang

moyyexy@gmail.com


原文地址:https://www.cnblogs.com/moy25/p/8378509.html