數據結構與演算法概念

来源:https://www.cnblogs.com/yangyuanhu/archive/2020/02/06/12267404.html
-Advertisement-
Play Games

數據結構小白入門 數據結構指一組相互之間存在一種或多種特定關係的數據元素的集合, 當我們需要在電腦中存儲這些數據時,還涉及到數據的,組織方式,在電腦中的存儲方式,以及定義在該數據上的一組操作; 一組數據相互之間有某種關係 組織方式 存儲方式 以及可對其進行的一組操作 理解: 我們學習的最終目的是 ...


數據結構小白入門

數據結構指一組相互之間存在一種或多種特定關係的數據元素的集合,
當我們需要在電腦中存儲這些數據時,還涉及到數據的,組織方式,在電腦中的存儲方式,以及定義在該數據上的一組操作;

  • 一組數據相互之間有某種關係
  • 組織方式
  • 存儲方式
  • 以及可對其進行的一組操作
理解:

我們學習的最終目的是要在電腦中存儲一組數據,但是不得不先考慮數據的組織方式,在電腦中的存儲方式,以及可以對這些數據進行的一組操作,當然了既然是一組數據必然表明瞭這寫數據之間是存在想換的關聯關係的;關係可能還會有多種;

例如:

一組數據:12345

組織方式:從小到大

存儲方式:可使用線性存儲結構

操作:要取出最大的一個

數據結構研究方向

問題:

  • 機外處理
  • 處理要求

建模:

  • 邏輯結構
  • 基本運算

實現:

  • 存儲結構
  • 演算法

基本術語

數據(Data):

​ 所有能被電腦處理的符號的集合

數據元素(DataElement):

​ 是數據集合中的一個 個體,即數據的基本單位

數據項(DataItem):

​ 數據元素常常可分為若幹個數據項,數據項是數據具有意義的最小單位

組織數據的三個層次:

數據(表)->數據元素(行)->數據項(欄位)

實際問題中的數據成為原始數據

邏輯結構(LogicalStructure)

​ 數據元素之間的結構關係,如從小到大/一對一/一對多

物理結構(PhysicalStructure)

​ 也會叫做存儲結構,指數據在電腦內的表示,邏輯結構在電腦中的具體實現

邏輯結構

常見的邏輯結構如下:

集合:

數據元素屬於同一個集合,表示為R{}; 數據之間不存在特定關係

組織結構鬆散,任意兩節點之間都沒有鄰接關係

線性:

除了起始節點d1和終端階段dn外,每個節點都有一個前驅和一個後繼,表示為R={d1,d2...dn},數據之間存在前後順序關係

各節點按邏輯關係排列,形成一條'鏈'

樹狀:

每個元素最多有一個前驅,可以有多個後繼,表示為(D,{R}),就像一個樹幹長了多個樹枝

具備分支,層次特性,上層節點可以和下層多個節點相鄰接,但是下層節點只能和一個上層節點鄰接

圖狀:

任何兩個元素之間都可以相鄰接,表示為(D,{R})

註意:

邏輯結構

  • 與元素本身的形式,內容,無關

  • 元素的相對位置,無關

  • 與包含的節點個數,無關

存儲結構

存儲結構由 存儲節點(每個存儲節點存放一個數據元素)節點之間的邏輯關係共同組成

反過來說,一個完整的存儲結構必須可以存儲數據元素,以及元素之間的邏輯關係

存儲結構分類 (缺圖)

  • 順序存儲

    使用索引(相對起始位置)來表示數據的邏輯結構,數據被存儲在一組連續的存儲單元中

    特點:

    • 需預先分配長度,
    • 插入和刪除慢,需要移動其他元素
    • 存取數據快捷,屬於隨機存儲結構(可通過索引直接訪問任意位置數據)
  • 鏈式存儲

    藉助元素地址指針表示數據的邏輯結構,每個元素都會包含指向下一個元素的指針

    這種結構需要在節點上附加一個指針項,指出後繼節點的位置,即每個節點存儲單元包含兩個部分:[數據項,指針項]

    特點:

    • 動態分配內容,不需要預先分配記憶體
    • 插入刪除快捷,不需要移動其他元素
    • 非隨機存取結構(獲取數據必須遍歷前面的所有節點)
  • 索引存儲(Map是否屬於索引結構 很疑惑?)

    藉助索引表來指示數據元素的存儲位置

    索引表中包含了所有數據元素的地址,查詢索引表能夠快速的定位到需要的數據

    特點:

    • 索引是一份獨立於實際存放數據,的數據結構(就像書的目錄都在正文前面)
    • 索引需要占用額外的存儲空間
    • 當實際數據發生改變時需要重建索引
    • 查詢數據快
    • 插入修改,刪除慢
  • 散列存儲(哈希表)

    通過散列函數計算得出元素的位置

    特點:

    • 在散列函數不變時,相同數據會得出相同的位置
    • 存入順序和取出順序通常不一致
    • 無法完成隨機存取(指定獲取某個元素)

順序和鏈式是最基本的也是最常用的存儲結構,需要重點掌握,包括各自的優缺點,使用場景等

