第2节 判断程序的质量

本文介绍了如何判断程序的质量,主要围绕算法效率展开,包括事前分析估算、简单估算、时间复杂度的大O表示法以及空间复杂度的计算。讨论了时间复杂度和空间复杂度之间的权衡策略,强调在实现算法时需要根据具体问题的需求来平衡执行时间和空间的要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-------------------------------------资源来源于网络,仅供自学使用,如有侵权,联系我必删.

第一:

算法效率的度量

?  事前分析估算
    依据统计的方法对算法效率进行估算
?  影响算法效率的主要因素
     算法采用的策略和方法
     问题的输入规模
     编译器所产生的代码
     计算机执行速度

 

第二:

  算法效率的简单估算

  二重循环估算

#include <stdio.h>

//(n*n + 4)T
int func(int a[], int len)
{
    // 3次
    int i = 0;
    int j = 0;
    int s = 0;
    //n*n
    for(i=0; i<len; i++)
    {
        for(j=0; j<len; j++)
        {
            s += i*j;
        }
    }
    //1
    return s;
}

int main()
{
    int array[] = {1, 2, 3, 4, 5};
    //估算func函数的操作数量
    printf("%d\n", func(array, 5));
    
    return 0;
}

?  启示
   上面的程序关键部分的操作数量为n*n

   随着问题规模n 的增大 , 它们操作数量的差异会越来越大 , 因此实际算法在时间效率上的差异也会变得非常明显 !

 

第三:

时间复杂度:

? 大O 表示法
     算法效率严重依赖于操作(Operation) 数量
     在判断时首先关注操作数量的最高次项
     操作数量的估算可以作为时间复杂度的估算

    O(5) = O(1)
    O(2n + 1) = O(2n) = O(n)
    O(n 2 + n + 1) = O(n 2 )
    O(3n 3 +1) = O(3n 3 ) = O(n 3 )

时间复杂度:

#include <stdio.h>

int search(int array[], int length, int n)
{
    int ret = -1;
    int i = 0;
    
    for(i=0; i<length; i++)
    {
        if( array[i] == n )
        {
            ret = i;
            break;
        }
    }
    
    return ret;
}

int main()
{
    int array[5] = {1, 2, 3, 4, 5};
    
    printf("%d\n", search(array, 5, 1)); //最好情况执行1次,复杂度o(1)
    printf("%d\n", search(array, 5, 5)); //最坏情况执行n次,复杂度o(n)
    
    return 0;
}

 在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度 

 

第四:

算法的空间复杂度

?  算法的空间复杂度通过计算算法的存储空间实现
                             S(n ) =  O(f(n ))
其中 ,n  为问题规模 , f(n)  为在问题规模为n 时所占用存储空间的函数

大O  表示法同样适用于算法的空间复杂度
当算法执行时所需要的空间是常数时 , 空间复杂度为 O(1)

 

空间复杂度估算

#include <stdio.h>
#include <malloc.h>

//4*n+12 byte
long sum1(int n)
{
    long ret = 0;    //4 byte
    int* array = (int*)malloc(n * sizeof(int)); //指针4 + 堆空间n*4 
    int i = 0;       //4
    
    for(i=0; i<n; i++)
    {
        array[i] = i + 1;
    }
    
    for(i=0; i<n; i++)
    {
        ret += array[i];
    }
    
    free(array);
    
    return ret;
}

//8 byte
long sum2(int n)
{
    long ret = 0;  //4 byte
    int i = 0;     //4
    
    for(i=1; i<=n; i++)
    {
        ret += i;
    }
    
    return ret;
}

//4 byte
long sum3(int n)
{
    long ret = 0; //4 byte
    
    if( n > 0 )
    {
        ret = (1 + n) * n / 2;
    }
    
    return ret;
}

int main()
{
    printf("%d\n", sum1(100));
    printf("%d\n", sum2(100));
    printf("%d\n", sum3(100));
    
    return 0;
}

  三种求和算法中求和的关键部分的操作数量分别为2n, n 和1

                                                             时间复杂度分别为o(n),o(n)和o(1)

                                                              空间复杂度分别为o(n),o(1)和o(1)

第五:

空间与时间的策略

?  多数情况下 , 算法执行时所用的时间更令人关注
?  如果有必要 , 可以通过增加空间复杂度来降低时间复杂度
?  同理 , 也可以通过增加时间复杂度来降低空间复杂度

 

                        在实现算法时

需要分析具体问题对执行时间和空间的要求 

 

空间换时间

#include <stdio.h>

/*
    问题: 
    在一个由自然数1-1000中某些数字所组成的数组中,每个数字可能出现零次或者多次。
    设计一个算法,找出出现次数最多的数字。
*/

//时间复杂度O(n)
void search(int a[], int len)
{
    //3
    int sp[1000] = {0};
    int i = 0;
    int max = 0;
    
    //遍历a[]数组,如果里面是1则sp[]对应的第一位(sp[0])就加1
    for(i=0; i<len; i++)    //n
    {
        int index = a[i] - 1;   
        
        sp[index]++;
    }
    
    //遍历数组sp[] 找到最大值
    for(i=0; i<1000; i++)    //1000
    {
        if( max < sp[i] )
        {
            max = sp[i];
        }
    }
    
    //打印满足最大值的数
    for(i=0; i<1000; i++)    //1000
    {
        if( max == sp[i] )
        {
            printf("%d\n", i+1);
        }
    }
}

int main()
{
    int array[] = {1, 1, 3, 4, 5, 6, 6, 6, 2, 3};
    
    search(array, sizeof(array)/sizeof(*array));
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值