一.概述
顺序表是在计算机内存中以数组(内存地址是连续的)的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素、使得线性表中在逻辑结构上响铃的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
Java中常见的ArrayList集合的底层也是一种顺序表,使用数组实现,同样提供了增删改查以及扩容等功能。
二.代码实现
首先创造一个sequen类,在sequence类的构造函数中初始化数组e和记录元素个数的N。
实现Iterable接口是为了使顺序表能够用增强for循环来遍历。
public class sequenceimplements Iterable { private T[] e; //初始化一个T类型的数组 private int N; //N用于记录当前顺序表中元素的个数 public sequence(int n){ e=(T[])new Object[n];//构造一个长度为n的空数组 N=0;}
清空数组,这里我令当前数组e的每个元素为null
如果使用重开一个数组,应该会增大开销。
//清空数组,重置N值
public void clear(){
//e=(T[]) new Object[e.length];
for(int i=0;i
返回顺序表的长度:
public int length(){
return N;}
是否为空:
public boolean isEmpty(){
return N==0;}
获取指定索引的元素:
public T get(int i) {
if (i < 0 || i >= N) {
throw new RuntimeException("不存在");//运行时异常
}
return e[i];
}
增删元素之前先来个扩容/缩容的方法resize(),参数为数组需要扩/缩到的指定的容量大小,所以不管是扩容还是缩容都调用此方法来改变数组长度。
//顺序表的扩容和缩容
public void resize(int newSize){
T[] temp=e; //创建一个临时数组temp记录原数组e
e=(T[])new Object[newSize]; //用原数组的引用e创建新容量的空数组
for(int i=0;i
向顺序表的末尾添加元素:
先判断数组容量是否已经满了,若是则先调用上面的resize进行扩容,扩容规则:扩至原数组的2倍大小
public void add(T t){//向顺序表末尾添加元素
if(N==e.length){
resize(e.length*2);
}
e[N++]=t;
}
在指定的位置 i 插入新元素 t :
同样先判断数组是否满了,若是则同样以2倍进行扩容 。
扩的过程中,数组原本最后一位元素的索引为N-1,插入新的元素后,最后一位元素的索引为N,此时需要将索引 i 到索引 N-1 的元素,依次向后移动一位至索引 i+1 到索引N 处。
而向后移动一位必须采用倒序遍历的方法。
然后将新元素 t 放到索引 i 处。
public void insert(int i,T t){
if (i < 0 || i > N) {
throw new RuntimeException("插入位置非法");}
if(N==e.length){ //若数组满了则进行扩容
resize(e.length*2);}
//扩完容之后,再插入元素t
for(int index=N;index>i;index--){ //索引i后面的元素后移一位,倒序遍历
e[index]=e[index-1];
}
e[i]=t;
N++;
}
在指定位置删除元素:
删除 i 位置的元素后,需要将索引 i+1 到N-1依次前移一位至 索引i到N-2处。前移则必须正序遍历。
缩容规则:若元素个数小于总长度的1/4则将数组容量调整至原长度的一半。
这里是先删元素再进行缩容,我也不知道为什么。。有没有大佬指点一下??
public T remove(int i){
T result=e[i]; //先记录下要删除的元素
if(i<0||i>N-1){ //索引N-1为最后一个元素
throw new RuntimeException("索引非法");
}
for(int index=i;index0&&N
查找指定元素第一次出现的位置:
public int index(T t){ //查找元素第一次出现的位置
if(t==null){
throw new RuntimeException("查找的元素不能为空");
}
for(int i=0;i
顺序表的遍历:
此处的sequence顺序表类实现了iterable接口,需要重写iterator方法
iterator方法固定返回一个Iterator,而Iterator还是一个接口,接口不能实例化对象,所以需要自己创建一个MyIterator类实现Iterator接口,并用MyIterator新建一个对象并return。
自己创建的MyIterator需要实现两个抽象方法。
//顺序表的遍历
public Iterator iterator(){ //需要返回一个Iterator接口的实现类
return new MyIterator();
}
private class MyIterator implements Iterator{ //成员内部类
private int cur=0; //初始化指针为0
public MyIterator(){
this.cur=0;
}
@Override
public boolean hasNext() {
return cur<=N-1; //最后一位元素的索引为N-1,所以指针<=N-1即都有值
}
@Override
public Object next() {
return e[cur++];
}
}
测试:
public static void main(String[] args) {
sequence list=new sequence<>(3);
list.add("姚明");
list.add("易建联");
list.add("林书豪");
list.add("这是琦");
list.add("大魔王");
System.out.println(list.length()); //输出4
for (String s : list) {
System.out.println(s);
} //输出: 姚明 易建联 林书豪 这是琦 大魔王
list.remove(0); //删去 "姚明"
System.out.println("------------");
System.out.println(list.get(2)); //输出: 这是琦
System.out.println("------------");
list.clear(); //清空顺序表
list.add("这是琦");
System.out.println(list.get(0)); //输出: 这是琦
}
}
需要注意的地方:
索引N-1处为最后一个元素



