1.算法的定义
2.算法和程序
算法是解决问题的一种方法或一个过程,考虑如何将输入转成输出,一个问题可以有多种算法。
程序是用某种程序设计语言对算法的具体实现。
程序=数据结构+算法
理解:对每一种菜肴,需要说明用什么原料(数据结构),再介绍操作步骤(算法)。
3.算法的特性
4.算法的效率
时间效率
比较总和比较麻烦↓
*时间复杂度
基本语句:算法中重复执行次数和算法的执行时间成正比的语句;对算法运行时间贡献最大的;执行次数最多
问题规模n:
平均时间复杂度:用代码在所有情况下执行的次数的加权平均值表示。
时间复杂度:
O(1)常数型:
O(n)线性型:
O(n的平方)平方型:
O(n的三次方)立方型:
O(2的n次方)指数型:
对数型:
O二维型:
*空间复杂度
O(1):常数空间复杂度。算法使用的额外空间是固定的,不随输入规模变化。例如,一个只使用几个变量的简单算法。x、y数值再大也不会影响空间分配
O(N):线性空间复杂度。算法使用的额外空间与输入规模成线性关系。例如,一个数组来存储输入数据。
O(n2):平方空间复杂度。算法使用的额外空间与输入规模的平方成正比。例如,在矩阵乘法中,如果需要创建一个新的矩阵来存储结果。
例题1:二分查找的复杂度分析
递归方法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
int search_(int a[], int l, int r, int x)//递归方法
{
int m = l + (r - l) / 2;
if (l > r) {
return -1;
}
if (x == a[m]){
return m;
}
if (x < a[m]) {//查找的数比中间值小,在左半区继续查找
search_(a,m-1,l,x);
}
else { //查找的数比中间值大,在右半区继续查找
search_(a, m + 1, r, x);
}
}
int main()
{
int n;
scanf("%d", &n);
int* a = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
int x;
scanf("%d", &x);//待查找元素
int result = search_(a, 0, n - 1, x);
if (result == -1) {
printf("元素未找到");
}
else {
printf("元素找到,位于索引%d", result);
}
free(a);//记得释放内存
}
非递归方法:
int search(int arr[], int n, int x) //非递归方法
{
int l = 0, r = n - 1;//查找范围的左边界和右边界
while (l <= r) {
int m = l + (r - l) / 2;
if (arr[m] == x)
return m;
if (arr[m] < x)//中间位置元素小于要查找的元素x 更新左边界
l = m + 1;
else //中间位置元素大于要查找的元素x 更新右边界
r = m - 1;
}
return -1;
}
int main(
{
int n;
scanf("%d", &n);
int* arr = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
int x;
scanf("%d", &x);
int result = search(arr, n, x);
if (result == -1) {
printf("元素未找到\n");
}
else {
printf("元素找到,位于索引 %d\n", result);
}
free(a);
return 0;
}
第一次:在n个元素中找到目标元素
第二次:在n/2个元素中找到目标元素
第三次:在n/22个元素中找到目标元素
...
第k次:在n/2k个元素中找到目标元素
2k<=n,k<=
最坏情况时间复杂度:
最好情况时间复杂度:一次找到----O(1)
平均情况时间复杂度(所有可能的输入实例以均等概率出现的情况下, 算法的运行运行时间)
假设要查找的元素等概率地分布在数组中的任意位置,则每次查找时,要查找的元素有 50% 的可能在左侧和 50% 的可能在右侧。因此,每次循环迭代最多将查找范围缩小一半。
空间复杂度(一个算法在运行过程中临时占用储存空间大小的量度,额外占取的空间的大小):
函数中没有使用额外的数据结构来存储中间结果或辅助信息,其空间复杂度主要取决于局部变量l,r,m的使用情况,这几个变量均只占用了固定的空间,是常数级别的,与输入的个数n无关。
O(1)
例题2:冒泡排序的复杂度分析
本段冒泡排序函数中,外部循环执行次数为n-1次。
内部循环的执行次数为n-1-i次,总执行次数为:T(n)=(n-1)*(n-1-i)次
最坏情况时间复杂度: O(n2)
最好情况时间复杂度:O(n2)
平均情况时间复杂度:O(n2)
空间复杂度(一个算法在运行过程中临时占用储存空间大小的量度,额外占取的空间的大小):
冒泡排序是一种原地排序算法,不需要开辟额外的数组或数据结构空间来储存数据
O(1)
优化写法:
最坏情况时间复杂度: O(n2)
最好情况时间复杂度:O(n)
在优化写法中,最好情况是输入的数据元素已经是有序的,这时只需要在i=0时,进行内部循环,执行n-1次
平均情况时间复杂度:O(n2)
空间复杂度:O(1)