1、数据结构基础
数据结构研究的是数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据或者修改数据。
数据结构的分类
课程设置
2、数组
数组之所以可以支持foreach的遍历,是因为数组具有 可遍历/可迭代 的能力。
1) 数组最大的优点:快速查询。scores[2]
2) 数组最好应用于“索引有语意”的情况,比如scores[2],就表示我们想要查询第二个人的成绩。但并非所有有语意的索引都适用于数组,身份证号:110103198512166666,如果设置为有语意的数组,开辟的空间太大造成浪费。数组也可以处理“索引没有语意”的情况,我们在这一章,主要处理“索引没有语意”的情况数组的使用。
3) 索引没有语意,如何表示没有元素?如何添加元素?如何删除元素?这些功能java数组(静态数组)并没有提供给我们,因此我们需要基于java的数组,二次封装属于我们自己的数组类(动态数组),添加这些功能。
大O阶描述时间复杂度
大O描述的是算法的运行时间和输入数据之间的关系。对于循环结构代码,我们可以使用问题规模n与循环内O(1)复杂度的代码执行的次数来表示时间复杂度。既循环结构代码的时间复杂度可以通过复杂度为O(1)的代码执行次数随n的变化规律函数来计算。(具体参考《大话数据结构》以及视频)
大O阶:渐进时间复杂度,描述n趋近于无穷的情况。
数组便于修改和查找,不便于增加和删除。
均摊时间复杂度以及防止复杂度的震荡
如果我们一直使用addLast()添加元素,它的时间复杂度为O(1),但是由于要修改容量resize(),resize()的时间复杂度为O(n),按照考虑最坏情况的规则,我们将时间复杂度算为O(n)。
但是考虑到并不是每一次addLast()都要扩容,这种按照最坏情况考虑的方式不太合适。(见视频9-2.10分析)
假设capacity=n,n+1次addLast,触发resize(执行n次元素赋值),总共进行2n+1次基本操作。平均,每次addLast操作,进行2次基本操作。平均,每次addLast操作,进行2次基本操作这样均摊计算,addLast()时间复杂度是O(1)的!
在这个例子里,这样均摊计算,比计算最坏情况有意义,这是因为,最坏的情况不会每次都出现。这种计算复杂度的方法,称之为均摊复杂度。
在实际工程过程中,y一个相对比较耗时的操作,如果我们可以保证它不会每次都触发,这个比较耗时的操作的时间可以分摊到其他的操作中。
同理,我们看removeLast操作,均摊复杂度也为O(1)。
复杂度的震荡(视频9-6.10)。
但是,当我们同时看addLast和removeLast操作,存在一种情况,每一次增加删除的操作都会耗费O(n)的复杂度,而实际上大部分情况下addLast和removeLast操作放入均摊复杂度都是O(1),这就是复杂度的震荡。
出现问题的原因:removeLast 时 resize过于着急(Eager)。当我们既减少元素个数为数组容积的1/2的时候,我们马上把当前的容积缩容成为1/2(O(n)),此时,我们数组中元素个数与容积是相等的,这种情况下,再添加一个元素就会马上进行O(n)复杂度的扩容。
解决方案:lazy方式——我们增加元素容积不够用的时候,必然要进行O(n)的扩容,但是此时再删除一个元素,数组元素个数为容积的1/2,先不急着缩容,而是等到数组元素个数为容积的1/4的时候再进行缩容,而且只缩容为数组原先容量的1/2,此时数组还有一半的空间可以存储数据,再增加也不需要马上扩容。
策略:当size==capacity/4时,才将capacity减半。
我们自己创建一个新的数组,这个数据基于java给我们提供的数组的功能,封装了新的功能——添加,删除,查询,搜索、插入、使用泛型,动态数组(数组容量自动变化)等功能。代码如下:(测试见视频与项目ArrayTest)
package com.lkj;
public class Array<E>
{
private E[] data;//数组容量capacity就是数组的length:data.length
private int size;//数组中有效元素的个数
//初始化数组的构造函数
public Array(int capacity)
{
//初始化数组容量为capacity,数组中有效元素个数为0
// data = new E[capacity];
/**
* 注意,java不支持直接:new E[capacity] 这样new一个E泛型类型的数组。
* 我们必须先new一个Object类型的数组,然后再将其转换为E类型的数组
*/
data = (E[])new Object[capacity];//注意,是转换为E类型的数组:E[] , 而不是转换为E类型
size = 0;
}
// 无参数的构造函数,如果用户不指定,默认数组的容量capacity=10
public Array