淄博安监局网站两体系建设,做网站的软件叫什么软件,wordpress有没有付费,门户网站为什么衰落目录 前言#xff1a; ✨什么是数据结构#xff1f; ✨ 什么是算法#xff1f; ✨数据结构和算法的重要性 #x1f351;算法的时间复杂度和空间复杂度 算法效率 #x1f389;时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 #x1f389;空间复杂度 前言#xf…目录 前言 ✨什么是数据结构 ✨ 什么是算法 ✨数据结构和算法的重要性 算法的时间复杂度和空间复杂度 算法效率 时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 空间复杂度 前言
什么是数据结构 数据结构是计算机科学中研究数据组织方式的一门学科。它主要研究如何将数据以某种逻辑方式组织和存储以便更有效地访问和修改。一些常见的数据结构包括数组、链表、栈、队列、树和图等。了解数据结构可以帮助我们更好地设计和实现算法以及优化程序的效率。 什么是算法 算法就是定义良好的计算过程他取一个或一组的值为输入并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤用来输入数据转化成输出结果。 数据结构和算法的重要性 提供高效的解决方案 算法和数据结构是为了提供高效的解决方案而设计的。它们提供了各种数据结构和算法可以在特定的时间复杂度内完成任务。高效的算法和数据结构可以节省计算机资源提高程序的性能。 提高编程技能 数据结构和算法是编程的核心概念。掌握这些概念可以提高编程技能和编程能力。它们可以帮助程序员设计更好的程序结构熟悉常见编程问题的解决方案以及在编写代码时注意效率。 推动新技术的发展 许多新技术都基于数据结构和算法的概念。例如人工智能和机器学习技术需要强大的算法和高效的数据结构来处理和分析大量数据。掌握数据结构和算法可以帮助人们更好地理解新技术从而推动新技术的发展和应用。 提高代码可读性和可维护性 数据结构和算法不仅可以提高程序的性能还可以提高程序的可读性和可维护性。良好的程序结构和算法可以使代码更易于阅读和修改同时也可以增强代码的可维护性。 算法的时间复杂度和空间复杂度
算法效率 算法的复杂度: 算法在编写成可执行程序后运行时需要耗费时间资源和空间 ( 内存 ) 资源 。因此 衡量一个算法的好坏一般 是从时间和空间两个维度来衡量的 即时间复杂度和空间复杂度。 时间复杂度 主要衡量一个算法的运行快慢而 空间复杂度 主要衡量一个算法运行所需要的额外空间 。在计算 机发展的早期计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展计 算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。 时间复杂度
2.1 时间复杂度的概念 时间复杂度的定义在计算机科学中 算法的时间复杂度是一个函数 它定量描述了该算法的运行时间。一 个算法执行所耗费的时间从理论上说是不能算出来的只有你把你的程序放在机器上跑起来才能知 道。但是我们需要每个算法都上机测试吗是可以都上机测试但是这很麻烦所以才有了时间复杂度这个 分析方式。一个算法所花费的时间与其中语句的执行次数成正比例 算法中的基本操作的执行次数为算法 的时间复杂度。 即找到某条基本语句与问题规模N之间的数学表达式就是算出了该算法的时间复杂度。 // 请计算一下Func1中count语句总共执行了多少次
void Func1(int N)
{
int count 0;
for (int i 0; i N ; i)
{for (int j 0; j N ; j){count;}
}for (int k 0; k 2 * N ; k)
{count;
}
int M 10;
while (M--)
{count;
}
printf(%d\n, count);
} 可以准确算出来嘛 哈哈哈哈哈为了解决这个问题我们的前辈想到了一个办法就是计算算法的大概执行次数。 Func1 执行的基本操作次数 N 10 F(N) 130 N 100 F(N) 10210 N 1000 F(N) 1002010 实际中我们计算时间复杂度时我们其实并不一定要计算精确的执行次数而只需要 大概执行次数那么这 里我们使用大 O 的渐进表示法。 2.2 大O的渐进表示法
实际中我们计算时间复杂度时我们其实不一定要计算精确的执行次数而只需要大概执行次数那么这里我们使用大O的渐进表示法。 推导大 O 阶方法 1 、用常数 1 取代运行时间中的所有加法常数。 2 、在修改后的运行次数函数中只保留最高阶项。 3 、如果最高阶项存在且不是 1 则去除与这个项目相乘的常数。得到的结果就是大 O 阶。 使用大 O 的渐进表示法以后 Func1 的时间复杂度为ON^ N 10 F(N) 100 N 100 F(N) 10000 N 1000 F(N) 1000000 通过上面我们会发现大 O 的渐进表示法 去掉了那些对结果影响不大的项 简洁明了的表示出了执行次数。 另外有些算法的时间复杂度存在最好、平均和最坏情况 最坏情况任意输入规模的最大运行次数 ( 上界 ) 平均情况任意输入规模的期望运行次数 最好情况任意输入规模的最小运行次数 ( 下界 ) 例如在一个长度为 N 数组中搜索一个数据 x 最好情况 1 次找到 最坏情况 N 次找到 平均情况 N/2 次找到 在实际中一般情况关注的是算法的最坏运行情况所以数组中搜索数据时间复杂度为 O(N) 即抓大头取决定性结果那一项。 2.3常见时间复杂度计算举例 实例1 // 计算Func2的时间复杂度
void Func2(int N)
{int count 0;for (int k 0; k 2 * N ; k){count;}int M 10;while (M--){count;}printf(%d\n, count);
} On 实例2 // 计算Func3的时间复杂度
void Func3(int N, int M)
{int count 0;for (int k 0; k M; k){count;}for (int k 0; k N ; k){count;}printf(%d\n, count);
} OMN 特殊情况 实例3 // 计算Func4的时间复杂度
void Func4(int N)
{int count 0;for (int k 0; k 100; k){count;}printf(%d\n, count);
} O1 实例4 // 计算strchr的时间复杂度
const char * strchr ( const char * str, int character ); ON 在实际中一般情况关注的是算法的最坏运行情况所以数组中搜索数据的时间复杂度为ON 时间复杂度计算时是一个稳健保守预期 实例5 // 计算BubbleSort的时间复杂度
void BubbleSort(int* a, int n)
{assert(a);for (size_t end n; end 0; --end){int exchange 0;for (size_t i 1; i end; i){if (a[i-1] a[i]){Swap(a[i-1], a[i]);exchange 1;}}if (exchange 0)break;}
} ON^2 实例6 // 计算BinarySearch的时间复杂度
int BinarySearch(int* a, int n, int x)
{assert(a);int begin 0;int end n-1;// [begin, end]begin和end是左闭右闭区间因此有号while (begin end){int mid begin ((end-begin)1);if (a[mid] x)begin mid1;else if (a[mid] x)end mid-1;elsereturn mid;}return -1;
} OlogN 最坏情况查找区间缩放只剩一个值时就是最坏 最坏情况下查找多少次除了多少次2就查找了多少次 假设查找x次2^xN, xlogN 实例7 // 计算阶乘递归Fac的时间复杂度
long long Fac(size_t N)
{if(0 N)return 1;return Fac(N-1)*N;
} ON 总结递归算法时间复杂度是多次调用的次数累加 实例8 // 计算斐波那契递归Fib的时间复杂度
long long Fib(size_t N)
{if(N 3)return 1;return Fib(N-1) Fib(N-2);
} O(2^N) 思路 1.实例 1 基本操作执行了 2N10 次通过推导大 O 阶方法知道时间复杂度为 O(N) 2. 实例 2 基本操作执行了 MN 次有两个未知数 M 和 N 时间复杂度为 O(NM) 3. 实例 3 基本操作执行了 10 次通过推导大 O 阶方法时间复杂度为 O(1) 4. 实例 4 基本操作执行最好 1 次最坏 N 次时间复杂度一般看最坏时间复杂度为 O(N) 5. 实例 5 基本操作执行最好 N 次最坏执行了 (N*(N1)/2 次通过推导大 O 阶方法 时间复杂度一般看最 坏时间复杂度为 O(N^2) 6. 实例 6 基本操作执行最好 1 次最坏 O(logN) 次时间复杂度为 O(logN) ps logN 在算法分析中表示是底 数为2 对数为 N 。有些地方会写成 lgN 。建议通过折纸查找的方式讲解 logN 是怎么计算出来的 7. 实例 7 通过计算分析发现基本操作递归了 N 次时间复杂度为 O(N) 。 8. 实例 8 通过计算分析发现基本操作递归了 2^N 次时间复杂度为 O(2^N) 。建议画图递归栈帧的二叉树 讲解 空间复杂度 空间复杂度也是一个数学表达式是对一个算法在运行过程中 额外 临时占用存储空间大小的量度 。 空间复杂度不是程序占用了多少 bytes 的空间因为这个也没太大意义所以空间复杂度算的是 变量的个数 。 空间复杂度计算规则基本跟实践复杂度类似也使用 大 O 渐进表示法 。 注意 函数运行时所需要的栈空间 ( 存储参数、局部变量、一些寄存器信息等 ) 在编译期间已经确定好了因 此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。 实例1 // 计算BubbleSort的空间复杂度
void BubbleSort(int* a, int n)
{assert(a);for (size_t end n; end 0; --end){int exchange 0;for (size_t i 1; i end; i){if (a[i-1] a[i]){Swap(a[i-1], a[i]);exchange 1;}}if (exchange 0)break;}
} 实例2 // 计算Fibonacci的空间复杂度
// 返回斐波那契数列的前n项
long long* Fibonacci(size_t n)
{if(n0)return NULL;long long * fibArray (long long *)malloc((n1) * sizeof(long long));fibArray[0] 0;fibArray[1] 1;for (int i 2; i n ; i){fibArray[i] fibArray[i - 1] fibArray [i - 2];}return fibArray;
} 实例3v 时间是累积的一去不复返 空间是可以重复利用的 // 计算阶乘递归Fac的空间复杂度
long long Fac(size_t N)
{if(N 0)return 1;return Fac(N-1)*N;
} 1. 实例 1 使用了常数个额外空间所以空间复杂度为 O(1) 2. 实例 2 动态开辟了 N 个空间空间复杂度为 O(N) 3. 实例 3 递归调用了 N 次开辟了 N 个栈帧每个栈帧使用了常数个空间。空间复杂度为 O(N) 常见复杂度对比 例题
轮转数组