數據結構與算法概念


一、程序的定義

  程序 = 數據結構 + 算法

  程序是為了解決實際問題而存在的。然而為了解決問題,必定會使用到某些數據結構以及設計一個解決這種數據結構的算法。例如:有些交友網站能夠列出你可能認識的好友,是為了解決網絡聊天的問題。要解決這個問題,必定會使用到圖這種數據結構(最短路徑), 然而光有數據結構還不行,要實現這個功能,必須在圖這種數據結構的基礎上,設計一種算法,一步一步的操作,這些一步一步的操作就是算法,算法是特定問題求解步驟的描述。 再如: abbyy軟件(一款OCR識別軟件,簡單說就是把圖片還原成word的形式), 是為了解決圖片處理的問題。要解決表格還原這個問題,必定會使用到"樹"這種數據結構,在樹這種結構上,一步一步實現還原功能。類似的軟件還有五子棋中的判斷輸贏算法, 走迷宮算法等等。

二、數據結構的定義

  一般來說,用計算機解決一個具體問題時,首先從具體問題抽象出一個適當的數學模型(也就是數據結構), 然后設計一個解決此數學模型的算法。

  數據結構: 我們要研究對象的數據元素之間的關系。通常我們說的數據結構是一種邏輯結構,程序運行時必須把這些邏輯結構轉為物理結構。

  常見邏輯數據結構:集合結構(兩個函數中分別定義的局部變量,兩者沒有任何關系),線性結構,樹形結構,圖形結構。

  物理結構:順序存儲,鏈式存儲。

三、算法的定義

  算法是特定問題求解步驟的描述

  算法是獨立存在的一種解決問題的方法和思想

四、成為一個算法需要滿足的條件

  要看是否是一個算法,必須滿足下面的這些條件

  1. 輸入

    算法具有0個或者多個輸入

  2. 輸出

    至少有1個或者多個輸出

  3. 有窮性

    算法在執行有限的步驟之后會自動結束而不會進行死循環狀態

  4. 確定性

    算法中的每一步都有意義,不會出現二義性

  5. 可行行

    算法中每一步都必須可行

五、如何評判一個算法的好壞

  1、正確性:

     對於合法輸入能夠得到滿足的結果

    算法能夠處理非法處理,並得到合理結果

    算法對於邊界數據和壓力數據都能得到滿足的結果

  2、可讀性

    算法要方便閱讀,理解和交流,只有自己能看得懂,其它人都看不懂,談和好算法。

  3、健壯性:

    算法不應該產生莫名其妙的結果,一會兒正確,一會兒又是其它結果

  4、高性價比

    利用最少的時間和資源得到滿足要求的結果,可以通過(時間復雜度和空間復雜度來判定)

六、時間復雜度與空間復雜度

  通常判定一種算法的效率可以采用事后統計法和事前分析估算

  事后統計法缺點:

         必須編寫相應的測試程序,嚴重依賴硬件和運行時的環境,算法的數據采集相當的困難。

  事前分析估算:

        主要取決於問題的規模。

  1、時間復雜度

    公式: T(n) = O( f(n) );    其中f(n)是問題規模n的函數,也就是執行某個操作的次數。

    在沒有特殊說明的情況下,我們所分析的時間復雜度都是指最壞的時間復雜度

    常見時間復雜度:

  

  此外還有O(n!)等

  各個時間復雜度的關系:

  2、空間復雜度

    公式: S(n) = O( f(n) )   其中f(n)是在問題規模為n時所占用的內存空間大小;

    大O表示法同樣也適合空間復雜度,這里就不在重復說明了。

  3.時間復雜度與空間復雜度的策略

    多算情況下,算法的執行時所用的時間更令人關注;

    如果有必要,可以增加空間復雜度來降低時間復雜度;

    同理,也可以添加時間復雜度來降低空間復雜度,例如像51單片機,嵌入式設備,內存資源是很珍貴的,就可以通過增加時間復雜度來降低空間復雜度;

    因此,我們在實現算法的時候,需要分析具體問題對執行時間和空間的要求;

    下面看一個通過添加空間復雜度來降低時間復雜度的例子:

#include <stdio.h>
#include <stdlib.h>
//功能: 從1---1000中,找出出現次數最多的那個數字
int Search(int array[], int nLen);

int main()
{
    int array[] = {1, 1, 3, 4, 5, 6, 6, 6, 2, 3};

    Search( array, sizeof(array) / sizeof(array[0]) );

    return 0;
}

int Search(int array[], int nLen)
{
    int anTemp[1000] = {0};
    int nIndex = 0;
    int nTempPos = 0; 
    int nMax = 0; 

    //把1---1000中的某一個數存儲在anTemp數組中的位置
    //把把1---1000中的某一個數的個數加1
    for(nIndex = 0; nIndex <nLen; nIndex++)
    {
        nTempPos = array[nIndex] - 1;            

        anTemp[nTempPos]++;                        
    }

    //在anTemp中找出最大值
    for(nIndex = 0; nIndex < 1000; nIndex++)    
    {
        if(nMax < anTemp[nIndex])
        {
            nMax = anTemp[nIndex];
        }
    }

    //輸出1---1000之間出現最多的那個數字
    for(nIndex = 0; nIndex < 1000; nIndex++)
    {
        if(nMax == anTemp[nIndex])
        {
            printf("%d\n", nIndex + 1);
        }
    }

    return 0;
}

    在這個例子中,通過開辟一個int anTemp[1000]大小的存儲空間,用來存放1---1000中每個數字出現的次數,雖然增加了空間復雜度,但是降低了時間復雜度。

    類似的例子還有表驅動算法,也是通過開辟一個空間,然后從該空間中找到需要的內容。舉個例子:像計算某年是否是閏年,就可以通過開辟一個2050大小的空間(1--2050年),並根據事先已經知道的結果,是閏年的就設為1,否則設為0;例如判斷2014是否是閏年,就只需要查找這個數組中索引為2013那個元素內容是否為1就可以了。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM