双链表对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实现双向链表的一例代码
以上就是php双向链表简介的详细内容。