学习数据结构Day2

以前学习过了数组的静态实现方法,同时将数组的全部有可能实现的方法都统一实现了一遍,以后支持了泛型的相关java

 

概念,接下来就是如何对数组进行扩容的操做也就是实现动态数组。算法

 

private void resize(int newcapacity){  E[] newdata = (E[]) new Object[newcapacity];  for (int i = 0; i < newcapacity; i++) {  newdata[i] = data[i];  }  data = newdata;  }

 

在此处,咱们写了一个关于resize的操做,其原理就是对就数组容量的扩容,扩容其原来的二倍。数组

 

同理,咱们还能够进行对删除操做的优化,若是删完数据后,数组的容量有一半可能是不用的空间,咱们就能够进行删学习

 

掉一半的操做。优化

 

 public E remove(int index) {  if (index < 0 || index > size) {  throw new IllegalArgumentException("require index >= 0 and index > size!");  }  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 / 2){  resize(data.length/2);  }  return ret;  }

 

注意代码的第11,12行 进行了优化。ui

 

至此,咱们就把数组的动态的实现整理完毕了。atom

 

接下来,我简单的描述一下时间复杂度的分析。spa

 

O(1) O(n) O(lgn) O(nlogn) O(n^2)3d

 

大O是描述的算法运行时间和输入数据之间的关系。code

 

O(n)中 n表示的是元素的个数  算法和n呈线性关系。

 

那么O(n^2)则表示的是 成二次方的关系。

 

针对于不一样的算法,咱们须要针对不一样的变量进行变量控制,来肯定这个算法是不是最快的。

 

image.png

 

同理,删除操做也是相应的时间复杂度。

 

在看完时间复杂度以后,咱们引入一个resize的时间复杂度分析。

 

对于添加的时间复杂度分析,咱们能够看到,resize的时间复杂度分析是O(n),那么咱们按最坏时间复杂度分析,

 

咱们就将添加的时间复杂度算为O(n),可是并非每次添加元素咱们都要resize的 ,因此假设capacity = n,n+1次

 

addLast,触发resize,总共进行2n+1次基本操做平均,每次addLast操做,进行两次基本操做。这样均摊计算,时间复

 

杂度是O(1)的!,同理removeLast()的时间复杂度也是O(1)的,可是,若是咱们综合去看待这个方法时,就会出现问

 

题。在填满数据后,我调用addLast()方法时,须要扩容,紧接着我又调用removeLast()方法,又开始缩容,一直这

 

样下去,时间复杂度一直是O(n),这样就产生了时间复杂度震荡。出现的缘由是:removeLast()时,过于着急,咱们

 

可让他懒惰一些,也就是说能够在等到size  ==  capacity/4时,才将capacity减半。

 

image.png

 

这样,咱们本身写完的动态数组就完成了!

相关文章
相关标签/搜索