数组基础
关于数组,综合来讲就是增删改查!
8种基本数据类型:boolean、byte、char、short、int、long、float、double
- int[] arr = new int[10]; //动态初始化数组
- int[] a = { 1, 2, 3 };// 静态初始化基本类型数组;
- Man[] mans = {new Man(1,1), new Man(2,2)};// 静态初始化引用类型数组;
代码实现
Array实现类
package cn.data.structure;
public class Array<E> {//声明泛型E
public static void main(String[] args) {
}
private E[] data;//泛型
private int size;
//构造函数,传入数组的容量capacity构造Array
public Array(int capacity) {
data = (E[])new Object[capacity];
size = 0;
}
//无参数构造函数,默认数组容量为capacity=10
public Array() {
this(10);
}
//获取数组中的元素个数
public int getSize() {
return size;
}
//获取数组的容量
public int getCapacity() {
return data.length;
}
//返回数组是否为空
public boolean isEmpty() {
return size == 0;
}
//向指定位置index添加元素e
public void add(int index,E e) {
if(index<0||index>size) {
throw new IllegalArgumentException("Add failed.Require index>=0 and index <=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++;
}
//向所有元素后添加一个新元素
public void addLast(E e) {
add(size,e);
}
//向所有元素前添加一个新元素
public void addFirst(E e) {
add(0,e);
}
//获取index索引位置的元素
E get(int index) {
if(index<0||index>size) {
throw new IllegalArgumentException("Get failed.Index is illegal.");
}
return data[index];
}
//修改index索引位置的元素为e
void set(int index,E e ) {
if(index<0||index>size) {
throw new IllegalArgumentException("Get failed.Index is illegal.");
}
data[index] = e;
}
//查找数组中是否存在元素e
public boolean contains(E e) {
for(int i=0;i<size;i++){
if(data[i].equals(e)) {
return true;
}
}
return false;
}
//查找数组中元素e所在的索引,如果不存在元素e,则返回-1
public int find(E e) {
for(int i=0;i<size;i++) {
if(data[i].equals(e)) {
return i;
}
}
return -1;
}
//从数组中删除index未知的元素,返回删除的元素
public E remove(int index) {
if(index<0||index>size) {
throw new IllegalArgumentException("Remove failed.Index is illegal.");
}
E ret = data[index];
for(int i=index+1;i<size;i++) {
data[i-1] = data[i];
}
size--;
data[size] = null;//loitering objects != memory leak
if(size==data.length/4 && data.length/2!=0) {//Lazy解决复杂度震荡,不选择size==data.length/2
resize(data.length/2);
}
return ret;
}
//从数组中删除第一个元素,返回删除的元素
public E removeFirst() {
return remove(0);
}
//从数组中删除最后一个元素,返回删除的元素
public E removeLast() {
return remove(size-1);
}
//从数组中删除元素e
public void removeElement(E e) {
int index = find(e);
if(index!=-1) {
remove(index);
}
}
@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();
}
private void resize(int newCapacity) {
E[] newData = (E[])new Object[newCapacity];
for(int i=0;i<size;i++) {
newData[i] = data[i];
}
data = newData;
}
}
两个测试类:
public class Student {
private String name;
private int score;
public Student(String studentName,int studentScore) {
this.name = studentName;
this.score = studentScore;
}
@Override
public String toString() {
return String.format("Student(name: %s, score: %d)", name, score);
}
public static void main(String[] args) {
Array<Student> arr = new Array<>();
arr.addLast(new Student("Alice",100));
arr.addLast(new Student("Bob",66));
arr.addLast(new Student("Charlie",88));
System.out.println(arr);
}
}
public class Main {
public static void main(String[] args) {
Array<Integer> arr = new Array<>();
for(int i=0;i<10;i++) {
arr.addLast(i);
}
System.out.println(arr);
arr.add(1, 100);
System.out.println(arr);
arr.addFirst(-1);
System.out.println(arr);
//[-1,0,100,1,2,3,4,5,6,7,8,9]
arr.remove(2);
System.out.println(arr);
arr.removeElement(4);
System.out.println(arr);
arr.removeFirst();
System.out.println(arr);
}
数组的一些操作
构造数组
//构造函数,传入数组的容量capacity构造Array
向数组中添加元素
//获取数组中的元素个数
//获取数组的容量
//返回数组是否为空
//向指定位置index添加元素add(index,e)—O(n/2)=O(n)
//向所有元素后添加一个新元素addLast—O(1)
//向所有元素前添加一个新元素addFirst—O(n)
数组中查询元素和修改元素
//获取index索引位置的元素 get(index)—O(1)
//修改index索引位置的元素为e set(index,e)—O(1)
数组中包含,搜索和删除
//查找数组中是否存在元素e contain(e)—O(n)
//查找数组中元素e所在的索引,如果不存在返回-1 find(e)—O(n)
//从数组中删除index未知的元素,返回删除的元素
//从数组中删除第一个元素,返回删除的元素addFirst—O(n)
//从数组中删除最后一个元素,返回删除的元素addLast—O(1)
//从数组中删除元素e add(index,e)—O(n/2)=O(n)
数组使用泛型
使用泛型可以让数据结构可以放置任意数据类型,使用泛型只能使用类对象
不可以是基本数据类型。每个基本数据类型都有对应的包装类Boolean、Byte、Char、Short、Integer、Long、Float、Double。
Array arr = new Array<>();
动态数组
对数组进行扩容、缩容
if(size==data.length) {
resize(2*data.length);
}
E[] newData = (E[])new Object[newCapacity];
for(int i=0;i<size;i++) {
newData[i] = data[i];
}
data = newData;
简单的时间复杂度分析
O(1)、O(n)、O(lgn)、O(nlgn)、O(n^2).大O描述的是算法的运行时间和输入数据之间的关系。N是nums中的元素个数,算法和n呈线性关系。
渐进时间复杂度,n趋向于正无穷大
增:O(n) resize情况
删:O(n) resize情况
改:已知索引O(1)、未知索引O(n)
查:已知索引O(1)、未知索引O(n)
均摊复杂度和防止复杂度的震荡
均摊复杂度:resize=O(n),addLast=O(1),removeLast=O(1)
复杂度震荡:removeLast时resize过于着急(Eager)
解决方案:Lazy。当size==capacity/4时,才将capacity减半。