用 PHP 的方式實現的各種算法合集

項目地址 https://github.com/m9rco/algo...php

每週最少一更,求出題,求虐待 At least once a week, ask for problems and abuse

簡易結構

├──Package
│    ├── Sort  排序篇
│    │    ├── BubbleSort.php          冒泡排序
│    │    ├── HeapSort.php            堆排序   大根堆
│    │    ├── MBaseSort.php           基數排序 MSD
│    │    ├── LBaseSort.php           基數排序 LSD
│    │    ├── QuickSort.php           快速排序
│    │    ├── ShellSort.php           希爾排序
│    │    ├── MergeSort.php           歸併排序
│    │    ├── InsertSort.php          插入排序
│    │    └── SelectSort.php          選擇排序
│    │
│    ├── Query 查找篇
│    │    ├── BinaryQuery.php         二分查找
│    │    ├── InseertQuery.php        插入查找
│    │    ├── FibonacciQuery.php      斐波那契查找
│    │    └── QulickQuery.php         快速查找
│    │     
│    ├── Structure 數據結構
│    │    ├── StackExample.php         堆棧   先進後出 LIFO (Last In First Out)
│    │    ├── LinearChain.php          線性表 單鏈存儲
│    │    └── LinearOrder.php          線性表 順序存儲 
│    │     
│    ├── Tools 小工具集
│    │    └──  SystemSwitch.php       堆棧實現進制轉換  
│    │  
│    └── Other 其餘
│         ├──  MonkeyKing.php         約瑟夫環
│         ├──  DynamicProgramming.php 動態規劃
│         ├──  Fibonacci.php          斐波那契數列
│         ├──  StealingApples.php     偷蘋果求餘
│         ├──  HanoiGames.php         漢諾塔遊戲
│         ├──  BidirectionalQueue.php 雙向隊列
│         ├──  ColorBricks.php        彩色磚塊
│         ├──  GetCattle.php          牛年求牛
│         ├──  OnlyNumbers.php        求惟一數
│         ├──  PokerGames.php         洗撲克牌
│         └──  BigSmallReplace.php    Hello World 輸出 Olleh Dlrow
│     
├──LICENSE
└──README.md

要作什麼?

記錄本身理解算法,數據結構的過程,儘量的簡單全面以及詳細,讓算法學習運用靈活自如,加油(ง •̀_•́)ง

固然

用 PHP 實現算法並替代官方提供的函數是愚蠢的事情 .但這覺不表明斟酌算法就是件無心義的事 , 每一個算法都是一種思想的結晶 , 學習優秀的思想 , 開拓思惟

什麼是算法?

直白地說,算法就是任何明肯定義的計算過程,它接收一些值或集合做爲輸入,併產生一些值或集合做爲輸出。這樣,算法就是將輸入轉換爲輸出的一系列計算過程。來源:Thomas H. Cormen, Chales E. Leiserson (2009), 《算法導論第三版》。html

簡而言之,咱們能夠說算法就是用來解決一個特定任務的一系列步驟(是的,不止計算機在使用算法,人類也一樣如此)。目前,一個有效的算法應該含有三個重要特性:git

  • 它必須是有限的:若是你設計的算法永無休止地嘗試解決問題,那麼它是無用的。
  • 它必須具有明肯定義的指令:算法的每一步都必須準肯定義,在任何場景下指令都應當沒有歧義。
  • 它必須是有效的:一個算法被設計用以解決某個問題,那麼它就應當能解決這個問題,而且僅僅使用紙和筆就能證實該算法是收斂的。

對數

log10100 至關於問"降多少個10相乘的結果爲100",答案固然是2個了
所以log10100=2,即對數運算是冪運算的逆運算github

left right
23 = 8 log28 = 3
24 = 16 log216 = 4
25 = 32 log232 = 5

戰鬥吧!少年算法

運行時間

以二分查找爲例,使用它可節省多少時間呢?簡單查找諸葛地檢查數字,若是列表包含100個數字,最多須要猜100次。
換而言之最多須要猜想的次數與列表長度相同,這被稱爲線性時間(linear time),而二分查找則不一樣,若是列表包含100個元素
最多須要7次,若是列表包含40億個數字,最多需猜32次,而分查找的運行時間爲對數時間 O(log)數據結構

大O表示法

大O表示法是一種特殊的表示法 ,指出了算法的速度有多快。有個屌用啊,實際上,你常常要去複製別人的代碼。
在這種狀況下,知道這些算法的速度有快有慢ide

  • 算法的運行時間以不一樣的速度增長函數

    • 例如簡單查找與二分查找的區別
