數據結構與算法(一),概述

轉載請註明出處:http://www.cnblogs.com/wangyingli/p/5919297.htmlhtml

數據結構學了有一年的時間了,可是一直沒有好好的總結一下,如今回想起來,感受好像都不怎麼記得了。因此接下來一段時間我將從新學習一下,算是溫故而知新了。本着「分享是一種美德」的精神,我將把個人學習總結記錄下來,並與你們分享。java

本節的主要內容有:算法

  • 1、數據結構
    • 一、定義
    • 二、關於數據結構的幾個術語
    • 三、邏輯結構與物理結構
  • 2、抽象數據類型
  • 3、算法
  • 4、算法的複雜度
    • 一、時間複雜度
    • 二、空間複雜度

1、數據結構

一、定義

數據結構是計算機存儲、組織數據的方式。在現實世界中,不一樣數據元素之間不是獨立的,而是存在特定關係的,咱們將這些關係稱爲結構。一樣在計算機中,數據元素也不是孤立、雜亂無序的,而是具備內在聯繫的數據集合。編程

數據元素之間存在的一種或多種特定關係,也就是數據的組織形式,叫數據結構。也能夠說,數據結構是指相互之間存在一種或多種特定關係的數據元素的集合。數組

一般狀況下,精心選擇的數據結構能夠帶來更高的運行或者存儲效率。程序設計的實質就是數據結構和算法是設計,所以咱們說程序設計 = 數據結構 + 算法數據結構

二、關於數據結構的幾個術語

  • 數據:是描述客觀事物的符號,是計算機中能夠操做的對象,是能被計算機識別,並輸入給計算機處理的符號集合。它不只包括整型等數值類型,還包括字符、聲音、圖像等非數值類型。這些類型都具有兩個特徵:
    • 能夠輸入計算機
    • 能被計算機程序處理
  • 數據元素:是組成數據的、有必定意義的基本單位,在計算機中一般做爲總體處理。也被稱爲記錄。併發

  • 數據項:一個數據元素能夠由若干個數據項組成。數據項是A數據的不可分割的最小單位。。數據結構和算法

  • 數據對象:是性質相同的數據元素的集合,是數據的子集。編程語言

例如:一本書的書目信息爲一個數據元素,而書目信息的每一項(如書名、做者名等)爲一個數據項。模塊化

三、邏輯結構與物理結構

按照不一樣的角度,數據結構可分爲邏輯結構和物理結構。其中邏輯結構是面向問題的,而物理結構是面向計算機的,它們的基本目標都是將數據及其邏輯關係存儲到計算機內存中。

  • 邏輯結構:是指數據對象中數據元素之間的相互關係。分爲四種:集合結構、線性結構、樹形結構和圖形結構。

四種邏輯結構

  • 物理(存儲)結構:是指數據的邏輯結構在計算機中的存儲形式。數據的存儲結構應正確反映數據元素之間的邏輯關係,這是關鍵。數據元素的存儲結構可分爲兩種:順序存儲結構和鏈式存儲結構。
    • 順序存儲結構:把數據元素放在地址連續的存儲單元中,數據間的邏輯關係和物理關係一致。如,數組。
    • 鏈式存儲結構:把數據元素放在任意的存儲單元中,數據間使用指針關聯。數據元素的存儲關係不能反映其邏輯關係。如,鏈表。

2、抽象數據類型

數據類型是指一組性質相同的值的集合及定義在該集合上的一些操做的總稱。而抽象是指抽象出事物具備的廣泛性的本質,它是抽出問題的特徵而忽略非本質的細節,是對具體事物的一個歸納。抽象隱藏了繁雜的細節,只保留實現目標所必須的信息。所以抽象數據類型能夠定義爲:

抽象數據類型(Abstract Data Type,ADT)是指一個數學模型及定義在該模型上的一組操做,它是一種向用例隱藏內部表示的數據類型。

面向對象編程的特徵之一就是使用數據類型的實現封裝數據,以簡化實現、隔離用例開發、實現模塊化編程。抽象數據類型體現了程序設計中問題分解、抽象和信息隱藏的特性。它將實際生活中的問題分解爲多個規模小、可以獨立開發和調試的小型模塊,而後進行獨立編程。這種方式將代碼的影響限制在局部區域,改進了咱們的軟件質量,促進了代碼複用。抽象數據類型抽象的層次越高,那麼可複用性也越強。好比:java中的Object是對全部對象的抽象。

java中數據類型能夠分爲兩類:

java數據類型

  • 基本(原子)類型:不能夠再分解的基本類型,包括int、short、long等
  • 引用(結構)類型:由其餘類型組合而成,能夠再分解。如,String、數組等

注意:

  1. 對原子類型的操做不必定是原子操做,這點併發編程時應特別注意。如,在32位機上對long類型的操做就不是原子操做,由於其高32位和低32位是分別存儲的。
  2. Java中全部的基本數據類型都有固定的存儲範圍和大小,其不受具體機器和操做系統的影響。

3、算法

