数据结构堆栈队列_PHP开发人员的数据结构:堆栈和队列

数据结构堆栈队列

A data structure, or abstract data type (ADT), is a model that is defined by a collection of operations that can be performed on itself and is limited by the constraints on the effects of those operations. It creates a wall between what can be done to the underlying data and how it is to be done.

数据结构或抽象数据类型 (ADT)是一种模型,该模型由可以对其自身执行的操作的集合定义,并受这些操作的影响的约束所限制。 它在基础数据可以做什么和如何完成之间建立了一道墙。

Most of us are familiar with stacks and queues in normal everyday usage, but what do supermarket queues and vending machines have to do with data structures? Let’s find out. In this article I’ll introduce you to two basic abstract data types – stack and queue – which have their origins in everyday usage.

我们大多数人都熟悉日常使用中的堆栈和队列,但是超市队列和自动售货机与数据结构有什么关系? 让我们找出答案。 在本文中,我将向您介绍两种基本的抽象数据类型-堆栈和队列-它们起源于日常使用。

堆栈 (Stacks)

In common usage, a stack is a pile of objects which are typically arranged in layers – for example, a stack of books on your desk, or a stack of trays in the school cafeteria. In computer science parlance, a stack is a sequential collection with a particular property, in that, the last object placed on the stack, will be the first object removed. This property is commonly referred to as last in first out, or LIFO. Candy, chip, and cigarette vending machines operate on the same principle; the last item loaded in the rack is dispensed first.

通常,一堆是通常按层排列的一堆对象,例如,桌上的一堆书或学校食堂中的一堆托盘。 用计算机科学的话来说,堆栈是具有特定属性的顺序集合,因为放置在堆栈上的最后一个对象将是删除的第一个对象。 此属性通常称为后进 先出 ( LIFO) 。 糖果,薯片和香烟自动售货机的工作原理相同。 货架上最后装载的物品将首先分配。

In abstract terms, a stack is a linear list of items in which all additions to (a “push”) and deletions from (a “pop”) the list are restricted to one end – defined as the “top” (of the stack). The basic operations which define a stack are:

用抽象的术语来说,堆栈是项目的线性列表,其中对列表的所有添加(“推送”)和对列表的删除(“ pop”)都限于一端-定义为(堆栈的“顶部” )。 定义堆栈的基本操作是:

  • init – create the stack.

    init –创建堆栈。

  • push – add an item to the top of the stack.

    –将项目添加到堆栈的顶部。

  • pop – remove the last item added to the top of the stack.

    弹出 –删除添加到堆栈顶部的最后一项。

  • top – look at the item on the top of the stack without removing it.

    top –在不删除的情况下查看堆栈顶部的项目。

  • isEmpty – return whether the stack contains no more items.

    isEmpty –返回堆栈是否不再包含任何项目。

A stack can also be implemented to have a maximum capacity. If the stack is full and does not contain enough slots to accept new entities, it is said to be an overflow – hence the phrase “stack overflow”. Likewise, if a pop operation is attempted on an empty stack then a “stack underflow” occurs.

堆栈也可以实现为具有最大容量。 如果堆栈已满,并且没有足够的插槽来容纳新实体,则称其为溢出 -因此称为“堆栈溢出”。 同样,如果在空堆栈上尝试执行弹出操作,则会发生“堆栈下溢”。

Knowing that our stack is defined by the LIFO property and a number of basic operations, notably push and pop, we can easily implement a stack using arrays since arrays already provide push and pop operations.

知道我们的堆栈是由LIFO属性和许多基本操作(尤其是推入和弹出)定义的,由于数组已经提供了推入和弹出操作,因此我们可以轻松地使用数组实现堆栈。

Here’s what our simple stack looks like:

我们的简单堆栈如下所示:

<?php
class ReadingList
{
    protected $stack;
    protected $limit;
    
    public function __construct($limit = 10) {
        // initialize the stack
        $this->stack = array();
        // stack can only contain this many items
        $this->limit = $limit;
    }

    public function push($item) {
        // trap for stack overflow
        if (count($this->stack) < $this->limit) {
            // prepend item to the start of the array
            array_unshift($this->stack, $item);
        } else {
            throw new RunTimeException('Stack is full!'); 
        }
    }

    public function pop() {
        if ($this->isEmpty()) {
            // trap for stack underflow
	      throw new RunTimeException('Stack is empty!');
	  } else {
            // pop item from the start of the array
            return array_shift($this->stack);
        }
    }

    public function top() {
        return current($this->stack);
    }

    public function isEmpty() {
        return empty($this->stack);
    }
}

In this example, I’ve used array_unshift() and array_shift(), rather than array_push() and array_pop(), so that the first element of the stack is always the top. You could use array_push() and array_pop() to maintain semantic consistency, in which case, the Nth element of the stack becomes the top. It makes no difference either way since the whole purpose of an abstract data type is to abstract the manipulation of the data from its actual implementation.

