數據結構與算法——初識(概念)

終於到了數據結構和算法的階段了,前段時間被校招題虐的慘慘的,毅然決定要好好學數據結構和算法了,希望和我一起參加校招的朋友們也加油啊!

數據結構在開發中是很重要的,不對應該是非常重要的,一定要好好學,如果想搞開發的話。在今後的大部分程序中,不管是一個小的系統也好,大的軟件也好,都離不開我們的數據結構和算法的運用,我們完全可以說:程序=數據結構+算法。

數據結構和算法是兩個概念,這是單獨的兩門課,在今後的博客中我會繼續整理筆記,前期是數據結構的內容,後期是算法的內容,今天這篇文章,我只想先介紹一下數據結構和算法這兩個概念。

數據結構

數據結構也是分兩個部分,一個是數據部分,一個是結構部分:

數據:但凡能夠被計算機存儲、識別和計算的東西都叫數據,但是這些數據都是以二進制存儲的。如:
        硬盤中的:MP3、JPG、doc、AVI、EXE、TXT
        內存中的:變量、常量、數組、對象、字節碼
結構則是數據與數據之間的一種或多種特定的關係。

雖然兩者在概念上是獨立的,但是在數據結構裏面,少其一則程序的結構就是不完整的,因此 數據結構就是數據+數據之間的關係,兩者的結合,組成數據結構,讓我們的程序更加完整。

那麼數據結構主要解決什麼樣的問題呢?——將零散的數據“整齊劃一”,方便後續操作。如在前期階段學習的時候,學到過數組,將一堆分散的變量,定義到數組裏面,變成一堆連續的變量,方便對整體進行操作。因此,學習數據結構讓我們對數據有一個比較方便的管理方式。

數據的結構也分兩種:
       邏輯結構:是指數據元素之間的相互關係,是我們想象出來的,並沒有實質性的將其存儲在計算機中

              集合結構:集合結構中的數據元素除了同屬於一個集合外,他們之間沒有其他關係
              線性結構:線性結構中的數據元素之間是一對一的關係
              樹形結構:樹形結構中的數據元素之間存在一種一對多的層次關係
              圖形結構:也叫網狀結構,其數據元素是多對多的關係

                           
由上圖可知,樹形結構是圖形結構的一個特殊結構,線性結構是樹形結構的一種特殊結構,當線性結構被打亂,元素之間沒有了關聯,就成了集合結構。因此,我們將由集合結構開始逐步向難,一走到底!
        物理結構:是指數據的邏輯結構在計算機中的存儲形式
               順序存儲結構:開闢一組連續的空間存儲數據(查找快,增刪慢)
                      通常用數組來實現,數組中空間本身是連續的,保證了數據之間的關係
               鏈式存儲結構:開闢一組隨機的空間存儲數據(增刪快,查找慢)
                      通常用節點來實現,節點不僅要存儲數據,還要存儲下一個節點的位置以保證數據之間的關係

因此我們要根據應用場景的不同,靈活的選擇最合適的數據結構,比如手機通訊錄,我們通常是要查找比較快的,所以他一般是用順序存儲,也就是數組存儲的。當然計算機中還有很多數據結構的應用,如:計算機文件系統,函數棧,遊戲地圖(找最短路徑)等等,可見——這裏再次強調數據結構的重要性。

算法

算法的概念是:解決特定問題求解步驟的描述,在計算機中表現爲指令的有序系列,並且每條指令表示一個或多個操作。簡單來說,就是求解一個問題的步驟。

如求1+2+...+100的和,在沒有學習循環的時候我們可以用公式來求解,而公式求解也有幾種:

方法一:常規公式求法                                方法二:等差數列求和法

int N=100;                                                          int  N=100;

int sum =(N+1)*N/2;                                             int sum = N*1+(N*(N-1))/2

在學習循環之後,我們就可以用循環來做:

方法三:使用循環求解

int sum =0;

int N=100;

for(int i=1;i<=N;i++){

    sum=sum+i;

}

因此可見,一個問題的求解步驟並不是唯一的,那麼是不是我們就可以隨便選擇這個問題的求解步驟了呢?顯然不是的,現在的程序強調的都是最優最優,因此我們要選擇一個最優的算法運用到我麼的程序中。

那麼如何評價一個算法的好壞以及是否達到最優?——設計算法要提高程序運行的效率,這裏效率大都指算法的執行時間,這裏提供兩種方法:

        事後統計方法:這種方法主要是通過已經設計好的程序和數據,利用計算機計時器對不同算法程序的運行時間進行比較,從而確定算法效率的高低。但是這樣會有很多缺陷

           必須事先編好程序,在進行運行,如果程序處理的數據量較大,則會花費大量的時間和精力(計算一年都不成問題)
           時間的比較主要依賴於計算機硬件和軟件環境
           算法的測試數據設計困難,在數量較小的時候,不管什麼算法其運行時間都是很微小的,相差幾乎爲零,如果數據量大了,算法的優越性就出來了,但是這樣又會耗費時間
    (所以該種方式一般不予採納

        事前分析估算方法:這種方法主要在計算機程序編制前,依據統計方法對算法進行估算,一個高級程序語言編寫的程序在計算機上運行時所消耗的時間取決於下列因素:

       算法採用的策略、方法(決定算法好壞的根本)
       編譯產生的代碼質量(軟件來支持)
       問題的輸入規模
       機器執行指令的速度(硬件性能)

也就是說,拋開這些與計算機硬件、軟件有關的因素, 一個程序的運行時間,依賴於算法的好壞和問題的輸入規模(即數據入量的多少)。在分析程序的運行時間時,最重要的是把程序看成是獨立於程序設計語言的算法或一系列步驟,因此我們引入算法時間複雜度的概念。

時間複雜度

算法時間複雜度:是衡量算法好壞的一個標準。

官方定義:一般情況下,算法中基本操作重複執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),存在一個正常數c使得fn*c>=T(n)恆成立。記作T(n)=O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。

But!常見的幾個時間複雜度也就幾個:常數階O(1)、線性階O(n)、對數階O(logn)、平方階O(n²)、立方階O(n³)、O(nlogn)、常數指數階O(2^n)、指數階O(n^n)、階乘階O(n!)。

其中的關係是:O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2^n)<O(n!)<O(n^n)

如上面的例子,計算前100項和:

方法一:常規公式求法                                方法二:等差數列求和法

int N=100;              // 執行1次                         int  N=100;     //執行一次

int sum =(N+1)*N/2; // 執行1次                         int sum = N*1+(N*(N-1))/2   //執行一次

因此上面兩種算法的每條語句執行次數爲常數,時間複雜度爲常數階O(1)

但是在循環中:

方法三:使用循環求解

int sum =0;                              //執行一次

int N=100;                              //執行一次

for(int i=1;i<=N;i++){              //執行N+1次

    sum=sum+i;                      //執行N次

}

隨着N的增大,循環裏面執行的次數越多,那麼此算法的執行次數爲2N+3次,但是是時間複雜度爲O(n),因爲隨着N的不斷增大,這個3就顯得微不足道了,如果N達到足夠大,這個係數2也顯得微不足道,因爲數量級是一樣的,因此最後的時間複雜度爲O(n)。

所以,在計算時間複雜度時,忽略常數,只保留冪的最高次,且忽略冪高項的係數(我們考慮的時間複雜度都是最壞的情況)

至此數據結構和算法的概念已經介紹完了,然後後面的內容就是伴隨着大量的代碼講解數據的結構,希望自己,也希望和我一起學習的人,都能堅持下去,我們一定會成爲大佬的!

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