双向链表

<?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;

 

posted @ 2015-03-26 16:52  wh-王东  阅读(218)  评论(0编辑  收藏  举报