顺序表
(本篇文章内容包含网上资料,如有侵权请联系博主)
一、概念
线性表的顺序存储结构称之为顺序表(Sequential List),它是用一组地址连续的存储单元存储数据元素。数据元素在内存的物理存储次序反映了线性表数据元素之间的逻辑次序。只要确定了存储的起始位置,顺序表中任何数据元素都可以随机存取。顺序存储结构底层是利用数组来实现的。
特点:
- 逻辑上相邻的数据,在物理存储的位置上也是相邻的。
- 使用数组作为内部容器简单且易用。
- 存储密度高,需要预先分配空间(一开始就要固定顺序表的最大长度)。
- 支持随机存取,空间利用率高(连续分配,不存在空间浪费)。
- 存储结构跟数组是一样,所以也就不便于插入和删除。当顺序表较大时,插入和删除都会引起大量数据的移动。如果插入和删除频繁操作的话,最好使用链表的数据结构。顺序表一般存储不经常变动的数据。
二、实现
//List接口
public interface IList {
// 返回线性表的大小,即数据元素的个数。
public int getSize();
// 如果线性表为空返回 true,否则返回 false。
public boolean isEmpty();
// 判断线性表是否包含数据元素 e
public boolean contains(Object e);
// 返回数据元素 e 在线性表中的序号
public int indexOf(Object e);
// 将数据元素 e 插入到线性表中 i 号位置
public void insert(int i, Object e) throws OutOfBoundaryException;
// 将数据元素 e 插入到元素 obj 之前
public boolean insertBefore(Object obj, Object e);
// 将数据元素 e 插入到元素 obj 之后
public boolean insertAfter(Object obj, Object e);
// 删除线性表中序号为 i 的元素,并返回之
public Object remove(int i) throws OutOfBoundaryException;
// 删除线性表中第一个与 e 相同的元素
public boolean remove(Object e);
// 替换线性表中序号为 i 的数据元素为 e,返回原数据元素
public Object replace(int i, Object e) throws OutOfBoundaryException;
// 返回线性表中序号为 i 的数据元素
public Object get(int i) throws OutOfBoundaryException;
}
// 顺序表类
public class MyArrayList implements IList {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
private final int LEN = 8; // 数组的默认大小
private IStrategy strategy; // 数据元素比较策略
private int size; // 线性表中数据元素的个数
private Object[] elements; // 数据元素数组
// 构造方法
public MyArrayList() {
this(new DefaultStrategy());
}
public MyArrayList(IStrategy strategy) {
this.strategy = strategy;
size = 0;
elements = new Object[LEN];
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return this.size;
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return size == 0;
}
@Override
public boolean contains(Object e) {
// TODO Auto-generated method stub
for (int i = 0; i < size; i++) {
if (this.strategy.equal(e, elements[i])) {
return true;
}
}
return false;
}
@Override
public int indexOf(Object e) {
// TODO Auto-generated method stub
for (int i = 0; i < size; i++) {
if (strategy.equal(e, elements[i])) {
return i;
}
}
return -1;
}
@Override
public void insert(int i, Object e) throws OutOfBoundaryException {
// TODO Auto-generated method stub
// 检查下标越界
if (i < 0 || i >= size) {
throw new OutOfBoundaryException("指定的插入序号越界。");
}
// 检查线性表数组的容量
if (size >= elements.length) {
expandSpace();
}
// 将插入位置后的数据元素依次向后移动一个单位
for (int j = size; j > i; j--) {
elements[j] = elements[j - 1];
}
// 插入数据
elements[i] = e;
size++; // 元素个数加1
}
// 扩展顺序表空间
private void expandSpace() {
Object[] a = new Object[elements.length * 2];
for (int i = 0; i < elements.length; i++) {
a[i] = elements[i];
}
elements = a;
}
@Override
public boolean insertBefore(Object obj, Object e) {
// TODO Auto-generated method stub
// 找到插入位置
int i = indexOf(obj);
if (i < 0) {
return false;
}
insert(i, e);
return true;
}
@Override
public boolean insertAfter(Object obj, Object e) {
// TODO Auto-generated method stub
int i = indexOf(obj);
if (i < 0) {
return false;
}
insert(i + 1, e);
return true;
}
@Override
public Object remove(int i) throws OutOfBoundaryException {
// TODO Auto-generated method stub
// 首先检查越界
if (i < 0 || i >= size) {
throw new OutOfBoundaryException("错误,指定的删除序号越界。");
}
Object obj = elements[i];
// 被删除的数据元素后的数据前移一个单位
for (int j = i; j < size - 1; j++) {
elements[j] = elements[j + 1];
}
//
elements[--size] = null;
return obj;
}
@Override
public boolean remove(Object e) {
// TODO Auto-generated method stub
// 找到被删除数据元素的位置
int i = indexOf(e);
if (i < 0) {
return false;
}
remove(i);
return true;
}
@Override
public Object replace(int i, Object e) throws OutOfBoundaryException {
// TODO Auto-generated method stub
if (i < 0 || i >= size) {
throw new OutOfBoundaryException("错误,指定的序号越界。");
}
Object obj = elements[i];
elements[i] = e;
return obj;
}
@Override
public Object get(int i) throws OutOfBoundaryException {
// TODO Auto-generated method stub
if (i < 0 || i >= size) {
throw new OutOfBoundaryException("错误,指定的序号越界。");
}
return elements[i];
}
}