按逻辑结构分为:
线性结构,树形结构,图形结构;
线性结构中的元素之间是一对一的关系;
树形结构中的元素存在一种一对多的关系;
图形结构中的元素是多对多的关系;
树形存储结构应用场景:Hash,二分查找,文件目录遍历等等。
顺序存储机构和链式存储机构;
每一种逻辑结构都可以有顺序存储结构和链式存储机构两种存储实现。
对于顺序存储结构:它是开辟了一组连续的空间存储数据,通常用数组来实现,数组中空间本身是连续的,保证了数据之间的关系。
而我们的链式存储结构:它是开辟一组随机的空间存储数据,通常用节点来实现,节点不仅存储数据,还要存储下一个节点的位置来保证数据之间的关系。
1.数据之间的关系,将离散的数据规整划一;
2.如何将这个关系具体实现并且存储在计算机中;
3.基于关系之上对数据的具体操作,例如基本的增删改查等。
4.数据结构具体在什么场景使用。
所谓算法就是特定问题解决步骤的描述,分析问题,并且一步步求解得到结果,我们将这一系列的步骤称为算法。
设计算法要提高程序运行的效率,这里效率大多指算法的执行时间
那么该如何去度量一个算法的执行时间呢?有以下两种方法:
1.事后统计法
2.事前分析法
顾名思义;就是将程序和数据设计完成,通过计算机计时器进行时间的统计加一比较,表明算法的效率。
但是缺点是必须事先编好程序,再进行运行,如果程序处理的数据量较大,则会花费大量的时间和精力
时间的比较主要依赖于计算机硬件和软件环境
算法的测试数据设计困难,在数据量较小的时候,不管什么算法其运行时间都是很微小的,相差几乎为零。如果数据量大了,算法的优越性就出来了,但是这样又会耗费时间。
在计算机程序编制前,依据统计方法对算法进行估算。
1.算法采用的策略、方法(算法好坏的根本因素)
2.编译产生的代码质量(编程语言如C就比Java代码质量好)
3.问题的输入规模
4.机器执行指令的速度 (硬件)
定义
在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度。简称时间复杂度。其中f(n)是问题规模n的某个函数。
注意:算法时间复杂度主要探究的是问题输入规模N的数量级
不是算法的具体执行次数
常数阶O(1):
例如我们的打印输出,变量声明及赋值等int a = 5;
线性阶O(n):
与问题输入规模有关的,主要是一层循环的代码,多个一层循环可以并列但不能包含。
int N = 10;
for (int i = 1; i <= N; i++) {
System.out.println(i);
}
for (int i = 1; i <= N; i++) {
System.out.println(i);
}
线性阶O(n+m):
与线性阶O(n)相比,我们只是拥有两种数据的输入规模而已
int n= 10;
int m = 20;
for (int i = 1; i <= n; i++) {
System.out.println(i);
}
for (int i = 1; i <= m; i++) {
System.out.println(i);
}
平方阶O(n^2)
它也是与输入规模有关,就是双层for循环
int N = 10;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
System.out.println(i + j);
}
}
平方阶O(nm)
也是双层for循环,只是在两层,一层是遍历n次,一层是m次,它和o(n)比较相似,它的增长曲线稍微能缓和一些。
对数阶O(logn)
与问题输入规模有关的,主要是一层循环迭代或递归的代码。
int count = 1;
int n = 100000;
while (count < n)
count = count * 2;
线性表的顺序存储机构是指用一段地址连续的存储单元依次存储线性表的数据元素。
所谓线性表就是0个或者多个数据元素的有限序列;在数学上定义为(ai-1,ai,…an),ai-1称为ai的直接前驱元素,ai是ai-1的直接后继元素,在i=1…n-1之间,ai都有且只有一个直接后继,在i=2…n之间ai有且只有一个直接前驱元素。线性表的元素个数n(n>=0)定义其长度,n=0时,叫做空表。
1.内置数组的特点:
(1).数组的长度只要确定就不可更改;
(2).数组它只能存储同一种类型的数据;
(3).数组中每个存储空间的地址是连续并且相等的。
(4).它访问元素的方式是通过下标。
2 .内置数组的缺点:
(1).由于数组长度一旦定义就不可更改,当容量不够时如何处理。
(2).通过角标访问元素效率很高,但是增删效率比较低。
(3).数组只有一个length属性,没有其他方法。
由于线性结构可以用顺序存储机构和链式存储结构实现,那么我们将两者对于线性结构共同操作进行抽取,定义出线性结构的接口List。
package ifce;
import java.util.Comparator;
public interface List<E> extends Iterable<E> {
//在表尾添加一个元素
public void add(E element);
//在指定角标处添加元素
public void add(int index,E element);
//删除元素
public void remove(E element);
//删除指定角标处的元素
public E remove(int index);
//获取指定角标处的元素
public E get(int index);
//修改指定角标的元素为element
public E set(int index,E element);
//获取线性表中元素个数
public int size();
//获取元素element第一次出现的角标;
public int indexOf( E element);
//判断线性表中是否包含元素element
public boolean contains(E element);
//判空
public boolean isEmpty();
//清空线性表
public void clear();
//按照比较器的内容进行排序
public void sort(Comparator<E> c);
//获取子线性表,原线性表[fromIndex,toIndex)部分;左闭右开;
public List<E> subList(int fromIndex,int toIndex);
}
1.构造方法:带参构造函数进行初始容量设置,不符合则抛出异常;无参构造通过this(参数)调用带参即可;
package linestract;
import ifce.List;
import java.util.*;
public class ArrayList<E> implements List<E> {
private E[] data;
private