鏈式存儲結構可實現樹結構(邏輯結構)

運算

運算指的是某種邏輯結構上可以進行的操作;

運算分為兩類:

  • 加工型運算

    會改變原邏輯結構的內容,順序,個數等的操作

  • 引用型運行

    與加工型運算相反

常見運算:

建立,查找,讀取,插入,刪除

加工型:建立,插入,刪除

引用型:讀取,查找

演算法

演算法字面意思,計算方法;

演算法規定了求解給定類型問題所需的所有處理步驟以及執行順序,使得問題能在有限時間內機械的求解,一個演算法就是對特定問題求解步驟的一種描述,再具體一點,演算法是一段有窮的指令序列;演算法必須能使用某種語言描述;

例如:

計算1到5的和 ,這個需求,如何來實現,第一步做什麼,第二步做什麼,整個計算步驟和執行順序統稱為演算法,如果最終能夠在有限的步驟下求出正確的和,那這就是一個合格的演算法;

演算法的特點:

  • 有窮性

    演算法必須在執行有窮步後結束

  • 確定性

    演算法的每一個步驟都必須是明確定義的,

  • 可行性

    演算法中的每一步都是可以通過已實現的操作來完成的

  • 輸入

    一個演算法具備0或多個輸入

  • 輸出

    一個演算法有一個或多個輸出,它們與輸入有著特定的關係

演算法與程式的區別,演算法只是一種描述,可以使用任何語言,但是通常不能直接被電腦運行,而程式則是演算法的具體實現,使用某種電腦語言;

演算法設計應滿足的要求

  • 正確性:對於合法的輸入產生符合要求的輸出

  • 易讀性:演算法應該儘可能易讀,便於交流,這也是保證正確性的前提(註釋可提高易讀性)

  • 健壯性:當輸入非法數據時,演算法可作出適當反應而不至於崩潰(例如輸出錯誤原因);

  • 時空性:指的是演算法的時間複雜度和空間複雜度,演算法分析主要也是分析演算法的時間複雜度和空間複雜的,其目的是提高演算法的效率;

演算法分析

解決同一問題的演算法可能有多種,我們希望從中選出最優的演算法,效率高的,占用空間小的,為此我們就需要對演算法進行評估和分析;

通常評估演算法根據兩個度量

  • 時間複雜度:演算法運行完成所需的總步數(標準操作),通常是問題規模的函數

  • 空間複雜度:演算法執行時所占用的存儲空間,通常是問題規模的函數

確定演算法的計算量

  • 合理選擇一種或幾種操作作為'標準操作',無特殊說明預設以賦值操作作為標準操作;
  • 確定演算法共執行多少次標準操作,並將此次數規定為演算法的計算量
  • 以演算法在所有時輸入下的計算量最大值作為演算法的最壞情況時間複雜度
  • 以演算法在所有時輸入下的計算量最小值作為演算法的最好情況時間複雜度
  • 以演算法在所有時輸入下的計算量平均值作為演算法的平均情況時間複雜度
  • 最壞/平均情況時間複雜度都可作為時間複雜度,通常以最壞情況衡量;

註意:時間複雜度通常以量級來衡量,也就是說不需要精確的計算到底執行了幾步,而是得出其計算量的數量級即可,並忽略常數,因為當數量級足夠大時,常數對於計算量的影響可以忽略不計;

如: (n-1)(n-2) 數量級為 n^2

時間複雜度使用大O表示,如O(1)

案例:

1.
void aFunction(){
    int c = 10 + 20;
    int d = c * c;
        printf(d);
}

上列演算法若以賦值運算作為標準操作,則該演算法的計算量為2,其時間複雜度記為O(1),為什麼是O(1)呢,是因為2是一個常數,常數對於函數的增長影響並不大,所以計算量為常數時表示為O(1),按照這種方式,即使計算量為2000,同樣記為O(1),稱為常數

2.
void bFunction(int n){
  for(int i = 0;i < n;i++){ // n
    int c = 2 * i;// 1
    int d = 3 * i;// 2
  }
}

此時函數的迴圈次數由未知數n來決定,迴圈體內計算量為2,當n是一個自然數時,函數的計算量等於(n)(2),此時時間複雜度為O(n),無論用常數2對n進行加減乘除對於n的指數都沒有影響,當n足夠大時,內部的2次計算量可以忽略,所以記為O(n),稱為線性階

更粗陋的度量方法是函數體包含一層迴圈時記為O(n)

3.
void bFunction(int n){
  for(int i = 0;i < n;i++){
      for(int j = 0;j < i;j++){
      }
  }
}

外層迴圈次數為n,內層迴圈次數隨著n的增長而增長且最大值為n-1次,那麼整個函數的計算量為(n)(n-1),常數可以忽略,所以時間複雜度記為O(n^2) ,稱為平方階

粗陋的方法是有兩層嵌套迴圈,且迴圈次數都隨著n的增長而增長,所以是O(n^2),以此類推,但是要註意下麵這種情況

