【数据结构初阶】一. 复杂度讲解

这篇具有很好参考价值的文章主要介绍了【数据结构初阶】一. 复杂度讲解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

=========================================================================

相关代码gitee自取

C语言学习日记: 加油努力 (gitee.com)

 =========================================================================

接上期

学C的第三十四天【程序环境和预处理】_高高的胖子的博客-CSDN博客

 =========================================================================

                     

1 . 算法效率

(1). 什么是数据结构:

               

数据结构(Data Structure)是计算机存储组织数据的方式

相互之间存在一种或多种特定关系的数据元素的集合

                     


                    

(2). 什么是算法:

                

算法(Algorithm)就是定义良好的计算过程

取一个或一组的值为输入,并产生出一个或一组值作为输出

简单来说算法就是一系列的计算步骤用来将输入数据转化成输出结果

                     


                    

(3). 算法的复杂度:

                     

算法编写成可执行程序后运行时需要耗费时间资源空间(内存)资源

因此衡量一个算法的好坏,一般是时间空间两个维度来衡量的,

时间复杂度空间复杂度

                      

时间复杂度主要衡量一个算法的运行快慢

空间复杂度主要衡量一个算法运行所需要的额外空间

计算机发展的早期计算机的存储容量很小。所以对空间复杂度很是在乎

但是经过计算机行业的迅速发展计算机的存储容量已经达到了很高的程度

所以我们如今已经不需要再特别关注一个算法的空间复杂度

               

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                   

2 . 时间复杂度

(1). 时间复杂度的概念:

               

计算机科学中算法的时间复杂度是一个函数,它定量描述了该算法的运行时间

一个算法执行所耗费的时间,从理论上说,是不能算出来的,

只有把你的程序放在机器上跑起来才能知道

但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦

所以才有了时间复杂度这个分析方式

            

一个算法所花费的时间其中语句的执行次数成正比例

算法中的基本操作的执行次数,为算法的时间复杂度

                       

即:

找到某条基本语句问题规模N之间数学表达式,就是算出该算法的时间复杂度

             

图例:Func1执行的基本操作次数

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

                 

上图得到的Func1执行的基本次数为:

F(N) = N^2 + 2*N +10

但实际我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数

只需要大概执行次数,那么这里我们使用大O的渐进表示法

                     


                    

(2). 大O的渐进表示法:

          

大O符号Big O notation):是用于描述函数渐进行为的数学符号

            

推导大O阶方法

1、常数1取代运行时间中的所有加法常数

2、在修改后的运行次数函数中,只保留最高阶项

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数得到的结果就是大O阶

            

使用大O的渐进表示法以后,

F(N) = N^2 + 2*N +10

第一步:+10 变为 +1

第二步:保留最高阶项 N^2

第三步:最高项相乘常数为1不用去除

            

所以Func1的时间复杂度O(N^2)

N = 10             F(N) = 100        

N = 100           F(N) = 10000    

N = 1000         F(N) = 1000000

通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项

简洁明了的表示出了执行次数

大O的渐进表示法本质计算的是算法属于哪个量级

           

另外有些算法的时间复杂度存在最好平均最坏情况

(可查看下方案例四)

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

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

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

                

例如:在一个长度为N数组中搜索一个数据x

最坏情况N次找到

平均情况N/2次找到

最好情况1次找到

实际操作下一般情况关注的是算法的最坏运行情况

所以数组中搜索数据时间复杂度为O(N)

                     


                    

(3). 常见时间复杂度计算案例:

          

案例一:

//示例一:
//计算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);
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例二:

//示例二:
//计算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);
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例三:

//示例三:
//计算Func4的时间复杂度:
void Func4(int N)
{
	int count = 0;
	for (int k = 0; k < 100; ++k)
	{
		++count;
	}

	printf("%d\n", count + N);
}
图示:“cpu技术太强了”

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例四:

//示例四:
//计算strchr的时间复杂度:
const char* strchr(const char* str, int character);
//strchr库函数:在str字符数组中查找一个字符
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例五:

//示例五:
#include <stdio.h>
//计算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;
		}
	}
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例六:

//示例六:
//计算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 = mid + 1;
		}
		else if (a[mid] > x)
		{
			end = mid - 1;
		}
		else
		{
			return mid;
		}
	}

	return -1;
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例七:

