线性表
1、ADT
/** * * 线性表ADT * @author sxw * */ public interface List { /** * 得到数据元素的个数。 * @return 返回线性表的大小 */ public int getSize(); /** * 判断线性表是否为空 * @return 如果线性表为空返回true,否则返回false。 */ public boolean isEmpty(); /** * 判断线性表是否包含数据元素e * @param e 数据元素 * @return 如果线性表包含e返回true,否则返回false。 */ public boolean contains(Object e); /** * 定位数据元素e在线性表中的位置 * @param e * @return 返回数据元素e在线性表中的序号,如果找不到返回-1。 */ public int indexOf(Object e); /** * 将数据元素e插入到线性表中index位置 * @param index * @param e * @throws OutOfBoundaryException 如果index超出线性表的容量,抛出此异常 */ public void insert(int index, Object e) throws OutOfBoundaryException; /** * 将数据元素e插入到元素obj之前 * @param obj * @param e * @return 是否插入成功 */ public boolean insertBefore(Object obj, Object e); /** * 将数据元素e插入到元素obj之后 * @param obj * @param e * @return 是否插入成功 */ public boolean insertAfter(Object obj, Object e); /** * 删除线性表中序号为i的元素,并返回之 * @param index * @return 返回删除的数据元素 * @throws OutOfBoundaryException 如果index超界,则抛出此异常。 */ public Object remove(int index) throws OutOfBoundaryException; /** * 删除线性表中第一个与e相同的元素 * @param e * @return 是否删除成功 */ public boolean remove(Object e); /** * 替换线性表中序号为i的数据元素为e * @param index * @param e * @return 返回原数据元素 * @throws OutOfBoundaryException 如果index超界,则抛出此异常。 */ public Object replace(int index, Object e) throws OutOfBoundaryException; /** * 取得序号index的数据元素 * @param index * @return 返回线性表中序号为index的数据元素 * @throws OutOfBoundaryException 如果index超界,则抛出此异常。 */ public Object get(int index) throws OutOfBoundaryException; }
2、线性表的顺序映像
顺序映像采用数组实现
线性表的顺序存储结构是一种随机存取的存储结构。
/** * 线性表顺序映像采用数组实现 * @author sxw * */ public class ListArray implements List { private static final int LEN = 10; // 数组的默认大小 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]; } // 返回线性表的大小,即数据元素的个数。 public int getSize() { return size; } // 如果线性表为空返回true,否则返回false。 public boolean isEmpty() { return size == 0; } // 判断线性表是否包含数据元素e public boolean contains(Object e) { // for (int i = 0; i < size; i++) // if (strategy.equal(e, elements[i])) return true; // return false; return indexOf(e) > 0; } // 返回数据元素e在线性表中的序号 public int indexOf(Object e) { if (e == null) { for (int i = 0; i < size; i++) { if (elements[i] == null) return i; } } for (int i = 0; i < size; i++) if (strategy.equal(e, elements[i])) return i; return -1; } // 将数据元素e插入到线性表中i号位置 public void insert(int index, Object e) throws OutOfBoundaryException { if (index < 0 || index > size) throw new OutOfBoundaryException("Index: "+index+", Size: "+size); // if (size >= elements.length) ensureCapacity(); // 数组扩容 ensureCapacity(size + 1); for (int j = size; j > index; j--) { elements[j] = elements[j - 1]; } // System.arraycopy(elementData, index, elementData, index + 1, size - index); elements[index] = e; size++; return; } private void ensureCapacity(int minCapacity) { // Object[] a = new Object[elements.length * 2]; // for (int i = 0; i < elements.length; i++) // a[i] = elements[i]; // elements = a; int oldCapacity = elements.length; if (minCapacity > oldCapacity) { // increase strategy int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) { newCapacity = minCapacity; } // minCapacity is usually close to size, so this is a win: elements = Arrays.copyOf(elements, newCapacity); } } // 将数据元素e插入到元素obj之前 public boolean insertBefore(Object obj, Object e) { int i = indexOf(obj); if (i < 0) return false; insert(i, e); return true; } // 将数据元素e插入到元素obj之后 public boolean insertAfter(Object obj, Object e) { int i = indexOf(obj); if (i < 0) return false; insert(i + 1, e); return true; } // 删除线性表中序号为i的元素,并返回之 public Object remove(int index) throws OutOfBoundaryException { if (index < 0 || index >= size) throw new OutOfBoundaryException("Index: "+index+", Size: "+size); Object obj = elements[index]; for (int j = index; j < size - 1; j++) elements[j] = elements[j + 1]; elements[--size] = null; return obj; } // 删除线性表中第一个与e相同的元素 public boolean remove(Object e) { int i = indexOf(e); if (i < 0) return false; remove(i); return true; } // 替换线性表中序号为i的数据元素为e,返回原数据元素 public Object replace(int index, Object e) throws OutOfBoundaryException { if (index < 0 || index >= size) throw new OutOfBoundaryException("Index: "+index+", Size: "+size); Object obj = elements[index]; elements[index] = e; return obj; } // 返回线性表中序号为i的数据元素 public Object get(int index) throws OutOfBoundaryException { if (index < 0 || index >= size) throw new OutOfBoundaryException("Index: "+index+", Size: "+size); return elements[index]; } }
3、分析
i.插入
首先过滤异常,如果传入参数超界,抛出异常
数组扩容,调用ensureCapacity函数
将index后的元素向后移动,将index位置赋值插入
数组长度增1
ii.删除
首先增加程序健壮性,过滤异常
指定删除的index位置元素后的元素前移,
之后设置数组最后一个元素为null,让gc去回收,并size减1
返回删除的元素
4、测试用例
/** * @author sxw * */ public class ListArrayTest { private static People people; private List list; /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { list = new ListArray(); people = new People(); insertToList(list); } private static void insertToList(List l) { for (int j = 0; j < 9; j++) { l.insert(j, new People("People" + " " + j, String.valueOf(j))); } l.insert(9, people); } /** * @throws java.lang.Exception */ @After public void tearDown() throws Exception { } /** * Test method for {@link dsa.adt.ListArray#getSize()}. */ @Test public final void testGetSize() { Assert.isTrue(list.getSize() == 10); System.out.println(list.getSize()); // fail("Not yet implemented"); // TODO } /** * Test method for {@link dsa.adt.ListArray#isEmpty()}. */ @Test public final void testIsEmpty() { Assert.isTrue(list.isEmpty() == false); // fail("Not yet implemented"); // TODO } /** * Test method for {@link dsa.adt.ListArray#contains(java.lang.Object)}. */ @Test public final void testContains() { Assert.isTrue(list.contains(people)); // fail("Not yet implemented"); // TODO } /** * Test method for {@link dsa.adt.ListArray#indexOf(java.lang.Object)}. */ @Test public final void testIndexOf() { Assert.isTrue(list.indexOf(people) > 0); // fail("Not yet implemented"); // TODO } /** * Test method for {@link dsa.adt.ListArray#insert(int, java.lang.Object)}. */ @Test public final void testInsert() { int size = list.getSize(); list.insert(list.getSize(), people); Assert.isNotNull(list.get(size)); // fail("Not yet implemented"); // TODO } /** * Test method for * {@link dsa.adt.ListArray#insertBefore(java.lang.Object, java.lang.Object)} * . */ @Test public final void testInsertBefore() { int size = list.getSize(); Object obj = new Object(); list.insertBefore(people, obj); Assert.isTrue(list.get(size - 1) == obj); // fail("Not yet implemented"); // TODO } /** * Test method for * {@link dsa.adt.ListArray#insertAfter(java.lang.Object, java.lang.Object)} * . */ @Test public final void testInsertAfter() { int size = list.getSize(); Object obj = new Object(); list.insertAfter(people, obj); Assert.isTrue(list.get(size) == obj); // fail("Not yet implemented"); // TODO } /** * Test method for {@link dsa.adt.ListArray#remove(int)}. */ @Test public final void testRemoveInt() { int size = list.getSize(); list.remove(size - 1); Assert.isTrue(list.getSize() == size - 1); // fail("Not yet implemented"); // TODO } /** * Test method for {@link dsa.adt.ListArray#remove(java.lang.Object)}. */ @Test public final void testRemoveObject() { int size = list.getSize(); list.remove(people); Assert.isTrue(list.getSize() == size - 1); } /** * Test method for {@link dsa.adt.ListArray#replace(int, java.lang.Object)}. */ @Test public final void testReplace() { list.replace(0, people); Assert.isTrue(list.get(0) == people); } /** * Test method for {@link dsa.adt.ListArray#get(int)}. */ @Test public final void testGet() { Assert.isNotNull(list.get(0)); } }