线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。
顺序表的实现主要有如下9种方法
- public void add(int pos, int data) 参数:下标pos,插入数据data。功能:将数据data插入到下标为pos的位置
- public void remove(int toRemove) 参数:元素toRemove,功能:删除顺序表中出现的第一个toRemove元素
- public int getPos(int pos) 参数:下标pos,功能:获取下标为pos的元素
- public void setPos(int pos, int value) 参数:下标pos,修改后的值value。功能:将下标pos的元素修改为value
- public boolean contains(int toFind) 参数:元素toFind,功能:查找顺序表中是否包含元素toFind
- public int search (int toFind) 参数:元素toFind,功能:查找元素toFind对应的下标
- public void display() 功能:打印顺序表的每一个元素
- public int size ( ) 功能:获取顺序表的元素个数
- public void clear () 功能:清空顺序表
源代码:
import java.util.Arrays;
/**
* @Description: 顺序表
* @Author: Cheng
* @Create: 2020-04-20 10:00
**/
public class MyArrayList { //顺序表
public int [ ] elem; // 数组类型整型 名字,此时还没分配空间 也可以直接后面写 =int [10]
public int usedSize; // 有效的数据个数
public static final int capacity= 10; //初始容量只有一份 且不能被修改
public MyArrayList( ) {
this.elem = new int [capacity] ; //通过构造方法初始化一下数组,分配了空间。也可以在第一步初始化
this.usedSize = 0;
}
//isFull 是独立提供给add函数的 ,就设置私有
private boolean isFull ( ) { //提供一个方法 判断数组元素是否为满 ,没有空位子了
if ( this.usedSize == this.elem.length ) {
return true;
}
return false;
}
/**---------------增 加一个元素-------------*/
public void add ( int pos, int data) { //pos位置 插入data
if ( isFull() ) { //判断是否满了,满了数组长度要扩容二倍
//扩容
this.elem = Arrays.copyOf(this.elem,2*this.elem.length) ; //新的elem指向扩容的2倍数组
} //指向新的数组 拷贝原数的数组,新数组长度是原理二倍
//数组最后一个元素紧邻的第一个空位置是可以插的 ,第二个往后不可以,没有前驱
if ( pos > this.usedSize || pos < 0 ) { //检查pos位置是否越界
return;
}
for (int i = usedSize-1; i >= pos ; i--) { //i位置为最后一个元素位置,通过不断向左移动,把i的值赋给i+1
this.elem[i+1] = this.elem[i]; //直到i的位置越过pos
}
this.elem[pos] = data; //插入
this.usedSize++; //元素个数加一
}
/**--------------删 除一个元素------------------*/
public void remove ( int toRemove ) {
int index= search( toRemove); //调用searc方法找到下标
if ( index == -1 ) { //判断一下这个数字是否存在
System.out.println("没有要删除的数字");
return;
}
for (int i = index; i <this.usedSize-1 ; i++) { //从让i从删除位子一直往前走, 直到 i < this.usedSize-1 ( 4 个元素 i 到倒数第二个就停下)
this.elem[i]= this.elem[i+1]; //更新i[ i ]= [ i+ 1 ] 让后一个给值给前一个
}
this.usedSize--; //this.usedSize - - ( 不减减,a [ 3 ] = 12依然在,因为只是赋值,减减才会真正删除最后一个 )
}
//------------------------------------------------------------
private boolean isEmpty () { //提供一个方法给getPos来判断数组是否为空
return this.usedSize == 0;//不能指为null,null是没有分配内存,反例new一个什么都放,是空数组,但是不为null
}
/**--------------------查 给下标求元素----------*/
public int getPos ( int pos ) {
if( isEmpty()) { // 判断顺序表是否为空
throw new RuntimeException("顺序表为空"); //空就手动抛出一个异常,以为如果返回-1,元素是可能有-1的 不合理
}
if ( pos < 0 || pos >= this.usedSize ) { //判断pos的位置是否越界 6个元素 拿不到6下标,所以pos>=
throw new RuntimeException("pos越界,位置不合法");
}
return this.elem[pos];
}
/**----------改 修改元素-----------------------*/
public void setPos (int pos ,int value) {
if ( pos < 0 || pos >= this.usedSize ) { //判断pos的位置是否越界 6个元素 拿不到6下标,所以pos>=
throw new RuntimeException("pos越界,位置不合法");
}
this.elem[pos] = value; //直接value赋值
}
/**-------------------查 是否包含某个元素---------------*/
public boolean contains(int toFind) {
for (int i = 0; i <this.usedSize ; i++) {
if ( toFind == this.elem [i]) {
return true;
}
}
return false;
}
/**-----------------查 给元素求位置------------*/
public int search (int toFind) {
for (int i = 0; i <this.usedSize ; i++) {
if ( toFind == this.elem [i]) {
return i ;
}
}
return -1;
}
/**----------打印顺序表----------*/
public void display() {
for (int i = 0; i <this.usedSize ; i++) {
System.out.print(this.elem[i]+ " ");
}
}
/**------获取顺序表的长度---------*/
public int size ( ) {
return this.usedSize;
}
/**-----清空顺序表-----------*/
public void clear () {
this.usedSize =0; //因为打印的时候, i的循环是从this.usedSiz判断的
}
}
总结
插入元素
- 判断数组是否满了,如果满了就需要二倍扩容
- 判断pos位置是否合法, 负数不合法 , > usedSize 不合法,因为数组最后一个元素紧邻的第一个空位置是可以插的 ,第一个往后不可以,没有前驱,比如4个元素,下摆最大到a[3],但是a[4]可以插
- 挪数据,初始值 i= usedSiez -1(4个元素,下标只有3),i从最后一位往后挪, 每次将this.elem [i+1]=this.elem[i] ,当前下标值赋给后一个下标的位置,当 i < pos 时候数据挪完了
- 插进去,将 this.elem = data
- 将数组的长度+1
删除元素 - 查找到元素下标 index
- 如果通过search方法返回的值是 -1 ,那么没有这个数字。
- 让i从删除位子一直往前走,每次将this.elem[ i ]= this.elem[ i+ 1 ],后一个值赋给前面, 直到 i < this.usedSize-1 ( 假如4 个元素 i 到倒数第二个就停下)
- this.usedSize - - ,因为不数组长度不自减,a [ 3 ] = 12依然在,因为只是赋值,减减才会真正删除最后一个
查找下标为pos的元素
- 判断顺序表是否为空,空就手动抛出异常 ,判空条件为this.usedSize == 0;判空不能指为null,null是没有分配内存,反例new一个什么都放,是空数组,但是不为null
- 手动抛出异常 throw new RuntimeException(“顺序表为空”);
- 检查pos合法性 , 负数不合法,> = usedSize 不合法 ,因为如果 6个元素 ,下标最大到5,没有6号下标
- 直接将this.elem[pos]=data,更新成功
关于this
讨论this前,我们首先要知道一个对象的产生分为几步? 如何产生?1.为对象分配内存 2.调用合适的构造方法(构造方法不止一个)。那么既然对象产生分两步,必须把两步骤完成,第二步走完之后才会产生对象,而产生对象的过程中就用this,this就不能代表当前对象,因为只完成了第一步为对象分配内存,那么此时this就代表当前对象的引用。