Java—实现一个顺序表
1.顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
静态顺序表:使用定长数组存储。
动态顺序表:使用动态开辟的数组存储。
静态顺序表适用于确定知道需要存多少数据的场景.
静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用.
相比之下动态顺序表更灵活, 根据需要动态的分配空间大小.
2.实现一个顺序表
1.首先定义顺序表的属性和构造方法:
顺序表的底层是一个数组,所以需要一个数组和一个定义数组中有效数字的属性,并提供构造方法,在构造方法中可以设置参数。
public class MyArrayList {
//顺序表所需要的属性;
public int[] elem;//引用类型默认为空
public int usedSize;//不给初始化,默认为0
//提供构造方法
public MyArrayList() {//无参数的构造方法
this.elem = new int[6];
}
public MyArrayList(int capacity) {//有参数的构造方法
this.elem = new int[capacity];
}
2.实现一些操作:
1、新增元素
// 在 pos 位置新增元素
public void add(int pos, int data) {
if(isFull()){
//System.out.println("顺序表为满");
resize();
//return;
}
if(pos <0 || pos >this.usedSize){
System.out.println("pos位置不合法");
}
//代码走这说明满足条件,插入
for (int i =usedSize-1; i >= pos ; i--) {
this.elem[i+1] = this.elem[i];//数据从后挪;
}
this.elem[pos] = data;
usedSize++;//重新记录有效数字
}
public void add2(int data){
if(isFull()){
//System.out.println("顺序表为满");
resize();
//return;
}
this.elem[usedSize]=data;
usedSize++;//重新记录有效数字
}
2、是否包含某个元素
// 判定是否包含某个元素
public boolean contains(int toFind) {
for (int i = 0; i <usedSize ; i++) {
if(this.elem[i] == toFind ){
return true;
}
}
return false;
}
3、查找某个元素对应的位置
// 查找某个元素对应的位置
public int search(int toFind) {
for (int i = 0; i <usedSize ; i++) {
if(this.elem[i] == toFind ){
return i;
}
}
return -1;
}
4、获取 pos 位置的元素
// 获取 pos 位置的元素
public int getPos(int pos) {
if(pos<0 || pos>=usedSize){
return -1;
}
for (int i = 0; i <usedSize ; i++) {
if(i==pos){
return this.elem[i];
}
}
return -1;
}
5、 给 pos 位置的元素设为 value
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value) {
//判断pos的值是否合法
if( pos<0 || pos>=usedSize ){
return;
}
//找到pos;
for (int i = 0; i <usedSize ; i++) {
if(i==pos){
this.elem[i]=value;
}
}
}
6、打印顺序表
// 打印顺序表
public void display() {
for (int i = 0; i < usedSize; i++) {
System.out.print(this.elem[i]+" ");
}
System.out.println();
}
7、判断数组是否为满
public boolean isFull(){//判断数组是否为满
if(this.usedSize == elem.length){
return true;
}
return false;
}
8、扩容操作
public void resize(){//扩容操作
this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
}
9、删除第一次出现的关键字key
// 删除第一次出现的关键字key
public void remove(int key) {
//1、查找是否有key index
int index = search(key);
if(index == -1) {
System.out.println("没有找到");
return;
}
//找到之后i = index; i < usdSize-1
for(int i = index;i < this.usedSize-1;i++) {
this.elem[i] = this.elem[i+1];
}
//3、this.usedSize--;
this.usedSize--;//长度减小
}
10、获取顺序表长度
// 获取顺序表长度
public int size() {
return usedSize;
}
11、清空顺序表
// 清空顺序表
public void clear() {
this.usedSize = 0;
}
测试类代码:
public class TestDemo {
public static void main(String[] args) {
MyArrayList myArrayList =new MyArrayList();//有参数
//myArrayList.add3(123);
//myArrayList.add3(124);
//MyArrayList myArrayList1 = new MyArrayList(20);//无参数
myArrayList.add(0,12);
myArrayList.add(1,22);
myArrayList.add(2,32);
myArrayList.add(3,42);
myArrayList.add2(123);
myArrayList.add2(124);
myArrayList.display();
System.out.println("===========");
int ret = myArrayList.usedSize;
System.out.println(ret);
System.out.println("========");
System.out.println(myArrayList.contains(12));
System.out.println("==========");
System.out.println(myArrayList.search(12));
System.out.println("==========");
myArrayList.remove(32);
myArrayList.display();
System.out.println("=========");
System.out.println(myArrayList.getPos(2));
System.out.println("========");
myArrayList.setPos(0,10);
myArrayList.display();
}
}
结果截图:
顺序表的缺点:
- 顺序表中间/头部的插入删除,时间复杂度为O(N)
- 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
- 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。