目录
一、线性表
理解:所谓的线性表,就是多个相同数据类型元素逻辑上呈直线排列,逻辑上连续。我们把这种结构称为线性表。
常见的线性表有:数组(顺序表),链表,栈,队列,字符串..
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。(物理上连续,一个元素挨着另一个元素,中间没有空隙)
二、动态数组
理解:就是在普通数组上,增加了一个可以根据元素的个数动态调整数组大小的功能。
为什么需要动态数组?
1,我们之前用的数组最大的问题就在于数组长度定长,一旦一个数组在定义时确定长度之后,使用过程中无法修改这个长度。
2,Java中提供的数组都是静态数组int[] char[] long[](定义之后没法改变长度)
所以需要我们自己定义一个类,拓展基础数组的功能。
例子
public class MyArray {
int [] data ;//存放元素仍然还是int[]
private int size;//表示当前动态数组中已经存储的元素个数
}
对于程序的设计者来说,不可能真正创建个新的数组,使用的还是Java提供的整型数组,若当前data数组已经满了,我们就给他"扩容”Arrays.copyOf(oldArr,newArrLen);=>就可以把旧数组的所有内容搬移到新数组中,新数组的长度为规定长度。
其中size和data.length的区别
size属性表示的是当前数组中有效元素的个数
data.length 表示的是整形数组长度为,此时没有存放元素
当size = data.length表示当前数组已满
三、动态数组的四大操作
3.1、增
1.1数组的增加和扩容
public class MyArray {
//存放元素仍然还是int[]
//data数组的长度自定义
private int [] data ;
//表示当前动态数组中已经存储的元素个数
private int size;
public MyArray(){
//默认开辟10个大小的整形数组长度
}
public MyArray(int initCap){//传入一个整型变量
this.data = new int[initCap];
}
/**
* 在当前数组中添加一个新元素val
* @param val
*/
public void add(int val){
data[size] = val;
size ++;
//元素在添加的过程中有可能把当前数组占满了
//当size=data.length数组已满
if(size == data.length){
grow();
}
}
/**
* 外部使用者对MyArray中有int[]数组,以及数组的扩容对外部是不可见的
* 执行扩容方法
*/
private void grow(){
//copyof方法返回扩容后的新数组
this.data = Arrays.copyOf(data,data.length * 2);
}
}
2、add(int index,int val): 在数组的index位置插入一个新元素val,新元素插入后的索引为index
add(1,6)=>在索引为1的位置插入新元素6
需要把这个位置之后的所有元素向后移动一个单位,空出index索引位置的元索
注意
先从最后一个有效元素开始向后搬移
然后再插入6
代码
//从当前最后一个有效元素开始向后移动元素,空出index的位置
for (int i = size - 1; i >= index ; i--) {
data[i + 1] = data[i];
}
data[index] = val;
size ++;
//判断数组是否满了
if (size == data.length){
grow();
}
}
3.2、查:
1.1 public int getByValue(int val):查询当前动态数组中第一个值为val的元素索引
1.2public int get(int index):查询当前动态数组中索引为index的元素值
1.3 public boolean contains(int val):查询当前动态数组中是否包含值为val的元素,若存在返回true,否则返回false
代码
public int get(int index) {
// 1.判断index的合法性
// size对应有效元素的下一个位置
if (index < 0 || index >= size) {
System.err.println("get index illegal!");
return -1;
}
return data[index];
}
public boolean contains(int val) {
int index = getByValue(val);
return index != -1;
}
public int getByValue(int val) {
// 遍历当前的动态数组
for (int i = 0; i < size; i++) {
if (data[i] == val) {
return i;
}
}
// 还没找到val,不存在
return -1;
}
3.3、改
1.1 public int set(int index,int newVal):修改index位置的元素为新的值newVal,返回修改前的值
1.2 public boolean set(int oldValint newVal):修改第一个值为oldVal的元素,更改为新的值newVal,返回是否修改成功
代码1.1
public int set(int index,int newVal) {
if (index < 0 || index >= size) {
System.err.println("set index illegal!");
return -1;
}
int oldVal = data[index];
data[index] = newVal;
return oldVal;
}
1.2
public boolean setValue(int oldVal,int newVal) {
int index = getByValue(oldVal);
if (index != -1) {
data[index] = newVal;
return true;
}
System.err.println("old value is not exist!");
return false;
}
3.4、删
1.1 public int remove(int index):删除索引为index对应的元素,返回删除前的元素值
1.2 public int removeFirst():删除数组的头元素
1.3 public int removeLast():删除数组的尾元素
1.4 public boolean removeByValueOnce(int val):删除第一个值为val的元素,返回是否删除成功
1.1
public int removeIndex(int index) {
if (index < 0 || index >= size) {
System.err.println("remove index illegal!");
return -1;
}
// 元素搬移,从index开始,后一个元素覆盖前一个元素,一直走到size - 1(最后一个有效元素)
// data[i] = data[i + 1]
// 最后一个元素向前搬移 i + 1 == size - 1 => i < size - 1
int oldVal = data[index];
for (int i = index; i < size - 1; i++) {
data[i] = data[i + 1];
}
size --;
return oldVal;
}
1.2
public int removeFirst() {
return removeIndex(0);
}
1.3
public int removeLast() {
return removeIndex(size - 1);
}
1.4
public boolean removeByValueOnce(int val) {
for (int i = 0; i < size; i++) {
if (data[i] == val) {
// 此时i就是第一个值为val的元素
removeIndex(i);
return true;
}
}
return false;
}