算法(Algorithm)一詞最先出如今波斯數學家al-Khwarizmi所寫的《印度數字算術》中。歐幾里得算法(求兩個整數的最大公約數)被認爲是史上第一個算法。

算法是解決特定問題求解步驟的描述,在計算機中表現爲指令的有限序列,而且每條指令表示一個或多個操做。

算法的基本特性:

  • 輸入輸出,算法具備零個或多個輸入,至少有一個或多個輸出。
  • 有窮性,算法在執行有限步後可以自動結束,不會出現無限循環。
  • 肯定性,算法的每一步都具備肯定的含義,不會出現二義性。
  • 可行性,算法的每一步都可以經過執行有限次操做完成。

程序與算法的區別:

程序(program)是軟件開發人員根據用戶需求開發的、用程序設計語言描述的適合計算機執行的指令(語句)序列。它包括「數據結構」、「算法」、「程序設計方法」和「編程語言」。程序是算法用某種程序設計語言的具體實現。程序能夠不知足算法的有窮性,好比操做系統也是一種程序,它能夠一直運行。

算法的設計要求:

  • 正確性,算法至少應該具備輸入、輸出和加工處理無歧義、能正確反映問題的需求、可以獲得問題的正確答案。
  • 可讀性,便於閱讀、理解和交流。
  • 健壯性,輸入不合法時,算法可以給出相應的處理,而不是產生錯誤的結果。
  • 高效性,算法應該儘可能知足高效率和低存儲的需求。

4、算法的複雜度

算法複雜度分爲時間複雜度和空間複雜度。其做用: 時間複雜度是指執行算法所須要的計算工做量;而空間複雜度是指執行這個算法所須要的內存空間。

一、時間複雜度

算法的時間複雜度反映了算法執行的時間長短,它是度量一個算法好壞的重要指標。

通常狀況下,算法中基本操做重複執行的次數是問題規模n的某個函數,用T(n)表示,如有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值爲不等於零的常數,則稱f(n)是T(n)的同數量級函數。記做T(n)=O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。

度量一個算法的時間複雜度一般有兩種方式:

  • 過後統計法
  • 事前分析法(大O表示法)

算法的時間複雜度是由最深層嵌套語句的頻度決定的。

大O表示法的推導:

  1. 用常數1取代運行時間中的全部加法常數
  2. 在修改後的運行次數函數中,只保留最高階
  3. 將最高階係數變爲1

例1:

int i, j, temp;
for(i=0; i<n; i++) {
    for(j=i, j<n; j++) {
        temp++;
    }
}

語句執行的總次數:
\[ T(n) = n+(n-1)+(n-2)+\cdots+1 =\frac{n(n+1)}{2} = \frac{n^2}{2} + \frac{n}{2} \]
因此其時間複雜度爲\(O(n^2)\)

例2:

for(i=1;i<=n;i=i*2){
   System.out.println(i);
}

執行的總次數知足:
\[2^{T(n)} <= n\]
\[T(n)=log_2n = Clogn\]
因此它的時間複雜度爲\(O(logn)\)

例3:分析冒泡排序算法的時間複雜度

//冒泡排序算法
public static void bubbleSort(int[] data) {

    if (data == null) {
        return;
    }
    int temp = 0;
    for (int i = data.length - 1; i > 0; --i){
        for (int j = 0; j < i; ++j){
            if (data[j + 1] < data[j]){
                temp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = temp;
            }
        }
    }
}

算法分析:

  • 最佳狀況下(初始狀態是正序時),冒泡排序算法只須要一次掃描便可完成排序,此時比較次數 \(C_{min} = n - 1\),移動次數 \(M_{min} = 0\),因此時間複雜度爲 \(O(n)\)
  • 最差狀況下(初始狀態爲逆序時),須要進行 \(n-1\) 次排序,每次排序進行 \(n-1\) 比較,此時比較次數 \(C_{max} = \frac{n(n+1)}{2}\),移動次數 \(M_{max} = \frac{3n(n+1)}{2}\),因此時間複雜度爲\(O(n^2)\)

常見時間複雜度大小關係:
\[O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)\]

算法的時間複雜度和兩個因素有關:算法中的最大嵌套循環層數;最大嵌套循環結構中每次循環的次數。通常來講,具備多項式時間複雜度的算法是能夠接受的;具備指數時間複雜度的算法,只有當n足夠小時纔可使用。通常效率較好的算法要控制在O(N)或者O(log2 N)

二、空間複雜度

空間複雜度(Space Complexity)是對一個算法在運行過程當中臨時佔用存儲空間大小的量度,記作S(n)=O(f(n))。其中,n爲問題規模,f(n)爲語句關於n所佔存儲空間的函數。

算法的空間複雜度分析方法和算法的時間複雜度分析方法基本相同。

例如:

int i, j, temp;
for(i=0; i<n; i++) {
    for(j=i, j<n; j++) {
        temp++;
    }
}

上方代碼中,僅需爲變量 i、j、temp分配空間便可,因此空間複雜度 \(S(n) = O(1)\)

參考

相關文章
相關標籤/搜索