【学习笔记之数据结构】时间复杂度与空间复杂度

简介: 【学习笔记之数据结构】时间复杂度与空间复杂度

一、算法效率


 算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。

 时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。


二、时间复杂度


 定义:在计算机科学中,算法的时间复杂度是一个函数(数学中带未知数的函数式),它定量描述了改算法的运行时间。一个算法执行所耗费的时间,从理论上说,不能计算的,只有把程序放在机器上跑起来,才能知道。但是如果每个算法都进行上机测试会非常的麻烦,所以引入时间复杂度分析方式。一个算法所花费的时间与程序中语句的执行次数成正比,算法中的基本操作的执行次数,就是算法的时间复杂度。

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

 因为计算机的运行速率是非常快的,所以我们不用精确的算出执行次数,只需要计算出大概次数就行了。这里就需要引入渐进表示法。

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


  1. 用常数1取代运行时间中的所有加法常数;
  2. 在修改后的运行次数函数中,只保留最高阶项(去掉其他项对结果的影响不大);
  3. 如果最高阶存在且不是1, 则取出与这个项目相乘的常数。得到的结果就是大O阶。
  4. 部分算法的时间复杂度存在最好、平均和最坏情况:
  5.  最坏情况:任意输入规模的最大运行次数(上界);
  6.  平均情况:任意输入规模的期望运行次数;
  7.  最好情况:任意输入规模的最小运行次数(下界)。
  8. 在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(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);
}


aaf467228b654a71a5c1b65d175fa45a.png


// 计算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);
}

be5bd02447b047ac8d6b637770a83c7d.png

// 计算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);
}

bc974e1068d542a2ba06ac0f508fe5de.png

// 计算Func4的时间复杂度?
void Func4(int N) {
  int count = 0;
  for (int k = 0; k < 100; ++k)
  {
    ++count;
  }
  printf("%d\n", count);
}


8044a846f4544cd9ab0ecccbc336e362.png

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

a053e48b42e44b15bb5c920d0621cf52.png

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

048e83f7fda64f4b8f6608b0d5856f65.png


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

d55d4deea5df4c2ebd912d7fca7d4d1d.png


三、空间复杂度


 空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。

 空间复杂度计算的是变量的个数,计算规则与时间复杂度类似,也是使用大O渐进表示法。

 函数运行是所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行显式申请的额外空间来确定。


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

c9bcdb462d014ed9a1b13a616748ec68.png

// 计算Fibonacci的空间复杂度?
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;
}

de24ecf79fc843a4a13e36188b3db2e4.png

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

6a95d021dc2a42f79032853539c243ba.png



目录
相关文章
|
7月前
|
算法 搜索推荐 程序员
数据结构中时间复杂度的介绍
冒泡排序是通过重复遍历数组,比较并交换相邻元素来排序数组的。因为它包含两层嵌套循环,每层循环的最大迭代次数近似于n,所以时间复杂度是O(n²)。 通过上述分析,我们可以看到不同代码结构对算法性能有着显著的影响。在设计数据结构和算法时,理解并计算时间复杂度是非常重要的,它帮助程序员选择或优化算法,以处理更大的数据集或提高程序的运行速度。
62 2
|
3月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
61 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
7月前
|
存储 算法 C语言
数据结构中的空间复杂度
优化空间复杂度对于提升程序性能和资源利用率至关重要,特别是在资源受限的环境(如嵌入式系统和移动设备)中。高效的数据结构和算法设计可以显著提升程序的执行效率和可扩展性。 综上所述,理解和优化空间复杂度是设计高效数据结构和算法的关键。通过分析常见数据结构的空间复杂度,并结合实际代码示例,我们可以更好地理解这一重要概念,并在实际编程中应用这些知识。希望本文能帮助你更好地掌握空间复杂度及其在数据结构中的应用。
54 2
|
3月前
|
机器学习/深度学习 存储 算法
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
|
4月前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
3月前
|
算法
[数据结构] -- 时间复杂度和空间复杂度
[数据结构] -- 时间复杂度和空间复杂度
33 0
|
5月前
|
存储 算法
【数据结构】——时间复杂度与空间复杂度
【数据结构】——时间复杂度与空间复杂度
|
7月前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
7月前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
292 9

热门文章

最新文章