SPL数据结构
数据结构是计算机存储、组织数据的方式。
SPL提供了双向链表、堆栈、队列、堆、降序堆、升序堆、优先级队列、定长数组、对象容器。
基本概念
Bottom:节点,第一个节点称Bottom;
Top:最后添加的链表的节点称Top;
当前节点(Current):链表指针指向的节点称为当前节点;
SplDoublyLinkedList 双向链表
SplDoublyLinkedList 实现了Iterator
, ArrayAccess
, Countable
接口。
类摘要
SplDoublyLinkedList implements Iterator , ArrayAccess , Countable {
/* 方法 */
public __construct ( void )
public void add ( mixed $index , mixed $newval )
public mixed bottom ( void )
public int count ( void )
public mixed current ( void )
public int getIteratorMode ( void )
public bool isEmpty ( void )
public mixed key ( void )
public void next ( void )
public bool offsetExists ( mixed $index )
public mixed offsetGet ( mixed $index )
public void offsetSet ( mixed $index , mixed $newval )
public void offsetUnset ( mixed $index )
public mixed pop ( void )
public void prev ( void )
public void push ( mixed $value )
public void rewind ( void )
public string serialize ( void )
public void setIteratorMode ( int $mode )
public mixed shift ( void )
public mixed top ( void )
public void unserialize ( string $serialized )
public void unshift ( mixed $value )
public bool valid ( void )
}
注意:SplDoublyLinkedList::setIteratorMode
用来设置链表模式:
迭代方向:
SplDoublyLinkedList::IT_MODE_LIFO (Stack style)
SplDoublyLinkedList::IT_MODE_FIFO (Queue style)
迭代器行为:
SplDoublyLinkedList::IT_MODE_DELETE (Elements are deleted by the iterator)
SplDoublyLinkedList::IT_MODE_KEEP (Elements are traversed by the iterator)
默认模式: SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_KEEP
当前节点操作:
rewind:将链表的当前指针指向第一个元素
current:链表当前指针,当节点被删除后,会指向空节点
prev:上一个
next:下一个
增加节点操作:
push 在双向链表的结尾处将元素压入
unshift 前置双链表元素,预备值在双链表的开始
删除节点操作:
pop 从双向链表的结尾弹出一个节点,不会改变指针位置
shift从双向链表的开头弹出一个节点,不会改变指针位置
定位操作:
bottom 返回当前双向链表的第一个节点的值,当前指针不变
top返回当前双向链表的最后一个节点的值,当前指针不变
特定节点操作:
offsetExists 理解为key是否存在
offsetGet将key节点拿出来
offsetSet把数据刷新
offsetUnset删除
示例:SplDoublyLinkedList.php
<?php
/**
*SplDoublyLinkedList 类学习
*/
$obj = new SplDoublyLinkedList();
$obj -> push(1);//把新的节点添加到链表的顶部top
$obj -> push(2);
$obj -> push(3);
$obj -> unshift(10);//把新节点添加到链表底部bottom
print_r($obj);
$obj ->rewind();//rewind操作用于把节点指针指向Bottom所在节点
$obj -> prev();//使指针指向上一个节点,靠近Bottom方向
echo 'next node :'.$obj->current().PHP_EOL;
$obj -> next();
$obj -> next();
echo 'next node :'.$obj->current().PHP_EOL;
$obj -> next();
if($obj -> current())
echo 'current node valid'.PHP_EOL;
else
echo 'current node invalid'.PHP_EOL;
$obj ->rewind();
//如果当前节点是有效节点,valid返回true
if($obj->valid())
echo 'valid list'.PHP_EOL;
else
echo 'invalid list'.PHP_EOL;
print_r($obj);
echo 'pop value :'.$obj -> pop().PHP_EOL;
print_r($obj);
echo 'next node :'.$obj ->current().PHP_EOL;
$obj ->next();//1
$obj ->next();//2
$obj -> pop();//把top位置的节点从链表中删除,并返回,如果current正好指>向top位置,那么调用pop之后current()会失效
echo 'next node:'.$obj -> current().PHP_EOL;
print_r($obj);
$obj ->shift();//把bottom位置的节点从链表中删除,并返回
print_r($obj);
SplStack 栈
栈(Stack)是一种特殊的线性表,因为它只能在线性表的一端进行插入或删除元素(即进栈和出栈)。
栈是一种后进先出(LIFO)的数据结构。
SplStack 继承自 双向链表 SplDoublyLinkedList。
示例:
<?php
$stack = new SplStack();
$stack->push(1);
$stack->push(2);
$stack->push(3);
echo 'bottom:'.$stack -> bottom().PHP_EOL;
echo "top:".$stack->top().PHP_EOL;
//堆栈的offset=0,是top所在位置(即栈的末尾)
$stack -> offsetSet(0, 10);
echo "top:".$stack->top().'<br/>';
//堆栈的rewind和双向链表的rewind相反,堆栈的rewind使得当前指针指向top所在位置,而双向链表调用之后指向bottom所在位置
$stack -> rewind();
echo 'current:'.$stack->current().'<br/>';
$stack ->next();//堆栈的next操作使指针指向靠近bottom位置的下一个节点,而双向链表是靠近top的下一个节点
echo 'current:'.$stack ->current().'<br/>';
//遍历堆栈
$stack -> rewind();
while ($stack->valid()) {
echo $stack->key().'=>'.$stack->current().PHP_EOL;
$stack->next();//不从链表中删除元素
}
echo '<br/>';
echo $stack->pop() .'--';
echo $stack->pop() .'--';
echo $stack->pop() .'--';
输出:
bottom:1 top:3 top:10
current:10
current:2
2=>10 1=>2 0=>1
10--2--1--
SplQueue 队列
队列是一种先进先出(FIFO)的数据结构。使用队列时插入在一端进行而删除在另一端进行。
SplQueue 也是继承自 双向链表 SplDoublyLinkedList,并有自己的方法:
/* 方法 */
__construct ( void )
mixed dequeue ( void )
void enqueue ( mixed $value )
void setIteratorMode ( int $mode )
示例1:
<?php
$queue = new SplQueue();
$queue->enqueue(1);
$queue->enqueue(2);
echo $queue->dequeue() .'--';
echo $queue->dequeue() .'--';
示例2:
<?php
$obj = new SplQueue();
$obj -> enqueue('a');
$obj -> enqueue('b');
$obj -> enqueue('c');
echo 'bottom:'.$obj -> bottom().PHP_EOL;
echo 'top:'.$obj -> top();
echo '<br/>';
//队列里的offset=0是指向bottom位置
$obj -> offsetSet(0,'A');
echo 'bottom:'.$obj -> bottom();
echo '<br/>';
//队列里的rewind使得指针指向bottom所在位置的节点
$obj -> rewind();
echo 'current:'.$obj->current();
echo '<br/>';
while ($obj ->valid()) {
echo $obj ->key().'=>'.$obj->current().PHP_EOL;
$obj->next();//
}
echo '<br/>';
//dequeue操作从队列中提取bottom位置的节点,并返回,同时从队列里面删除该元素
echo 'dequeue obj:'.$obj->dequeue();
echo '<br/>';
echo 'bottom:'.$obj -> bottom().PHP_EOL;
输出:
bottom:a top:c
bottom:A
current:A
0=>A 1=>b 2=>c
dequeue obj:A
bottom:b
SPLHEAP 堆
堆(Heap)就是为了实现优先队列而设计的一种数据结构,它是通过构造二叉堆(二叉树的一种)实现。
根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。二叉堆还常用于排序(堆排序)。
SplHeap 是一个抽象类,实现了Iterator
, Countable
接口。最大堆(SplMaxHeap)和最小堆(SplMinHeap)就是继承它实现的。最大堆和最小堆并没有额外的方法。
如果要使用SplHeap类,需要实现其抽象方法int compare ( mixed $value1 , mixed $value2 )
。
类摘要:
abstract SplHeap implements Iterator , Countable {
/* 方法 */
public __construct ( void )
abstract protected int compare ( mixed $value1 , mixed $value2 )
public int count ( void )
public mixed current ( void )
public mixed extract ( void )
public void insert ( mixed $value )
public bool isEmpty ( void )
public mixed key ( void )
public void next ( void )
public void recoverFromCorruption ( void )
public void rewind ( void )
public mixed top ( void )
public bool valid ( void )
}
示例:
<?php
class MySimpleHeap extends SplHeap
{
//compare()方法用来比较两个元素的大小,绝对他们在堆中的位置
public function compare( $value1, $value2 ) {
return ( $value1 - $value2 );
}
}
$obj = new MySimpleHeap();
$obj->insert( 4 );
$obj->insert( 8 );
$obj->insert( 1 );
$obj->insert( 0 );
echo $obj->top(); //8
echo $obj->count(); //4
echo '<br/>';
foreach( $obj as $number ) {
echo $number.PHP_EOL;
}
输出:
84
8 4 1 0
SPLMAXHEAP 最大堆
最大堆(SplMaxHeap)继承自抽象类SplHeap实现的。最大堆并没有额外的方法。
SPLMINHEAP 最小堆
最小堆(SplMinxHeap)继承自抽象类SplHeap实现的。最小堆并没有额外的方法。
如下:最小堆(任意节点的优先级不小于它的子节点)
示例:
<?php
$obj = new SplMinHeap();
$obj->insert(4);
$obj->insert(8);
//提取
echo $obj->extract(). PHP_EOL;
echo $obj->extract();
//4 8
SplPriorityQueue 优先级队列
优先级队列SplPriorityQueue是基于堆实现的。和堆一样,也有int compare ( mixed $priority1 , mixed $priority2 )
方法。
SplPriorityQueue 实现了Iterator
, Countable
接口。
示例:
$pq = new SplPriorityQueue();
$pq->insert('a', 10);
$pq->insert('b', 1);
$pq->insert('c', 8);
echo $pq->count() .PHP_EOL; //3
echo $pq->current() . PHP_EOL; //a
/**
* 设置元素出队模式
* SplPriorityQueue::EXTR_DATA 仅提取值
* SplPriorityQueue::EXTR_PRIORITY 仅提取优先级
* SplPriorityQueue::EXTR_BOTH 提取数组包含值和优先级
*/
$pq->setExtractFlags(SplPriorityQueue::EXTR_DATA);
while($pq->valid()) {
print_r($pq->current()); //a c b
$pq->next();
}
SplFixedArray 定长数组
SplFixedArray 实现了Iterator
, ArrayAccess
, Countable
接口。
和普通数组不一样,定长数组规定了数组的长度。优势就是比普通的数组处理更快。
<?php
$arr = new SplFixedArray(5);
$arr[0] = 1;
$arr[1] = 2;
$arr[2] = 3;
print_r($arr);
//SplFixedArray Object ( [0] => 1 [1] => 2 [2] => 3 [3] => [4] => )
SplObjectStorage 对象容器
SplObjectStorage是用来存储一组对象的,特别是当你需要唯一标识对象的时候。该类实现了Countable
,Iterator
,Serializable
,ArrayAccess
四个接口。可实现统计、迭代、序列化、数组式访问等功能。
示例:
class A {
public $i;
public function __construct($i) {
$this->i = $i;
}
}
$a1 = new A(1);
$a2 = new A(2);
$a3 = new A(3);
$a4 = new A(4);
$container = new SplObjectStorage();
//SplObjectStorage::attach 添加对象到Storage中
$container->attach($a1);
$container->attach($a2);
$container->attach($a3);
//SplObjectStorage::detach 将对象从Storage中移除
$container->detach($a2);
//SplObjectStorage::contains用于检查对象是否存在Storage中
var_dump($container->contains($a1)); //true
var_dump($container->contains($a4)); //false
//遍历
$container->rewind();
while($container->valid()) {
var_dump($container->current());
$container->next();
}
SPL数据结构的更多相关文章
- PHP——大话PHP设计模式——SPL数据结构
- php spl数据结构
1.双链表SplDoublyLinkedList 结构如图: 类定义: SplDoublyLinkedList implements Iterator , ArrayAccess , Countabl ...
- PHP标准库 (SPL) 笔记
简介 SPL是Standard PHP Library(PHP标准库)的缩写. The Standard PHP Library (SPL) is a collection of interfaces ...
- SPL类
用途:对类,方法,属性,参数的提取生成文档:自动加载插件 实列化类同于new:$ref = new ReflectionClass($classname);$class = $ref->newI ...
- 详解OJ(Online Judge)中PHP代码的提交方法及要点【举例:ZOJ 1001 (A + B Problem)】
详解OJ(Online Judge)中PHP代码的提交方法及要点 Introduction of How to submit PHP code to Online Judge Systems Int ...
- Standard PHP Library(SPL)中的数据结构
SPL提供了一组标准数据结构. SplDoublyLinkedList Class:双向链表(DLL)是在两个方向上相互链接的节点列表.当底层结构是dll时,迭代器的操作.对两端的访问.节点的添加或删 ...
- PHP SPL标准库之数据结构栈(SplStack)介绍(基础array已经可以解决很多问题了,现在开始解决问题)
PHP SPL标准库之数据结构栈(SplStack)介绍(基础array已经可以解决很多问题了,现在开始解决问题) 一.总结 SplStack就是继承双链表(SplDoublyLinkedList)实 ...
- PHP SPL标准库-数据结构
SPL是用于解决典型问题的一组接口与类的集合. 双向链表 SplDoublyLinkedList SplStack SplQueue 双链表是一种重要的线性存储结构,对于双链表中的每个节点,不仅仅存储 ...
- PHP的SPL扩展库(一)数据结构
SPL 库也叫做 PHP 标准库,主要就是用于解决典型问题的一组接口或类的集合.这些典型问题包括什么呢?比如我们今天要讲的数据结构,还有一些设计模式的实现,就像我们之前讲过的观察者模式相关的接口在 S ...
随机推荐
- 通过express框架为前端提供api(数据),妈妈再也不用担心后端不给我数据了~
个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! 首先,确保自己安装了express框架. 没有安装的同学可以参照下面这篇博 ...
- log4net进阶手札(二):基本用法
本节将主要在WebSite中,对保存日志在文本文件的基本用法来进行介绍,并结合WebForm的初始化方式区别进行说明,解决方案如下图所示: 一.WebSite应用第1步:配置Web.Config文件, ...
- vue 遮罩层阻止默认滚动事件
vue中提供 @touchmove.prevent 方法可以完美解决这个问题. <div class="child" @touchmove.prevent ></ ...
- POJ 2230 Watchcow 欧拉回路的DFS解法(模板题)
Watchcow Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 9974 Accepted: 4307 Special Judg ...
- 入职半年多,Guide哥总结了这些帮助你领先90%程序员的好习惯!
大家好,我是 Guide 哥,这篇文章还是不分享技术文章了,我想简单聊聊一些程序员的好习惯. 其实自己写这篇文章还是很忐忑的,毕竟自己算不上一个优秀的程序员,但也不是那么差.大学学习编程 4 年,工作 ...
- ASP.NET Core 包管理工具(4)
之前忘记介绍ASP.NET Core静态文件wwwroot了.再来补充一下.步骤比较简单在项目上右击添加文件夹输入文件名称 wwwroot就搞定了.这个文件主要是放置一些静态文件的,比如css.js. ...
- D. Distance in Tree(树型Dp计数)
\(其实思路都能想到一点,就是去重这里特别麻烦,没有好的思路.\) \(设dp[i][j]为以i为根深度为j的节点数量\) \(dp[parent][j]=\sum{dp[son][j-1]}\) \ ...
- Codeforces 1332 D. Walk on Matrix(构造矩阵)
怎么构造呢? \(首先我们不可能去构造一个2000*2000的矩阵,那太复杂了\) \(也许我们可以看看2*2的矩阵??\) \[\left[ \begin{matrix} x&y\\ z&a ...
- LTE网络概述
LTE主要由两部分组成:无线接入技术演进(E-UTRAN)+系统架构演进(SAE):其中,SAE主要含有的是演进型分组交换核心网(EPC),其控制处理部分为移动性管理实体(MME),数据承载部分称为业 ...
- Python 为什么抛弃累赘的花括号,使用缩进来划分代码块?
大家好,这是"Python为什么"系列节目的文字稿(文末有观看地址). 本期话题:Python 为什么使用缩进来划分代码块,而不像其它语言使用花括号 {} 或者 "end ...