C语言数据结构时间复杂度及空间复杂度简要分析

目录
  • 一、时间复杂度和空间复杂度是什么?
    • 1.1算法效率定义
    • 1.2时间复杂度概念
    • 1.3空间复杂度概念
  • 二、如何计算常见算法的时间复杂度和空间复杂度
    • 2.1时间复杂度计算
    • 2.2空间复杂度计算
    • 2.3快速推倒大O渐进表达法
  • 三、一些特殊的情况
  • 总结

一、时间复杂度和空间复杂度是什么?

1.1算法效率定义

算法效率分为两种,一种是时间效率——时间复杂度,另一种是空间效率——空间复杂度

1.2时间复杂度概念

时间复杂度,简言之就是你写一个代码,它解决一个问题上需要走多少步骤,需要花费多长时间。打个简单的比方:现在给10个数,要求找到7在哪里1,2,3,4,5,6,7,8,9,10。我们要求写一个代码,同学狗蛋写了一个暴力查找,从第一个数依次往后遍历,他的算法要找7次,同学狗剩写了一个二分法查找,只要找2次,这就是时间复杂度的比较
算法中的基本操作的执行次数,为算法的时间复杂度

1.3空间复杂度概念

空间复杂度,是对一个算法在运行过程中临时占用存储空间大小的量度。举个栗子:我们现在要求写一个代码,狗蛋啪啪啪敲了一大堆变量,程序运行了,狗剩就用了很少的变量,程序也运行了。但是他们两个在代码运行中变量多少不同,占用的内存多少是不一样的。空间复杂度,它计算的是变量的个数。

二、如何计算常见算法的时间复杂度和空间复杂度

我们在计算时间/空间复杂度时用的都是大O渐进表示法(是一种估算法)

2.1时间复杂度计算

我们以一个简单的函数举例
代码如下:

void func1(int n)
{
	int i = 0;
	int j = 0;
	int k = 0;
	int count = 0;
	for (i = 0;i < n;i++)
	{
		for (j = 0;j < n;j++)
		{
			count++;
		}
	}
	for (k = 0;k < 3 * n - 1;k++)
	{
		count++;
	}
}

试问:该函数如果被调用,要运行多少次?
我们清楚的看出i进去有n次,共有n个i,第一个for结束要运行n^ 2次,第二个for要执行3n-1次,共执行n^ 2+3n-1次
那么我们这里的时间复杂度是否就是n^2+3n-1呢?答案是否的
我们前面说过,时间复杂度和空间复杂度用的都是大O渐进表示法,是一种估算法

我们取的值,是取对表达式中影响最大的那个

我们以n^ 2+3 * n-1这个式子进行举例:设f(n)=n^2+3n-1
n=1,f(n)=1+3-1=3
n=10,f(n)=100+30-1=129
n=100,f(n)=10000+300-1=10299
n=1000,f(n)=1002999

很容易发现,对f(n)影响最大的是n^ 2,设g(n)=n^2
n=1,g(n)=1
n=10,g(n)=100
n=100,g(n)=10000
n=1000,g(n)=1000000

当n越大,g(n)就越接近f(n)
那么这里的时间复杂度大O渐进表达法写法是这样的:O(n^2)

2.2空间复杂度计算

在学习空间复杂度的求解之前,我们要知道,空间复杂度也是用大O渐进表达法进行求解,我们计算的不是所占空间大小,而是变量的个数。先来看一段代码:
代码如下(示例):

#include<stdio.h>
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;
	}
}

在上面这个代码中,我们创建了三个变量分别是size_t endint exchangesize_t i,尽管我们这个函数会经历很多的循环,但这三个变量是反复使用的,也就是说他们所占的空间是被反复使用的,空间的多少是没有变的,这里区别时间复杂度——时间是累计的,空间是不累计的(对于时间复杂度,每次循环都会被计算;对于空间复杂度,空间是可以被反复使用的)。

我们上面说过,空间复杂度计算也是用的大O渐进表示法,对于常数,我们统一用O(1)表示(大O渐进表示法详情见时间和空间复杂度篇1)

