首先复习一下数组,数组是一组相同数据类型元素的集合,因为数组在内存中占据连续的空间,数组有能通过索引进行查询,实现快速检索的优点,应用于“索引有语义”的情况,同时存在一些缺点,会导致内存浪费且无法存储更多数据,插入和删除操作的效率较低。数组通常用于存储大量相同类型的数据,在实现算法方面也有应用,快速排序和二分查找算法都可以通过数组实现
数组作为一种固定大小的数据结构,它在初始化时长度就已经确定,动态数组ArrayList(也叫做列表)就可以完成数据的增删查改,那如何实现动态数组呢,先要定义一个数组,接着需要一个计数器size计算这个数组有多少个数据,接下来自己实现插入、移除和获取
public class MArrList {
//初始数组
public int[] arr = new int[0];
public int size;
//在末尾添加
public void add(int data){
int[] nArr = new int[arr.length+1];
nArr[arr.length] = data;
for(int i=0;i<arr.length;i++){
nArr[i] = arr[i];
}
arr = nArr; //更新对象头 因为原数组已经没有变量接收,更新后原数组内存被释放
size++;
}
//在指定位置插入
public void add(int index,int data){
int[] nArr = new int[arr.length+1];
nArr[index] = data;
for(int i=0;i<index;i++){
nArr[i] = arr[i];
}
for(int i=index+1;i<arr.length+1;i++){
nArr[i] = arr[i-1];
}
arr = nArr;
size++;
}
//在指定位置移除
public int remove(int index){
int[] nArr = new int[arr.length-1];
for(int i=0;i<index;i++){
nArr[i] = arr[i];
}
for(int i=index;i<arr.length-1;i++){
nArr[i] = arr[i+1];
}
arr = nArr;
size--;
return 0; //返回被移除数据
}
//移除指定数据
public boolean removes(int data){
int[] nArr = new int[arr.length-1];
int index = -1;
for(int i=0;i<arr.length;i++){
if(arr[i] == data){
index = i;
break;
}
}
if(index == -1) return false;
for(int i=0;i<index;i++)
nArr[i] = arr[i];
for(int i=index;i<arr.length-1;i++){
nArr[i] = arr[i+1];
}
arr = nArr;
size--;
return true;
}
//获取数据
public int get(int index){
//判断index 是否在超出范围
if(index<0 || index>size){
System.out.println("");
}
return arr[index];
}
//长度
public int size(){
return size;
}
//添加主函数进行测试
public static void main(String[] args) {
int[] a = {8,4,6,3,1};
MArrList list = new MArrList();
for(int i=0;i<a.length;i++){
list.add(a[i]);
}
// list.remove(3);
// list.removes(8);
list.add(1,0);
for(int j=0;j<list.size();j++){
System.out.println(list.get(j));
}
}
}
验证结果:
1.在指定位置插入
2.在指定位置移除
3.移除指定数据
此时已经实现基本的插入、移除和获取方法,但每个方法之内都需要创建一个新数组,大大增加了时间复杂度,使运行效率降低,那如何进行优化呢,这里可以定义一个扩容方法,初始设置数组长度len为10,在扩容方法中判断当前数组中数据个数和数组长度是否相等,如果相等就创建一个长度为len*2的新数组,循环复制所有数据到新数组,这样插入方法只需要调用扩容方法,移除方法也不需要创建新数组,从尾部到指定位置从后往前遍历,把这部分数据往前挪一个位置,具体实现如下:
public class ArrayList {
//初始数组
private Object[] arr;
private int size = 0;
private static int len = 10;
//构造方法初始化初始数组长度
public ArrayList(int len){
arr = new Object[len];
}
public ArrayList(){
this(len);
}
//添加
public void add(Object data){
dilatation();
//保存数据
arr[size] = data;
size++;
}
//扩容数组
private void dilatation(){
if(size == arr.length){
Object[] nArr = new Object[arr.length*2];
for(int i=0;i<arr.length;i++){
nArr[i] = arr[i];
}
arr = nArr;
}
}
//插入
public void add(int index,Object data){
dilatation();
if(index<0||index>size){
System.out.println("位置不合法!");
}else{
for(int i=size-1;i>=index;i--){ //注意这里size-1,执行for循环时size已经是size++后的值,但数据还没插入,所以按原数组的size值
arr[i+1] = arr[i];
}
arr[index] = data;
size++;
}
}
//移除
public Object remove(int index){
if(index<0||index>size){
System.out.println("位置不合法!");
}else{
for(int i=index;i<=size-1;i++){
arr[i] = arr[i+1];
}
}
size--;
return null;
}
//移除指定数据
public boolean removes(Object data){
int index = -1;
for(int i=0;i<size;i++){
if(arr[i] == data){
index = i;
break;
}
}
if(index == -1) return false;
for(int i=index;i<size-1;i++){
arr[i] = arr[i+1];
}
size--;
return true;
}
//获取
public Object get(int index){
if(index < 0 || index >= size){
System.out.println("下标越界!!!");
return null;
}
return arr[index];
}
//长度
public int size(){
return size;
}
//主函数
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
// list.add(2,"d");
// list.remove(2);
list.removes("c");
list.add(10);
for(int i=0;i<list.size();i++){
System.out.print(list.get(i)+" ");
}
}
}