検索
ホームページバックエンド開発PHPの問題PHPでのキューの詳しい説明

今日は、もう 1 つの非常に古典的な論理構造タイプであるキューについて学習します。 redis や Rabbitmq などのキャッシュ キュー ツールをすでに使用している学生も多いと思います。実際、データベースとプログラム コードはすべてキュー操作を実装できます。スタックと同様に、キューにも独自のルールがあり、これらのルールに従っている限り、キューと呼ばれます。

PHPでのキューの詳しい説明

#キューとは何ですか?

スタックと比較すると、キューは先入れ先出し (FIFO) 順次論理構造です。先入れ先出しとは何ですか?私たちの行列と同じように、銀行や病院に行くときも、必ず入り口で番号を受け取り、その番号が順番に呼ばれます。先に来た人が先に用事を済ませたり、診察を受けたりすることができるのが典型的な行列です。同様に、毎日のキューイングは標準のキュー モードです。

キューを飛び越える人がいる場合、正当な理由がある場合は、その優先順位が高いと見なすことができます。これはキュー内の要素の特殊な形式です。地下鉄やバスを待つときに妊婦を優先するのと同じように、鉄道の切符を買うために並ぶときにも軍人のための優先窓口があります。ただし、これは今回の議論の範囲外です。

バス停に並ぶときは、当然のことながら、最初に並んでいる人が先にバスに乗り、その後に他の人が続きます。この時点でバス停に来たら、最後尾に並ぶしかありません。これはキューの具体的な現れです。

同様に、スタックと同様に、理解する必要がある名詞がいくつかあります。バス停に来て列の最後尾になったとき、この操作を「列に加わる」といいます。バスが駅に進入し、最初の乗客がバスに乗車することを「降車」といいます。最初の乗客の位置は「列の先頭」と呼ばれ、現在の列の最後の乗客であるあなたの位置は「列の最後尾」と呼ばれます。コードのロジックに戻ります。つまり、キューは「末尾」から「入力」され、「先頭」から「終了」されます。

シーケンシャル キュー

OK、コードを直接見てみましょう。最初に表示されるのは、やはりシーケンシャル キューの実装です。

class SqQueue{
    public $data;
    public $front;
    public $rear;
}

シーケンシャル チームであるため、チーム内の要素を表すために配列データを引き続き使用します。次に、チームの先頭と最後尾を表す 2 つのポインターを前後に定義します。これはシーケンシャルキューであるため、ここでのポインターには実際には配列の添字が格納されます。次の操作は実際には非常に簡単で、「キューに入る」場合は後方、「キューから出る」場合は前です。

function InitSqQueue(){
    $queue = new SqQueue();
    $queue->data = [];
    $queue->front = 0;
    $queue->rear = 0;
    return $queue;
}

function EnSqQueue(SqQueue &$queue, $e){
    $queue->data[$queue->rear] = $e;
    $queue->rear ++;
}

function DeSqQueue(SqQueue &$queue){
    // 队列为空
    if($queue->front == $queue->rear){
        return false;
    }
    $e = $queue->data[$queue->front];
    $queue->front++;
    return $e;
}

$q = InitSqQueue();
EnSqQueue($q, 'A');
EnSqQueue($q, 'B');
print_r($q);
// SqQueue Object
// (
//     [data] => Array
//         (
//             [0] => A
//             [1] => B
//         )

//     [front] => 0
//     [rear] => 2
// )

スタックを学ぶと、キューも理解しやすくなったと感じますか。キューを初期化するときは、先頭ポインターと末尾ポインターを添字 0 のレコードに設定するだけです。キューに参加するときは、キューの末尾を増やしてください。このコードでは、2 つの要素をキューに結合しており、出力される順次キューの内容はコメントに示されているとおりです。

EnSqQueue($q, 'C');
EnSqQueue($q, 'D');
EnSqQueue($q, 'E');
print_r($q);
// SqQueue Object
// (
//     [data] => Array
//         (
//             [0] => A
//             [1] => B
//             [2] => C
//             [3] => D
//             [4] => E
//         )

//     [front] => 0
//     [rear] => 5
// )

echo DeSqQueue($q), PHP_EOL; // A
echo DeSqQueue($q), PHP_EOL; // B
echo DeSqQueue($q), PHP_EOL; // C
echo DeSqQueue($q), PHP_EOL; // D
echo DeSqQueue($q), PHP_EOL; // E

echo DeSqQueue($q), PHP_EOL; // 

