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(); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)