Java实现数据结构之【动态数组】
数组
数组是学习编程语言时较先接触到的一种数据结构,本章基于java的静态数组实现动态数组,并进行简单的复杂度分析
public class array<e> { private int size; private object[] data; public array(int capacity) { size = 0; data = new object[capacity]; } public array() { this(10); } public int getsize() { return size; } public int getcapacity() { return data.length; } public boolean isempty() { return size == 0; } public void addlast(e e) { add(size, e); } public void addfirst(e e) { add(0, e); } public void add(int index, e e) { if (index < 0 || index > size) throw new illegalargumentexception("add failed,index need >=0 and <=size"); if (size == data.length) { resize(2 * data.length); } for (int i = size - 1; i >= index; i--) { data[i + 1] = data[i]; } data[index] = e; size++; } private void resize(int newcapacity) { object[] newdata = new object[newcapacity]; for (int i = 0; i < size; i++) newdata[i] = data[i]; data = newdata; } public object get(int index) { if (index < 0 || index >= size) throw new illegalargumentexception("get failed,index is illegal"); return data[index]; } public void removeelement(e e) { int index = find(e); if (index != -1) remove(index); } @suppresswarnings("unchecked") public e remove(int index) { if (index < 0 || index >= size) throw new illegalargumentexception("remove failed,index is illegal"); if (size == data.length / 4 && data.length / 2 != 0) { resize(data.length / 2); } object temp = data[index]; for (int i = index + 1; i < size; i++) { data[i - 1] = data[i]; } size--; data[size] = null; return (e) temp; } public e removefirst() { return remove(0); } public e removelast() { return remove(size - 1); } public boolean contains(e e) { for (int i = 0; i < size; i++) { if (data[i].equals(e)) return true; } return false; } public int find(e e) { for (int i = 0; i < size; i++) { if (data[i].equals(e)) return i; } return -1; } @override public string tostring() { stringbuilder res = new stringbuilder(); res.append(string.format("array: size = %d , capacity = %d\n", size, data.length)); res.append("["); for (int i = 0; i < size; i++) { res.append(data[i]); if (i != size - 1) res.append(", "); } res.append("]"); return res.tostring(); } }
简单时间复杂度分析
增:
add(e) o(n)
addlast(e) o(1)
addfirst(index,e) o(n)
取最坏的情况所以增的时间复杂度是 o(n)
删:
删除与增加同理同是 o(n)
改:
set(index,e)
已知索引的情况下是o(1),未知索引的情况下是o(n)
查:
get(index) o(1)
contains(e) o(n)
find(e) o(n)
已知索引的情况下是o(1),未知索引的情况下是o(n)
均摊复杂度分析
addlast:o(1)
当数组增加元素达到一定数量时,会调用resize方法进行扩容操作,例如:
一个容量为8的数组,当addlast调用9次时,会调用resize方法进行扩容操作,显然并不是每次addlast都会调用resize,所以说9次addlast操作会触发一次resize(给容量为8的数组扩容时,会有8次元素存入新数组的操作),总共进行了17 (9次addlast加上扩容的8次元素存入新数组的操作) 次基本操作
平均每次addlast操作,进行2 (17÷9≈2) 次基本操作
也就是说,当数组容量为n时,n+1次addlast操作会调用一次resize操作,总共2n+1次基本操作
平均每次addlast操作,进行2次基本操作
所以addlast的时间复杂度可以算是o(1)的,也就是说在均摊计算中,比计算最坏的情况有意义
removelast:与addlast同理
复杂度的震荡
当同时思考addlast和removelast操作的时候:
假如调用addlast触发resize扩容后调用removelast显然也会调用resize进行缩容,这个操作如果反复执行就会导致复杂度的震荡,所以代码中removelast方法中
if (size == data.length / 4 && data.length / 2 != 0) { resize(data.length / 2); }
并没有像addlast中那样直接让data.length/2,而是当数组内的元素等于四分之一容量的时候,才会执行缩容的操作,就可以解决复杂度的震荡
上一篇: Visual Studio Code 远程开发探秘
下一篇: day04-jQuery