数据结构与算法
10个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、调表、图、Trie 树
10个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
1.什么是数据结构
定义 操作系统中组织数据的集合
1.1 逻辑数据结构
反映数据元素之间的逻辑关系,与数据在计算机中存储的位置无关
形式:集合、线性、树形、图
1.2 物理数据结构
逻辑数据在计算机真正存储的形式
形式:1)顺序存储 --数组:数据元素放在地址连续的空间中,数据的逻辑关系与物理关系一致
优点:方便进行随机元素的查找,查找速度快(下标);
缺点:数组的插入与删除操作很耗时,需要频繁的进行元素的移动,比较浪费内存空间
2)不连续存储–链表:元素存储在随机单元中,可以是连续的,也可以是不连续的
(类比排队 只知前后的元素,对其他的不清楚,第一个节点一定知道第二个节点,但不知道第三个)
优点:方便进行元素的插入与删除(若删除第三个元素,只需将第二个元素指向第四个元素);
缺点:元素查找速度慢,只能从前向后遍历(若需要找特定元素需从头遍历),节省空间
总结: 频繁查找用数组,频繁插入删除用链表、内存紧张用链表
计算机组成原理
内存:高速存储 CPU直接管理工作站:128G 读写速率高于磁盘先将数据读取到内存中,数据用完后清除出去,再读取新的数据
外存:硬盘 磁盘:PB C盘
内存:100MB 连续空间:可用连续空间70MB
要储存71MB,采用数组:一个元素也放不下(连续空间不足) 若采用链式存储:能存储70MB空间元素
2. 什么是算法
**定义:**算法是在特定的数据结构上一组输入按照特定的方式输出。是良好的计算过程,是解决问题求解的步骤。
如何衡量一个算法的优缺点?
以空间换时间
从两个角度:时间上;空间上;
3.时间复杂度
时间复杂度:衡量一个算法的运行速度,时间效率;
3.1 评判方法:
事后统计法:把代码跑一遍,通过统计、监测等手段就能得到算法执行时间和占用内存大小
缺点:1)测试结果非常依赖测试环境
2)测试结果受数据影响很大
3.2 大O时间复杂度方法
所有代码的执行时间T(n)与每行代码的执行次数 n 成正比:T(n)=O( f ( n ) );当n足够大只需计算最大量级;
大O时间复杂度实际上并不具体表示代码的真正执行时间,而是表示代码执行时间随数据规模度增长的变化趋势,所以也叫作 渐进时间复杂度,简称时间复杂度
分析方法:
- 只关心循环次数最多的代码(代码中只有一个循环体时);
- 加法法则:总复杂度等于量级最大的那段代码的复杂度(代码中有多个循环体);
- 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
3.2.1多项式时间复杂度: O(1)、O(n)、O(log n)、O(O^2)
O(1):常数级时间复杂度 只要代码不随n增长变化,都属于O(1)常数级复杂度;
O(n):
O(n^2):
for(int i=0;i<n;i++){//看自变量有没有参与运算
for(int j=0;j<i;j++){
}
}
O(m+n):与m、n、趋势有关,由于m与n的数据规模不定,因此使用加法法则保留两者的复杂度。
int cal(int m,int n){
int sum_1=0;
int i=i;
for(;i < m;i++){//只有当这个循环的规模也不确定时,两个复杂度都保留
sum_i = sum_i+1;
}
int sum_2 = 0;
int j = 1;
for(; j < n; ++j){
sum_2 = sum_2 + j;
}
return sum_1 + sum_2;
}
O(log n):对数时间复杂度 :任意底数的对数都可以换成以2为底
O(nlogn):快速排序、归并排序、
for(int i=0;i<n;i++){//两层循环
while(i<=n){
i=i*2;
}
}
3.2.2非多项式时间复杂度:O(2^n) 、O( n! )
复杂度量级分为两类:当n越来越大时,非多项式的时间复杂度急剧增加,因此非多项式的算法基本不用。
3.3 最好、最坏、平均时间复杂度
//n表示数组array的长度
int find(int[] array, int n, int x) {
int i = 0; int pos = -1;
for (; i < n; ++i) {
if (array[i] == x)
pos = i;
}
return pos;
}
//这个代码的时间复杂度为O(n);
//优化后代码
int find(int[] array, int n, int x) {
int i = 0; int pos = -1;
for (; i < n; ++i) {
if (array[i] == x){
pos = i;
break;
}
}
return pos;
}
//代码时间复杂度
//最好情况:第一个元素即为所要查找元素 O(1)
//最坏情况:最后一个元素为所要查找元素 O(n)
//平均情况: 有n+1中情况 O(n)
时间复杂度排序:O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)
4.空间复杂度:
代码所占用的空间所需内存大小
S(n)=O(f(n));
public static int sun(int n){
int count =0;
for(int i=1;i<=n;i++){
count +=i;
}
retuen count;
}
//上述代码空间复杂度是:O(1)
另:
public class Test{
public static void main(String[] args){
fun();
}
public static void fun(){
fun();
}
}
上述程序出现:栈溢出异常:
这个异常属于非受查异常