//示例七:
//计算阶乘递归Fac的时间复杂度:
long long Fac(size_t N)
{
	if (0 == N)
	{
		return 1;
	}

	return Fac(N-1)*N;
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

               

               

案例八:

//示例八:
//计算斐波那契递归Fib的时间复杂度:
long long Fib(size_t N)
{
	if (N < 3)
	{
		return 1;
	}
	
	return Fib(N - 1) + Fib(N - 2);
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

                     


                    

(4). 常见时间复杂度对比

             

一般算法常见的复杂度如下表:

5201314 O(1) 常数阶
3n + 4 O(n) 线性阶
3n^2 + 4n + 5 O(n^2) 平方阶
3log(2)n + 4 O(logn) 对数阶
2n + 3nlog(2)n + 14 O(nlogn) nlogn阶
n^3 + 2n^2 + 4n + 6 O(n^3) 立方阶
2^n O(2^n) 指数阶

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

3 . 空间复杂度

(1). 空间复杂度的概念:

                     

空间复杂度是一个数学表达式

对一个算法在运行过程中额外临时占用存储空间大小的量度

                

空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,

所以空间复杂度算的是变量的个数

空间复杂度计算规则基本跟时间复杂度类似也使用大O渐进表示法

                   

注意:

函数运行时所需要的栈空间(存储参数局部变量、一些寄存器信息等)

编译期间已经确定好了

因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定

                     


                    

(2). 常见空间复杂度计算案例:

           

案例一:

//计算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;
		}
	}
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

           

           

案例二:

