数据结构和算法: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(); }
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("自定义执行测试方法之前:\t" + simpleList); System.out.println("官方的执行测试方法之前:\t" + 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("自定义执行测试方法之后:\t" + simpleList); System.out.println("官方的执行测试方法之后:\t" + 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(); } }
4、个人总结
a、这个简单实现是加深自己对线性表的认识,写一遍就知道和源码的差距了,也知道为什么ArrayList查找快,而删除,增加扩容时慢。
b、查看官方实现java.util.ArrayList源码可知,还需要考虑int类型溢出、扩容的效率、和实现迭代器时,删除,迭代下一个元素要考虑数据正确性等问题。
c、源码毕竟是源码...
yexiangyang
moyyexy@gmail.com