【C语言数据结构】空间复杂度和时间复杂度(详细分析)

目录

1. 数据结构介绍

2.算法介绍

3.时间复杂度,(空间复杂度)


1.数据结构介绍

首先我们讲解一下什么是数据结构(从今天开始,博主要开始学习数据结构啦,以后再学习算法会给大家分享更多深入浅出的干货!)

 这个听起来就很高大上的名字,其实是计算机存储和组成数据的方式,他是一些数据元素的组合,这些元素之间相互存在着一些一种或者多种的联系

我们学习数据结构是为了更好的了解计算机工作的原理,实现更好的人机交流

2.算法

和数学公式一样,其实算法就是对于某一类计算机问题的   总结好的  特定实现思路

比如说我现在做到一个题目,需要用到排序

这时候我们就想到一些排序的方法,这些方法就相当于算法,当然算法不是这么简单的,也有很多很有技巧的,这里只是为了举例子

所以算法就是对于某一种特定问题(比如排序)的具体实现形式(堆排,快排,冒泡..)

3.时间复杂度

首先解释什么是复杂度

对于两个算法(比如冒泡和堆排),应用到实际问题里谁更好呢?难道我说第一个更好就一定是对的吗

当然有一个衡量标准:复杂度

复杂度分为两种:时间,空间

但是主要说的还是时间复杂度

因为

时间复杂度:一个关于时间的函数,用来描述一个程序结束之后,某一部分被调用的次数,用俩衡量算法的效率

空间复杂度:程序运行需要额外开辟的空间的大小

而我们知道,随着时间的推移,现在的电脑内存已经很大了,空间复杂度已经不作为特别重要的参考依据,并且计算空间复杂度本身也不是特别复杂

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

现在是这样的过程,所以总共的次数应该是加起来

但是真的有这么麻烦吗

我们来看一段代码

#include <time.h>
#include <stdio.h>
int main()
{
	int begin=clock();
	int count = 0;
	for (size_t i = 0; i < 1000; i++)
	{
		count++;
	}
	int end = clock();
	printf("%d毫秒\n", end - begin);
	return 0;
}

 这个代码调用一个<time.h>的函数来实现整个程序运行时间的计算

 其实如果我们把数字再改的更大

 

 5毫秒真的是很短的时间,也就是在循环中,常数次的循环其实时间上来讲和一次没很大区别

这里我们用到一个大O渐进的方法来表示时间复杂度

常数次的调用定义为O(1)

大O渐进:

常数次都当成1次

系数不影响阶   可以忽略(O(2*N)=O(N))

抓大头  O(N^2+2*N+10)=O(N^2)

需要注意的是,以后我们计算时间复杂度的题目可能都不会给出代码,因为最重要的是思想,训练的就是给一个函数我立马就能想起来他用的什么方法实现的!!!!!

 来看他的时间复杂度

 这个时候我们就蒙了,这个字符到底出现在哪里我是不知道的

所以我们提出

最好情况:一次找到

最坏情况:(假设字符串长度为n)n次找到

平均情况:N/2

但是我们思考一下就知道,只有最坏情况才是真正有意义的 

所以定义:在这种很蒙的情况,最坏情况对应的时间复杂度就是我们要找的时间复杂度

对于上面strchr函数的时间复杂度就是O(N)

再看一个

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

 根据大O渐进的方法,最后的时间复杂度就是O(N)

冒泡排序的时间复杂度是多少呢

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

所以一个数字需要的次数分别是N ,N-1,N-2,...........,2

等差数列

就是O(N^2)

 递归的时间复杂度呢

long long Fac(size_t N)
{
if(0 == N)
return 1;
return Fac(N-1)*N;
}

 注意我们在这里不能以为往下递和往上推各有N次一共就是2*N

在递归函数的时间复杂度里,我们定义每次递归调用的函数次数累加就是最后的结果

3.2 空间复杂度

其实就是在程序里 定义的变量,或者新开辟空间的大小

还是符合大O渐进的规则

常数个还是令为O(1)

递归的空间复杂度就是每次递归调用的变量个数的累加,最多有多少个栈帧

不是递归就算一个栈帧里有多少个变量

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

现在问冒泡排序里面的空间复杂度是多少呢

一看肯定是常数个所以O(1)

 

再来看斐波那契的空间复杂度

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

 其实只要有这个N+1,我们就知道别的常数个可以都不看了

O(N)

再看一个递归

long long Fac(size_t N)
{
if(N == 0)
return 1;
return Fac(N-1)*N;
}

一共创建了N+1个栈帧所以空间复杂度是O(N)

本文到此结束啦,相信你一定收获满满

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值