数组的增删改查
数组中增删查改较简单,不做赘述。
使用泛型
让我们的数据结构可以放置“任何”数据类型。
不可以是基本数据类型,只能是类对象(以Java为例)
基本数据类型:boolean,byte,char,short,int,long,float,double
每个基本数据类型都有对应的包装类。
包装类:Boolean,Byte,Char,Short,Int,Long,Float,Double
public class Array<Element> { //Element是Array一种数据类型名字,自定义
private Element[] data;//创建Element数据类型的一个data数组
// 构造函数,传入数组的容量capacity构造Array
public Array(int capacity){
data = (Element[])new Object[capacity];//指定new 一个Element类型的数组,并传入容量
}
//
public static void main(String[] args) {
Array<Integer> arr = new Array<>(20);// 使用Array类,申明一个整型的arr对象
Array<Student> arr1 = new Array<>(); //使用Array类,申明一个Student的arr1对象,其中student是一个类
})
动态数组
// 将数组空间的容量变成newCapacity大小
private void resize(int newCapacity){
Element[] newData = (Element[])new Object[newCapacity];//重新new一个ELement类型的数组
for(int i = 0 ; i < size ; i ++)
newData[i] = data[i];//将data中值赋值给新数组
data = newData;//再重新赋值给data数组
}
简单的复杂度分析
我们常见一些时间复杂度表示O(n)、O(n^2)、O(lgn)…等等
简单的说O表示的是算法的运行时间和输入数据之间的关系。
eg:
public static int sum (int[] nums){
int sum =0;
for (int num:nums)sum+=num;
return sum ;
}
//O(n)是时间复杂度,n是nums中元素的个数,算法和n呈线性关系
为什么要用O,叫做O(n)??,忽略常数,实际时间T=c1*n+c2
1、T=2*n+2 O(n)
2、T=2000*n+10000 O(n)
3、T=1*n*n+0 O(n^2)
性能的好坏算法的选择取决于数据的多少。并不代表3永远比2好,或者2比3好。取决于n的数据趋势。
均摊复杂度和防止复杂度的震荡
resize O(n)
假设当前capacity =8,并且每一次添加操作都向数组尾部添加一个元素,当数组容量达到8时,执行resize函数进行扩容并向数组中添加一个元素
即 8+8+1
9次添加操作,出发resize,总共进行了17次基本操作。
平均,每次添加操作,进行了2次基本操作。
同理:假设capacity =n,n+1次添加操作,触发resize,总共进行了2n+1次基本操作
平均,每次添加操作,进行2次基本操作。这样均摊计算下来,时间复杂度是O(1)的!!
在这个例子中,这样均摊计算,比计算最坏情况有意义。这就是均摊复杂度!!
同理,我们执行在尾部移除一个元素,时间复杂度也是这样。但当我们同时执行添加和删除操作,他们会频繁重复执行O(n)。所以我们应该当移除时判断不会频繁执行移除操作。
if(size == data.length / 4 && data.length / 2 != 0)
resize(data.length / 2);