數據結構實現基礎

引子

數據統計

例子:在日常數據處理中,經常碰到需要對一組數據進行基本的統計分析,包含這些操作:平均數、最大值、最小值、中位數、標準差、方差等。這類統計可能發生在各種情況,比如學生成績統計、家庭開支情況、GDP 統計等等,都會涉及到這類數據統計。

爲每個具體應用都編寫一個程序不會是一個好方法,程序都具有很大的相似性。數據結構的處理方法是從這些具體應用中抽象出共性的數據組織與操作方法,進而採用某種具體的程序設計語言實現相應的數據存儲與操作

數據抽象

  • 類型名稱:統計數據集
  • 數據對象集:N 個元素 {x1, x2, ... , xN} 的集合 S
  • 操作集:
  1. ElementType Average(S, N):求 S 中 N 個元素的平均值
  2. ElementType Max(S, N):求 S 中 N 個元素的最大值
  3. ElementType Min(S, N):求 S 中 N 個元素的最小值
  4. ElementType Median(S, N):求 S 中 N 個元素的中位數

數據存儲

數據組織的基本存儲方式主要是利用數組和鏈表方式來實現的,包括很複雜的數據結構,如圖、樹,也都不外乎應用數組和鏈表來實現

  • 若要實現的操作不是基本統計,而是集合運算,需要判斷元素是否屬於集合、對集合進行並和交運算、元素插入集合等。這些操作雖然在簡單數組也可以實現,但是效率不高,使用樹的組織方式可以更方便的實現集合的上述運算。
  • 若除了基本的統計操作外,還需要動態的維護一個集合,即經常往集合里加入/刪除元素,那應該設計多大的數組來保存這些元素呢,太大浪費空間,太小不夠用。使用鏈表來保存數據或許更適合,但是鏈表也有缺點,鏈表需要記錄後續節點地址,跟數組存儲相比,鏈表需要更多的存儲空間,同時程序實現也比數組更加複雜。

數據結構的存儲實現跟所需要的操作密切相關,沒有最好的存儲方式,只有最合適的存儲方式

操作實現

  • 在確定數據的存儲方式後,數據結構涉及的另一個問題是相關的操作如何實現。這些操作的實現需要利用程序設計語言提供的另一個功能,即流程設計功能
  • 在任何高級程序設計語言都提供了一種的基本流程控制語句,即分支控制語句和循環控制語句。分支控制結構、循環控制結構加上程序自然的語句順序執行結構,是實現任何算法流程的基本結構。
  • 在程序中,我們可以將程序的某個基本功能設計爲函數,這一方面降低了程序設計的複雜性,另一方面也提高了程序設計的重用性。遞歸是數據結構算法設計的很重要的手段。
《PHP面試問答》https://github.com/colinlet/PHP-Interview-QA 歡迎 star 關注~~
結合實際PHP面試,彙總自己遇到的問題,以及網上其他人遇到的問題,嘗試提供簡潔準確的答案
包含網絡、數據結構與算法、PHP、Web、MySQL、Redis、Linux、安全、設計模式、架構、面試等部分

數據結構存儲基礎

變量是數據存儲的基本單位,而變量是有類型的,例如:整型、浮點型、字符型、布爾型

數組

數組是最基本的構造類型,它是一組相同類型數據的有序集合

指針

指針變量用於存放變量的地址,通過指針就能間接訪問那個變量

結構體

結構類型是一種允許把一些數據分量聚合成一個整體的數據類型,它能夠把有內在聯繫的不同類型的數據統一成一個整體,使它們相互關聯。同時,結構又是一個變量的集合,可以按照與成員類型變量相同的操作方法單獨使用其變量成員。結構與數組的區別在於,數組的所有元素必須是相同類型的,而結構的成員可以是不同的數據類型。

struct 結構名 {
    類型名 結構成員名 1;
    類型名 結構成員名 2;
    ......
    類型名 結構成員名 n;
};

鏈表

鏈表使一種常見而重要的基礎數據結構,也是實現複雜數據結構的重要手段。它不按照線性的順序存儲數據,而是由若干個同一結構類型的"結點"依次串聯而成的,即每一個結點裏保存着下一個結點的地址。使用鏈表結構可以克服數據需要預先知道數據大小的缺點,可以充分利用計算機內存空間,實現靈活的內存動態管理。但鏈表失去了數組方便隨機存儲的優點,同時鏈表由於增加了結點的指針域,空間開銷比較大。

單向鏈表

單向鏈表的結構

單向鏈表的組成示意圖

//單向鏈表結點
class node
{
    public $data;
    public $next;

    /**
     * @param $p1 結點數據
     * @param $p2 下一個結點
     */
    public function __construct($p1, $p2)
    {
        $this->data = $p1;
        $this->next = $p2;
    }
}

單向鏈表的常見操作

  • 鏈表的建立

應用鏈表進行程序設計時,往往需要先建立一個鏈表,建立鏈表的過程實際上就是不斷在鏈表中插入結點的過程

class singleLinkList
{
    /**
     * @param $n int 結點數目
     * @return $head obj 頭結點
     */
    public function create($n)
    {
        $head = new node(0, null);
        for ($i=$n; $i > 0; $i--) { 
            $newNode = new node($i, null);
            $newNode->next = $head->next;
            $head->next = $newNode;
        }
        return $head;
    }
}
  • 插入結點

在單向鏈表 head 的某個結點 p 之後插入一新結點:找到正確位置 p,申請新結點 t 並對 t 的結點信息賦值,最後將 t 插入在 p 之後

  • 刪除結點

從單向鏈表 head 中刪除一個結點:找到被刪除結點的前面一個結點 p,刪除 p 之後的結點

  • 單向鏈表的遍歷

對單向鏈表最常見的處理方式:逐個查看鏈表中每個結點的數據並進行處理

雙向鏈表

雙向鏈表

在單向鏈表基礎上增加指向前驅單元指針的鏈表叫做雙向鏈表。結點增加指向其前驅結點的指針,將犧牲一部分空間代價,前驅單元查找可以不必從鏈頭開始查找

//雙向鏈表結點
class node
{
    public $data;
    public $next;
    public $previous;

    /**
     * @param $p1 結點數據
     * @param $p2 下一個結點
     * @param $p3 前一個結點
     */
    public function __construct($p1, $p2, $p3)
    {
        $this->data = $p1;
        $this->next = $p2;
        $this->previous = $p3;
    }
}

雙向循環鏈表

雙向循環鏈表

將雙向鏈表最後一個單元的 Next 指針指向鏈表的第一個單元,而第一個單元的 Previous 指針指向鏈表的最後一個單元,這樣構成的鏈表稱爲雙向循環鏈表

流程控制基礎

程序設計語言除了能表達各種各樣的數據外,還必須提供一種手段來表達數據處理的過程,即程序的控制過程。程序的控制過程通過程序中的一系列語句來實現。

按照結構化程序設計的觀點,任何程序都可以將程序模塊通過三種基本的控制結構進行組合來實現。這三種基本的控制結構是順序分支循環

《數據結構實現基礎》 原文鏈接:https://blog.maplemark.cn/2019/07/數據結構實現基礎.html

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