第2節 審判程序的靈魂

-------------------------------------資源來源於網絡,僅供自學使用,如有侵權,聯繫我必刪.

第一:

算法效率的度量

?  事前分析估算
    依據統計的方法對算法效率進行估算
?  影響算法效率的主要因素
     算法採用的策略和方法
     問題的輸入規模
     編譯器所產生的代碼
     計算機執行速度

 

第二:

  算法效率的簡單估算

  二重循環估算

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章