双向链表

<?php

/**

 * Created by PhpStorm.

 * User: dongdong

 * Date: 2015/3/26

 * Time: 10:01

 */



class LinkNode{



    public $pre=null;



    public $next=null;



    public $key;



    public $data;



    public function __construct($key,$data){

        $this->key = $key;

        $this->data = $data;

    }

}



class DoubleLink implements Countable,Iterator {

    private $head; // 头指针

    private $tail; // 尾指针

    private $current; // 当前指针

    private $len; // 链表长度



    public function __construct(){

        $this->head = new LinkNode(null,null);

        $this->current = $this->head;

        $this->tail = $this->head;

        $this->len =0;

    }



    public static function newNode($key,$data){

        if(empty($key)){

            throw new Exception('键值不能为空');

        }

        return new LinkNode($key,$data);

    }



    public function add($key,$data){

        if(!is_null($this->find($key))){

            throw new Exception("键值已存在");

        }

        $node = self::newNode($key,$data);

        $this->tail->next = $node;

        $node->pre = $this->tail;

        $this->tail = $node;

        $this->len++;

        return $this;

    }



    public function insert($pos,$key,$data){

        $cur = $this->find($pos);

        if(is_null($cur)){

           throw new Exception('您要插入的位置不存在');

        }

        $node = self::newNode($key,$data);

        if(is_null($cur->next)){

            $this->tail = $node;

            $cur->next = $node;

            $node->pre = $cur;

        }else{

            $oldNext = $cur->next;

            $cur->next = $node;

            $node->next = $oldNext;

        }

        $this->len++;

        return $this;

    }



    public function remove($key){

        $cur = $this->find($key);

        if(is_null($cur)){

            throw new Exception('链表中不存在该键值');

        }

        $pre = $cur->pre;

        if(is_null($cur->next)){

            $this->tail = $pre;

        }else{

            $next = $cur->next;

            $pre->next = $next;

            $next->pre = $pre;

        }

        unset($cur);

        $this->len--;

        return $this;

    }



    public function find($key){

        $cur = $this->head;

        while(!is_null($cur->next)){

            $cur = $cur->next;

            if($cur->key == $key){

                return $cur;

            }

        }

        return null;

    }



    public function toArray(){

        if($this->len <= 0){

            return null;

        }

        $cur = $this->head;

        while(!is_null($cur->next)){

            $cur = $cur->next;

            $a[$cur->key] = $cur->data;

        }

        return $a;

    }



    public function getTail(){

        return $this->tail;

    }



    /**

     * (PHP 5 &gt;= 5.1.0)<br/>

     * Count elements of an object

     * @link http://php.net/manual/en/countable.count.php

     * @return int The custom count as an integer.

     * </p>

     * <p>

     * The return value is cast to an integer.

     */

    public function count()

    {

        return $this->len;

    }



    /**

     * (PHP 5 &gt;= 5.0.0)<br/>

     * Return the current element

     * @link http://php.net/manual/en/iterator.current.php

     * @return mixed Can return any type.

     */

    public function current()

    {

        return $this->current->data;

    }



    /**

     * (PHP 5 &gt;= 5.0.0)<br/>

     * Move forward to next element

     * @link http://php.net/manual/en/iterator.next.php

     * @return void Any returned value is ignored.

     */

    public function next()

    {

        $this->current = $this->current->next;

    }



    /**

     * (PHP 5 &gt;= 5.0.0)<br/>

     * Return the key of the current element

     * @link http://php.net/manual/en/iterator.key.php

     * @return mixed scalar on success, or null on failure.

     */

    public function key()

    {

        return $this->current->key;

    }



    /**

     * (PHP 5 &gt;= 5.0.0)<br/>

     * Checks if current position is valid

     * @link http://php.net/manual/en/iterator.valid.php

     * @return boolean The return value will be casted to boolean and then evaluated.

     * Returns true on success or false on failure.

     */

    public function valid()

    {

        return $this->len > 0 && !is_null($this->current);

    }



    /**

     * (PHP 5 &gt;= 5.0.0)<br/>

     * Rewind the Iterator to the first element

     * @link http://php.net/manual/en/iterator.rewind.php

     * @return void Any returned value is ignored.

     */

    public function rewind()

    {

        $this->current = $this->head->next;

    }

}



header('Content-Type:text/html;charset=utf-8');

$dl = new DoubleLink();

for($i=1;$i<=10;$i++){

    $dl->add($i,'a'.$i);

}



foreach($dl as $key=>$val){

    var_dump( $val );

}echo "<br />当前链表顺序:";

print_r($dl->toArray());

echo "<br />";

echo "输出当前尾节点的值:";

echo $dl->getTail()->data;

echo "<br >";

echo "输出键值为4的值:";

echo $dl->find(4)->data;

echo "<br >";

echo "删除键值为4的节点";

$dl->remove(4);

echo "<br>当前链表";

print_r($dl->toArray());

echo "<br>往键值为8的节点后面插入一个新的节点";

$dl->insert(8,99,'999999');

echo "<br>当前链表";

print_r($dl->toArray());

echo "<br>往键值为10的节点后面插入一个新的节点";

$dl->insert(10,12,'1212121212');

echo "<br>当前链表";

print_r($dl->toArray());

echo "<br />";

echo "输出当前尾节点的值:";

echo $dl->getTail()->data;

 

你可能感兴趣的:(双向链表)