/*
数组实现可扩容线性表
*/
class MyArrayListTest {
public static void main(String[] args) {
MyArrayList<String> arrayList = new MyArrayList<>(3);
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
// System.out.println(arrayList.contains("a"));
// arrayList.remove("d");
// arrayList.insert(0 ,"e");
arrayList.remove(0);
System.out.println(arrayList);
}
}
//数组线性表类
public class MyArrayList<T> {
//底层数组
Object[] arr;
//元素数量
int size;
//数组定义的最大长度
static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;
public MyArrayList() {
//默认构造长度10
this.arr = new Object[10];
}
public MyArrayList(int initCapacity) {
if (initCapacity < 1 || initCapacity > MAX_CAPACITY) throw new IllegalArgumentException("param is illegal");
this.arr = new Object[initCapacity];
}
/**
* 判断表是否为空
*
* @return true 空
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 往线性表中尾部添加元素的方法
*
* @param t 要添加的元素
* @return true 成功
*/
public boolean add(T t) {
//添加的元素不能为空
if (t == null) throw new IllegalArgumentException("param is null");
//如果数组满了,扩容得到新数组
if (size == arr.length) {
int newLen = getLen();
grow(newLen);
}
//到这里说明底层数组扩容成功
arr[size++] = t;
return true;
}
/**
* 判断表中是否包含某一元素,并返回元素下标
* @param t
* @return 返回下标,-1代表元素不存在
*/
public int contains(T t) {
//查询的元素不能为null
if (t == null) throw new IllegalArgumentException("param is null");
int tag = -1;
//表为空,直接返回-1
if (isEmpty()) return tag;
//遍历,找到了就返回对应元素的下标
for (int i = 0; i < size; i++) {
if (arr[i].equals(t)) {
tag = i;
break;
}
}
return tag;
}
/**
* 删除表中某一个元素
*
* @param t 要删除的元素
* @return true 删除成功
*/
public boolean remove(T t) {
//删除的元素不能为null
if (t == null) throw new IllegalArgumentException("param is null");
//表为空,抛出异常
if (isEmpty()) throw new RuntimeException("List is empty");
//遍历查找元素/可以用contains方法
int tag = -1;
for (int i = 0; i < size; i++) {
if (arr[i].equals(t)) {
tag = i;
break;
}
}
//没找到元素,返回false
if (tag == -1) return false;
//从要删除的元素处开始遍历,将后面所有的数据往前挪一位,最后一位数据不用考虑再赋值
for (int i = tag; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
//元素长度减1
size--;
return true;
}
/**
* 根据数组下标插入元素的方法
*
* @param index 要插入元素的下标
* @param t 要插入的元素
* @return true 插入成功
*/
public boolean insert(int index,T t) {
//插入元素的下标只能是[0,size]
if(index<0||index>size) throw new IllegalArgumentException("param is illegal");
//如果是从数组尾部插入元素,调用前面的方法
if(index == size){
add(t);
return true;
}
//如果当前数组元素已经满了,先扩容
if(size == arr.length){
int newLen = getLen();
grow(newLen);
}
//进行插入操作,先将目标下标元素及其后面元素后移,再赋值,从后往前操作
for (int i = size;i>index; i--){
arr[i] = arr[i-1];
}
arr[index] = t;
size++;
return true;
}
/**
*根据指定下标删除元素
* @param index
* @return
*/
public T remove(int index){
//插入元素的下标只能是[0,size)
if(index<0||index>size-1) throw new IllegalArgumentException("param is illegal");
//将对应下标的元素的后面元素全部前移,最后一个元素不用操作
T value = (T)arr[index];
for (int i = index;i<size-1;i++){
arr[i]=arr[i+1];
}
size--;
return value;
}
/**
* 数组扩容的私有方法
*
* @param newLen :扩容后数组的长度
*/
private void grow(int newLen) {
//创建新数组
Object[] objects = new Object[newLen];
//转移原来数组的元素到新数组上
for (int i = 0; i < arr.length; i++) {
objects[i] = arr[i];
}
//让新数组成为当前底层数组
arr = objects;
}
/**
* 获取扩容数组长度的私有方法
*
* @return 新数组的长度
*/
private int getLen() {
int oldLen = arr.length;
//如果扩容前数组长度已经为最大值,抛出异常
if (oldLen == MAX_CAPACITY) throw new RuntimeException("Arr is fullMax");
//新数组扩容后的长度等于原来数组长度的两倍
int newLen = (oldLen << 1);
//如果扩容后长度参数溢出或者大于最大数组长度,就让数组扩容为最大长度
if (newLen < 0 || newLen > MAX_CAPACITY) {
newLen = MAX_CAPACITY;
}
return newLen;
}
@Override
public String toString() {
//打印线性表时只打印有效元素,如:[],[a,b,c]
if (size == 0) return "[]";
StringBuilder s = new StringBuilder();
s.append("[");
for (int i = 0; i < size; i++) {
s.append(arr[i] + ",");
}
//去掉最后的逗号
String str = s.toString().substring(0, s.length() - 1);
return str + "]";
}
}
Java实现:数组实现可扩容线性表
最新推荐文章于 2022-12-15 15:39:21 发布
本文展示了如何使用Java实现一个基于数组的可扩容线性表`MyArrayList`。类包括了添加、删除、查找和插入等基本操作,并通过动态扩容确保线性表的容量。代码详细注释解释了每个方法的功能和实现逻辑。
摘要由CSDN通过智能技术生成