顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
静态顺序表:使用定长数组存储。
动态顺序表:使用动态开辟的数组存储。
静态顺序表适用于确定知道需要存多少数据的场景.
静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用.
相比之下动态顺序表更灵活, 根据需要动态的分配空间大小.
以下实现了一个动态的顺序表:
import java.util.Arrays;
public class SeqList {
//这个数组的最大容量为10,初始情况下:
//这10个元素并不都是有效元素
//执行插入操作之后,被插入的元素才是有效元素
private int[] data = new int[10];
//size表示当前数组中有多少个有效元素
private int size = 0;
//打印顺序表
public void display(){
//System.out.println(Arrays.toString(data));
//也可自己实现:
System.out.println("[");
for(int i = 0;i < size;i++){
System.out.println(data[i]);
if(i != size - 1){
System.out.println(",");
}
}
System.out.println("]");
}
//在 pos 位置新增元素
//pos表示把元素放到哪个下标上,elem表示插入的元素是什么
//时间复杂度为O(N)(最坏)
public void add(int pos,int elem){
if(pos > data.length || pos < 0){
return;
}
if(size >= data.length){
//进行扩容
realloc();
}
if(pos == size){
data[pos] = elem;
size++;
}else{
for(int i = size;i > pos;i--){
data[i] = data[i - 1];
}
data[pos] = elem;
size++;
}
}
private void realloc(){
//扩容的策略很灵活,根据实际问题场景的特点
//来决定具体是线性增长还是指数增长还是其他方式增长
//原则是扩容是比较大的开销,尽量应根据实际场景
//让扩容的次数尽量少
int[] newData = new int[this.data.length * 2];
for(int i = 0;i < this.data.length;i++){
newData[i] = this.data[i];
}
this.data = newData;
}
// 判定是否包含某个元素
public boolean contains(int toFind) {
return this.search(toFind) != -1;
}
//查找某个元素对应的位置
public int search(int toFind){
for(int i = 0;i < this.size;i++){
if(this.data[i] == toFind){
return i;
}
}
return -1;
}
//获取pos位置的元素
public int getPos(int pos){
return this.data[pos];
}
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value){
this.data[pos] = value;
}
//删除第一次出现的关键字key
public void remove(int toRemove){
int pos = search(toRemove);
if(pos == -1){
return;
}
if(pos == this.size - 1){
this.size--;
return;
}
for(int i = pos;i < this.size;i++){
this.data[i] = this.data[i+1];
}
this.size--;
}
//获取顺序表长度
public int size(){
return this.size;
}
//清空顺序表
public void clear(){
this.size = 0;
this.data = new int[10];
}
}