1.顺序表的定义
顺序表是用物理地址连续存储单元依次存储元素的线性数据结构,一般底层采用数组存储,其中Arraylist也是一个动态修改的数组,于此大致相同
在计算机科学中,数组是由一组元素(值或变量)组成的数据结构,每个元素有至少一个索引或键来标识
2.顺序表的功能介绍
注意:不要担心扩容多余的元素问题, 有useSize控制不会访问到那些无效的元素
3.基本功能的实现
1.在构造方法中创建动态数组的默认大小
//初始化顺序表 public MyArraysList() { this.elem = new int[8]; }
2.判断顺序表的数组是否为空
//判断当前顺序表是否为空(true为空,false还没为空) public boolean isEmpty(){ if (this.useSize == 0){ return true; } else return false; }
3.判断顺序表是否已满
//判断当前顺序表是不是满了(true满了,false还没有满) public boolean isFull(){ if (this.useSize == this.elem.length){ return true; }else { return false; } }
4.顺序表已满进行扩容
//对顺序表进行扩容 public void expand() { //把原数组拷贝给新数组,并且新数组长度扩大1.5倍 //这里之所以用位运算符,就是防止使用除法自动类型转换成double this.elem = Arrays.copyOf(this.elem, this.useSize += this.useSize >> 1); }
5.添加功能
5.1在指定索引插入元素
public void addIndex1(int index ,int data){ //判断你要插入的位置是否合法 if (index < 0 || index > this.useSize){ System.out.println("你的索引位置不合法"); return; } if (isFull()){ System.out.println("数组满了需要扩容"); expand(); }else { //通过拷贝后移元素 System.arraycopy(elem , index, elem ,index + 1 , useSize - index); elem[index] = data; useSize++; } }
5.2头插法
public void addFirst(int data){ if (isFull()){ System.out.println("数组满了需要扩容"); expand(); }else { //从usedSize下标开始,不会数组越界(此时elem.length > usedSize) for (int i = this.useSize; i > 0; i--) { //从后往前挪动元素为表头添加开辟一个空间(这样不会造成元素的覆盖) this.elem[i] = this.elem[i - 1]; this.elem[0] = data;//在顺序表的表头添加 this.useSize++;//数组的有效长度 + 1 } } }
5.3尾插法
public void add(int data){ if (isFull()){ System.out.println("数组满了需要扩容"); expand(); }else { //把最后一个参数当索引传给addIndex()方法处理 addIndex(this.useSize,data); //直接在最后一个元素添加 //this.elem[this.useSize++] = data; } }
6.删除功能
6.1指定索引删除元素
public void removeIndex(int index){ if (isEmpty()){ System.out.println("顺序表为空,删除不合法"); return; } if (index < 0 || index >= this.useSize){ System.out.println("index的下标不合法"); return; } //利用拷贝进行元素覆盖 System.arraycopy(this.elem,index + 1,this.elem , index,this.useSize - index - 1); //把index和index之后的元素覆盖 /*for (int i = index; i < this.useSize - 1; i++) { this.elem[i] = this.elem[i + 1]; }*/ //最后一个元素赋值为0 this.elem[this.useSize - 1] = 0; this.useSize--; }
6.2头删法
public void removeFirst(){ if (isEmpty()){ System.out.println("顺序表为空,删除不合法"); return; } //从第一个元素开始,用后面元素的值覆盖掉前面的值, // 遍历整个数组就相当于把第一个元素用覆盖的方式抹去了 for (int i = 1; i < this.useSize; i++) { this.elem[i - 1] = this.elem[i]; } /* //用拷贝写 System.arraycopy(this.elem,1,this.elem , 0 ,this.useSize - 1);*/ //此处的 - 1 是因为this.useSize是下一个要存元素的索引 this.elem[this.useSize - 1] = 0;//现在的最后一个元素是原来的倒数第二个元素,所以原来的的最后一个有效元素要置0 this.useSize--;//不要忘记修改有效数组的长度 }
6.3尾删法
public void removeLast(){ if (isEmpty()){ System.out.println("顺序表为空,删除不合法"); return; } //只需要让最后一个元素为 0即可 this.elem[this.useSize - 1] = 0; this.useSize--; }
6.4删除首次出现的指定元素
public void remove(int key){ if (isEmpty()){ System.out.println("顺序表为空,删除不合法"); return; } for (int i = 0; i < this.useSize; i++) { //先找到你要删除元素的位置 if (this.elem[i] == key){ //注意是:this.usedSize - 1, 将此时 i 之后的元素统一往前挪动一个位置 for (int j = i; j < this.useSize - 1; j++) { this.elem[j] = this.elem[j + 1]; } this.elem[this.useSize - 1] = 0; this.useSize--; return; } } }
7.查找功能
7.1获得指定位置元素
public int getIndex(int index){ if (index < 0 || index >= this.useSize){ System.out.println("当前索引不合法"); return -1; } return this.elem[index]; }
7.2获得指定元素所在的位置
public int indexOf(int toFind){ for (int i = 0; i < this.elem.length; i++) { if (elem[i] == toFind){ return i; } } return -1; }
7.3查找表中是否存在这个元素
public boolean contains(int toFind){ for (int i = 0; i < this.elem.length; i++) { if (elem[i] == toFind){ return true; } } return false; }
8.修改功能
//给index位置的元素设置为value public void setIndex(int index,int value){ this.elem[index] = value; }
9. 遍历功能
9.1利用线性遍历
public void display(){ for (int i = 0; i < elem.length; i++) { System.out.print(this.elem[i] + " "); } System.out.println(); /*2.利用Arrays的API进行打印 Arrays.toString(this.elem);*/ }
这样需求不是调用方写的,也就是不是用户写的,扩展性不强可以利用函数式接口Consumer进行优化
比如你想输出 具体值是 4 具体值是 5 而你用上述方法只能输出 4 5
9.2forEach遍历
public void forEach(Consumer<Integer> consumer){ for (int i = 0; i < this.elem.length; i++) { consumer.accept(this.elem[i]); }
list.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println("具体值是" + integer); } });
9.3迭代器遍历
public Iterator<Integer> iterator(){ return new Iterator<Integer>() { int i = 0; @Override public boolean hasNext() {//判断有没有下一个元素 return i < useSize; } @Override public Integer next() { return elem[i++]; } }; }
时间复杂度就不一一分析了,希望大佬给取意见,我会一一改进的,谢谢大家