目次
链式队列
PHP 为我们提供的数组队列操作
总结
ホームページ バックエンド開発 PHPの問題 PHPでのキューの詳しい説明

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

Jul 23, 2021 pm 05:37 PM
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 サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホット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ヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

今まで知らなかったことを後悔している 7 つの PHP 関数 今まで知らなかったことを後悔している 7 つの PHP 関数 Nov 13, 2024 am 09:42 AM

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

See all articles