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