print_r($q);
// SqQueue Object
// (
//     [data] => Array
//         (
//             [0] => A
//             [1] => B
//             [2] => C
//             [3] => D
//             [4] => E 
//         )

//     [front] => 5
//     [rear] => 5
// )

チームを離れるときは、フロントに1を加える操作を行わせます。ただし、デキューする際には、配列内のすべての要素がデキューされたかどうかを判断する必要があるため、ここでは、前と後ろが等しいかどうかという非常に単純な判定条件のみを使用して、キューが空であるかどうかを判断します。コードの理解を助けるために図を使用できます。

PHPでのキューの詳しい説明

回覧キュー

多くの学生が気づいたと思います。キュー操作はキューの先頭とキューの末尾のポインタ レコードを変更するだけですが、配列は増加し続けます。増加し続けると、配列がメモリをいっぱいにしてしまいます。これは明らかに良いキュー実装ではありません。実際、C 言語では配列には固定長が与えられます。 PHP の配列はハッシュ構造に似ているため、無限に増加する可能性があり、最初に特定の配列の長さを定義する必要はありません。

これも PHP の便利な機能ですが、メモリ領域を無駄にしたくない場合はどうすればよいでしょうか? C 言語と同様に、PHP でも配列の長さを指定し、非常に古典的な「循環キュー」を使用してキュー配列のストレージの問題を解決します。以下の図に示すように:

PHPでのキューの詳しい説明

実際には、限られた配列スペース内で配列の最大値に達すると、新しいデータが保存されることを意味します。前に戻る下付き文字の位置。たとえば、この図には 6 つの要素があり、現在のチームの先頭は添字 2 にあり、チームの最後尾は添字 5 にあります。要素をキューに入れると、キューの最後はインデックス 6 に移動します。別の要素を追加すると、キューの末尾の添字は 0 の添字に戻ります。追加を続けると、キューの末尾の添字がキューの先頭の添字から 1 を引いた値に等しい場合、キューがいっぱいでこれ以上要素はないと考えられます。を追加することができます。

デキュー時も同様に、チームヘッド要素も周期的に操作し、チームヘッド要素が添字6に到達した時点でデキューを続けると、添字0の位置に戻ってデキューを継続します。 . .キューの先頭とキューの末尾が等しい場合も、現在のキューは空のキューであると判断できる。

由此,我们可以看出,循环队列相比普通的线性队列来说,多了一个队满的状态。我们还是直接从代码中来看看这个队满的条件是如何判断的。

define('MAX_QUEUE_LENGTH', 6);

function EnSqQueueLoop(SqQueue &$queue, $e){
    // 判断队列是否满了
    if(($queue->rear + 1) % MAX_QUEUE_LENGTH == $queue->front){
        return false;
    }
    $queue->data[$queue->rear] = $e;
    $queue->rear = ($queue->rear + 1) % MAX_QUEUE_LENGTH; // 改成循环下标
}

function DeSqQueueLoop(SqQueue &$queue){
    // 队列为空
    if($queue->front == $queue->rear){
        return false;
    }
    $e = $queue->data[$queue->front];
    $queue->front = ($queue->front + 1) % MAX_QUEUE_LENGTH; // 改成循环下标
    return $e;
}

$q = InitSqQueue();
EnSqQueueLoop($q, 'A');
EnSqQueueLoop($q, 'B');
EnSqQueueLoop($q, 'C');
EnSqQueueLoop($q, 'D');
EnSqQueueLoop($q, 'E');

EnSqQueueLoop($q, 'F');

print_r($q);
// SqQueue Object
// (
//     [data] => Array
//         (
//             [0] => A
//             [1] => B
//             [2] => C
//             [3] => D
//             [4] => E
//             [5] =>   // 尾
//         )

//     [front] => 0
//     [rear] => 5
// )

echo DeSqQueueLoop($q), PHP_EOL;
echo DeSqQueueLoop($q), PHP_EOL;
print_r($q);
// SqQueue Object
// (
//     [data] => Array
//         (
//             [0] => A
//             [1] => B
//             [2] => C // 头
//             [3] => D
//             [4] => E
//             [5] =>   // 尾
//         )

//     [front] => 2
//     [rear] => 5
// )

EnSqQueueLoop($q, 'F');
EnSqQueueLoop($q, 'G');

EnSqQueueLoop($q, 'H');
print_r($q);
// SqQueue Object
// (
//     [data] => Array
//         (
//             [0] => G
//             [1] => B // 尾
//             [2] => C // 头
//             [3] => D
//             [4] => E
//             [5] => F
//         )

