数据结构(复杂度)

简介: 数据结构(复杂度)

前言 

 这是我学习数据结构的第一份笔记,有关复杂度的知识。后期我会继续将数据结构知识的笔记补全。


数据结构含义

1. 通过数据结构,有利于把杂乱无章的数据,进行管理操作。

2. 数据结构有很多种,例如:数组等。


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
  int a = 1;//直接赋值给变量
  int arr[1000];
  arr[0] = 55;//通过数组这种数据结构,从而对数组里面的变量进行赋值
}


算法的含义

1. 通过一系列的计算步骤,将输入的数据转化成结果。


复杂度

复杂度的含义

1. 复杂度用来衡量一个算法的好坏。

2. 复杂度分为时间复杂度和空间复杂度。

3. 时间复杂度(主要):算法运行的快慢。

4. 空间复杂度:算法运行所需要的额外空间。


时间复杂度

可以表示为一个函数式:T(N) 。


计算时间复杂度的公式

1. n:程序运行时间效率。

2. a:每条语句的运行时间(注:a不是一个确定的值,与编译环境有关。)

3. b:每条语句的运行次数(注:b是一个确定的值。)


计算程序运行时间

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
int main()
{
  int begin=clock();//记录程序刚开始的时间
  int count = 0;
  for (int i = 0; i < 10000000; i++)
  {
    count++;
  }
  int end = clock();//记录程序刚结束的时间
  printf("%d", end - begin);//需要在debug模式下
  return 0;
}
//多运行几次都不同,没有精确值


大O的渐进表示法

1. 大O符号:用于描述函数渐进行为的符号。例如:O(N^2)

2. 我们通过大O的渐进表示法,来计算运行的次数。

3. 大O的渐进表示法的规则:

  1.        只看最高阶项。
  2.        如果存在最高阶项,则忽略其系数和其他常数项。
  3.        如果只有常数项,则直接视为1。
  4.        重点看循环或递归次数。


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
void Func1(int N) 
{
    int count = 0;
    // 第一个循环:N * N 次迭代
    for (int i = 0; i < N; ++i) 
    {
        for (int j = 0; j < N; ++j) 
        {
            ++count;
        }
    }
    // 第二个循环:2 * N 次迭代
    for (int k = 0; k < 2 * N; ++k) 
    {
        ++count;
    }
    // while 循环:10 次迭代
    int M = 10;
    while (M--) 
    {
        ++count;
    }
}
    //T(N)=N^2+2N+10
    //复杂度为:O(N^2)
void Func2(int N)
{
    int count = 0;
    // 这个循环将执行 2 * N 次
    for (int k = 0; k < 2 * N; ++k)
    {
        ++count;
    }
    // 这个循环将执行 10 次
    int M = 10;
    while (M--)
    {
        ++count;
    }
    printf("%d\n", count);
}
    //T(N)=2*N+10
    //复杂度为:O(N)
void Func3(int N, int M)
 {
    int count = 0;
    // 这个循环将执行 M 次
    for (int k = 0; k < M; ++k)
    {
            ++count;
    }
    // 这个循环将执行 N 次
    for (int k = 0; k < N; ++k)
    {
        ++count;
    }
    printf("%d\n", count);
}
    //T(N)=M+N
    //复杂度为:O(M+N)
void Func4(int N) 
{
    int count = 0;
    // 这个循环将执行 100 次
    for (int k = 0; k < 100; ++k) 
    {
        ++count;
    }
    printf("%d\n", count);
}
    //T(N)=100
    //复杂度为:O(1)
const char * strchr ( const char* str, int character)
{
    const char* p_begin = s;
    while (*p_begin != character)
    {
        if (*p_begin == '\0')
        {
                return NULL;
         }
        p_begin++;
    }
    return p_begin;
}
 
    //上界:最坏的情况O(N),若要查找的字符在字符串第⼀个位置。
    //下界:最好的情况O(1),若要查找的字符在字符串最后的⼀个位置。
    //主要关注上界最差的情况
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define N
int main()
{
  int arr[N] = { 0 };
  int i = 0;
  for (i = 0; i < N; i++)
  {
    scanf("%d", &arr[i]);
  }
  int a = 0, b = 0;
  for (a = 0; a < N-1; a++)
  {
    for (b = 0 ; b < N-1-a; b++)
    {
      if (arr[b] > arr[b + 1])
      {
        int mid = 0;
        mid = arr[b + 1];
        arr[b + 1] = arr[b];
        arr[b] = mid;
      }
    }
  }
  for (i = 0; i < N; i++)
  {
    printf("%d\n", arr[i]);
  }
  return 0;
}
    //T(N)=N(N-1)/2
    //复杂度为:O(N^2)

void func5(int n) 
{
    int cnt = 1;
    while (cnt < N) 
    {
        cnt *= 2;
    }
}
    //T(N)=log(N),不管底数。