在此示例中,我使用了array_unshift()array_shift() ,而不是array_push()array_pop() ,因此堆栈的第一个元素始终是顶部。 您可以使用array_push()array_pop()来保持语义一致性,在这种情况下,堆栈的第N个元素将成为顶部。 两种方法都没有区别,因为抽象数据类型的全部目的是从实际实现中抽象出对数据的操作。

Let’s add some items to the stack:

让我们将一些项目添加到堆栈中:

<?php
$myBooks = new ReadingList();

$myBooks->push('A Dream of Spring');
$myBooks->push('The Winds of Winter');
$myBooks->push('A Dance with Dragons');
$myBooks->push('A Feast for Crows');
$myBooks->push('A Storm of Swords'); 
$myBooks->push('A Clash of Kings');
$myBooks->push('A Game of Thrones');

To remove some items from the stack:

要从堆栈中删除一些项目:

<?php
echo $myBooks->pop(); // outputs 'A Game of Thrones'
echo $myBooks->pop(); // outputs 'A Clash of Kings'
echo $myBooks->pop(); // outputs 'A Storm of Swords'

Let’s see what’s at the top of the stack:

让我们看一下堆栈顶部的内容:

<?php
echo $myBooks->top(); // outputs 'A Feast for Crows'

What if we remove it?

如果我们将其删除怎么办?

<?php
echo $myBooks->pop(); // outputs 'A Feast for Crows'

And if we add a new item?

如果我们添加一个新项目?

<?php
$myBooks->push('The Armageddon Rag');
echo $myBooks->pop(); // outputs 'The Armageddon Rag'

You can see the stack operates on a last in first out basis. Whatever is last added to the stack is the first to be removed. If you continue to pop items until the stack is empty, you’ll get a stack underflow runtime exception.

您可以看到堆栈在后进先出的基础上运行。 最后添加到堆栈中的所有内容都是第一个要删除的。 如果您继续弹出项目,直到堆栈为空,您将得到堆栈下溢运行时异常。

PHP Fatal error:  Uncaught exception 'RuntimeException' with message 'Stack is empty!' in /home/ignatius/Data Structures/code/array_stack.php:33
Stack trace:
#0 /home/ignatius/Data Structures/code/example.php(31): ReadingList->pop()
#1 /home/ignatius/Data Structures/code/array_stack.php(54): include('/home/ignatius/...')
#2 {main}
  thrown in /home/ignatius/Data Structures/code/array_stack.php on line 33

Oh, hello… PHP has kindly provided a stack trace showing the program execution call stack prior and up to the exception!

哦,你好……PHP提供了一个堆栈跟踪,该跟踪显示了程序执行调用的堆栈,直到异常为止!

SPLStack (The SPLStack)

The SPL extension provides a set of standard data structures, including the SplStack class (PHP5 >= 5.3.0). We can implement the same object, although much more tersely, using an SplStack as follows:

SPL扩展提供了一组标准数据结构,包括SplStack类(PHP5> = 5.3.0)。 我们可以使用SplStack来实现相同的对象(尽管更为简洁):

<?php
class ReadingList extends SplStack
{
}

The SplStack class implements a few more methods than we’ve originally defined. This is because SplStack is implemented as a doubly-linked list, which provides the capacity to implement a traversable stack.

SplStack类实现的方法比我们最初定义的要多。 这是因为SplStack是作为双链表实现的,它提供了实现可遍历堆栈的能力。

A linked list, which is another abstract data type itself, is a linear collection of objects (nodes) used to represent a particular sequence, where each node in the collection maintains a pointer to the next node in collection. In its simplest form, a linked list looks something like this:

链表本身就是另一种抽象数据类型,它是用于表示特定序列的对象(节点)的线性集合,其中集合中的每个节点都维护着指向集合中下一个节点的指针。 以最简单的形式,链接列表看起来像这样:

dstructure1-01

In a doubly-linked list, each node has two pointers, each pointing to the next and previous nodes in the collection. This type of data structure allows for traversal in both directions.

在双向链接列表中,每个节点都有两个指针,每个指针都指向集合中的下一个和上一个节点。 这种类型的数据结构允许在两个方向上遍历。

dstructure1-02

Nodes marked with a cross (X) denotes a null or sentinel node – which designates the end of the traversal path (i.e. the path terminator).

标有叉号(X)的节点表示空节点或前哨节点-表示遍历路径的终点(即路径终止符)。

Since ReadingList is implemented as an SplStack, we can traverse the stack forward (top-down) and backward (bottom-up). The default traversal mode for SplStack is LIFO:

