数据结构分为四类:集合(元素间无内在关系),线性(一对一关系),树型(一对多关系),图型(多对多关系)
存储方式:顺序存储(连续,类似于排队),链式存储(可以不连续,通过保存其他元素地址可得到,类似于医院叫号)
算法要素:输入,输出,有穷性,确定性(不会有二意),可行性
算法要求:正确性(1.无语法错误 2.根据正确输入给出正确输出 3.非输入给出说明 4.刁钻边缘情况给出提示)
可读性
健壮性
时间效率高存储量低
e.g
sum=0
n=100
for i in range(1,n+1):
sum+=i
时间复杂度为n+2
n=100
(1+n)*n/2
时间复杂度为2
如何分析一个算法的时间复杂度:
用常数1取代运行时间中的所有加法常数
在修改后的运行次数函数中,只保留最高阶项
如果最高阶项存在且不是1,则去除与这个项相乘的常数
得到最后的结果就是大O阶
int sum = 0, n = 100;
printf("aaaaaaaaaaaan");
printf("aaaaaaaaaaaan");
printf("aaaaaaaaaaaan");
printf("aaaaaaaaaaaan");
printf("aaaaaaaaaaaan");
printf("aaaaaaaaaaaan");
sum = (1+n)*n/2
//这段代码的时间复杂度为O(1),因为这段代码执行了8次,没有与n相关,常数都简化为1
1.线性阶:一般含有非嵌套循环设计线性阶,线性阶就是随着问题规模n的扩大,对应计算次数呈直线增长。
int i, n = 100, sum = 0;
for(i = 0; i{
sum = sum + i;
}
上面这段代码的循环复杂度为O(n),因为循环体中的代码需要执行n次
2.平方阶
int i,j,n = 100;
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
printf("aaaaaaaaaaaa\n");
}
}
上面这段代码的时间复杂度为O(n²)。
3.int i,j,n = 100;
for(i = 0; i < n; i++)
{
for(j = i; j < n; j++)
{
pringtf("aaaaaaaaaaaaaa\n");
}
}
分析,由于当i=0时,内循环执行了n次,当i=1时,内循环则执行n-1次。。。。。。当i=n-1时,内循环执行1次,所以总的执行次数应该是n+(n-1)+(n-2)+...+1=n(n+1)/2用上面的简化方法来简化½n²+½n,这个式子中没有常数项不用考虑第一条,根据第二条只保留最高项,去掉½n这一项,根据第三条去掉与最高项相乘的常数½,最终得到O(n²)
对数阶
int i = 1, n = 100;
while(i < n)
{
i = i*2;
}
由于每次i*2之后就距离n更近一步,假设有x个2相乘后大于或等于n,则会退出循环。于是由2x=n得到x=log2n,所以这个循环的时间复杂度为O(logn)。
4.int i,j;
for(i = 0; i < b; i++)
{
function(i);
}
void function(int count)
{
printf("%d",count);
}
function函数的时间复杂度是O(1),所以整体的时间复杂度就是循环的次数O(n)。
和平方阶中第二个例子一样,function内部的循环次数随count的增加而减少,所以根据方法简化后的时间复杂度为O(n²)
5.
n++;-------------------------------------执行1次
function(n);-----------------------------执行n²次
for(i = 0;i < n; i++) {------------------执行n²次
function(i);
}
for(i = 0;i < n; i++) {------------------执行n²次
for(j = i;j < n; j++) {
printf("%d",j);
}
}
void function(int count) {
int j;
for (j = count; j < n;j++) {
printf("%d",j);
}
}
上面几次操作是并列的,整体的执行次数应该是各个操作执行次数之和3n²+1,简化后得到时间复杂度为O(n²)
常见的时间复杂度
5201314 O(1)
常数阶
3n+4 O(n)
线性阶
3n²+4n+5 O(n²)
平方阶
3log2n+4 O(logn)
对数阶
2n+3nlog2n+14 O(nlogn)
nlogn阶
n^3+2n^2+4n+6 O(n3)
立方阶
2^n O(2n)
指数阶
1.常见的时间复杂度所耗费的时间从小到大依次是
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < (nn)
2.平均运行时间是期望的运行时间
3.最坏运行时间是一种保证。在应用中,这是一种最重要的需求,通常除非特别指定,我们提到的运行时间都是最坏情况的运行时间。
- 算法的空间复杂度通过计算算法所需的存储空间实现,算法的空间复杂度的计算公式记做S(n) = O(f(n)),其中,n为问题的规模,f(n)为语句关于n所占存储空间的函数。
5.通常,我们都是用“时间复杂度”来指运行时间的需求,用“空间复杂度”指空间需求。
6.当直接让我们求“复杂度”时,通常指的是时间复杂度。