PHP雙向鏈表簡介

來源:互聯網
上載者:User
雙鏈表對PHP開發程式來講是很重要的一種資料結構,可以把PHP數組中想想成一個雙鏈表,而PHP內建的SplDoublyLinkedList類通過實現迭代器、數組訪問和擷取數量的介面使程式訪問對象變得訪問數組一樣方便。

SplDoublyLinkedList類代碼如下:

<?php/** * PS:關於預定義介面Iterator, ArrayAccess, Countable的文章已經介紹過了,不認識的可以往前翻翻 */class SplDoublyLinkedList implements Iterator, ArrayAccess, Countable{    /**      * @var _llist 定義一個數組用於存放資料     */    protected $_llist   = array();    /**      * @var _it_mode 鏈表的迭代模式     */    protected $_it_mode = 0;    /**      * @var _it_pos 鏈表指標     */    protected $_it_pos  = 0;    /**      * 迭代模式     * @see setIteratorMode     */    const IT_MODE_LIFO     = 0x00000002;    const IT_MODE_FIFO     = 0x00000000;    const IT_MODE_KEEP     = 0x00000000;    const IT_MODE_DELETE   = 0x00000001;    /**      * @return 返回被移出尾部節點元素     * @throw RuntimeException 如果鏈表為空白則拋出異常     */    public function pop()    {        if (count($this->_llist) == 0) {            throw new RuntimeException("Can't pop from an empty datastructure");        }        return array_pop($this->_llist);    }    /**      * @return 返回被移出頭部節點元素     * @throw RuntimeException 如果鏈表為空白則拋出異常     */    public function shift()    {        if (count($this->_llist) == 0) {            throw new RuntimeException("Can't shift from an empty datastructure");        }        return array_shift($this->_llist);    }    /**      * 往鏈表尾部添加一個節點元素     * @param $data 要添加的節點元素     */    public function push($data)    {        array_push($this->_llist, $data);        return true;    }    /**      * 往鏈表頭部添加一個節點元素     * @param $data 要添加的節點元素     */    public function unshift($data)    {        array_unshift($this->_llist, $data);        return true;    }    /**      * @return 返回尾部節點元素,並把指標指向尾部節點元素     */    public function top()    {        return end($this->_llist);    }    /**      * @return 返回頭部節點元素,並把指標指向頭部節點元素     */    public function bottom()    {        return reset($this->_llist);    }    /**      * @return 返回鏈表節點數     */    public function count()    {        return count($this->_llist);    }    /**      * @return 判斷鏈表是否為空白     */    public function isEmpty()    {        return ($this->count() == 0);    }    /**      * 設定迭代模式     * - 迭代的順序 (先進先出、後進先出)     *  - SplDoublyLnkedList::IT_MODE_LIFO (堆棧)     *  - SplDoublyLnkedList::IT_MODE_FIFO (隊列)     *     * - 迭代過程中迭代器的行為     *  - SplDoublyLnkedList::IT_MODE_DELETE (刪除已迭代的節點元素)     *  - SplDoublyLnkedList::IT_MODE_KEEP   (保留已迭代的節點元素)     *     * 預設的模式是 0 : SplDoublyLnkedList::IT_MODE_FIFO | SplDoublyLnkedList::IT_MODE_KEEP     *     * @param $mode 新的迭代模式     */    public function setIteratorMode($mode)    {        $this->_it_mode = $mode;    }    /**      * @return 返回當前的迭代模式     * @see setIteratorMode     */    public function getIteratorMode()    {        return $this->_it_mode;    }    /**      * 重設節點指標     */    public function rewind()    {        if ($this->_it_mode & self::IT_MODE_LIFO) {            $this->_it_pos = count($this->_llist)-1;        } else {            $this->_it_pos = 0;        }    }    /**      * @return 判斷指標對應的節點元素是否存在     */    public function valid()    {        return array_key_exists($this->_it_pos, $this->_llist);    }    /**      * @return 返回當前指標的位移位置     */    public function key()    {        return $this->_it_pos;    }    /**      * @return 返回當前指標對應的節點元素     */    public function current()    {        return $this->_llist[$this->_it_pos];    }    /**      * 將指標向前移動一個位移位置     */    public function next()    {        if ($this->_it_mode & self::IT_MODE_LIFO) {            if ($this->_it_mode & self::IT_MODE_DELETE) {                $this->pop();            }            $this->_it_pos--;        } else {            if ($this->_it_mode & self::IT_MODE_DELETE) {                $this->shift();            } else {                $this->_it_pos++;            }        }    }    /**      * @return 位移位置是否存在     *     * @param $offset             位移位置     * @throw OutOfRangeException 如果位移位置超出範圍或者無效則拋出異常     */    public function offsetExists($offset)    {        if (!is_numeric($offset)) {            throw new OutOfRangeException("Offset invalid or out of range");        } else {            return array_key_exists($offset, $this->_llist);        }    }    /**      * @return 擷取位移位置對應的值     *     * @param $offset             位移位置     * @throw OutOfRangeException 如果位移位置超出範圍或者無效則拋出異常     */    public function offsetGet($offset)    {        if ($this->_it_mode & self::IT_MODE_LIFO) {            $realOffset = count($this->_llist)-$offset;        } else {            $realOffset = $offset;        }        if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {            throw new OutOfRangeException("Offset invalid or out of range");        } else {            return $this->_llist[$realOffset];        }    }    /**      * @return 設定位移位置對應的值     *     * @param $offset             位移位置     * @throw OutOfRangeException 如果位移位置超出範圍或者無效則拋出異常     */    public function offsetSet($offset, $value)    {        if ($offset === null) {            return $this->push($value);        }        if ($this->_it_mode & self::IT_MODE_LIFO) {            $realOffset = count($this->_llist)-$offset;        } else {            $realOffset = $offset;        }        if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {            throw new OutOfRangeException("Offset invalid or out of range");        } else {            $this->_llist[$realOffset] = $value;        }    }    /**      * @return 刪除位移位置對應的值     *     * @param $offset             位移位置     * @throw OutOfRangeException 如果位移位置超出範圍或者無效則拋出異常     */    public function offsetUnset($offset)    {        if ($this->_it_mode & self::IT_MODE_LIFO) {            $realOffset = count($this->_llist)-$offset;        } else {            $realOffset = $offset;        }        if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {            throw new OutOfRangeException("Offset invalid or out of range");        } else {            array_splice($this->_llist, $realOffset, 1);        }    }}?>

