线性结构
线性结构是一个数据元素的有序集合。它有四个基本特征
- 集合中必存在唯一的一个”第一个元素”
- 集合中必存在唯一的一个”最后的元素”
- 除最后元素之外,其它数据元素均有唯一的”后继”
- 除第一元素之外,其它数据元素均有唯一的”前扑”
线性表
线性表是最基本、最简单、也是最常用的一种数据结构。
线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
顺序表
元素的存储空间是连续的。在内存中是以顺序存储,内存划分的区域是连续的。存储结构如下图:
实现代码,简单实现增加 移除……操作
import java.io.Serializable;
import java.util.Arrays;
/**
* 顺序表
* @author admin
*
* @param <E>
*/
public class ArrayList<E> implements Serializable {
private static final long serialVersionUID = 8233103956132228603L;
/**
* 定义一个顺序结构的允许最大容量,这里参考了jdk源码的方法,官方文档解释说
* Object[]的最大容量一般收到VMs的限制,推荐设置为Integer.MAX_VALUE-8
*/
private static final int MAX_SIZE = Integer.MAX_VALUE-1;
/**
* ArrayList的大小
*/
private int size;
/**
* 存储数据的实际长度
*/
private int currentSize = -1;
/**
* 存放数据的数组
*/
private Object[] elementData;
/**
* 默认初始化方法,默认设置Object的初始大小为10
*/
public ArrayList(){
this.size = 10;
}
/**
* 构造方法,指定初始容量大小
* @param initCapacity 初始化容量
*/
public ArrayList(int initCapacity) {
if(initCapacity < 0)
throw new RuntimeException("容量数值小于0");
if(initCapacity > MAX_SIZE)
throw new RuntimeException("超出最大容量");
this.elementData = new Object[initCapacity];
this.size = initCapacity;
}
/**
* 扩展容量,确保容量不超过初始化容量
* @param requireCapacity
*/
private void ensureCapacity(int requireCapacity){
if(requireCapacity < 0)
throw new ExceptionInInitializerError();
if(requireCapacity >= this.size){
int newCapacity = requireCapacity+10; // 每次扩展容量只扩展10个单位的容量。
if(newCapacity > MAX_SIZE){
newCapacity = requireCapacity + (10 - (newCapacity - MAX_SIZE)); // 重新计算新的容量
}
this.size = newCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
/**
* 获取顺序表的容量
* @return
*/
public int getSize() {
return this.size;
}
/**
* 获取顺序表实际存储长度
* @return
*/
public int getCurrentSize() {
return this.currentSize;
}
/**
* 判断当前表是否为空
* @return
*/
public boolean isEmpty() {
return (this.currentSize == -1);
}
/**
* 判断索引的范围
* @param index 需要判断的索引
*/
private void checkRange(int index){
if(index<0 || index > currentSize)
throw new ArrayIndexOutOfBoundsException();
}
/**
* 增加泛型的支持,使每个放入ArrayList容器的元素不会丢失其数据类型
* @param index
* @return E
*/
@SuppressWarnings("unchecked")
private E elementData(int index) {
checkRange(index);
return (E) elementData[index];
}
/**
* 往顺序表ArrayList尾部添加元素的方法。
* @param e
* @return
*/
public boolean add(E e) {
this.ensureCapacity(currentSize + 1);
this.elementData[currentSize + 1] = e;
currentSize ++;
return true;
}
/**
* 获取元素所在的索引位置
* @param e
* @return
*/
public int indexOf(Object e) {
if(e == null || e == "" || e.equals(null) || "".equals(e)) {
return -1;
} else {
for (int i = 0; i <=currentSize; i++) {
if(e.equals(elementData[i]) || e.hashCode()==elementData[i].hashCode())
return i;
}
}
return -1;
}
/**
* 移除一个元素
* @param e
* @return
*/
public boolean removeElement(E e) {
int index = indexOf(e);
if(index > 0) {
elementData[index] = null;
currentSize--;
}
return false;
}
/**
* 移除所有元素
* @return
*/
public boolean removeAll() {
for (int i = 0; i < currentSize; i++) {
elementData[i] = null;
}
currentSize = -1;
return true;
}
}