线性表的顺序存储
2019-12-16 本文已影响0人
暮想sun
优点:
1.无须为表示表中元素之间的逻辑关系二增加额外的存储空间
2.可以快速地存取表中任一位置的元素
缺点:
1.插入和删除需要移动大量元素
2.当线性表长度变化较大时,难以确定存储空间的容量
3.造成存储空间的'碎片'
初始化构造函数:
/**
* 默认初始化数组大小
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空数组
*/
private static final Object[] EMPTY_ELEMENT_DATA = {};
/**
* 数组
*/
private Object[] elementData;
private int size;
public OrderList() {
this.elementData = EMPTY_ELEMENT_DATA;
}
public OrderList(int initialCapacity) {
if (initialCapacity == 0) {
elementData = EMPTY_ELEMENT_DATA;
} else if (initialCapacity > 0) {
elementData = new Object[initialCapacity];
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
public OrderList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class) {
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
} else {
elementData = EMPTY_ELEMENT_DATA;
}
}
元素个数:
public int size() {
return size;
}
判断是否为空:
public Boolean isEmpty() {
return size == 0;
}
获取元素下标:
public int indexOf(Object o) {
//区分null,相等则返回对应下标。否则返回-1,因为数组下标从0开始
if (o == null) {
for (int i = 0; i < size; i++) {
if (elementData[i] == null) {
return i;
}
}
} else {
for (int i = 0; i < size; i++) {
if (o.equals(elementData[i])) {
return i;
}
}
}
return -1;
}
判断是否包含某个元素:
public Boolean contains(Object o) {
return indexOf(o) >= 0;
}
获取指定下标数据:
public Object get(int index) {
//判断下标是否越界
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
return elementData[index];
}
插入:
public void add(E e) {
//判断是否需要扩容
ensureCapacityInternal(size + 1);
//将e赋值给当前size, 再执行size+1
elementData[size++] = e;
}
private void ensureCapacityInternal(int minCapacity) {
//判断是否为空数组
if (elementData == EMPTY_ELEMENT_DATA) {
//空数组,则确定需要确认的数组大小
minCapacity = Math.min(DEFAULT_CAPACITY, minCapacity);
}
//如果数据大小,比当前数据大小大,则需要扩容
if (minCapacity - elementData.length > 0) {
grow(minCapacity);
}
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果扩容一次的大小不满足最小需要扩容的大小
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
//赋值数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
指定下标插入:
public void add(int index, E e) {
//判断下标是否越界
if (index > size || index < 0) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
//判断是否需要扩容
ensureCapacityInternal(size + 1);
//数组copy,index以及后的数据需要向后移动
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = e;
size++;
}
删除:
public Boolean remove(Object o) {
//判断元素是否为空,空与非空,判断元素相等有区别。相等则根据下标删除
if (o == null) {
for (int i = 0; i < size; i++) {
if (elementData[i] == null) {
//删除对应下标数据
fastRemove(i);
return true;
}
}
} else {
for (int i = 0; i < size; i++) {
if (o.equals(elementData[i])) {
//删除对应下标数据
fastRemove(i);
return true;
}
}
}
return false;
}
private void fastRemove(int index) {
//需要移动的数据,index下标删除。index+1以及以后的数据,需要向前移动
int numMoved = size - 1 - index;
if (numMoved > 0) {
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
}
//删除元素置空
elementData[--size] = null;
}
指定下标删除:
public void remove(int index) {
//判断下标是否越界
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
fastRemove(index);
}
清空:
public void clear() {
//引用指向空,gc会清除内存数据
for (int i = 0; i < size; i++) {
elementData[i] = null;
}
size = 0;
}