80.【C语言】数据结构之时间复杂度

news/2024/10/18 12:28:22/

目录

1.数据结构的定义

2.算法的定义

3.算法的效率

1.衡量一个算法的好坏的方法

例题:计算以下代码的循环次数

2.大O的渐进表示法

练习1:求下列代码的时间复杂度

练习2:求下列代码的时间复杂度

练习3:求下列代码的时间复杂度

练习4:求下列代码的时间复杂度

4.总结:计算时间复杂度的方法

5.时间复杂度的排名


1.数据结构的定义

参见63.【C语言】再议结构体(上)

也可以理解为数据在内存中的存储形式(管理数据)

比如说写通讯录可以用静态数组,动态数组和链表形式存储

2.算法的定义

简单的定义:一系列的计算步骤,用来将输入数据转化成输出结果

3.算法的效率

1.衡量一个算法的好坏的方法

两个方面衡量:时间效率(计算时间分复杂度)和空间效率(空间复杂度)

比较时间要在同一个环境下进行(为了控制变量,但在实际情况下难以控制)

-->比较运行次数(和环境无关)

运行次数举例:对于同一组数据,快速排序和冒泡排序的运行次数不同

例题:计算以下代码的循环次数

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);
}

定义一个函数F(N),其值为循环次数

可得:F(N)=N^2+2N+10

N=10F(N)=130
N=100F(N)=10210
N=1000F(N)=1002010

但实际中计算时间复杂度时,其实并不一定要计算精确的执行次数,而只需要知道大概的执行次数,那么这里使用大O的渐进表示法

比如可以计算量级(N=10的次方),当N较大时(可理解为n \to \infty),影响F(N)的值主要为N^2,因此$F(N) \approx N^2$

对比N^2N^2+2N+10的两张图

2.大O的渐进表示法

大O符号:用于描述函数渐近行为的数学符号,可以用来衡量时间复杂度和空间复杂度

在上述函数中,Func1的时间复杂度为O(N^2),其去掉了对结果影响不大的地方

练习1:求下列代码的时间复杂度

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);
}

运行次数n==2N+10

1.取最高阶的式子(去常数)

n \to \infty时,+10对结果影响不大,因此$2N+10 \approx 2N$

2.去系数

因为n \to \infty时,N前面的系数对结果影响也不大(\lim_{n \to \infty} 2N = \lim_{n \to \infty} N = \infty),因此时间复杂度为O(N)

练习2:求下列代码的时间复杂度

void Func3(int N)
{int count = 0;for (int k = 0; k < 100; ++ k){count++;}printf("%d\n", count);
}

O(100)吗?不是,为O(1),这里的1不是次数,而是指常数次

练习3:求下列代码的时间复杂度

#include <stdio.h>
const char* strchr( const char* str, char character)
{while (*str){if (*str == character)return str;str++;}return str;
}int main()
{char character;char str[100] = { 0 };scanf("%c", &character);scanf("%s", str); // 数组名就是数组的首元素地址const char* s_str=strchr(str, character);printf("%s", s_str);
}

发现:运算次数和字符串的长度以及和要找的字符位置有关

即该题的时间复杂度存在最好,平均和最坏情况:

最坏情况:任意输入规模的最大运行次数(上界)

平均情况:任意输入规模的期望运行次数

最好情况:任意输入规模的最小运行次数(下界)

按预期管理来看,应该取最坏的情况,即O(N),N为输入字符串的长度

练习4:求下列代码的时间复杂度

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{int n = 0;int arr[100] = { 0 };int tmp = 0;//输入元素a:printf("输入数组元素个数:");scanf("%d", &n);if (n > 100 || n < 1){printf("输入的元素个数超出范围或无效!请重新输入!\n");goto a;}printf("输入数组元素:");for (int k = 0; k < n; k++){scanf("%d", &arr[k]);}//冒泡排序for (int i = 1; i <= n - 1; i++)//趟数{int flag = 1;//每趟排序时置为1for (int j = 0; j <= n - i - 1; j++)//步数{if (arr[j] > arr[j + 1]){tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;flag = 0;//发生交换flag置0}}if (1 == flag){break;//未发生交换则退出循环}}//打印结果for (int q = 0; q < n; q++){printf("%d ", arr[q]);}return 0;
}

同样的,在冒泡排序(参见42.【C语言】冒泡排序)中,运算次数也有最好和最坏的情况