//计算Fibonacci的空间复杂度:
//返回斐波那契数列的前n项
long long* Fibonacci(size_t n)
{
	if (n==0)
	{
		return NULL;
	}
	
	long long* fibArray = (long long*)malloc((n + 1) * 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;
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

           

           

案例三:

//计算阶乘递归Fac的空间复杂度:
long long Fac(size_t N)
{
	if (N == 0)
	{
		return 1;
	}

	return Fac(N-1)*N;
}
图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

4 . 复杂度的oj练习

(1). 时间复杂度练习:消失的数字

                   

对应链接:

面试题 17.04. 消失的数字 - 力扣(LeetCode)

              

题目:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

           

解决思路一:使用等差数列公式

             

假设数组nums包含从0到n的所有整数

那么就可以使用 0+N等差公式 计算出一个结果

该结果等于 0~n的各数相加总和

用这个结果 减去 数组中的值

结果就是消失的数字的值

              

图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

对应代码:
int missingNumber(int* nums, int numsSize){
    int N = numsSize;

    int ret = N*(N+1)/2;

    for(int i = 0; i < N; i++)
    {
        ret -= nums[i];
    }

    return ret;
}

              

解决思路二:异或法

             

用 0 异或 完整的0~N各值

再用该异或的结果异或 nums数组少一个值

因为异或后相同为0相异为1

此时两对值中相同的值就会异或为0

nums少的一个值异或后就会得到该值

              

图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

对应代码:
int missingNumber(int* nums, int numsSize){

    int N = numsSize;

    int x = 0; //用来保存异或后的结果

    for(int i = 0; i <= N; ++i)
    {
        x ^= i;
    }

    for(int i = 0; i < N; ++i)
    {
        x ^= nums[i];
    }

    return x;
}

                      


                    

(2). 空间复杂度练习:轮转数组

                   

对应链接:

189. 轮转数组 - 力扣(LeetCode)

               

题目:要求时间复杂度为O(N),空间复杂度为为O(1)

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

           

解决思路一:整体右旋

             

原数组分为两部分

假设需要右旋k个数字

以原数组末尾k个数字为一组剩下其他数字为一组

两组进行调换,即可实现

              

图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言

对应代码:
void rotate(int* nums, int numsSize, int k){
    
    //用空间换时间:

    int n = numsSize; //数组长度

    int* tmp = (int*)malloc(sizeof(int)*n);

    k %= n; //确保要右旋个数小于数组大小
    
    //直接使用memcpy函数进行调换:

    memcpy(tmp, nums+n-k, sizeof(int)*k); //把后k个值移到前面
    // tmp : 起始位置
    // nums+n-k : 数组nums后k个值的起始位置
    // sizeof(int)*k :拷贝k个int大小的数据

    memcpy(tmp+k, nums, sizeof(int)*(n-k)); //把后k个值移到前面
    // tmp+k : 拷贝到tmp+k的位置,因为上面把后k个值放在了前面
    // nums : 数组nums开始位置
    // sizeof(int)*(n-k) :拷贝(n-k)个int大小的数据

    //再赋给数组nums:
    memcpy(nums, tmp, sizeof(int)*n);

    //释放开辟的动态空间:
    free(tmp);
}

           

解决思路二:逆置

             

将原数组的前 n-k 个数逆置

后 k 个数也逆置

最后再整体逆置,即可实现

              

图示:

【数据结构初阶】一. 复杂度讲解,CCC全是C,数据结构,c语言文章来源地址https://www.toymoban.com/news/detail-695106.html

对应代码:
//逆置函数:
void reverse(int* a, int left, int right)
{
    while(left < right)
    {
        int tmp = a[left];
        a[left] = a[right];
        a[right] = tmp;
        ++left;
        --right;
    }
}

void rotate(int* nums, int numsSize, int k){
    k %= numsSize;

    //逆置前 n-k 个数:
    reverse(nums, 0, numsSize-k-1);

    //逆置后 k 个数:
    reverse(nums, numsSize-k, numsSize-1);

    //最后整体逆置:
    reverse(nums, 0, numsSize-1);
}

到了这里,关于【数据结构初阶】一. 复杂度讲解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构 --- 复杂度概念及计算讲解(时间复杂度,空间复杂度)

    今天没有sao话,今天认真学习 前言: 经常刷题的人都知道,我们在解决一道题时可能有多个解法,那么如何判断那个解法才是最优解呢? 我们通常从代码的两个方面进行判断:1.时间 2.空间。 –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀

    2024年03月22日
    浏览(43)
  • 数据结构——复杂度讲解

    复杂度是我们学习数据结构的第一节,下面是我对该知识内容的一些理解。 1.什么是数据结构 概念:数据结构是计算机存储、组织数据的方式,指互相之间存在的一种或多种特定关系的数据元素的集合。 在实现一些项目时,需要在内存中将数据存储起来,存储需要各种方式

    2024年02月20日
    浏览(28)
  • 数据结构学习分享之复杂度讲解

    在我们学习完C语言的所有内容后,现在就可以开始我们的数据结构的学习,如果有读者也想走C/C++研发方向,可以跟着我一起往后学. 本篇文章将收于专栏 数据结构学习分享, 会持续更新内容. 数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定

    2024年02月01日
    浏览(29)
  • 数据结构_复杂度讲解(附带例题详解)

    数据结构是计算机科学中研究数据组织、存储、管理和操作的方法和原则。它涉及到各种不同的数据类型和数据组织方式,包括数组、链表、树、图等。数据结构的设计和实现可以影响到程序的效率和可靠性,因此是计算机科学中非常重要的一个领域。 (数据结构是计算机存

    2024年02月07日
    浏览(46)
  • 数据结构----完全二叉树的时间复杂度讲解,堆排序

    目录 一.建堆的时间复杂度 1.向上调整算法建堆 2.向下调整算法建堆 二.堆排序 1.概念 2.代码思路 3.代码实现 我们就以极端情况考虑时间复杂度(满二叉树+遍历所有层) 假设所有节点个数为N,树的高度为h N = 2^0+2^1+2^2......+2^(h-1) 即N = 2^h - 1 h = log(N+1) 时间复杂度我们以交换次数为

    2024年03月14日
    浏览(62)
  • 数据结构(时间复杂度,空间复杂度)

    算法的时间复杂度是一个数学函数,算法中的基本操作的执行次数,为算法的时间复杂度。 1.大O的表示法 2.推导大O表示法 1、用常数1取代运行时间中的所有加法常数。 2、在修改后的运行次数函数中,只保留最高阶项。 3、如果最高阶项存在且不是1,则去除与这个项目相乘的

    2024年02月07日
    浏览(47)
  • 数据结构 — 时间复杂度、空间复杂度

    数据结构_空间复杂度_时间复杂度讲解_常见复杂度对比 本文介绍数据结构中的时间复杂度和空间复杂度 ***文章末尾,博主进行了概要总结,可以直接看总结部分*** 博主博客链接:https://blog.csdn.net/m0_74014525 点点关注,后期持续更新系列文章 算法效率指的是算法在处理数据时

    2024年02月13日
    浏览(48)
  • 数据结构——时间复杂度和空间复杂度

    1.算法效率 2.时间复杂度 3.空间复杂度 4. 常见时间复杂度以及复杂度oj练习 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法的好坏呢?比如对于以下斐波那契数的计算 我们看到虽然用递归的方式实现斐波那契很简单,但是简单一定代表效率高吗? 我们接着往下看。

    2024年02月13日
    浏览(45)
  • 数据结构入门 — 时间复杂度、空间复杂度

    数据结构_空间复杂度_时间复杂度讲解_常见复杂度对比 本文介绍数据结构中的时间复杂度和空间复杂度 ***文章末尾,博主进行了概要总结,可以直接看总结部分*** 博主博客链接:https://blog.csdn.net/m0_74014525 点点关注,后期持续更新系列文章 算法效率指的是算法在处理数据时

    2024年02月13日
    浏览(49)
  • 数据结构之时间复杂度-空间复杂度

    大家好,我是深鱼~ 目录 1.数据结构前言 1.1什么是数据结构 1.2什么是算法 1.3数据结构和算法的重要性 1.4如何学好数据结构和算法 2.算法的效率 3.时间复杂度 3.1时间复杂度的概念 3.2大O的渐进表示法 【实例1】:双重循环的时间复杂度:O(N) 【实例2】:双重循环的时间复杂度

    2024年02月14日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包