元素 簡單查找 二分查找
100個元素 100ms 7ms
10000個元素 10s 14ms
1 000 000 000 個元素 11天 30ms
    • O表示髮指出了算法有多快,例如列表包含n個元素,簡單查找須要檢查每一個元素,所以須要執行n次操做
      使用大O表示發這個運行時間爲O(n),二分查找須要執行logn次操做,使用大O表示爲O(log n)
    • 一些常見的大O運行時間工具

      • O(log n) ,也叫對數時間,這樣的算法包括二分算法
      • O(n),也叫線性時間,這樣的算法包括簡單查找。
      • O(n * log n) 快速排序
      • O(n2),選擇排序
      • O(n!) 即階乘時間
    • 這裏是重點性能

      • 算法的速度指的並不是時間,而是操做數的增速
      • 談論算法的速度時間時,咱們說的是隨着輸入的增長,其運行時間將以什麼樣的速度增長
      • 算法的運行時間用大O表示發表示
      • O(log n)比O(n)快,當須要搜索的元素越多時,前者比後者快的越多

    編寫解決實際問題的程序過程

    • 如何用數據形式描述問題,即將問題抽象爲一個數學模型
    • 問題所涉及到的數據量的大小及數據之間的關係
    • 如何在計算機中儲存數據及體現數據之間的關係
    • 處理數據時須要對數據執行的操做
    • 編寫的程序的性能是否良好

    數據(Data)

    • 是客觀事物的符號表示,在計算機科學中指的是全部能輸入到計算機中並被計算機程序處理的符號的總稱。
    • 數據元素(Data Element) :是數據的基本單位,在程序中一般做爲一個總體來進行考慮和處理。一個數據元素可由若干個數據項(Data Item)組成。
    • 數據項(Data Item) : 是數據的不可分割的最小單位。數據項是對客觀事物某一方面特性的數據描述。
    • 數據對象(Data Object) :是性質相同的數據元素的集合,是數據的一個子集。如字符集合C={‘A’,’B’,’C,…} 。
    • 數據結構 :相互之間具備必定聯繫的數據元素的集合。
    • 數據的邏輯結構 : 數據元素之間的相互關係稱爲邏輯結構。
    • 數據操做 : 對數據要進行的運算
    • 數據類型(Data Type):指的是一個值的集合和定義在該值集上的一組操做的總稱。

    數據的邏輯結構有四種基本類型

    • 集合:結構中數據元素之間除了「屬於同一個集合"外,再也沒有其餘的關係
    • 線性結構:結構中的數據元素存在一對一的關係
    • 樹形結構:結構中的數據元素存在一對多的關係
    • 網狀或者圖狀結構:結構中的數據元素存在多對多的關係

    數據結構的儲存方式

    由數據元素之間的關係在計算機中有兩種不一樣的表示方法——順序表示和非順序表示,從則導出兩種儲存方式,順序儲存結構和鏈式儲存結構

    • 順序存儲結構:用數據元素在存儲器中的相對位置來表示數據元素之間的邏輯結構(關係),數據元素存放的地址是連續的
    • 鏈式存儲結構:在每個數據元素中增長一個存放另外一個元素地址的指針(pointer),用該指針來表示數據元素之間的邏輯結構(關係),數據元素存放的地址是否連續沒有要求

    數據的邏輯結構和物理結構是密不可分的兩個方面,一個算法的設計取決於所選定的邏輯結構,而算法的實現依賴於所採用的存儲結構

    算法(Algorithm)

    是對特定問題求解方法(步驟)的一種描述,是指令的有限序列,其中每一條指令表示一個或多個操做。

    算法具備如下五個特性
    • 有窮性: 一個算法必須老是在執行有窮步以後結束,且每一步都在有窮時間內完成
    • 肯定性:算法中每一條指令必須有確切的含義,不存在二義性,且算法只有一個入口和一個出口
    • 可行性: 一個算法是能行的,即算法描述的操做均可以經過已經實現的基本運算執行有限次來實現
    • 輸入: 一個算法有零個或多個輸入,這些輸入取自於某個特定的對象集合
    • 輸出: 一個算法有一個或多個輸出,這些輸出是同輸入有着某些特定關係的量
    算法和程序是兩個不一樣的概念

    一個計算機程序是對一個算法使用某種程序設計語言的具體實現。算法必須可終止意味着不是全部的計算機程序都是算法。

    評價一個好的算法有如下幾個標準
    • 正確性(Correctness ): 算法應知足具體問題的需
    • 可讀性(Readability): 算法應容易供人閱讀和交流,可讀性好的算法有助於對算法的理解和修改
    • 健壯性(Robustness): 算法應具備容錯處理,當輸入非法或錯誤數據時,算法應能適當地做出反應或進行處理,而不會產生莫名其妙的輸出結果
    • 通用性(Generality): 算法應具備通常性 ,即算法的處理結果對於通常的數據集合都成立
    效率與存儲量需求: 效率指的是算法執行的時間;存儲量需求指算法執行過程當中所須要的最大存儲空間,通常地,這二者與問題的規模有關

    算法的時間複雜度

    算法中基本操做重複執行的次數是問題規模n的某個函數,其時間量度記做T(n)=O(f(n)),稱做算法的漸近時間複雜度(Asymptotic Time complexity),簡稱時間複雜度

    算法的空間複雜度

    是指算法編寫成程序後,在計算機中運行時所需存儲空間大小的度量,記做:S(n)=O(f(n)),其中n爲問題規模

    遞歸和循環的簡單比較:

    1. 從程序上看,遞歸表現爲本身調用本身,循環則沒有這樣的形式。
    2. 遞歸是從問題的最終目標出發,逐漸將複雜問題化爲簡單問題,而且簡單的問題的解決思路和複雜問題同樣,同時存在基準狀況,就能最終求得問題,是逆向的。而循環是從簡單問題出發,一步步的向前發展,最終求得問題,是正向的。
    3. 任意循環都是能夠用遞歸來表示的,可是想用循環來實現遞歸(除了單向遞歸和尾遞歸),都必須引入棧結構進行壓棧出棧。
    4. 通常來講,非遞歸的效率高於遞歸。並且遞歸函數調用是有開銷的,遞歸的次數受堆棧大小的限制。

    一塊兒進步學習

    1. Fork 個人項目並提交你的 idea
    2. Pull Request
    3. Merge

    糾錯

    若是你們發現有什麼不對的地方,能夠發起一個issue或者pull request,我會及時糾正

    補充:發起pull request的commit message請參考文章 Commit message 和 Change log 編寫指南

    致謝

    感謝如下朋友的issue或pull request:

    License

    MIT

    相關文章
    相關標籤/搜索