顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,我们这里是用数组存储数据。在数组上完成数据的增删查改。
线性表分为:
静态顺序表:使用定长数组存储。
动态顺序表:使用动态开辟的数组存储。
静态顺序表适用于确定知道需要存多少数据的场景。
静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用,所以很多时候还有动态的更好用。
因为我们写的顺序表是由数组组成的,而且我们要知道顺序表存储的时候,被占用了几个空间,是否需要扩容,所以我们再定义一个变量 usedSize 来表示用了多少顺序表的空间。
public int[] elem;
public int usedSize;
public OrderTable(){
this.elem = new int[10];
}
这里用 OrderTable 来初始化顺序表的大小。
就是封装一个接口来输出顺序表的内容。
public void display() {
for (int i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i]+" ");
}
System.out.println();
}
通过遍历来输出顺序表的内容。
public int size() {
return this.usedSize;
}
因为我们是以 usedSize 来表示顺序表的长度,所以我们直接返回 usedSize 就可以了。
因为在增加元素的时候,如果顺序表满了的话,就要扩容。所以直接封装一个判断满没满的方法就好了。
public boolean full(int[] elem) {
return usedSize == this.elem.length;
}
满了的情况就是 usedSize 和顺序表长度的比较就好了。
在新增元素的时候,pos 位置不能小于 0 而且最远的时候只能放在 usedSize 下标处的位置。如图所示:
因为数组的下标最小是 0 ,所以不能小于 0 。但是如果大于 usedSize 的话,就会导致数据没有连续起来,所以最大就是下标为 usedSize 。如果 usedSize 满了也不能放,就扩容。移动的时候,就从后往前移,然后把 pos 位置放上自己要放的元素。放入一个数字之后就让 usedSize++ 增加顺序表的长度。
public void add(int pos, int data) {
if(pos < 0 || pos > usedSize){
System.out.println("pos 位置不合法");
return;
}
if(full(elem)){
this.elem = Arrays.copyOf(elem,elem.length * 2);
}
for(int i = this.usedSize - 1; i >= pos; i--){
this.elem[i + 1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
我们通过遍历数组就可以知道有没有某个元素,所以可以直接遍历得出。
public boolean contains(int toFind) {
for (int i = 0; i < this.usedSize; i++){
if(this.elem[i] == toFind){
return true;
}
}
return false;
}
同理,我们也可以通过遍历,直接返回下标。
public int search(int toFind) {
for (int i = 0; i < this.usedSize; i++){
if(this.elem[i] == toFind){
return i;
}
}
return -1;
}
因为我们在进行增删查改的时候,会判断顺序表是否为空,因为如果为空的话,可能会有空引用异常。当然判断的依据也很简单,只要看 usedSize 是不是 0 就好了。
public boolean isEmpty(){
return this.usedSize == 0;
}
在查找 pos 位置的元素的时候,应该先判断 pos 位置是否合法,如果不合法的话,访问就会越界。然后再判断顺序表是否为空。最后再返回 pos 位置的元素。
public int getPos(int pos) {
if(pos < 0 || pos >= usedSize){
System.out.println("pos 位置不合法");
return -1;//业务上的处理 这里不考虑是否存在这个元素 之后就可以抛出异常
}
if(isEmpty()){
System.out.println("顺序表为空");
return -1;
}
return this.elem[pos];
}
也就是更新 pos 位置的值,第一步也是先判断 pos 位置合不合法。然后判断顺序表是否为空。最后再更新值。
public void setPos(int pos, int value) {
if(pos < 0 || pos >= usedSize){
System.out.println("pos 位置不合法");
return;
}
if(isEmpty()){
System.out.println("顺序表为空");
return;
}
this.elem[pos] = value;
}
因为是查找元素,所以要判断顺序表是否为空。然后再看是否存在元素,如果存在的话就删除。删除就是把后面的元素覆盖掉前面的就好了。
注意:如果是引用类型的话 就把它置为 null this.elem[usedSize] = null 。因为如果不置为 null 的话,引用指向的对象依然占用内存。
public void remove(int toRemove) {
if (isEmpty()){
System.out.println("顺序表是空的");
return;
}
int index = search(toRemove);
if(index == -1){
System.out.println("找不到该元素");
return;
}
for(int i = index;i < this.usedSize - 1; i++){
this.elem[i] = this.elem[i + 1];
}
this.usedSize--;
}
当清空顺序表的时候,因为这里是整型,不是引用类型,所以可以直接把 usedSize 置为 0 就好了。当然,如果数组里面放的是引用类型 那么就需要遍历 把每个引用都置为 null 然后再把 usedSize 置为 0 。
public void clear() {
this.usedSize = 0;
}