ps1:assert通常用于诊断程序中潜在的BUG,通过使用assert(condition), 当condition为false时,程序提前结束运行,利于程序BUG的定位。
ps2:size_t是一种类型,把它看作long unsigned int

我们再来看一段代码:
代码如下(示例):

//计算bubblesort的空间复杂度
#include<stdio.h>
long long Factorial(size_t n)
{
	return N < 2 ? N : Factorial(n - 1)*n;
}

这段代码是一个很简单的递归实现阶乘运算,那么它的空间复杂度是多少呢?我们先假设传过去的n=10。

10传过来我们会进行10次递归,每次递归是创建一个函数栈帧(也就是一个空间),共创建10次,每一次的空间复杂度都是O(1)。把10换成n,也就是进行n次递归,每次递归会创建1个函数栈帧,空间复杂度是O(n)。

ps:可能会有小伙伴问,那函数栈帧递归往回走的时候不是销毁了吗?注意:这里的空间复杂度是计算的“最坏、最多的情况”,况且不管是什么函数,在使用过后其栈帧都会销毁,空间复杂度算的是它用的空间最多的时候。

2.3快速推倒大O渐进表达法

1.常数1代替所有加法运算中的常数
2.只保留最高阶(高数极限思想)
3.若最高阶存在且不为常数,则去除最高阶的系数,比如3*n^ 9,去掉系数变为n^9

我们再来看两个代码训练一下
代码1如下:

void func2(int n)
{
	int i = 0;
	int k = 0;
	int count = 0;
	for (i = 0;i < 3n;i++)
	{
		count++;
	}
	for (k = 0;k < 6;k++)
	{
		count++;
	}
}

这里f(n)=3n+6,它的大O渐进表达法就是O(n)

代码2如下:

void func3(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0;i < 1000;i++)
	{
		count++;
	}
}

这里一眼就看出是运行1000次,用什么来表示呢?前面说过:常数1代替所有加法运算中的常数,所以这里不管常数有多大,只要你只有一个常数都用O(1)表示

一些注意事项:

O(1)这个时间复杂度的估值是不随n的改变而改变的,以大白话说,不管你输入的n是多少,我这个算法的效率是不变的

O(n)这个时间复杂度是随n改变的
打个通俗的比方:设一个函数O(x)=1,那你x随意多少,函数值都是1
设一个函数O(X)=x,那这里函数值就随x变换而变换了

三、一些特殊的情况

有些算法的时间复杂度是存在最好、平均、最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
不多说,举例说明:
代码如下:

const char*strchr(char*str, char c)
{
	while (*str != '\0')
	{
		if (*str == c)
		{
			return str;
		}
		++str;
	}
	return NULL;
}

上面的代码是一个简单的查找字符的函数,比如我们现在给一串字符共n个字符“aaaaba…aaac”(省略号省略a)
这里查找a一下子就找到了,查找b要点功夫,查找c就更慢了,如果查找d,不好意思,查无此d。
那么这里就出现了最好情况:一次找到O(1)
平均情况:O(n/2)
最差情况:O(n)
对于这里最坏情况可能有同学要说为什么是O(n),你看最坏情况没找到不是吗?这里解释是这样的,你找c要n次,找d是找不到也要找n次才能确定找不到。

总结

本文介绍了时间和空间复杂度的定义及大O渐进表达法的算法及一些特殊情况的解释,希望对屏幕前的读者有所帮助,祝您学习愉快!

以上就是C语言数据结构时间复杂度及空间复杂度简要分析的详细内容,更多关于数据结构时间复及空间复杂度的资料请关注我们其它相关文章!

(0)