//     [front] => 2
//     [rear] => 1
// )

出、入队的下标移动以及队满的判断,都是以 (queue->rear + 1) % MAX_QUEUE_LENGTH 这个形式进行的。根据队列长度的取模来获取当前的循环下标,是不是非常地巧妙。不得不感慨先人的智慧呀!当然,这也是基本的数学原理哦,所以,学习数据结构还是要复习一下数学相关的知识哦!

链式队列

顺序队列有没有看懵?没关系,队列的链式结构其实相比顺序结构还要简单一些,因为它真的只需要操作队头和队尾的指针而已,别的真的就不太需要考虑了。而且这个指针就是真的指向具体对象的指针了。

class LinkQueueNode{
    public $data;
    public $next;
}

class LinkQueue{
    public $first; // 队头指针
    public $rear; // 队尾指针
}

这里我们需要两个基本的物理结构。一个是节点 Node ,一个是队列对象,节点对象就是一个正常的链表结构,没啥特别的。而队列对象里面就更简单了,一个属性是队头指针,一个属性是队尾指针。

function InitLinkQueue(){
    $node = new LinkQueueNode();
    $node->next = NULL;
    $queue = new LinkQueue();
    $queue->first = $node;
    $queue->rear = $node;
    return $queue;
}

function EnLinkQueue(LinkQueue &$queue, $e){
    $node = new LinkQueueNode();
    $node->data = $e;
    $node->next = NULL;

    $queue->rear->next = $node;
    $queue->rear = $node;
}

function DeLinkQueue(LinkQueue &$queue){
    if($queue->front == $queue->rear){
        return false;
    }

    $node = $queue->first->next;
    $v = $node->data;

    $queue->first->next = $node->next;
    if($queue->rear == $node){
        $queue->rear = $queue->first;
    }

    return $v;
}

$q = InitLinkQueue();
EnLinkQueue($q, 'A');
EnLinkQueue($q, 'B');
EnLinkQueue($q, 'C');
EnLinkQueue($q, 'D');
EnLinkQueue($q, 'E');

print_r($q);
// LinkQueue Object
// (
//     [first] => LinkQueueNode Object
//         (
//             [data] => 
//             [next] => LinkQueueNode Object
//                 (
//                     [data] => A
//                     [next] => LinkQueueNode Object
//                         (
//                             [data] => B
//                             [next] => LinkQueueNode Object
//                                 (
//                                     [data] => C
//                                     [next] => LinkQueueNode Object
//                                         (
//                                             [data] => D
//                                             [next] => LinkQueueNode Object
//                                                 (
//                                                     [data] => E
//                                                     [next] => 
//                                                 )

//                                         )

//                                 )

//                         )

//                 )

//         )

//     [rear] => LinkQueueNode Object
//         (
//             [data] => E
//             [next] => 
//         )

// )

echo DeLinkQueue($q), PHP_EOL; // A
echo DeLinkQueue($q), PHP_EOL; // B

EnLinkQueue($q, 'F');
print_r($q);
// LinkQueue Object
// (
//     [first] => LinkQueueNode Object
//         (
//             [data] => 
//             [next] => LinkQueueNode Object
//                 (
//                     [data] => C
//                     [next] => LinkQueueNode Object
//                         (
//                             [data] => D
//                             [next] => LinkQueueNode Object
//                                 (
//                                     [data] => E
//                                     [next] => LinkQueueNode Object
//                                         (
//                                             [data] => F
//                                             [next] => 
//                                         )

//                                 )

//                         )

//                 )

//         )

//     [rear] => LinkQueueNode Object
//         (
//             [data] => F
//             [next] => 
//         )

// )

出、入队的代码函数和测试代码就一并给出了,是不是非常的简单。初始的队头元素依然是一个空节点做为起始节点。然后入队的时候,让 rear 等于新创建的这个节点,并在链表中建立链式关系。出队的时候也是同样的让 first 变成当前这个 first 的下一跳节点,也就是 first->next 就可以了。判断队空的条件也是简单的变成了队头和队尾指针是否相等就可以了。链队相比顺序队其实是简单了一些,不过同样的,next 这个东西容易让人头晕,硬记下来就可以了。大家还是可以结合图示来学习:

PHPでのキューの詳しい説明

PHP 为我们提供的数组队列操作

最后,就和栈一样,PHP 代码中也为我们提供了一个可以用于队列操作的函数。

$sqQueueList = [];

array_push($sqQueueList, 'a');
array_push($sqQueueList, 'b');
array_push($sqQueueList, 'c');