显然此代码是按升序排列

最好:给的数组就是按升序排列的(如0 1 2 3 4 5 6 7 8 9)

尽管j的for循环中的if判断的交换没有执行(相当于空转),但由于flag一直为0,因此到j为8时才能退出循环

因此运行次数n==N-1-->舍去常数后-->N

因此最好:O(N)

最坏:给的数组就是按降序排列的(如9 8 7 6 5 4 3 2 1 0)

因此因此运行次数n==(N-1)+(N-2)+(N-3)+...+(1)==(1+N-1)*(N-1)/2==(N^2-N)/2

取最高阶的式子0.5N^2,去掉最高阶式子前的系数-->N^2

因此最坏:O(N^2)

4.总结:计算时间复杂度的方法

若次数为常数,时间复杂度为O(1)

若次数为N的表达式

1.取最高阶的式子(去常数) 2.去掉最高阶式子前的系数

若存在最好,最坏情况,取最坏的情况作为时间复杂度

5.时间复杂度的排名

O(1)<O(logN)<O(N)<O(N*logN)<O(N^3)<O(2^N)


http://www.ppmy.cn/news/1538550.html

相关文章

解决github每次pull push输入密码问题

# 解决git pull/push每次都需要输入密码问题 git bash进入你的项目目录&#xff0c;输入&#xff1a; git config --global credential.helper store然后你会在你本地生成一个文本&#xff0c;上边记录你的账号和密码。配置项写入到 "C:\Users\用户名\ .gitconfig" …

工具软件分享:11个免费的 android数据恢复应用程序功能分析

在手机上丢失数据是一个很大的错误。但是&#xff0c;在这种情况下&#xff0c;除了惊慌失措之外&#xff0c;最好开始使用android数据恢复应用程序搜索以查找将其取回的方法。您可以检查手机的备份存储以在Android上进行数据恢复&#xff0c;但是如果数据仍然无处可寻&#xf…

Android Studio 打包混淆失效问题

项目场景&#xff1a; 通过 Python 脚本运行打包 Apk &#xff0c;实现动态配置各个版本的 Apk。 问题描述 通过 Python 脚本打包编译 Apk&#xff0c;开启混淆后&#xff0c;打包成功&#xff0c;反编译出来的 Apk 并没有被混淆。 原因分析&#xff1a; 首先确认打包混淆…

校车购票微信小程序的设计与实现(lw+演示+源码+运行)

摘 要 由于APP软件在开发以及运营上面所需成本较高&#xff0c;而用户手机需要安装各种APP软件&#xff0c;因此占用用户过多的手机存储空间&#xff0c;导致用户手机运行缓慢&#xff0c;体验度比较差&#xff0c;进而导致用户会卸载非必要的APP&#xff0c;倒逼管理者必须改…

Python+whisper/vosk实现语音识别

目录 一、Whisper 1、Whisper介绍 2、安装Whisper 3、使用Whisper-base模型 4、使用Whisper-large-v3-turbo模型 二、vosk 1、Vosk介绍 2、vosk安装 3、使用vosk 三、总结 一、Whisper 1、Whisper介绍 Whisper 是一个由 OpenAI 开发的人工智能语音识别模型&#xf…

解决 Qt 中提升控件后样式表无法正确应用的问题

在使用 Qt Designer 进行界面设计时,控件提升(Widget Promotion) 是一个强大的功能,允许开发者将标准控件(如 QWidget、QPushButton 等)替换为自定义的子类,以实现更丰富的功能或更独特的外观。然而,当你将一个控件提升为自定义类后,可能会遇到样式表(Stylesheet)无…

【SQL学习笔记】

Pycharm社区版的页面中无database选项&#xff1f; 1、进入Setting-Pluggins窗口&#xff0c;输入database navigator 2、安装后&#xff0c;重启即可 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层 1、Server 层负责建⽴连接、分析和执⾏ SQL 2、存储引擎层负…

理论篇| 移动端爬虫

移动应用的快速发展和广泛普及带来了海量的数据,这些数据对于市场分析、用户行为洞察和业务优化具有重要价值。然而,由于移动应用的特殊性和防护措施,传统的爬虫技术在采集移动应用数据方面面临许多挑战。因此,App爬虫采集与逆向在爬虫领域的重要性不可低估 然而,App采集…