概念
线性结构是最常见的一种数据结构,其特点是数据元素之间存在一对一线性关系。
线性结构实现有两种存储结构:顺序存储结构(数组)和链式存储结构(链表)。顺序存储的线性表称为顺序表。
线性结构常见有:顺序表、队列、链表、栈。
- 关于数组、顺序表、链表等概念
- 线性表:属于逻辑结构中的线性结构,它包括顺序表和链表。
- 顺序表:用顺序存储(数组)实现的线性表。
- 链表:用链式存储实现的线性表。
- 数组:一种物理结构,它的存储单元是连续的。
顺序表
顺序表是以数组形式保存的线性表,逻辑结构上相邻的元素物理存储结构上也相邻。
import java.util.Iterator;
public class MySequenceList<T> implements Iterable<T> {
//存储元素的数组
private T[] eles;
//当前顺序表元素个数
private int N;
public MySequenceList(int capacity){
if(capacity >= 1){
this.eles = (T[]) new Object[capacity];
this.N = 0;
}else {
this.eles = (T[]) new Object[1];
this.N = 0;
}
}
public MySequenceList(){
//默认大小为10
this.eles = (T[]) new Object[10];
this.N = 0;
}
//清空线性表
public void clear(){
this.N = 0;
}
//判断是否为空
public boolean isEmpty(){
return N == 0;
}
//返回顺序表长度
public int length(){
return N;
}
//获取第i个元素
public T get(int i){
if(i <= N){
return eles[i];
}
return null;
}
//末尾插入
public void insert(T t){
//判断数组是不是满了,满了就扩容
if(N >= eles.length)
resize(2 * eles.length);
eles[N++] = t;
}
//指定位置插入
public void insert(int i,T t){
//判断i是否落在有数据的地方
if(0 <= i && i <= N){
//判断数组是不是满了,满了就扩容
if(N >= eles.length)
resize(2 * eles.length);
for(int index = N;index > i;index--){
eles[index] = eles[index - 1];
}
eles[i] = t;
N++;
}
}
//删除
public T remove(int i){
//判断i是否落在有数据的地方
if (i >= 0 && i < N) {
T current = eles[i];
for(int index = i;index<N-1;index++){
eles[index] = eles[index+1];
}
N--;
//如果用到的地方太少就缩容
if(N < eles.length / 4){
resize(eles.length/2);
}
return current;
}
return null;
}
//重新设定数组大小
public void resize(int newSize){
T[] temp = eles;
eles = (T[]) new Object[newSize];
for (int i = 0;i < N;i++){
eles[i] = temp[i];
}
}
//获取元素下标
public int indexOf(T t){
for(int i = 0;i <N;i++){
if(eles[i].equals(t)){
return i;
}
}
return -1;
}
//提供遍历方法
@Override
public Iterator<T> iterator(){
return new SIterator();
}
//自定义内部类用于遍历
private class SIterator implements Iterator{
private int cusor;
public SIterator(){
this.cusor = 0;
}
@Override
public boolean hasNext(){
return cusor < N ;
}
@Override
public Object next(){
return eles[cusor++];
}
}
public static void main(String[] args) {
MySequenceList<String> test = new MySequenceList<>();
test.insert("111");
test.insert("222");
test.insert("333");
test.insert(1,"bbb");
test.remove(2);
test.insert(3,"444");
test.insert(-1,"ccc");
test.insert(5,"ddd");
for(String s : test){
System.out.println(s);
}
System.out.println(test.length());
System.out.println(test.indexOf("bbb"));
System.out.println(test.indexOf("222"));
System.out.println("============");
MySequenceList<String> test2 = new MySequenceList<>(-2);
test2.insert("111");
test2.insert("222");
for(String s : test2){
System.out.println(s);
}
}
}
顺序表操作的时间复杂度
假如数组的长度为 n。
访问:O(1)//访问特定位置的元素
插入:O(n )//最坏的情况发生在插入发生在数组的首部并需要移动所有元素时
删除:O(n)//最坏的情况发生在删除数组的开头发生并需要移动第一元素后面所有的元素时
顺序表底层是由数组实现的,涉及到扩容操作,这样导致顺序表在使用过程中时间复杂度不是线性的,在需要扩容的节点处,耗时会