星期四, 7月 27, 2006

PHP 的陣列

就 prototyping 而言,我相當喜歡 PHP 的陣列。

上回提到,PHP 的 array 其實是用 Hash table + Double Linked List 實作的。因此,要存取 $array[100],實際上是用 "100" 作為雜湊表 $array 的鍵值 (key),然後傳回表中所儲存的值。

所以,在實際的應用上,使用 PHP 的陣列,效能會比「一般程式語言的陣列」慢上許多(因為需要計算 hash key,有時也必須處理 hash collision 的問題)。

即使有著這麼大的效能缺陷,我還是相當喜歡 PHP 的陣列。為什麼呢?

因為,除了「一般陣列」的處理方式外,我們還可以很簡單地利用 PHP array 來實作出基本的資料結構(像是 linked list、stack、queue、tree 等等),而 PHP 也內建了許多有用的函式,可以讓我們方便地操作陣列的內容。例如,我們可以
  • 用 array_push() 與 array_pop() 來實作出堆疊 (stack) 的行為。

  • 用 array_shift() 與 array_push() 來實作簡單的佇列 (queue)。

  • 用 array_push()、array_pop()、array_shift()、array_unshift()來實作雙向佇列 (dqueue)。傳統的人工智能 (artificial intelligence) ,有許多問題相當著重於「狀態空間搜尋」(state space search);傳統的課本裡,也經常會以一些「玩具問題」 (toy problems) 來介紹這樣的解題概念。之前解傳教士與食人族的程式、解數獨的程式、解 Pentominoes的程式,都是利用狀態空間搜尋的例子。

    狀態空間的搜尋,大致上類似於樹狀結構的巡走 (tree traversal)。利用雙向佇列,可以很容易地實作出廣度優先 (breadth-first) 或深度優先 (depth-first) 搜尋。

  • 用 array_merge()、array_intersect()、array_diff() 來實作集合之間的聯集、交集、以及差集。

  • 用多重陣列實作樹狀結構 (tree)。也就是說,可以直接利用 PHP 的多重陣列來實作像是 parse tree 般的階層結構。

  • 其他還有許多「有時會顯得很方便」的內建函式,像是 sort() 可以對陣列排序,usort() 可以呼叫自己定義的另一個函式來對陣列內容排序,shuffle() 可以打亂陣列內容的順序(不必自己寫一小段程式來做洗牌的動作),array_fill()、array_pad() 與 range() 可以填滿一個陣列... 等等。
有時,我甚至會覺得,PHP array 所提供的便利性,有些接近傳統人工智能常用的語言(像是 LISP 或者 Prolog)呢。

2 則留言:

lcat 提到...

PHP 的陣列不是來自 Perl 啊?

tu 提到...

如果沒記錯,Perl 應該是把一般的陣列和雜湊陣列,分開成兩種資料型態 ($array 與 @Hash),而 PHP 則把這兩者合成單一的資料型態 (同樣用 $array,卻兼具兩種特性)。

為什麼不像 Perl 一樣,用不同的資料型態來處理「一般陣列」與「雜湊陣列」呢?

雖然犧牲傳統陣列較好的執行效能;但將這兩種資料型態合而為一,卻似乎可以簡化程式語言的複雜性。

我想,這應該曾是個困難的抉擇。