4.
void bFunction(int n){
  for(int i = 0;i < n;i++){
      for(int j = 0;j < 3;j++){
      }
  }
}

此時內層迴圈的迴圈次數是固定(常數)所以不會影響計算量的數量級,時間複雜度記為O(n)

5.
void bFunction(int n){
  for(int i = 3;i < n;){
      i *= 3;
  }
}

此時函迴圈次數會隨著3迴圈體中的常數3的的變化而變化,我們可以用對數來表示,

假設迴圈次數為s,迴圈條件可表示為 s = 3^s < n;(即i本身為3,其次冪會不斷的增長,但結果要小於n)

當然這裡有個條件是i的初值必須和每次乘等的值相同,形成次冪的增長;

用對數表示為s = log3n,時間複雜度記為O(log3n),常數可以忽略,所以最後是O(logn)稱之為對數階

對數階的數量級小於線性階,因為若n的值相同,對數階計算量必然小於線性階

6.
void bFunction(int n){
 for(int i = 0;i < n;i++){
     for(int j = 0;j < n;j++){
         for(int k = 0;k < n;k++){
       }
     }   
 }
}

上述演算法時間複雜度為O(n^3),3為常數,對應著迴圈的嵌套層數;也可以用O(n^C)表示,稱為多項式階

7.
void bFunction(int n){
  int num = 2;
  for(int i = 0;i < n;){ //O(n)
        num *= 2;
  }
  for (int j = 0;j<num;j++){ //O(n)
  }
}

上述函數輸入的參數n將作為迴圈次數的指數,假設迴圈次數為s, s = 2^n,那麼時間複雜度為O(2^n),

稱之為指數階,可記為O(C^n)

8.
void bFunction(int n)
{
    for(int i=0;i<n;i++){
          for(int j=0;j<n;j++){
          }
    }   
  
      for(int i=0;i<n;i++){
      }             
}

對於順序運行的演算法,總時間複雜度等於演算法中最大時間複雜度,即O(n^2)

9.
void bFunction(int n)
{
  if(n % 2 ==0){
    for(int i=0;i<n;i++){
          for(int j=0;j<n;j++){
          }
    }   
  }else{
      for(int i=0;i<n;i++){
      }             
  } 
}

對於具備分支結構的演算法,總時間複雜度等於演算法中時間複雜度最大路徑的複雜度,即O(n^2)

時間複雜度大小順序

常數 < 對數階 < 線性階 < 平方階 < 多項式階 < 指數階

O(1) < O(logn) < O(n) < O(n^2) < O(n^C) < O(C^n)

優劣:

通常具有常數階複雜度的演算法是好的演算法
具有指數階複雜度的演算法是差的演算法

個人觀點,若有錯誤敬請指出,謝謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • getElementById() 根據id獲取dom元素 沒有找到則返會Null <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id ...
  • jquery.ui實現新聞模塊 jquery也有ui,瞭解即可,用的不多,類似element ui 和bootstrap JQuery UI API: jquery.ui實現新聞模塊 draggale拖動,並用屬性handle,指定下拖動手柄 $(".drag-wrapper").draggable ...
  • jquery.color.js的使用 瞭解即可 <!--1. 引入jquery的js文件--> <script src="jquery-1.12.4.js"></script> <!--2. 引入插件的js文件--> <script src="jquery.color.js"></script> < ...
  • jQuery插件 使用插件的步驟 1. 引入jQuery文件 2. 引入插件(如果有用到css的話,需要引入css) 3. 使用插件 <!--1. 引入jquery的js文件--> <script src="jquery-1.12.4.js"></script> <!--2. 引入插件的js文件-- ...
  • 單步跟蹤調試 debugger; 控制台watch功能查看變數當前值 進入函數操作 隨著不斷點擊,不停進行迴圈,指定變數的值也在發生改變 添加斷點 跳入跳出函數 throw new Error() 主動拋出異常 後面的代碼不再運行 代碼會跳轉到離這句最近的try語句中 使用 try{ }catch( ...
  • nodemon是一種工具,通過在檢測到目錄中的文件更改時自動重新啟動節點應用程式來幫助開發基於node.js的應用程式。 nodemon並沒有要求任何對你的代碼或開發的方法中的額外變化。nodemon是一個替換包裝器node,用於在執行腳本時nodemon替換node命令行上。 安裝方法:npm i ...
  • 安裝C++環境MacOS安裝xcode查看是否安裝成功:$ g++ -vHell WorldC++ 程式的源文件通常使用擴展名 .cpp、.cp 或 .c。Hello WorldC++ 程式的源文件通常使用擴展名 .cpp、.cp 或 .c。編譯源文件$ g++ c.cpp由於命令行中未指定可執行程... ...
  • 一、ProxyHandler處理(代理伺服器) 1.使用代理IP,是爬蟲的常用手段 2.獲取代理伺服器的地址: www.xicidaili.com www.goubanjia.com 3.代理用來隱藏真實訪問中,代理不允許頻繁訪問某一個固定網站,所以代理一定要很多很多。 4.基本使用步驟: (1)設 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...