long long Fac(size_t N) 
{
    if (0 == N)
    {
        return 1;
    }
    return Fac(N - 1) * N;
}
    //T(N)=N
    //复杂度为:O(N)

上下界

最坏情况:任意输⼊规模的最⼤运⾏次数(上界)

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

最好情况:任意输⼊规模的最⼩运⾏次数(下界)


空间复杂度

计算空间复杂度

1. 专指函数在运行时所额外占用的空间。

2. 规则与时间复杂度相同。

3. 重点看定义的变量个数。

void BubbleSort(int* a, int n) 
{
    assert(a);
    for (size_t end = n; end > 0; --end) //第一个end
    {
        int exchange = 0;//第二个exchange
        for (size_t i = 1; i < end; ++i) //第三个i
        {
            if (a[i - 1] > a[i])
            {
                Swap(&a[i - 1], &a[i]);
                exchange = 1;
            }
        }
        if (exchange == 0)
            break;
    }
}
    //空间复杂度为:O(1)

long long Fac(size_t N) 
{
    if (N == 0)
        return 1;
    return Fac(N - 1) * N;//第一个Fac(N - 1) * N
}
    //空间复杂度为:O(N),每一次递归,空间复杂度增加一次。

复杂度的大小


总结

若在算法题型中,如果时间复杂度超过要求,则可以提高空间复杂度来降低时间复杂度。


例题:轮转数组

将一个数组的元素向后移k位。


void rotate(int* nums, int numsSize, int k)
{
    while(k--)
    {
        int end = nums[numsSize-1];
        for(int i = numsSize - 1;i > 0 ;i--)
        {    
            nums[i] = nums[i-1];
        }
        nums[0] = end;
    }
}
//通过两个内外层循环从而达到目标
 
改进后:
void rotate(int* nums, int numsSize, int k)
{
    int newArr[numsSize];
    for (int i = 0; i < numsSize; ++i)
    {
        newArr[(i + k) % numsSize] = nums[i];
    }
    for (int i = 0; i < numsSize; ++i)
    {
        nums[i] = newArr[i];
    }
}
//通过创建一个新的数组从而达到目标

致谢

感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能!

相关文章
|
7月前
|
机器学习/深度学习 存储 算法
【算法与数据结构】复杂度深度解析(超详解)
【算法与数据结构】复杂度深度解析(超详解)
【算法与数据结构】复杂度深度解析(超详解)
|
7月前
|
存储 算法
数据结构与算法:复杂度
数据结构: 数据结构是用于存储和组织数据的方式,以便可以有效地访问和修改数据。不同的数据结构适用于不同类型的应用,并且具体的数据结构可以大幅影响程序的性能。数据结构分为两大类:线性数据结构和非线性数据结构。 算法: 算法是完成特定任务的一系列操作步骤,是解决问题的明确规范。算法的效率通常通过时间复杂度和空间复杂度来评估,即算法执行所需的时间和空间资源。
|
2月前
|
存储 机器学习/深度学习 算法
探索数据结构:入门及复杂度的解锁
探索数据结构:入门及复杂度的解锁
|
4月前
|
机器学习/深度学习 存储 算法
【初阶数据结构篇】时间(空间)复杂度
复杂度是计算机科学中的一个基础概念,它帮助我们理解和评估算法的效率,对于算法设计和优化至关重要。
47 2
【初阶数据结构篇】时间(空间)复杂度
|
4月前
|
算法
【初阶数据结构】复杂度算法题篇
该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 kmodn 个元素会移动至数组头部,其余元素向后移动 kmodn 个位置。
30 1
|
5月前
|
机器学习/深度学习 存储 算法
【数据结构】算法的复杂度
算法的时间复杂度和空间复杂度
82 1
【数据结构】算法的复杂度
|
4月前
|
存储 算法
【数据结构】复杂度(长期维护)
【数据结构】复杂度(长期维护)
|
7月前
|
存储 算法 C语言
数据结构与算法②(复杂度相关OJ)(六道数组OJ题)(上)
数据结构与算法②(复杂度相关OJ)(六道数组OJ题)
59 2
|
6月前
|
算法 搜索推荐
数据结构和算法——表排序(算法概述、物理排序、复杂度分析,包含详细清晰图示过程)
数据结构和算法——表排序(算法概述、物理排序、复杂度分析,包含详细清晰图示过程)
54 0
|
6月前
|
存储 机器学习/深度学习 算法
数据结构和算法学习记录——空间复杂度的计算(冒泡排序、阶乘递归、斐波那契数列递归、常见复杂度对比、栈帧、栈溢出)
数据结构和算法学习记录——空间复杂度的计算(冒泡排序、阶乘递归、斐波那契数列递归、常见复杂度对比、栈帧、栈溢出)
51 0