一、前置知识:线性表的定义:https://blog.csdn.net/jdie00/article/details/81045814
二、类定义
顺序表,就是利用顺序结构存储的线性表,在数据结构的操作上和线性表别无二致。而在存储方式上对线性表进行了限制。
顺序存储结构即在内存中用连续的存储空间来将数据存储下来,用物理上的线性关系来表示逻辑上的线性关系。
元素关系、行为定义和存储方式有了,我们要实现我们的顺序表类了。但是还有两个问题需要解决:
1.确定类中的成员变量和静态方法:两个都是要看实际需要,之后讨论
2.确定构造器:接口只能定义行为,不能定义初始化(构造器),我们还需要自行定义构造器
我认为的解决:
1.成员变量中一定要有的是Object数组,用于存储数据;书上还提到了一个用于记录大小的int变量,我们来讨论一下是否具有合理性:有些意见可能是,方便得到整个表的大小,而不是每一次都要统计;这个原因有,而且非常大。但是我认为,如果你在ArrayList中尾插null,此时的数组和没有插入是一样的,这个int变量可以处理尾插入null的情况。(让我们知道真正有多少个元素,而不是最后一个非空元素之前有多少元素!)
2.构造器...,空构造、指定容量的、指定初始化数组的、容量和数组都指定的、用其他表初始化
三、实现
不一定正确,算是笔记性质
package DataStructure.LinerList;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 第一版的ArrayList,看了一遍书写的
* @param <T>
*/
//里面的所有复制算法都可以用System.arrayCopy()方法代替
public class ArrayList1<T> implements List1<T>{
/*大小*/
private int size;
/*存储数据*/
private Object[] elementData;
public ArrayList1() {//默认构造,长度10
this.elementData = new Object[10];
}
public ArrayList1(int size) {//看起来好看,然而空间的话,还不如写开了if-else
this();
if (size > 0) {
this.elementData = new Object[size];
}
}
public ArrayList1(int size, T[] elementData) {
if (elementData != null) {//二参非法
if (size > elementData.length) {//一参大于二参长度
this.elementData = new Object[size];//创建
copy(elementData, this.elementData);//复制
} else {
this.elementData = elementData;//赋值
}
this.size = elementData.length;//不要忘了,只要更改elementData,一定对size进行核查
} else {
this.elementData = new Object[size > 0 ? size : 10];//实际上就是this(size),然而放在第一句的话,浪费空间时间
}
}
public ArrayList1(T[] elementData) {//你懂得~
this(0, elementData);
}
public ArrayList1(List1 list) {
if (list == null || list.size() == 0) {//list为空,....,或者为空/xk
elementData = new Object[10];
} else {
elementData = new Object[list.size() + (list.size() >> 1)];//运算优先级...小心一点
for (int i = 0 ; i < list.size() ; i ++) {
insert((T) list.get(i));//方便,快捷~
}
}
}
@Override
public boolean isEmpty() {//不解释
return size == 0;
}
@Override
public int size() {//不解释
return size;
}
@Override
public T get(int i) {
if (i < 0) {//非法参数
throw new IllegalArgumentException("Exception for input i:" + i);
} else if (i > size - 1) {//非法参数
throw new IllegalArgumentException("Exception for input i:" + i + " bigger than elementData.length");
}
return (T) elementData[i];
}
@Override
public void set(int i, T x) {
if (i < 0) {//非法
throw new IllegalArgumentException("Exception for input i:" + i);
} else if (i > size - 1) {//非法
throw new IllegalArgumentException("Exception for input i:" + i + " bigger than elementData.length");
}
elementData[i] = x;
}
@Override
public int insert(int i, T x) {
if (i < 0) {//头插
moveToNext(0);//将从0开始的元素向后移一位
elementData[0] = x;//赋值
size ++;//size变化
return 0;//返回插入位置
} else if (i > size - 1){//尾插
return insert(x);//尾插
}
//正常插入
moveToNext(i);//从i之后每一个向后移一位
elementData[i] = x;//赋值
size++;//size变动
return i;//返回插入位置
}
/**
* 将从index开始的数组元素向后移动一个位数
* @param index 开始位置
*/
private void moveToNext(int index) {
if (size == elementData.length) {//满容
dilatation();//扩容
}
for (int i = size - 1 /*从后向后移*/; i >= index ; i --) {
//如果从前向后移,将会使后面的每一个值都变成elementData[index]
//首次循环:elementData[size] = elementData[size - 1]
//末次循环:elementData[index + 1] = elementData[index]
elementData[i + 1] = elementData[i];//后移
}
}
//扩容
private void dilatation() {
Object[] oldElementData = elementData;//旧的
elementData = new Object[size + (size >> 1)];//新的
copy(oldElementData, elementData);//复制,将旧的复制到新的中,旧的一定是满容的
}
//复制,可以用System.arrayCopy方法替代
private void copy(Object[] old, Object[] target) {
for (int i = 0 ; i < old.length ; i ++)
target[i] = old[i];
}
@Override
public int insert(T x) {//尾插
if (size == elementData.length)//满容
dilatation();//扩容
elementData[size] = x;
size ++;
return size - 1;//因为size自增,之前的位置是size - 1
}
@Override
public T remove(int i) {
if (i < 0)
throw new IllegalArgumentException("for input i:" + i);
if (i >= size)
throw new IllegalArgumentException("for input i:" + i + " exceed the size-1");
//正常
T result = (T)elementData[i];//暂存,否则将覆盖
moveToPre(i);//i之后的元素向前移,将i覆盖
size --;//size变动
return result;
}
private void moveToPre(int index) {
for (int i = index + 1 ; i < size ; i ++)
//从前向前移,若从后向前,则index之后元素值都为elementData[size - 1]
//首次循环:elementData[index] = elementData[index + 1]
//末次循环:element[size - 2] = elementData[size - 1]
elementData[i - 1] = elementData[i];
}
@Override
public void clear() {//不解释,size是一个逻辑变量
size = 0;
}
@Override
public int search(T key) {//这个就基本上和java源码实现差不多了
if (key == null) {
for (int i = 0 ; i < size ; i ++) {
if (elementData[i] == null)
return i;
}
} else {
for (int i = 0 ; i < size ; i ++) {
if (key.equals(elementData[i]))
return i;
}
}
return -1;
}
@Override
public int lastSearch(T key) {//不解释
if (key == null) {
for (int i = size - 1 ; i >= 0 ; i --) {
if (elementData[i] == null)
return i;
}
} else {
for (int i = size - 1 ; i >= 0 ; i --) {
if (key.equals(elementData[i]))
return i;
}
}
return -1;
}
@Override
public int search(T key, int count) {//不解释
int num = 0;
if (key == null) {
for (int i = 0 ; i < size ; i ++) {
if (elementData[i] == null){
num++;
if (num == count)
return i;
}
}
} else {
for (int i = 0 ; i < size ; i ++) {
if (key.equals(elementData[i])) {
num++;
if (num == count)
return i;
}
}
}
return -1;
}
@Override
public boolean contains(T key) {//不解释
return search(key) != -1;
}
@Override
public int insertDifferent(T x) {
if (!contains(x)) {//若不含
return insert(x);
}
return -1;
}
@Override
public int insertDifferent(int i, T x) {
if (!contains(x)) {
return insert(i, x);
}
return -1;
}
@Override
public T remove(T key) {//外层if判断不解释。内层直接调用remove(i)
if (key == null) {
for (int i = 0 ; i < size ; i ++) {
if (elementData[i] == null) {
return remove(i);
}
}
} else {
for (int i = 0 ; i < size ; i ++) {
if (key.equals(elementData[i])) {
return remove(i);
}
}
}
throw new RuntimeException("no such key:" + key);
}
@Override
public T remove(int count, T key) {//同上
int num = 0;
if (key == null) {
for (int i = 0 ; i < size ; i ++) {
if (elementData[i] == null) {
num ++;
if (num == count) {
return remove(i);
}
}
}
} else {
for (int i = 0 ; i < size ; i ++) {
if (key.equals(elementData[i])) {
num ++;
if (num == count) {
return remove(i);
}
}
}
}
throw new RuntimeException("no such key:" + key);
}
@Override
public void addAll(List1 list) {//不解释
for (int i = 0 ; i < list.size() ; i ++)
insert((T)list.get(i));
}
@Override
public List1 removeAll(List1 list) {
List1 result = new ArrayList1();
int temp = -1;
for (int i = 0 ; i < list.size() ; i ++) {
// for (int j = 0 ; j < size ; j ++) {
// if (elementData[j] == null && list.get(i) == null) {
// result.insert(remove(j));
// } else if (elementData[j] != null && elementData[j].equals(list.get(i))) {
// result.insert(remove(j));
// }
// }
temp = search((T) list.get(i));//查询,第一次出现的值
if (temp != -1)
result.insert(remove(i));//将出现的值移除,并添加在结果中
}
return result;
}
@Override
public String toString() {//线程不安全,不使用StringBuffer
StringBuilder stringBuilder = new StringBuilder(this.getClass().getName());
stringBuilder.append(":[");
if (size != 0) {
for (int i = 0 ; i < size - 1 ; i ++)
stringBuilder.append(get(i) + ", ");
stringBuilder.append(get(size - 1));
}
stringBuilder.append("]");
return stringBuilder.toString();
}
}