例子說明:

<?php$doubly=new SplDoublyLinkedList();$doubly->push('a');$doubly->push('b');$doubly->push('c');$doubly->push('d');echo '初始鏈表結構:';var_dump($doubly);echo '<br/> 先進先出Keep模式迭代輸出: <br/>';$doubly->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_KEEP);$doubly->rewind();foreach($doubly as $key=>$value){    echo $key.' '.$value."<br/>";}echo '<br/>後進先出Keep模式迭代輸出:<br/>';$doubly->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_KEEP);$doubly->rewind();foreach($doubly as $key=>$value){    echo $key.' '.$value."<br/>";}echo '<br/>後進先出Delete模式迭代輸出:<br/>';$doubly->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_DELETE);$doubly->rewind();foreach($doubly as $key=>$value){    if($key == 1) break;    echo $key.' '.$value."<br/>";}echo '<br/>Delete模式迭代之後的鏈表:';var_dump($doubly);?>


輸出:

初始鏈表結構:

object(SplDoublyLinkedList)[1]  private 'flags' =>  0  private 'dllist' =>     array (size=4)      0 =>  'a' (length=1)      1 =>  'b' (length=1)      2 =>  'c' (length=1)      3 =>  'd' (length=1)


先進先出Keep模式迭代輸出:
0 a
1 b
2 c
3 d

後進先出Keep模式迭代輸出:
3 d
2 c
1 b
0 a

後進先出Delete模式迭代輸出:
3 d
2 c

Delete模式迭代之後的鏈表:

object(SplDoublyLinkedList)[1]  private 'flags' =>  3  private 'dllist' =>     array (size=2)      0 =>  'a' (length=1)      1 =>  'b' (length=1)

最後一個問題:SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_KEEP 模式下迭代輸出什嗎?
相關推薦:

PHP雙向鏈表基礎詳解

JavaScript雙向鏈表定義與使用方法

PHP實現雙向鏈表的一例代碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.