由于ReadingList是作为实现SplStack ,我们可以遍历堆栈向前(自上而下) 向后(自下而上)。 SplStack的默认遍历模式为LIFO:

<?php
// top-down traversal
// default traversal mode is SplDoublyLinkedList::IT_MODE_LIFO|SplDoublyLinkedList::IT_MODE_KEEP
foreach ($myBooks as $book) {
    echo $book . "n"; // prints last item first!
}

To traverse the stack in reverse order, we simply set the iterator mode to FIFO (first in, first out):

要以相反的顺序遍历堆栈,我们只需将迭代器模式设置为FIFO(先进先出):

<?php
// bottom-up traversal
$myBooks->setIteratorMode(
    SplDoublyLinkedList::IT_MODE_FIFO|SplDoublyLinkedList::IT_MODE_KEEP
);
foreach ($myBooks as $book) {
    echo $book . "n";  // prints first added item first
}

Queue列 (Queues)

If you’ve ever been in a line at the supermarket checkout, then you’ll know that the first person in line gets served first. In computer terminology, a queue is another abstract data type, which operates on a first in first out basis, or FIFO. Inventory is also managed on a FIFO basis, particularly if such items are of a perishable nature.

如果您去过超市结帐处的排队,那么您会知道第一位排队的人是第一位得到服务的。 在计算机术语中,队列是另一种抽象数据类型,其在入先出的基础的第一 ,或FIFO操作。 库存也以FIFO为基础进行管理,特别是在此类物品易腐的情况下。

The basic operations which define a queue are:

定义队列的基本操作是:

  • init – create the queue.

    init –创建队列。

  • enqueue – add an item to the “end” (tail) of the queue.

    入队 –将项目添加到队列的“末端”(尾部)。

  • dequeue – remove an item from the “front” (head) of the queue.

    出队 –从队列的“前”(头)中删除一项。

  • isEmpty – return whether the queue contains no more items.

    isEmpty –返回队列是否不再包含任何项目。

Since SplQueue is also implemented using a doubly-linked list, the semantic meaning of top and pop are reversed in this context. Let’s redefine our ReadingList class as a queue:

由于SplQueue也使用双向链表实现,因此top和pop的语义在这种情况下是相反的。 让我们将ReadingList类重新定义为队列:

<?php
class ReadingList extends SplQueue
{
}

$myBooks = new ReadingList();

// add some items to the queue
$myBooks->enqueue('A Game of Thrones');
$myBooks->enqueue('A Clash of Kings');
$myBooks->enqueue('A Storm of Swords');

SplDoublyLinkedList also implements the ArrayAccess interface so you can also add items to both SplQueue and SplStack as array elements:

SplDoublyLinkedList还实现了ArrayAccess接口,因此您还可以将元素作为数组元素添加到SplQueueSplStack中:

<?php
$myBooks[] = 'A Feast of Crows';
$myBooks[] = 'A Dance with Dragons';

To remove items from the front of the queue:

要从队列的最前面删除项目:

<?php
echo $myBooks->dequeue() . "n"; // outputs 'A Game of Thrones'
echo $myBooks->dequeue() . "n"; // outputs 'A Clash of Kings'

enqueue() is an alias for push(), but note that dequeue() is not an alias for pop(); pop() has a different meaning and function in the context of a queue. If we had used pop() here, it would remove the item from the end (tail) of the queue which violates the FIFO rule.

enqueue()push()的别名,但请注意, dequeue()不是pop()的别名; pop()在队列上下文中具有不同的含义和功能。 如果我们在此处使用了pop() ,它将从队列的末端(尾部)删除违反FIFO规则的项目。

Similarly, to see what’s at the front (head) of the queue, we have to use bottom() instead of top():

同样,要查看队列的最前面(头),我们必须使用bottom()而不是top()

<?php
echo $myBooks->bottom() . "n"; // outputs 'A Storm of Swords'

摘要 (Summary)

In this article, you’ve seen how the stack and queue abstract data types are used in programming. These data structures are abstract, in that they are defined by the operations that can be performed on itself, thereby creating a wall between its implementation and the underlying data.

在本文中,您已经了解了如何在编程中使用堆栈和队列抽象数据类型。 这些数据结构是抽象的,因为它们是由可以对其自身执行的操作定义的,从而在其实现和基础数据之间创建了一堵墙。

These structures are also constrained by the effect of such operations: You can only add or remove items from the top of the stack, and you can only remove items from the front of the queue, or add items to the rear of the queue.

这些操作的效果也限制了这些结构:您只能从堆栈的顶部添加或删除项目,并且只能从队列的前面删除项目,或者将项目添加到队列的后面。

Image by Alexandre Dulaunoy via Flickr

图片由Alexandre Dulaunoy通过Flickr 拍摄

翻译自: https://www.sitepoint.com/php-data-structures-1/

数据结构堆栈队列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值