相关推荐

  • 理解数据结构

    从宏观上理解数据结构     1.数据结构对编程为什么如此重要? 现在就根据我自己的体会来为大家阐述一下数据结构对我们编程为什么如此重要.记得在开始学习编程的时候,对数据结构没什么概念,感觉编程就是那么回事,不用数据结构也能编出一大堆程序,然而我只能说那都是些小孩子过家家玩的小程序而已,程序中几乎没有用到多少数据,无论你怎么存储,程序运行起来都是很快的.然而当你为工程应用去编写程序的时候,那都是处理大批的数据,那时候就不能随便乱存储数据了,必须根据实际情况选择一种合适的数据结构来存储数据,从而能

  • C语言编程数据结构线性表之顺序表和链表原理分析

    目录 线性表的定义和特点 线性结构的特点 线性表 顺序存储 顺序表的元素类型定义 顺序表的增删查改 初始化顺序表 扩容顺序表 尾插法增加元素 头插法 任意位置删除 任意位置添加 线性表的链式存储 数据域与指针域 初始化链表 尾插法增加链表结点 头插法添加链表结点 打印链表 任意位置的删除 双向链表 测试双向链表(主函数) 初始化双向链表 头插法插入元素 尾插法插入元素 尾删法删除结点 头删法删除结点 doubly-Linked list.c文件 doubly-Linkedlist.h 线性表的定

  • 数据结构之归并排序的实例详解

    归并排序 基本思想         归并排序是建立在二路归并和分治法的基础上的一个高效排序算法,将已有序的子序列合并,得到完全有序的序列:即先使每个子序 列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表:将这些有序序列 再次归并,得到n/4个长度为4的有序序列:如此反复进行下去,最后得到一个长度为n的有序序列.所以呢,我们总结一下归并排序 其实就只有两步:

  • 用C语言举例讲解数据结构中的算法复杂度结与顺序表

    数据结构算法复杂度 1.影响算法效率的主要因素 (1)算法采用的策略和方法: (2)问题的输入规模: (3)编译器所产生的代码: (4)计算机执行速度. 2.时间复杂度 // 时间复杂度:2n + 5 long sum1(int n) { long ret = 0; \\1 int* array = (int*)malloc(n * sizeof(int)); \\1 int i = 0; \\1 for(i=0; i<n; i++) \\n { array[i] = i + 1; } for(

  • C语言数据结构时间复杂度及空间复杂度简要分析

    目录 一.时间复杂度和空间复杂度是什么? 1.1算法效率定义 1.2时间复杂度概念 1.3空间复杂度概念 二.如何计算常见算法的时间复杂度和空间复杂度 2.1时间复杂度计算 2.2空间复杂度计算 2.3快速推倒大O渐进表达法 三.一些特殊的情况 总结 一.时间复杂度和空间复杂度是什么? 1.1算法效率定义 算法效率分为两种,一种是时间效率--时间复杂度,另一种是空间效率--空间复杂度 1.2时间复杂度概念 时间复杂度,简言之就是你写一个代码,它解决一个问题上需要走多少步骤,需要花费多长时间.打个

  • C语言数据结构通关时间复杂度和空间复杂度

    目录 1.时间复杂度: 1.常数阶 2.线性阶 3.对数阶 4.平方阶 2.算法空间复杂度 算法的时间复杂度和空间复杂度 1.时间复杂度: 首先,为什么会有这个概念的出现呢? 原来啊,在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级.算法的时间复杂度,也就是算法的时间量度,记作T(n) = O(f(n)).它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度,其中f(

  • C语言数据结构与算法之时间空间复杂度入门

    目录 数据结构与算法 什么是数据结构?什么是算法? 分析维度 大O的渐进表示法 常数阶 线性阶 对数阶 其他时间复杂度指标 空间复杂度 数据结构与算法 终于开始搞这块难啃的骨头了,走上这条漫漫长路之前要明白: 什么是数据结构?什么是算法? 是数据之间存在一种或多种特定关系的数据元素集合,为编写出一个“好”的程序,必须分析待处理对象的特性及各处理对象之间存在的关系,这也就是研究数据结构的意义所在为编写出一个“好”的程序,必须分析待处理对象的特性及各处理对象之间存在的关系这也就是研究数据结构的意义所

  • C语言 超详细讲解算法的时间复杂度和空间复杂度

    目录 1.前言 1.1 什么是数据结构? 1.2 什么是算法? 2.算法效率 2.1 如何衡量一个算法的好坏 2.2 算法的复杂度 2.3 复杂度在校招中的考察 3.时间复杂度 3.1 时间复杂度的概念 3.2 大O的渐进表示法 3.3 常见时间复杂度计算举例 4.空间复杂度 5. 常见复杂度对比 1.前言 1.1 什么是数据结构? 数据结构(Data Structure)是计算机存储.组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合. 1.2 什么是算法? 算法(Algorit

  • C语言数据结构之算法的时间复杂度

    目录 1.算法的复杂度 2.时间复杂度 2.1 时间复杂度的定义 2.2 大O的渐进表示法 3.常见时间复杂度计算举例 3.1 冒泡排序的时间复杂度 3.2 二分查找的时间复杂度 3.3 阶乘(递归)的时间复杂度 3.4菲波那切数列的时间复杂度 1.算法的复杂度 算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 .因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度. 时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的

  • C语言三分钟精通时间复杂度与空间复杂度

    目录 一.时间复杂度 1)O(n)的含义 2)复杂表达式的简化 3)O(n)不一定优于O(n^2) ​4)递归的时间复杂度 二.空间复杂度 1)O(1)空间复杂度​ 2)​​​​​​​O(n)空间复杂度​ 3)​​​​​​​O(mn)空间 复杂度​ 4)递归算法空间算法复杂度分析​ 一.时间复杂度 1)O(n)的含义 程序消耗的时间用算法的操作单元数来表示 假设数据的规模为n,则用f(n)表示操作单元数的大小,而f(n)常被简化 O表示的是一般的情况,而不是上界或下界.并且它是在数据量级非常大的

  • C语言数据结构与算法时间空间复杂度基础实践

    目录 小感想 时间复杂度 空间复杂度 小感想 今天去看了看许多人今年去各个大厂面试的面经,确实如大体所说,各大公司越来越注重性能迭代,时代需要数据结构与算法这样的考试. 一个公司的成本主要来自于人力成本,但是上了规模写核心代码的人少了,成本就会来自于机器,资源,时间,抢占到这些就相当于无时无刻在减少客户流失.所以同样一段代码给两个人写,甲拿 8000,乙拿 25000,但是后者效率提高了50%,而这50%带来的收益远远超过了(25000-8000),这就是为什么许多大厂要给出如此吸引人的高薪资来

  • C语言 详细解析时间复杂度与空间复杂度

    目录 一.概念 1.1.算法效率 1.2.时间复杂度 1.3.空间复杂度 二.计算 2.1.大O的渐进表示法 2.2.时间复杂度计算 2.3.空间复杂度计算 三.有复杂度要求的习题 一.概念 1.1.算法效率 如何衡量一个算法的好坏?比如对于以下斐波那契数列: long long Fib(int N) { if (N < 3) return 1; return Fib(N - 1) + Fib(N - 2); } 斐波那契数列用递归实现方式非常简洁,但简洁一定好吗?那该如何衡量其好与坏呢?在学完

  • Java数据结构通关时间复杂度和空间复杂度

    目录 算法效率 时间复杂度 空间复杂度 小结 算法效率 算法效率分析分为两种:第一种是时间效率,第二种是空间效率.时间效率被称为时间复杂度,而空间效率被 称作空间复杂度. 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额 外空间,在计算机发展的早期,计算机的存储容量很小.所以对空间复杂度很是在乎(以前是以时间换空间).但是经过计算机行业的 迅速发展,计算机的存储容量已经达到了很高的程度.所以我们如今已经不需要再特别关注一个算法的空间复 杂度(现在是以空间换时间).

  • C语言算法的时间复杂度和空间复杂度

    目录 1.算法效率 1.1 如何衡量一个算法的好坏 1.2算法的复杂度 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3常见时间复杂度计算举例 3.空间复杂度 4.常见复杂度对比 5.复杂度的OJ练习 5.1消失的数字OJ 3.2 旋转数组OJ 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法的好坏呢?比如对于以下斐波那契数列: long long Fib(int N) { if (N < 3) return 1; return Fib(N - 1) +

随机推荐