print_r($sqQueueList);
// Array
// (
//     [0] => a
//     [1] => b
//     [2] => c
// )

array_shift($sqQueueList);
print_r($sqQueueList);
// Array
// (
//     [0] => b
//     [1] => c
// )

array_shift() 函数就是弹出数组中最前面的那个元素。请注意,这里元素的下标也跟着变动了,如果我们是 unset() 掉数组的 0 下标元素的话,b 和 c 的下标依然还会是 1 和 2 。而 array_shift() 则会重新整理数组,让其下标依然有序。

unset($sqQueueList[0]);
print_r($sqQueueList);
// Array
// (
//     [1] => c
// )

总结

关于栈的队列的内容我们就通过两篇文章介绍完了。不过光说不练假把式,接下来,我们来一点真实的干货,使用栈和队列来做做题呗,学算法就得刷题,一日不刷如隔三秋呀!!!

测试代码:

https://github.com/zhangyue0503/Data-structure-and-algorithm/blob/master/3.栈和队列/source/3.2队列的相关逻辑操作.php

推荐学习:php视频教程

以上がPHPでのキューの詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はsegmentfaultで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
酸とベースデータベース:違いとそれぞれを使用するタイミング。酸とベースデータベース:違いとそれぞれを使用するタイミング。Mar 26, 2025 pm 04:19 PM

この記事では、酸とベースのデータベースモデルを比較し、その特性と適切なユースケースを詳述しています。酸は、財務およびeコマースアプリケーションに適したデータの整合性と一貫性を優先し、ベースは可用性に焦点を当て、

PHPセキュアファイルアップロード:ファイル関連の脆弱性の防止。PHPセキュアファイルアップロード:ファイル関連の脆弱性の防止。Mar 26, 2025 pm 04:18 PM

この記事では、コードインジェクションのような脆弱性を防ぐために、PHPファイルのアップロードを確保することについて説明します。ファイルタイプの検証、セキュアストレージ、およびアプリケーションセキュリティを強化するエラー処理に焦点を当てています。

PHP入力検証:ベストプラクティス。PHP入力検証:ベストプラクティス。Mar 26, 2025 pm 04:17 PM

記事では、組み込み関数、ホワイトリストアプローチ、サーバー側の検証などの手法に焦点を当てたセキュリティを強化するためのPHP入力検証のベストプラクティスについて説明します。

PHP APIレート制限:実装戦略。PHP APIレート制限:実装戦略。Mar 26, 2025 pm 04:16 PM

この記事では、Token BucketやLeaky BucketなどのアルゴリズムやSymfony/Rate-Limiterなどのライブラリを使用するなど、PHPでAPIレート制限を実装するための戦略について説明します。また、監視、動的に調整されたレートの制限、および手をカバーします

PHPパスワードハッシュ:password_hashおよびpassword_verify。PHPパスワードハッシュ:password_hashおよびpassword_verify。Mar 26, 2025 pm 04:15 PM

この記事では、パスワードを保護するためにPHPでpassword_hashとpassword_verifyを使用することの利点について説明します。主な議論は、これらの関数が自動塩の生成、強力なハッシュアルゴリズム、およびSecurを通じてパスワード保護を強化するということです

OWASPトップ10 PHP:共通の脆弱性を説明し、軽減します。OWASPトップ10 PHP:共通の脆弱性を説明し、軽減します。Mar 26, 2025 pm 04:13 PM

この記事では、PHPおよび緩和戦略におけるOWASPトップ10の脆弱性について説明します。重要な問題には、PHPアプリケーションを監視および保護するための推奨ツールを備えたインジェクション、認証の壊れ、XSSが含まれます。

PHP XSS予防:XSSから保護する方法。PHP XSS予防:XSSから保護する方法。Mar 26, 2025 pm 04:12 PM

この記事では、PHPでのXSS攻撃を防ぐための戦略について説明し、入力の消毒、出力エンコード、セキュリティを向上させるライブラリとフレームワークの使用に焦点を当てています。

PHPインターフェイスvs抽象クラス:それぞれを使用する時期。PHPインターフェイスvs抽象クラス:それぞれを使用する時期。Mar 26, 2025 pm 04:11 PM

この記事では、PHPでのインターフェイスと抽象クラスの使用について説明し、それぞれをいつ使用するかに焦点を当てています。インターフェイスは、無関係なクラスや複数の継承に適した、実装なしで契約を定義します。抽象クラスは共通の機能を提供します

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター